From 3a3f13e4e24bca487f9c858c3e783d4303bfce72 Mon Sep 17 00:00:00 2001 From: Steven Clark Date: Fri, 27 Sep 2024 21:13:20 +0000 Subject: [PATCH] backport of commit 70d5c5e5822344a7ad0a6334e96ad28e1fde834c --- .github/docs/pull_request_template.md | 8 - .github/pull_request_template.md | 17 - .github/workflows/backport-ce.yml | 2 +- .github/workflows/changelog-checker.yml | 10 +- .github/workflows/do-not-merge-checker.yml | 22 - .../workflows/enos-release-testing-oss.yml | 2 +- .github/workflows/plugin-update.yml | 22 +- .github/workflows/security-scan.yml | 6 +- .github/workflows/test-enos-scenario-ui.yml | 2 +- .release/versions.hcl | 14 +- CHANGELOG.md | 947 +------------ Makefile | 6 - README.md | 25 +- api/auth/approle/LICENSE | 365 ----- api/auth/approle/go.mod | 4 +- api/auth/approle/go.sum | 8 +- api/auth/aws/LICENSE | 365 ----- api/auth/aws/go.mod | 4 +- api/auth/aws/go.sum | 8 +- api/auth/azure/LICENSE | 365 ----- api/auth/azure/azure.go | 6 +- api/auth/azure/go.mod | 4 +- api/auth/azure/go.sum | 8 +- api/auth/gcp/LICENSE | 365 ----- api/auth/gcp/gcp.go | 4 +- api/auth/gcp/go.mod | 4 +- api/auth/gcp/go.sum | 8 +- api/auth/kubernetes/LICENSE | 365 ----- api/auth/kubernetes/go.mod | 4 +- api/auth/kubernetes/go.sum | 8 +- api/auth/ldap/LICENSE | 365 ----- api/auth/ldap/go.mod | 4 +- api/auth/ldap/go.sum | 8 +- api/auth/userpass/LICENSE | 365 ----- api/auth/userpass/go.mod | 4 +- api/auth/userpass/go.sum | 8 +- api/client.go | 28 +- api/client_test.go | 55 - api/go.mod | 2 +- api/go.sum | 4 +- api/lifetime_watcher.go | 2 +- api/request.go | 5 +- api/response.go | 3 +- api/secret.go | 4 - api/sudo_paths.go | 1 - api/sys_raft.go | 2 +- audit/backend.go | 2 - audit/backend_test.go | 18 - audit/entry_formatter.go | 11 - audit/entry_formatter_ce.go | 18 - audit/entry_formatter_ce_test.go | 37 - audit/entry_formatter_config.go | 8 - audit/entry_formatter_config_ce.go | 16 - builtin/credential/aws/backend_test.go | 4 +- builtin/credential/aws/client.go | 3 +- builtin/credential/aws/path_login.go | 4 +- builtin/credential/cert/backend_test.go | 23 +- builtin/credential/cert/path_login.go | 16 +- builtin/credential/cert/path_login_test.go | 4 +- builtin/credential/cert/test_responder.go | 4 +- builtin/logical/database/backend_test.go | 74 +- builtin/logical/database/path_roles.go | 15 - builtin/logical/database/path_roles_test.go | 8 +- builtin/logical/database/rollback_test.go | 6 +- builtin/logical/database/rotation.go | 11 - builtin/logical/database/rotation_test.go | 16 +- builtin/logical/database/secret_creds.go | 6 - builtin/logical/pki/acme_challenge_engine.go | 8 +- builtin/logical/pki/acme_state.go | 2 +- builtin/logical/pki/acme_wrappers.go | 33 +- builtin/logical/pki/acme_wrappers_test.go | 8 +- builtin/logical/pki/backend.go | 83 +- builtin/logical/pki/backend_test.go | 31 +- builtin/logical/pki/ca_util.go | 19 +- builtin/logical/pki/cert_util.go | 68 +- builtin/logical/pki/cert_util_test.go | 4 +- builtin/logical/pki/cieps_util_oss.go | 2 +- builtin/logical/pki/cmpv2_util_oss.go | 16 - builtin/logical/pki/crl_test.go | 34 +- builtin/logical/pki/crl_util.go | 269 ++-- builtin/logical/pki/fields.go | 35 - builtin/logical/pki/issuing/context.go | 22 - builtin/logical/pki/issuing/issue_common.go | 11 +- builtin/logical/pki/issuing/issuers.go | 96 +- builtin/logical/pki/issuing/keys.go | 33 - builtin/logical/pki/issuing/sign_cert.go | 24 +- builtin/logical/pki/key_util.go | 6 +- builtin/logical/pki/parsing/certificate.go | 8 - builtin/logical/pki/path_acme_order.go | 18 +- builtin/logical/pki/path_acme_revoke.go | 7 +- builtin/logical/pki/path_config_acme.go | 2 +- builtin/logical/pki/path_config_crl.go | 39 +- builtin/logical/pki/path_fetch.go | 9 +- builtin/logical/pki/path_fetch_issuers.go | 6 +- builtin/logical/pki/path_fetch_keys.go | 2 +- builtin/logical/pki/path_issue_sign.go | 2 +- builtin/logical/pki/path_manage_issuers.go | 11 +- builtin/logical/pki/path_ocsp.go | 33 +- builtin/logical/pki/path_ocsp_test.go | 8 +- builtin/logical/pki/path_resign_crls.go | 5 +- builtin/logical/pki/path_revoke.go | 9 +- builtin/logical/pki/path_root.go | 5 +- builtin/logical/pki/path_sign_issuers.go | 4 +- builtin/logical/pki/path_tidy.go | 83 +- builtin/logical/pki/periodic.go | 48 +- builtin/logical/pki/pki_backend/common.go | 85 +- .../logical/pki/pki_backend/crl_builder.go | 20 - builtin/logical/pki/pki_backend/crl_config.go | 38 - .../pki/pki_backend/rolepathpolicy_enumer.go | 80 -- .../pki/pki_backend/storage_context.go | 25 - .../pki/revocation/revocation_entry.go | 34 - builtin/logical/pki/revocation/revoke.go | 100 -- builtin/logical/pki/secret_certs.go | 2 +- builtin/logical/pki/storage.go | 128 +- builtin/logical/pki/storage_test.go | 1 - builtin/logical/pki/storage_unified.go | 27 +- builtin/logical/pki/util.go | 9 +- builtin/logical/pkiext/nginx_test.go | 2 +- builtin/logical/rabbitmq/path_role_create.go | 10 +- changelog/10624.txt | 3 - changelog/11084.txt | 3 - changelog/14723.txt | 4 - changelog/16484.txt | 3 - changelog/16974.txt | 3 - changelog/17007.txt | 3 - changelog/19064.txt | 3 - changelog/21159.txt | 4 - changelog/21993.txt | 3 - changelog/25080.txt | 3 - changelog/26073.txt | 3 - changelog/26570.txt | 3 - changelog/26660.txt | 3 - changelog/26828.txt | 3 - changelog/26868.txt | 3 - changelog/27033.txt | 3 - changelog/27123.txt | 6 - changelog/27202.txt | 3 - changelog/27265.txt | 3 - changelog/27348.txt | 3 - changelog/27350.txt | 4 - changelog/27379.txt | 5 - changelog/27394.txt | 4 - changelog/27405.txt | 3 - changelog/27426.txt | 4 - changelog/27455.txt | 3 - changelog/27457.txt | 3 - changelog/27510.txt | 6 - changelog/27538.txt | 3 - changelog/27578.txt | 3 - changelog/27605.txt | 3 - changelog/27633.txt | 3 - changelog/27681.txt | 3 - changelog/27796.txt | 3 - changelog/27799.txt | 3 - changelog/27816.txt | 3 - changelog/27830.txt | 3 - changelog/27831.txt | 3 - changelog/27846.txt | 7 - changelog/27918.txt | 3 - changelog/27920.txt | 3 - changelog/27927.txt | 6 - changelog/27929.txt | 3 - changelog/27950.txt | 3 - changelog/27966.txt | 3 - changelog/28024.txt | 3 - changelog/28036.txt | 3 - changelog/28064.txt | 7 - changelog/28076.txt | 3 - changelog/28148.txt | 3 - changelog/28186.txt | 3 - changelog/28199.txt | 3 - changelog/28212.txt | 3 - changelog/28237.txt | 3 - changelog/28263.txt | 3 - changelog/28264.txt | 3 - changelog/28266.txt | 3 - changelog/28267.txt | 3 - changelog/28268.txt | 3 - changelog/28269.txt | 3 - changelog/28271.txt | 3 - changelog/28275.txt | 3 - changelog/28277.txt | 3 - changelog/28287.txt | 3 - changelog/28289.txt | 3 - changelog/28293.txt | 3 - changelog/28294.txt | 3 - changelog/28300.txt | 3 - changelog/28307.txt | 3 - changelog/28312.txt | 3 - changelog/28324.txt | 3 - changelog/28325.txt | 3 - changelog/28327.txt | 3 - changelog/28334.txt | 3 - changelog/28348.txt | 3 - changelog/28349.txt | 3 - changelog/28360.txt | 3 - changelog/28361.txt | 3 - changelog/28366.txt | 3 - changelog/28371.txt | 3 - changelog/28404.txt | 3 - changelog/28478.txt | 3 + changelog/28479.txt | 3 - changelog/28519.txt | 3 - changelog/9733.txt | 3 - changelog/_go-ver-1170.txt | 2 +- changelog/_go-ver-1172.txt | 3 + changelog/_go-ver-1174.txt | 3 + .../{_go-ver-1180.txt => _go-ver-1176.txt} | 0 command/agent.go | 12 - command/agent_test.go | 1 - command/agentproxyshared/auth/auth.go | 44 +- command/agentproxyshared/auth/gcp/gcp.go | 4 +- .../auth/kubernetes/kubernetes.go | 3 +- command/agentproxyshared/cache/handler.go | 7 +- command/agentproxyshared/cache/proxy.go | 2 +- .../agentproxyshared/sink/file/file_sink.go | 30 +- .../sink/file/file_sink_test.go | 92 +- command/base.go | 18 +- command/command_stubs_oss.go | 7 +- command/command_test.go | 12 +- command/commands.go | 179 ++- command/commands_full.go | 96 -- command/commands_full_test.go | 46 - command/commands_min.go | 14 - command/commands_test.go | 3 - command/operator_diagnose.go | 12 +- command/operator_migrate_test.go | 19 +- command/operator_usage.go | 22 +- command/pki_reissue_intermediate.go | 4 - command/proxy.go | 12 - command/proxy_test.go | 1 - command/read.go | 12 +- command/server.go | 349 ++++- command/server/listener_tcp_test.go | 71 +- command/util.go | 39 - command/write.go | 12 +- go.mod | 278 ++-- go.sum | 583 ++++---- helper/benchhelpers/benchhelpers.go | 22 + helper/builtinplugins/registry.go | 149 +- helper/builtinplugins/registry_full.go | 149 -- helper/builtinplugins/registry_full_test.go | 30 - helper/builtinplugins/registry_min.go | 10 - .../builtinplugins/registry_testing_util.go | 27 - helper/locking/core_locking.go | 44 - helper/locking/core_locking_test.go | 103 -- helper/testhelpers/corehelpers/corehelpers.go | 10 +- helper/testhelpers/minimal/minimal.go | 5 +- .../pluginhelpers/pluginhelpers.go | 35 +- .../postgresql/postgresqlhelper.go | 259 +--- helper/testhelpers/seal/sealhelper.go | 8 +- helper/testhelpers/testhelpers.go | 76 +- helper/testhelpers/testhelpers_oss.go | 5 +- .../testhelpers/teststorage/consul/consul.go | 10 +- helper/testhelpers/teststorage/teststorage.go | 28 +- .../teststorage/teststorage_reusable.go | 28 +- http/forwarding_bench_test.go | 5 +- http/handler.go | 12 +- http/handler_test.go | 4 +- http/plugin_test.go | 11 +- http/sys_health_test.go | 4 +- internalshared/configutil/listener.go | 2 +- internalshared/configutil/telemetry.go | 5 - physical/azure/azure.go | 6 +- physical/cassandra/cassandra.go | 8 - physical/couchdb/couchdb.go | 6 +- physical/couchdb/couchdb_test.go | 6 +- physical/dynamodb/dynamodb.go | 28 +- physical/gcs/gcs.go | 4 +- physical/oci/oci.go | 6 +- physical/oci/oci_ha.go | 6 +- physical/postgresql/postgresql_test.go | 2 +- physical/raft/raft.go | 6 - physical/raft/raft_autopilot.go | 187 +-- physical/raft/snapshot.go | 2 +- physical/raft/snapshot_test.go | 2 +- physical/s3/s3.go | 8 +- plugins/database/mssql/mssql.go | 2 +- plugins/database/mssql/mssql_test.go | 4 +- plugins/database/mysql/connection_producer.go | 9 +- plugins/database/postgresql/postgresql.go | 107 +- .../database/postgresql/postgresql_test.go | 731 ++-------- sdk/database/dbplugin/v5/conversions_test.go | 2 - sdk/database/dbplugin/v5/database.go | 7 - sdk/database/dbplugin/v5/grpc_client.go | 11 +- sdk/database/dbplugin/v5/grpc_server.go | 11 +- sdk/database/dbplugin/v5/proto/database.pb.go | 163 ++- sdk/database/dbplugin/v5/proto/database.proto | 1 - .../helper/cacheutil/cache_stubs_oss.go | 16 - sdk/database/helper/connutil/cloudsql.go | 24 +- sdk/database/helper/connutil/postgres.go | 466 ------- sdk/database/helper/connutil/sql.go | 203 +-- sdk/database/helper/connutil/sql_stubs_oss.go | 16 - sdk/go.mod | 35 +- sdk/go.sum | 348 +---- sdk/helper/certutil/certutil_test.go | 95 -- sdk/helper/certutil/helpers.go | 95 +- sdk/helper/certutil/types.go | 5 - sdk/helper/docker/testhelpers.go | 3 +- sdk/helper/metricregistry/metricregistry.go | 107 -- .../metricregistry/metricregistry_test.go | 122 -- sdk/helper/ocsp/ocsp_test.go | 5 +- sdk/helper/pluginutil/env.go | 5 - sdk/helper/policyutil/policyutil.go | 24 +- sdk/helper/policyutil/policyutil_test.go | 58 +- sdk/helper/testcluster/docker/environment.go | 20 +- .../testcluster/docker/environment_test.go | 38 - sdk/helper/testcluster/exec.go | 7 +- sdk/helper/testhelpers/output.go | 4 +- sdk/logical/testing.go | 6 +- .../consul/consul_service_registration.go | 19 +- .../consul_service_registration_test.go | 60 - tools/semgrep/ci/no-nil-check.yml | 7 - ui/.gitignore | 1 - ui/.yarnrc | 6 + ui/app/adapters/aws/lease-config.js | 43 - ui/app/adapters/aws/root-config.js | 43 - ui/app/adapters/capabilities.js | 57 +- ui/app/adapters/clients/activity.js | 73 +- ui/app/adapters/generated-item-list.js | 126 +- ui/app/adapters/identity/oidc/config.js | 38 - ui/app/adapters/kmip/role.js | 33 +- ui/app/adapters/kv/data.js | 104 +- ui/app/adapters/kv/metadata.js | 8 +- ui/app/adapters/named-path.js | 2 +- ui/app/adapters/secret-engine.js | 29 + ui/app/adapters/ssh/ca-config.js | 46 - ui/app/app.js | 12 +- ui/app/components/app-footer.hbs | 12 - ui/app/components/auth-form.js | 103 +- ui/app/components/auth/login-form.hbs | 23 - ui/app/components/auth/login-form.js | 108 -- ui/app/components/auth/page.hbs | 119 -- ui/app/components/auth/page.js | 72 - ui/app/components/calendar-widget.js | 103 ++ ui/app/components/clients/activity.ts | 131 +- ui/app/components/clients/attribution.hbs | 139 +- ui/app/components/clients/attribution.js | 242 +++- ui/app/components/clients/chart-container.hbs | 6 +- ui/app/components/clients/charts/line.hbs | 129 ++ ui/app/components/clients/charts/line.ts | 146 ++ .../clients/charts/vertical-bar-grouped.hbs | 133 -- .../clients/charts/vertical-bar-grouped.ts | 179 --- ui/app/components/clients/date-range.hbs | 109 -- ui/app/components/clients/date-range.ts | 125 -- ui/app/components/clients/page-header.hbs | 112 -- ui/app/components/clients/page-header.js | 126 -- ui/app/components/clients/page/acme.hbs | 14 + ui/app/components/clients/page/counts.hbs | 100 +- ui/app/components/clients/page/counts.ts | 152 ++- ui/app/components/clients/page/overview.hbs | 22 +- ui/app/components/clients/page/overview.ts | 15 - ui/app/components/clients/page/sync.hbs | 14 + ui/app/components/clients/page/token.hbs | 13 +- ui/app/components/clients/page/token.ts | 8 +- ui/app/components/clients/running-total.hbs | 14 +- ui/app/components/clients/running-total.ts | 23 - ui/app/components/configure-aws-secret.js | 56 + ui/app/components/configure-ssh-secret.js | 38 + ui/app/components/console/ui-panel.js | 2 +- .../dashboard/quick-actions-card.js | 4 +- ui/app/components/database-connection.js | 52 +- .../components/database-role-setting-form.js | 2 +- ui/app/components/date-dropdown.js | 78 ++ ui/app/components/generate-credentials.js | 199 ++- ui/app/components/generated-item-list.js | 2 +- .../modal-form/oidc-key-template.hbs | 6 - .../modal-form/oidc-key-template.js | 41 - ...-backend-form.ts => mount-backend-form.js} | 42 +- ui/app/components/oidc/key-form.js | 5 +- ui/app/components/raft-storage-overview.js | 2 +- ui/app/components/raft-storage-restore.js | 2 +- ui/app/components/secret-create-or-update.js | 3 - .../secret-engine/configuration-details.hbs | 49 - .../secret-engine/configure-aws.hbs | 136 -- .../components/secret-engine/configure-aws.ts | 232 ---- .../secret-engine/configure-ssh.hbs | 75 - .../components/secret-engine/configure-ssh.ts | 119 -- ui/app/components/sidebar/nav/cluster.hbs | 8 +- ui/app/components/sidebar/nav/cluster.js | 6 +- ui/app/components/tool-actions-form.js | 156 +++ ui/app/components/tool-hash.js | 33 + ui/app/components/tool-lookup.js | 39 + ui/app/components/tool-random.js | 34 + ui/app/components/tool-rewrap.js | 36 + ui/app/components/tool-unwrap.js | 34 + ui/app/components/tool-wrap.js | 47 + ui/app/components/tools/hash.hbs | 86 -- ui/app/components/tools/hash.js | 61 - ui/app/components/tools/lookup.hbs | 50 - ui/app/components/tools/lookup.js | 56 - ui/app/components/tools/random.hbs | 66 - ui/app/components/tools/random.js | 54 - ui/app/components/tools/rewrap.hbs | 56 - ui/app/components/tools/rewrap.js | 48 - ui/app/components/tools/unwrap.hbs | 73 - ui/app/components/tools/unwrap.js | 56 - ui/app/components/tools/wrap.hbs | 68 - ui/app/components/tools/wrap.js | 66 - ui/app/components/transit-edit.js | 4 +- ui/app/components/z-docfy-filter.hbs | 19 - ui/app/components/z-docfy-filter.js | 24 - ui/app/controllers/application.js | 14 + ui/app/controllers/application.ts | 16 - .../vault/cluster/access/leases/list.js | 4 +- .../vault/cluster/access/leases/show.js | 4 +- ui/app/controllers/vault/cluster/auth.js | 77 +- ui/app/controllers/vault/cluster/init.js | 3 +- .../cluster/secrets/backend/configuration.js | 14 + .../cluster/secrets/backend/credentials.js | 5 +- .../configure-secret-backend.js} | 25 + ui/app/decorators/model-validations.js | 2 +- ui/{lib/core/addon => app}/helpers/await.js | 0 ui/app/helpers/aws-regions.js | 1 - .../addon => app}/helpers/date-from-now.js | 0 ui/app/helpers/mountable-secret-engines.js | 16 - ui/app/initializers/deprecation-filter.js | 3 +- ui/app/models/auth-config.js | 10 +- ui/app/models/auth-config/azure.js | 1 + ui/app/models/auth-config/gcp.js | 1 + ui/app/models/auth-config/github.js | 1 + ui/app/models/auth-config/jwt.js | 1 + ui/app/models/auth-config/kubernetes.js | 1 + ui/app/models/auth-config/ldap.js | 1 + ui/app/models/auth-config/okta.js | 1 + ui/app/models/auth-config/radius.js | 1 + ui/app/models/auth-method.js | 4 +- ui/app/models/aws-credential.js | 61 +- ui/app/models/aws/lease-config.js | 39 - ui/app/models/aws/root-config.js | 90 -- ui/app/models/capabilities.js | 11 +- ui/app/models/clients/config.js | 4 - ui/app/models/database/connection.js | 2 +- ui/app/models/database/role.js | 2 +- ui/app/models/generated-item.js | 44 - ui/app/models/identity/oidc/config.js | 23 - ui/app/models/kmip/config.js | 4 + ui/app/models/kmip/role.js | 82 +- ui/app/models/kv/data.js | 8 +- ui/app/models/kv/metadata.js | 8 +- ui/app/models/mount-config.js | 8 - ui/app/models/pki/certificate/base.js | 7 + ui/app/models/pki/certificate/generate.js | 3 + ui/app/models/pki/certificate/sign.js | 3 + ui/app/models/pki/config/acme.js | 8 + ui/app/models/pki/config/cluster.js | 7 + ui/app/models/pki/config/urls.js | 6 + ui/app/models/pki/issuer.js | 5 +- ui/app/models/pki/role.js | 8 + ui/app/models/pki/sign-intermediate.js | 4 + ui/app/models/pki/tidy.js | 14 +- ui/app/models/role-ssh.js | 4 + ui/app/models/secret-engine.js | 45 +- ui/app/models/ssh-otp-credential.js | 38 +- ui/app/models/ssh/ca-config.js | 54 - ui/app/models/sync/destinations/aws-sm.js | 9 +- ui/app/models/sync/destinations/azure-kv.js | 17 +- ui/app/models/sync/destinations/gcp-sm.js | 8 +- ui/app/models/sync/destinations/gh.js | 9 +- .../sync/destinations/vercel-project.js | 8 +- ui/app/router.js | 14 +- ui/app/routes/application.js | 103 +- ui/app/routes/vault/cluster/clients/counts.ts | 97 +- .../vault/cluster/secrets/backend/actions.js | 2 +- .../cluster/secrets/backend/configuration.js | 34 + .../secrets/backend/configuration/edit.ts | 90 -- .../secrets/backend/configuration/index.js | 136 -- .../cluster/secrets/backend/credentials.js | 32 +- .../vault/cluster/secrets/backend/list.js | 2 +- .../cluster/secrets/backend/secret-edit.js | 32 +- .../settings/auth/configure/section.js | 6 - .../settings/auth/{enable.ts => enable.js} | 7 +- .../settings/configure-secret-backend.js | 70 + ...ret-backend.ts => mount-secret-backend.js} | 7 +- ui/app/serializers/aws/root-config.js | 29 - ui/app/serializers/capabilities.js | 21 +- ui/app/serializers/database/connection.js | 2 +- ui/app/serializers/secret-engine.js | 8 - ui/app/services/auth.js | 3 +- ui/app/services/capabilities.ts | 120 -- ui/app/services/console.js | 2 +- ui/app/services/control-group.js | 4 - ui/app/services/download.ts | 2 - ui/app/services/path-help.js | 316 +++-- ui/app/styles/app.scss | 6 +- ui/app/styles/components/chart-container.scss | 7 + .../styles/components/clients-date-range.scss | 14 - ui/app/styles/components/kmip-role-edit.scss | 5 +- .../components/replication-mode-summary.scss | 16 + ui/app/styles/components/tool-tip.scss | 4 +- ui/app/styles/core.scss | 2 +- ui/app/styles/core/charts-lineal.scss | 10 - ui/app/styles/core/charts.scss | 14 +- ui/app/styles/docs.scss | 121 -- ui/app/styles/helper-classes/layout.scss | 8 +- ui/app/styles/helper-classes/spacing.scss | 19 +- ui/app/styles/helper-classes/typography.scss | 3 - ui/app/templates/components/auth-form.hbs | 368 ++--- .../components/configure-aws-secret.hbs | 159 +++ .../components/configure-ssh-secret.hbs | 89 ++ .../components/database-connection.hbs | 16 +- ui/app/templates/components/date-dropdown.hbs | 38 + .../components/generate-credentials.hbs | 111 +- ui/app/templates/components/mfa/mfa-form.hbs | 4 +- .../components/mount-backend-form.hbs | 18 +- ui/app/templates/components/oidc/key-form.hbs | 101 +- .../components/okta-number-challenge.hbs | 63 +- ui/app/templates/components/role-aws-edit.hbs | 2 +- .../components/secret-create-or-update.hbs | 2 +- .../components/tool-actions-form.hbs | 66 + ui/app/templates/components/tool-hash.hbs | 86 ++ ui/app/templates/components/tool-lookup.hbs | 48 + ui/app/templates/components/tool-random.hbs | 69 + ui/app/templates/components/tool-rewrap.hbs | 62 + ui/app/templates/components/tool-unwrap.hbs | 81 ++ ui/app/templates/components/tool-wrap.hbs | 64 + ui/app/templates/docs.hbs | 79 -- .../vault/cluster/access/oidc/keys/create.hbs | 14 - .../cluster/access/oidc/keys/key/edit.hbs | 19 - ui/app/templates/vault/cluster/auth.hbs | 136 +- .../cluster/secrets/backend/configuration.hbs | 46 +- .../secrets/backend/configuration/index.hbs | 64 - .../cluster/secrets/backend/credentials.hbs | 3 +- .../vault/cluster/secrets/backend/error.hbs | 2 +- .../cluster/secrets/backend/overview.hbs | 47 +- .../vault/cluster/secrets/backend/sign.hbs | 17 +- .../configure-secret-backend.hbs} | 28 +- ui/app/templates/vault/cluster/tools/tool.hbs | 16 +- .../{model-helpers => }/database-helpers.js | 0 ui/app/utils/kv-path.ts | 15 - .../utils/model-helpers/kmip-role-fields.js | 27 - ui/app/utils/model-helpers/validators.js | 84 -- ui/app/utils/openapi-helpers.ts | 236 +--- ui/app/utils/openapi-to-attrs.js | 121 +- ui/app/utils/query-param-string.js | 36 - ui/app/utils/validators.js | 41 + ui/config/deprecation-workflow.js | 20 +- .../{building-components.md => components.md} | 51 +- ui/docs/how-to-docfy.md | 102 -- ui/docs/index.md | 21 - ui/docs/model-validations.md | 55 +- ui/docs/models.md | 301 +---- ui/ember-cli-build.js | 3 - ui/jsdoc2md.json | 18 - .../components/messages/preview-image.hbs | 2 +- ui/lib/core/addon/components/alert-inline.js | 14 +- .../addon/components/autocomplete-input.js | 12 +- .../core/addon/components/certificate-card.js | 7 +- ui/lib/core/addon/components/checkbox-grid.ts | 14 +- ui/lib/core/addon/components/chevron.js | 21 +- .../addon/components/choose-pgp-key-form.js | 5 +- .../core/addon/components/confirm-action.js | 34 +- .../addon/components/confirmation-modal.js | 19 +- .../components/control-group-inline-error.hbs | 35 - ui/lib/core/addon/components/doc-link.js | 12 +- .../core/addon/components/download-button.js | 27 +- ui/lib/core/addon/components/external-link.js | 15 +- .../components/form-field-groups-loop.js | 9 +- .../addon/components/form-field-groups.hbs | 10 +- .../addon/components/form-field-groups.js | 51 + .../addon/components/form-field-groups.ts | 47 - ui/lib/core/addon/components/form-field.hbs | 3 +- ui/lib/core/addon/components/form-field.js | 45 +- .../addon/components/form-save-buttons.js | 17 +- ui/lib/core/addon/components/icon.js | 7 +- .../addon/components/info-table-item-array.js | 20 +- .../core/addon/components/info-table-row.js | 4 +- ui/lib/core/addon/components/info-tooltip.js | 6 +- ui/lib/core/addon/components/input-search.hbs | 1 - ui/lib/core/addon/components/input-search.js | 7 +- ui/lib/core/addon/components/json-editor.hbs | 10 +- ui/lib/core/addon/components/json-editor.js | 20 +- .../core/addon/components/key-value-header.js | 5 +- .../addon/components/kv-object-editor.hbs | 12 +- .../core/addon/components/kv-object-editor.js | 29 +- .../addon/components/kv-suggestion-input.ts | 14 +- ui/lib/core/addon/components/linked-block.js | 12 +- ui/lib/core/addon/components/list-view.js | 8 +- ui/lib/core/addon/components/masked-input.hbs | 2 +- ui/lib/core/addon/components/masked-input.js | 20 +- ui/lib/core/addon/components/message-error.js | 9 +- .../addon/components/namespace-reminder.js | 16 - .../core/addon/components/navigate-input.js | 12 +- .../addon/components/object-list-input.js | 12 +- .../core/addon/components/overview-card.hbs | 50 +- ui/lib/core/addon/components/page-header.hbs | 20 +- ui/lib/core/addon/components/page-header.js | 12 + .../core/addon/components/page/breadcrumbs.ts | 5 +- ui/lib/core/addon/components/page/error.hbs | 6 +- .../core/addon/components/policy-example.js | 15 +- ui/lib/core/addon/components/read-more.js | 11 +- .../addon/components/readonly-form-field.js | 7 +- .../components/replication-mode-summary.js | 68 + .../core/addon/components/replication-page.js | 7 +- .../components/search-select-with-modal.hbs | 3 +- .../components/search-select-with-modal.js | 25 +- ui/lib/core/addon/components/search-select.js | 14 +- .../components/secret-list-header-tab.js | 3 +- .../addon/components/secret-list-header.hbs | 1 - .../addon/components/secret-list-header.js | 18 +- .../components/secrets-engine-mount-config.ts | 18 +- ui/lib/core/addon/components/select.js | 14 +- ui/lib/core/addon/components/string-list.js | 5 +- ui/lib/core/addon/components/text-file.js | 9 +- ui/lib/core/addon/components/toggle-button.js | 14 +- ui/lib/core/addon/components/toggle.js | 5 +- ui/lib/core/addon/components/tool-tip.js | 22 - ui/lib/core/addon/components/toolbar-link.js | 4 +- ui/lib/core/addon/components/ttl-picker.js | 21 +- ui/lib/core/addon/components/upgrade-page.js | 7 - .../decorators/fetch-secrets-engine-config.ts | 7 +- ui/lib/core/addon/helpers/date-format.js | 2 +- ui/lib/core/addon/helpers/is-empty-value.js | 6 +- .../components/replication-mode-summary.hbs | 122 ++ .../addon/templates/components/select.hbs | 1 - ui/lib/core/addon/utils/advanced-secret.js | 25 + ui/lib/core/addon/utils/client-count-utils.ts | 237 ++-- .../components/control-group-inline-error.js | 6 - .../replication-mode-summary.js} | 2 +- ui/lib/core/app/helpers/date-from-now.js | 6 - ui/lib/core/app/utils/advanced-secret.js | 2 +- .../addon/components/edit-form-kmip-role.js | 55 + .../kmip/addon/components/kmip/role-form.hbs | 82 -- .../kmip/addon/components/kmip/role-form.js | 107 -- .../addon/controllers/credentials/index.js | 2 +- ui/lib/kmip/addon/controllers/scope/roles.js | 2 +- ui/lib/kmip/addon/controllers/scopes/index.js | 2 +- ui/lib/kmip/addon/routes/configuration.js | 2 +- ui/lib/kmip/addon/routes/configure.js | 2 +- ui/lib/kmip/addon/routes/role.js | 2 +- ui/lib/kmip/addon/routes/role/edit.js | 2 +- ui/lib/kmip/addon/routes/scope/roles.js | 2 +- .../kmip/addon/routes/scope/roles/create.js | 3 +- .../components/edit-form-kmip-role.hbs | 107 ++ ui/lib/kmip/addon/templates/role/edit.hbs | 5 +- .../addon/templates/scope/roles/create.hbs | 6 +- ui/lib/kmip/index.js | 4 - .../addon/components/page/overview.hbs | 69 +- .../kubernetes/addon/components/page/roles.js | 2 +- .../kubernetes/addon/routes/configuration.js | 3 +- ui/lib/kubernetes/addon/routes/configure.js | 4 +- .../kubernetes/addon/routes/roles/create.js | 4 +- ui/lib/kubernetes/addon/routes/roles/index.js | 3 +- .../addon/routes/roles/role/credentials.js | 4 +- .../addon/routes/roles/role/details.js | 2 +- .../addon/routes/roles/role/edit.js | 4 +- ui/lib/kv/addon/components/kv-data-fields.hbs | 1 + ui/lib/kv/addon/components/kv-delete-modal.js | 2 +- .../components/kv-patch/editor/alerts.hbs | 22 - .../addon/components/kv-patch/editor/form.hbs | 74 - .../addon/components/kv-patch/editor/form.js | 199 --- .../addon/components/kv-patch/editor/row.hbs | 76 -- .../addon/components/kv-patch/json-form.hbs | 25 - .../kv/addon/components/kv-patch/json-form.js | 50 - .../components/kv-patch/subkeys-reveal.hbs | 13 - .../components/kv-patch/subkeys-reveal.js | 20 - ui/lib/kv/addon/components/kv-paths-card.hbs | 82 -- .../kv/addon/components/kv-subkeys-card.hbs | 67 - ui/lib/kv/addon/components/kv-subkeys-card.js | 48 - ui/lib/kv/addon/components/page/list.hbs | 60 +- ui/lib/kv/addon/components/page/list.js | 4 +- .../addon/components/page/secret/details.hbs | 26 +- .../addon/components/page/secret/details.js | 42 +- .../kv/addon/components/page/secret/edit.js | 6 +- .../page/secret/metadata/details.hbs | 64 +- .../page/secret/metadata/details.js | 70 +- .../components/page/secret/metadata/edit.hbs | 1 - .../page/secret/metadata/version-history.hbs | 5 +- .../addon/components/page/secret/overview.hbs | 109 -- .../addon/components/page/secret/overview.js | 63 - .../kv/addon/components/page/secret/patch.hbs | 73 - .../kv/addon/components/page/secret/patch.js | 91 -- .../kv/addon/components/page/secret/paths.hbs | 67 +- .../secret/paths.js} | 28 +- .../addon/components/page/secrets/create.js | 2 +- ui/lib/kv/addon/engine.js | 8 +- ui/lib/kv/addon/routes.js | 1 - ui/lib/kv/addon/routes/configuration.js | 2 +- ui/lib/kv/addon/routes/create.js | 2 +- ui/lib/kv/addon/routes/secret.js | 65 +- ui/lib/kv/addon/routes/secret/details.js | 25 +- ui/lib/kv/addon/routes/secret/details/edit.js | 2 +- ui/lib/kv/addon/routes/secret/index.js | 11 +- ui/lib/kv/addon/routes/secret/metadata.js | 20 +- .../kv/addon/routes/secret/metadata/diff.js | 4 +- .../kv/addon/routes/secret/metadata/edit.js | 4 +- .../kv/addon/routes/secret/metadata/index.js | 2 +- .../addon/routes/secret/metadata/versions.js | 2 +- ui/lib/kv/addon/routes/secret/patch.js | 30 - ui/lib/kv/addon/routes/secret/paths.js | 2 +- .../addon/templates/secret/details/index.hbs | 9 +- ui/lib/kv/addon/templates/secret/index.hbs | 15 - .../addon/templates/secret/metadata/index.hbs | 8 +- ui/lib/kv/addon/templates/secret/patch.hbs | 13 - ui/lib/kv/addon/templates/secret/paths.hbs | 2 +- ui/lib/kv/addon/utils/kv-breadcrumbs.js | 2 +- .../addon/components/accounts-checked-out.hbs | 60 +- .../ldap/addon/components/page/libraries.ts | 2 +- .../page/library/details/accounts.hbs | 18 +- .../page/library/details/accounts.ts | 2 +- .../ldap/addon/components/page/overview.hbs | 70 +- ui/lib/ldap/addon/components/page/roles.ts | 2 +- ui/lib/ldap/addon/routes/configuration.ts | 3 +- ui/lib/ldap/addon/routes/libraries/create.ts | 4 +- ui/lib/ldap/addon/routes/libraries/index.ts | 3 +- ui/lib/ldap/addon/routes/roles/create.ts | 4 +- ui/lib/ldap/addon/routes/roles/index.ts | 3 +- .../addon/components/page/pki-overview.hbs | 192 ++- .../addon/controllers/certificates/index.js | 2 +- ui/lib/pki/addon/controllers/issuers/index.js | 2 +- ui/lib/pki/addon/controllers/keys/index.js | 2 +- ui/lib/pki/addon/controllers/roles/index.js | 2 +- ui/lib/pki/addon/routes/application.js | 18 +- .../certificates/certificate/details.js | 2 +- .../pki/addon/routes/configuration/create.js | 2 +- ui/lib/pki/addon/routes/configuration/edit.js | 4 +- .../routes/issuers/generate-intermediate.js | 4 +- .../pki/addon/routes/issuers/generate-root.js | 2 +- ui/lib/pki/addon/routes/issuers/import.js | 4 +- ui/lib/pki/addon/routes/issuers/index.js | 2 +- ui/lib/pki/addon/routes/issuers/issuer.js | 2 +- .../addon/routes/issuers/issuer/cross-sign.js | 4 +- .../addon/routes/issuers/issuer/details.js | 2 +- .../pki/addon/routes/issuers/issuer/edit.js | 4 +- .../routes/issuers/issuer/rotate-root.js | 4 +- .../pki/addon/routes/issuers/issuer/sign.js | 4 +- ui/lib/pki/addon/routes/keys/create.js | 4 +- ui/lib/pki/addon/routes/keys/import.js | 4 +- .../components/enable-replication-form.hbs | 8 +- .../components/enable-replication-form.js | 35 +- .../addon/components/page/mode-index.hbs | 6 +- .../addon/components/page/mode-index.js | 40 - .../components/replication-overview-mode.hbs | 49 - .../components/replication-overview-mode.js | 39 - .../addon/components/replication-summary.js | 8 +- ui/lib/replication/addon/controllers/index.js | 20 - ui/lib/replication/addon/engine.js | 1 - .../replication/addon/routes/application.js | 63 +- .../components/replication-summary.hbs | 113 +- ui/lib/replication/addon/templates/index.hbs | 35 +- .../components/secrets/page/destinations.ts | 2 +- .../page/destinations/create-and-edit.hbs | 31 +- .../page/destinations/create-and-edit.ts | 14 - .../page/destinations/destination/secrets.hbs | 4 +- .../page/destinations/destination/secrets.ts | 2 +- .../page/destinations/destination/sync.hbs | 2 +- .../components/secrets/page/overview.hbs | 234 ++-- ui/lib/sync/addon/engine.js | 2 +- ui/mirage/factories/kv-metadatum.js | 18 +- ui/mirage/handlers/clients.js | 143 +- ui/mirage/handlers/ldap.js | 71 +- ui/mirage/handlers/sync.js | 42 + ui/mirage/models/ldap-account-status.js | 13 - ui/mirage/scenarios/ldap.js | 13 +- ui/package.json | 18 +- ui/scripts/docfy-md.js | 56 - ui/scripts/enos-test-ember.js | 2 +- ui/scripts/gen-story-md.js | 45 + ui/scripts/generate-docs.sh | 22 - ui/{scripts => }/testem.enos.js | 0 .../access/namespaces/index-test.js | 11 +- ui/tests/acceptance/auth-list-test.js | 15 +- ui/tests/acceptance/auth-test.js | 144 +- ui/tests/acceptance/aws-test.js | 102 ++ ui/tests/acceptance/chroot-namespace-test.js | 52 +- ui/tests/acceptance/clients/counts-test.js | 107 +- .../acceptance/clients/counts/acme-test.js | 112 +- .../clients/counts/overview-test.js | 214 ++- ui/tests/acceptance/dashboard-test.js | 8 +- ui/tests/acceptance/enterprise-kmip-test.js | 46 +- .../acceptance/enterprise-replication-test.js | 7 +- .../oidc-config/clients-assignments-test.js | 353 +++++ .../oidc-config/clients-keys-test.js | 310 +++++ .../acceptance/oidc-config/clients-test.js | 655 --------- ui/tests/acceptance/oidc-provider-test.js | 10 +- .../acceptance/open-api-path-help-test.js | 12 +- ui/tests/acceptance/pki/pki-overview-test.js | 20 +- .../backend/aws/aws-configuration-test.js | 384 ------ .../secrets/backend/aws/aws-test.js | 197 --- .../secrets/backend/cubbyhole/secret-test.js | 12 +- .../secrets/backend/database/secret-test.js | 16 +- .../backend/kv/kv-v2-workflow-create-test.js | 202 ++- .../backend/kv/kv-v2-workflow-delete-test.js | 87 +- .../kv/kv-v2-workflow-edge-cases-test.js | 172 +-- .../kv/kv-v2-workflow-navigation-test.js | 683 ++-------- .../secrets/backend/kv/secret-test.js | 6 +- .../secrets/backend/ldap/libraries-test.js | 39 +- .../secrets/backend/ldap/overview-test.js | 62 +- .../secrets/backend/ldap/roles-test.js | 36 +- .../secrets/backend/ssh/configuration-test.js | 132 -- .../secrets/backend/ssh/role-test.js | 112 ++ .../secrets/backend/ssh/roles-test.js | 236 ---- .../configure-ssh-secret-test.js | 48 + .../settings/mount-secret-backend-test.js | 121 +- ui/tests/acceptance/ssh-test.js | 187 +++ .../sync/secrets/destination-test.js | 11 +- .../acceptance/sync/secrets/overview-test.js | 7 +- ui/tests/acceptance/tools-test.js | 301 ++--- ui/tests/acceptance/wrapped-token-test.js | 59 +- ui/tests/helpers/auth/auth-form-selectors.ts | 1 - ui/tests/helpers/auth/auth-helpers.ts | 6 +- .../helpers/clients/client-count-helpers.js | 548 +++++++- .../helpers/clients/client-count-selectors.ts | 41 +- ui/tests/helpers/general-selectors.ts | 20 +- ui/tests/helpers/kv/kv-run-commands.js | 30 - ui/tests/helpers/kv/kv-selectors.js | 16 +- ui/tests/helpers/kv/policy-generator.js | 20 +- ui/tests/helpers/ldap/ldap-helpers.js | 10 +- .../helpers/openapi/expected-secret-attrs.js | 12 - ui/tests/helpers/pki/pki-selectors.ts | 11 + .../helpers/secret-engine/policy-generator.ts | 36 - .../secret-engine/secret-engine-helpers.js | 208 --- .../secret-engine/secret-engine-selectors.ts | 46 - ui/tests/helpers/sync/sync-selectors.js | 9 +- ui/tests/helpers/tools-selectors.ts | 1 + .../integration/components/auth-form-test.js | 292 ++-- .../integration/components/auth/page-test.js | 205 --- .../components/calendar-widget-test.js | 240 ++++ .../charts/vertical-bar-basic-test.js | 5 +- .../components/clients/attribution-test.js | 408 ++++-- .../charts/vertical-bar-grouped-test.js | 249 ---- .../components/clients/config-test.js | 42 +- .../components/clients/date-range-test.js | 131 -- .../components/clients/line-chart-test.js | 397 ++++++ .../components/clients/page-header-test.js | 291 ---- .../components/clients/page/acme-test.js | 15 +- .../components/clients/page/counts-test.js | 149 +- .../components/clients/page/overview-test.js | 110 -- .../components/clients/page/sync-test.js | 29 +- .../components/clients/page/token-test.js | 13 +- .../components/clients/running-total-test.js | 19 +- .../components/confirm-action-test.js | 22 +- .../components/date-dropdown-test.js | 165 +++ .../enable-replication-form-test.js | 48 +- .../integration/components/form-field-test.js | 8 +- .../components/json-editor-test.js | 22 + .../components/kv/kv-data-fields-test.js | 5 + .../kv/kv-patch/editor/alerts-test.js | 80 -- .../kv/kv-patch/editor/form-test.js | 569 -------- .../components/kv/kv-patch/editor/row-test.js | 169 --- .../components/kv/kv-patch/json-form-test.js | 96 -- .../components/kv/kv-paths-card-test.js | 137 -- .../components/kv/kv-subkeys-card-test.js | 67 - .../kv/page/kv-page-metadata-details-test.js | 119 +- .../kv/page/kv-page-metadata-edit-test.js | 8 +- .../kv/page/kv-page-overview-test.js | 347 ----- .../components/kv/page/kv-page-patch-test.js | 374 ----- .../kv/page/kv-page-secret-details-test.js | 161 ++- .../kv/page/kv-page-secret-edit-test.js | 27 +- .../kv/page/kv-page-secret-paths-test.js | 136 +- .../kv/page/kv-page-secrets-create-test.js | 9 +- .../kv/page/kv-page-version-diff-test.js | 2 +- .../kv/page/kv-page-version-history-test.js | 2 +- .../ldap/page/library/create-and-edit-test.js | 4 +- .../page/library/details/accounts-test.js | 5 +- .../ldap/page/role/create-and-edit-test.js | 4 +- .../components/mount-backend-form-test.js | 44 +- .../components/oidc/key-form-test.js | 6 +- .../components/okta-number-challenge-test.js | 49 +- .../components/overview-card-test.js | 45 +- .../components/page/mode-index-test.js | 44 +- .../components/pki/page/pki-overview-test.js | 28 +- .../components/pki/pki-tidy-form-test.js | 3 +- .../replication-overview-mode-test.js | 124 -- .../search-select-with-modal-test.js | 128 +- .../configuration-details-test.js | 57 - .../secret-engine/configure-aws-test.js | 590 -------- .../secret-engine/configure-ssh-test.js | 149 -- .../secrets-engine-mount-config-test.js | 4 +- .../components/sidebar/nav/cluster-test.js | 26 - .../page/destinations/create-and-edit-test.js | 95 +- .../sync/secrets/page/overview-test.js | 6 +- .../integration/components/tools/hash-test.js | 101 -- .../components/tools/lookup-test.js | 78 -- .../components/tools/random-test.js | 92 -- .../components/tools/rewrap-test.js | 95 -- .../components/tools/tool-wrap-test.js | 81 ++ .../components/tools/unwrap-test.js | 146 -- .../integration/components/tools/wrap-test.js | 141 -- .../integration/helpers/date-format-test.js | 9 - .../integration/helpers/date-from-now-test.js | 2 +- .../utils/client-count-utils-test.js | 375 ++--- ui/tests/pages/access/namespaces/index.js | 10 + ui/tests/pages/secrets/backend/kmip/roles.js | 2 +- .../pages/secrets/backend/pki/edit-role.js | 35 + .../secrets/backend/pki/generate-cert.js | 36 + ui/tests/pages/secrets/backend/pki/show.js | 25 + .../pages/secrets/backend/ssh/generate-otp.js | 4 +- ui/tests/unit/adapters/capabilities-test.js | 172 +-- .../unit/adapters/clients-activity-test.js | 104 +- ui/tests/unit/adapters/kmip/role-test.js | 10 +- ui/tests/unit/adapters/kv/data-test.js | 526 +++----- ui/tests/unit/adapters/secret-engine-test.js | 96 +- ui/tests/unit/components/auth-form-test.js | 33 +- .../fetch-secrets-engine-config-test.js | 2 +- .../model-expanded-attributes-test.js | 108 +- .../unit/decorators/model-form-fields-test.js | 139 +- .../unit/decorators/model-validations-test.js | 2 +- ui/tests/unit/models/capabilities-test.js | 45 +- ui/tests/unit/models/generated-item-test.js | 18 - ui/tests/unit/models/secret-engine-test.js | 127 +- ui/tests/unit/services/capabilities-test.js | 345 ----- ui/tests/unit/services/path-help-test.js | 118 -- ui/tests/unit/services/path-helper-test.js | 78 ++ ui/tests/unit/utils/advanced-secret-test.js | 109 +- ui/tests/unit/utils/kmip-role-fields-test.js | 52 - ui/tests/unit/utils/kv-breadcrumbs-test.js | 4 +- ui/tests/unit/utils/kv-path-test.js | 44 +- ui/tests/unit/utils/openapi-helpers-test.js | 265 +--- ui/tests/unit/utils/openapi-to-attrs-test.js | 219 ++- .../unit/utils/query-param-string-test.js | 47 - .../{model-helpers => }/validators-test.js | 66 +- ui/types/vault/models/aws/lease-config.d.ts | 22 - ui/types/vault/models/aws/root-config.d.ts | 32 - ui/types/vault/models/capabilities.d.ts | 7 +- .../vault/models/identity/oidc/config.d.ts | 22 - .../vault/models/pki/certificate/base.d.ts | 2 + ui/types/vault/models/pki/config/urls.d.ts | 2 + ui/types/vault/models/pki/issuer.d.ts | 1 + ui/types/vault/models/pki/role.d.ts | 2 + ui/types/vault/models/pki/tidy.d.ts | 2 + ui/types/vault/models/secret-engine.d.ts | 2 +- ui/types/vault/services/store.d.ts | 7 +- ui/yarn.lock | 1201 +---------------- vault/activity/test_fixtures/aug.csv | 21 + vault/activity/test_fixtures/aug.json | 20 + vault/activity/test_fixtures/aug_oct.csv | 41 + vault/activity/test_fixtures/aug_oct.json | 40 + vault/activity/test_fixtures/aug_sep.csv | 31 + vault/activity/test_fixtures/aug_sep.json | 30 + vault/activity/test_fixtures/full_history.csv | 46 + .../activity/test_fixtures/full_history.json | 45 + vault/activity_log.go | 570 +------- vault/activity_log_test.go | 339 +++-- vault/activity_log_util_common.go | 16 +- vault/census.go | 14 +- vault/census_manager.go | 45 - vault/census_stubs_oss.go | 14 + vault/core.go | 48 +- vault/core_test.go | 73 - vault/eventbus/bus.go | 3 - vault/expiration.go | 4 +- vault/expiration_test.go | 9 +- .../external_tests/activity/activity_util.go | 48 - .../acme_regeneration_test.go | 4 + .../activity_testonly_test.go | 230 ---- .../api/api_integration_test.go | 5 +- .../api/feature_flag_ext_test.go | 4 +- .../audit/audit_exclusion_test.go | 50 - vault/external_tests/audit/audit_test.go | 214 --- .../metrics/core_metrics_int_test.go | 6 +- .../plugin/external_plugin_test.go | 207 +-- vault/external_tests/pprof/pprof.go | 34 +- .../pprof/pprof_binary/pprof_test.go | 26 +- vault/external_tests/pprof/pprof_test.go | 24 +- vault/external_tests/raft/raft_test.go | 17 +- vault/ha.go | 21 - vault/ha_test.go | 2 +- vault/identity_store_oidc.go | 14 - vault/identity_store_structs.go | 5 +- vault/identity_store_util.go | 1 - vault/logical_system.go | 9 +- vault/logical_system_activity.go | 99 +- .../logical_system_activity_write_testonly.go | 22 +- ...cal_system_activity_write_testonly_test.go | 16 +- vault/logical_system_raft.go | 8 - vault/logical_system_test.go | 87 -- vault/login_mfa.go | 4 +- vault/mount.go | 1 + vault/plugincatalog/testing.go | 4 +- vault/raft.go | 81 +- vault/raft_test.go | 33 - vault/seal_testing.go | 6 +- vault/seal_testing_util.go | 11 +- vault/testing.go | 88 +- vault/testing_util.go | 5 +- vault/token_store.go | 6 +- vault/token_store_test.go | 7 +- version/VERSION | 2 +- website/content/api-docs/auth/approle.mdx | 16 + website/content/api-docs/libraries.mdx | 1 - website/content/api-docs/secret/azure.mdx | 8 +- .../api-docs/secret/databases/postgresql.mdx | 12 - .../secret/{pki/index.mdx => pki.mdx} | 540 +++++++- .../content/api-docs/secret/pki/issuance.mdx | 652 --------- .../api-docs/system/internal-counters.mdx | 267 ++-- .../content/api-docs/system/secrets-sync.mdx | 13 +- .../docs/agent-and-proxy/agent/index.mdx | 2 - .../docs/agent-and-proxy/agent/winsvc.mdx | 11 +- .../agent-and-proxy/autoauth/sinks/file.mdx | 4 +- .../content/docs/agent-and-proxy/index.mdx | 12 +- .../proxy/caching/static-secret-caching.mdx | 10 - website/content/docs/commands/index.mdx | 6 - website/content/docs/commands/server.mdx | 5 - .../adaptive-overload-protection/index.mdx | 22 +- .../vault-server-temporarily-overloaded.mdx | 7 +- website/content/docs/concepts/seal.mdx | 1 + .../service-registration/consul.mdx | 3 - .../docs/configuration/storage/cassandra.mdx | 6 - .../docs/configuration/storage/consul.mdx | 3 - website/content/docs/deprecation/index.mdx | 4 +- .../docs/enterprise/audit/exclusion.mdx | 285 ---- website/content/docs/enterprise/index.mdx | 4 +- .../license/utilization-reporting.mdx | 32 +- website/content/docs/enterprise/lts.mdx | 18 +- .../docs/platform/aws/lambda-extension.mdx | 3 +- .../docs/platform/k8s/consul-to-raft.mdx | 375 ----- .../content/docs/platform/k8s/helm/index.mdx | 9 - .../content/docs/platform/k8s/helm/run.mdx | 20 +- website/content/docs/release-notes/1.15.0.mdx | 2 +- website/content/docs/release-notes/1.17.0.mdx | 17 +- website/content/docs/secrets/azure.mdx | 17 +- .../content/docs/secrets/databases/hanadb.mdx | 2 +- .../docs/secrets/databases/mongodbatlas.mdx | 6 +- .../docs/secrets/databases/postgresql.mdx | 47 - website/content/docs/secrets/pki/cmpv2.mdx | 144 -- website/content/docs/secrets/pki/est.mdx | 6 +- website/content/docs/secrets/pki/index.mdx | 16 +- website/content/docs/sync/github.mdx | 95 +- .../docs/upgrading/upgrade-to-1.16.x.mdx | 6 +- .../docs/upgrading/upgrade-to-1.17.x.mdx | 2 +- .../docs/upgrading/upgrade-to-1.18.x.mdx | 99 -- .../partials/api/restricted-endpoints.mdx | 1 + .../content/partials/audit-options-common.mdx | 6 - .../audit/request-entry-json-schema.mdx | 224 --- .../audit/response-entry-json-schema.mdx | 418 ------ .../known-issues/1_15-auto-upgrade.mdx | 2 +- website/data/api-docs-nav-data.json | 11 +- website/data/docs-nav-data.json | 40 +- website/redirects.js | 7 +- 1030 files changed, 16149 insertions(+), 36372 deletions(-) delete mode 100644 .github/docs/pull_request_template.md delete mode 100644 .github/pull_request_template.md delete mode 100644 .github/workflows/do-not-merge-checker.yml delete mode 100644 api/auth/approle/LICENSE delete mode 100644 api/auth/aws/LICENSE delete mode 100644 api/auth/azure/LICENSE delete mode 100644 api/auth/gcp/LICENSE delete mode 100644 api/auth/kubernetes/LICENSE delete mode 100644 api/auth/ldap/LICENSE delete mode 100644 api/auth/userpass/LICENSE delete mode 100644 audit/entry_formatter_ce.go delete mode 100644 audit/entry_formatter_ce_test.go delete mode 100644 audit/entry_formatter_config_ce.go delete mode 100644 builtin/logical/pki/cmpv2_util_oss.go delete mode 100644 builtin/logical/pki/issuing/context.go delete mode 100644 builtin/logical/pki/pki_backend/crl_builder.go delete mode 100644 builtin/logical/pki/pki_backend/crl_config.go delete mode 100644 builtin/logical/pki/pki_backend/rolepathpolicy_enumer.go delete mode 100644 builtin/logical/pki/pki_backend/storage_context.go delete mode 100644 builtin/logical/pki/revocation/revocation_entry.go delete mode 100644 builtin/logical/pki/revocation/revoke.go delete mode 100644 changelog/10624.txt delete mode 100644 changelog/11084.txt delete mode 100644 changelog/14723.txt delete mode 100644 changelog/16484.txt delete mode 100644 changelog/16974.txt delete mode 100644 changelog/17007.txt delete mode 100644 changelog/19064.txt delete mode 100644 changelog/21159.txt delete mode 100644 changelog/21993.txt delete mode 100644 changelog/25080.txt delete mode 100644 changelog/26073.txt delete mode 100644 changelog/26570.txt delete mode 100644 changelog/26660.txt delete mode 100644 changelog/26828.txt delete mode 100644 changelog/26868.txt delete mode 100644 changelog/27033.txt delete mode 100644 changelog/27123.txt delete mode 100644 changelog/27202.txt delete mode 100644 changelog/27265.txt delete mode 100644 changelog/27348.txt delete mode 100644 changelog/27350.txt delete mode 100644 changelog/27379.txt delete mode 100644 changelog/27394.txt delete mode 100644 changelog/27405.txt delete mode 100644 changelog/27426.txt delete mode 100644 changelog/27455.txt delete mode 100644 changelog/27457.txt delete mode 100644 changelog/27510.txt delete mode 100644 changelog/27538.txt delete mode 100644 changelog/27578.txt delete mode 100644 changelog/27605.txt delete mode 100644 changelog/27633.txt delete mode 100644 changelog/27681.txt delete mode 100644 changelog/27796.txt delete mode 100644 changelog/27799.txt delete mode 100644 changelog/27816.txt delete mode 100644 changelog/27830.txt delete mode 100644 changelog/27831.txt delete mode 100644 changelog/27846.txt delete mode 100644 changelog/27918.txt delete mode 100644 changelog/27920.txt delete mode 100644 changelog/27927.txt delete mode 100644 changelog/27929.txt delete mode 100644 changelog/27950.txt delete mode 100644 changelog/27966.txt delete mode 100644 changelog/28024.txt delete mode 100644 changelog/28036.txt delete mode 100644 changelog/28064.txt delete mode 100644 changelog/28076.txt delete mode 100644 changelog/28148.txt delete mode 100644 changelog/28186.txt delete mode 100644 changelog/28199.txt delete mode 100644 changelog/28212.txt delete mode 100644 changelog/28237.txt delete mode 100644 changelog/28263.txt delete mode 100644 changelog/28264.txt delete mode 100644 changelog/28266.txt delete mode 100644 changelog/28267.txt delete mode 100644 changelog/28268.txt delete mode 100644 changelog/28269.txt delete mode 100644 changelog/28271.txt delete mode 100644 changelog/28275.txt delete mode 100644 changelog/28277.txt delete mode 100644 changelog/28287.txt delete mode 100644 changelog/28289.txt delete mode 100644 changelog/28293.txt delete mode 100644 changelog/28294.txt delete mode 100644 changelog/28300.txt delete mode 100644 changelog/28307.txt delete mode 100644 changelog/28312.txt delete mode 100644 changelog/28324.txt delete mode 100644 changelog/28325.txt delete mode 100644 changelog/28327.txt delete mode 100644 changelog/28334.txt delete mode 100644 changelog/28348.txt delete mode 100644 changelog/28349.txt delete mode 100644 changelog/28360.txt delete mode 100644 changelog/28361.txt delete mode 100644 changelog/28366.txt delete mode 100644 changelog/28371.txt delete mode 100644 changelog/28404.txt create mode 100644 changelog/28478.txt delete mode 100644 changelog/28479.txt delete mode 100644 changelog/28519.txt delete mode 100644 changelog/9733.txt create mode 100644 changelog/_go-ver-1172.txt create mode 100644 changelog/_go-ver-1174.txt rename changelog/{_go-ver-1180.txt => _go-ver-1176.txt} (100%) delete mode 100644 command/commands_full.go delete mode 100644 command/commands_full_test.go delete mode 100644 command/commands_min.go create mode 100644 helper/benchhelpers/benchhelpers.go delete mode 100644 helper/builtinplugins/registry_full.go delete mode 100644 helper/builtinplugins/registry_full_test.go delete mode 100644 helper/builtinplugins/registry_min.go delete mode 100644 helper/builtinplugins/registry_testing_util.go delete mode 100644 helper/locking/core_locking.go delete mode 100644 helper/locking/core_locking_test.go delete mode 100644 sdk/database/helper/cacheutil/cache_stubs_oss.go delete mode 100644 sdk/database/helper/connutil/postgres.go delete mode 100644 sdk/database/helper/connutil/sql_stubs_oss.go delete mode 100644 sdk/helper/metricregistry/metricregistry.go delete mode 100644 sdk/helper/metricregistry/metricregistry_test.go delete mode 100644 sdk/helper/testcluster/docker/environment_test.go create mode 100644 ui/.yarnrc delete mode 100644 ui/app/adapters/aws/lease-config.js delete mode 100644 ui/app/adapters/aws/root-config.js delete mode 100644 ui/app/adapters/identity/oidc/config.js delete mode 100644 ui/app/adapters/ssh/ca-config.js delete mode 100644 ui/app/components/auth/login-form.hbs delete mode 100644 ui/app/components/auth/login-form.js delete mode 100644 ui/app/components/auth/page.hbs delete mode 100644 ui/app/components/auth/page.js create mode 100644 ui/app/components/calendar-widget.js create mode 100644 ui/app/components/clients/charts/line.hbs create mode 100644 ui/app/components/clients/charts/line.ts delete mode 100644 ui/app/components/clients/charts/vertical-bar-grouped.hbs delete mode 100644 ui/app/components/clients/charts/vertical-bar-grouped.ts delete mode 100644 ui/app/components/clients/date-range.hbs delete mode 100644 ui/app/components/clients/date-range.ts delete mode 100644 ui/app/components/clients/page-header.hbs delete mode 100644 ui/app/components/clients/page-header.js create mode 100644 ui/app/components/configure-aws-secret.js create mode 100644 ui/app/components/configure-ssh-secret.js create mode 100644 ui/app/components/date-dropdown.js delete mode 100644 ui/app/components/modal-form/oidc-key-template.hbs delete mode 100644 ui/app/components/modal-form/oidc-key-template.js rename ui/app/components/{mount-backend-form.ts => mount-backend-form.js} (80%) delete mode 100644 ui/app/components/secret-engine/configuration-details.hbs delete mode 100644 ui/app/components/secret-engine/configure-aws.hbs delete mode 100644 ui/app/components/secret-engine/configure-aws.ts delete mode 100644 ui/app/components/secret-engine/configure-ssh.hbs delete mode 100644 ui/app/components/secret-engine/configure-ssh.ts create mode 100644 ui/app/components/tool-actions-form.js create mode 100644 ui/app/components/tool-hash.js create mode 100644 ui/app/components/tool-lookup.js create mode 100644 ui/app/components/tool-random.js create mode 100644 ui/app/components/tool-rewrap.js create mode 100644 ui/app/components/tool-unwrap.js create mode 100644 ui/app/components/tool-wrap.js delete mode 100644 ui/app/components/tools/hash.hbs delete mode 100644 ui/app/components/tools/hash.js delete mode 100644 ui/app/components/tools/lookup.hbs delete mode 100644 ui/app/components/tools/lookup.js delete mode 100644 ui/app/components/tools/random.hbs delete mode 100644 ui/app/components/tools/random.js delete mode 100644 ui/app/components/tools/rewrap.hbs delete mode 100644 ui/app/components/tools/rewrap.js delete mode 100644 ui/app/components/tools/unwrap.hbs delete mode 100644 ui/app/components/tools/unwrap.js delete mode 100644 ui/app/components/tools/wrap.hbs delete mode 100644 ui/app/components/tools/wrap.js delete mode 100644 ui/app/components/z-docfy-filter.hbs delete mode 100644 ui/app/components/z-docfy-filter.js create mode 100644 ui/app/controllers/application.js delete mode 100644 ui/app/controllers/application.ts create mode 100644 ui/app/controllers/vault/cluster/secrets/backend/configuration.js rename ui/app/controllers/vault/cluster/{secrets/backend/configuration/edit.js => settings/configure-secret-backend.js} (58%) rename ui/{lib/core/addon => app}/helpers/await.js (100%) rename ui/{lib/core/addon => app}/helpers/date-from-now.js (100%) delete mode 100644 ui/app/models/aws/lease-config.js delete mode 100644 ui/app/models/aws/root-config.js delete mode 100644 ui/app/models/generated-item.js delete mode 100644 ui/app/models/identity/oidc/config.js delete mode 100644 ui/app/models/ssh/ca-config.js create mode 100644 ui/app/routes/vault/cluster/secrets/backend/configuration.js delete mode 100644 ui/app/routes/vault/cluster/secrets/backend/configuration/edit.ts delete mode 100644 ui/app/routes/vault/cluster/secrets/backend/configuration/index.js rename ui/app/routes/vault/cluster/settings/auth/{enable.ts => enable.js} (65%) create mode 100644 ui/app/routes/vault/cluster/settings/configure-secret-backend.js rename ui/app/routes/vault/cluster/settings/{mount-secret-backend.ts => mount-secret-backend.js} (64%) delete mode 100644 ui/app/serializers/aws/root-config.js delete mode 100644 ui/app/services/capabilities.ts delete mode 100644 ui/app/styles/components/clients-date-range.scss create mode 100644 ui/app/styles/components/replication-mode-summary.scss delete mode 100644 ui/app/styles/docs.scss create mode 100644 ui/app/templates/components/configure-aws-secret.hbs create mode 100644 ui/app/templates/components/configure-ssh-secret.hbs create mode 100644 ui/app/templates/components/date-dropdown.hbs rename ui/app/{ => templates}/components/generate-credentials.hbs (57%) rename ui/app/{ => templates}/components/mount-backend-form.hbs (77%) create mode 100644 ui/app/templates/components/tool-actions-form.hbs create mode 100644 ui/app/templates/components/tool-hash.hbs create mode 100644 ui/app/templates/components/tool-lookup.hbs create mode 100644 ui/app/templates/components/tool-random.hbs create mode 100644 ui/app/templates/components/tool-rewrap.hbs create mode 100644 ui/app/templates/components/tool-unwrap.hbs create mode 100644 ui/app/templates/components/tool-wrap.hbs delete mode 100644 ui/app/templates/docs.hbs delete mode 100644 ui/app/templates/vault/cluster/secrets/backend/configuration/index.hbs rename ui/app/templates/vault/cluster/{secrets/backend/configuration/edit.hbs => settings/configure-secret-backend.hbs} (56%) rename ui/app/utils/{model-helpers => }/database-helpers.js (100%) delete mode 100644 ui/app/utils/model-helpers/kmip-role-fields.js delete mode 100644 ui/app/utils/model-helpers/validators.js delete mode 100644 ui/app/utils/query-param-string.js create mode 100644 ui/app/utils/validators.js rename ui/docs/{building-components.md => components.md} (51%) delete mode 100644 ui/docs/how-to-docfy.md delete mode 100644 ui/docs/index.md delete mode 100644 ui/jsdoc2md.json delete mode 100644 ui/lib/core/addon/components/control-group-inline-error.hbs create mode 100644 ui/lib/core/addon/components/form-field-groups.js delete mode 100644 ui/lib/core/addon/components/form-field-groups.ts create mode 100644 ui/lib/core/addon/components/page-header.js create mode 100644 ui/lib/core/addon/components/replication-mode-summary.js create mode 100644 ui/lib/core/addon/templates/components/replication-mode-summary.hbs delete mode 100644 ui/lib/core/app/components/control-group-inline-error.js rename ui/lib/core/app/{helpers/await.js => components/replication-mode-summary.js} (53%) delete mode 100644 ui/lib/core/app/helpers/date-from-now.js create mode 100644 ui/lib/kmip/addon/components/edit-form-kmip-role.js delete mode 100644 ui/lib/kmip/addon/components/kmip/role-form.hbs delete mode 100644 ui/lib/kmip/addon/components/kmip/role-form.js create mode 100644 ui/lib/kmip/addon/templates/components/edit-form-kmip-role.hbs delete mode 100644 ui/lib/kv/addon/components/kv-patch/editor/alerts.hbs delete mode 100644 ui/lib/kv/addon/components/kv-patch/editor/form.hbs delete mode 100644 ui/lib/kv/addon/components/kv-patch/editor/form.js delete mode 100644 ui/lib/kv/addon/components/kv-patch/editor/row.hbs delete mode 100644 ui/lib/kv/addon/components/kv-patch/json-form.hbs delete mode 100644 ui/lib/kv/addon/components/kv-patch/json-form.js delete mode 100644 ui/lib/kv/addon/components/kv-patch/subkeys-reveal.hbs delete mode 100644 ui/lib/kv/addon/components/kv-patch/subkeys-reveal.js delete mode 100644 ui/lib/kv/addon/components/kv-paths-card.hbs delete mode 100644 ui/lib/kv/addon/components/kv-subkeys-card.hbs delete mode 100644 ui/lib/kv/addon/components/kv-subkeys-card.js delete mode 100644 ui/lib/kv/addon/components/page/secret/overview.hbs delete mode 100644 ui/lib/kv/addon/components/page/secret/overview.js delete mode 100644 ui/lib/kv/addon/components/page/secret/patch.hbs delete mode 100644 ui/lib/kv/addon/components/page/secret/patch.js rename ui/lib/kv/addon/components/{kv-paths-card.js => page/secret/paths.js} (67%) delete mode 100644 ui/lib/kv/addon/routes/secret/patch.js delete mode 100644 ui/lib/kv/addon/templates/secret/index.hbs delete mode 100644 ui/lib/kv/addon/templates/secret/patch.hbs delete mode 100644 ui/lib/replication/addon/components/page/mode-index.js delete mode 100644 ui/lib/replication/addon/components/replication-overview-mode.hbs delete mode 100644 ui/lib/replication/addon/components/replication-overview-mode.js delete mode 100644 ui/mirage/models/ldap-account-status.js delete mode 100644 ui/scripts/docfy-md.js create mode 100755 ui/scripts/gen-story-md.js delete mode 100644 ui/scripts/generate-docs.sh rename ui/{scripts => }/testem.enos.js (100%) create mode 100644 ui/tests/acceptance/aws-test.js create mode 100644 ui/tests/acceptance/oidc-config/clients-assignments-test.js create mode 100644 ui/tests/acceptance/oidc-config/clients-keys-test.js delete mode 100644 ui/tests/acceptance/oidc-config/clients-test.js delete mode 100644 ui/tests/acceptance/secrets/backend/aws/aws-configuration-test.js delete mode 100644 ui/tests/acceptance/secrets/backend/aws/aws-test.js delete mode 100644 ui/tests/acceptance/secrets/backend/ssh/configuration-test.js create mode 100644 ui/tests/acceptance/secrets/backend/ssh/role-test.js delete mode 100644 ui/tests/acceptance/secrets/backend/ssh/roles-test.js create mode 100644 ui/tests/acceptance/settings/configure-secret-backends/configure-ssh-secret-test.js create mode 100644 ui/tests/acceptance/ssh-test.js delete mode 100644 ui/tests/helpers/secret-engine/policy-generator.ts delete mode 100644 ui/tests/helpers/secret-engine/secret-engine-helpers.js delete mode 100644 ui/tests/helpers/secret-engine/secret-engine-selectors.ts delete mode 100644 ui/tests/integration/components/auth/page-test.js create mode 100644 ui/tests/integration/components/calendar-widget-test.js delete mode 100644 ui/tests/integration/components/clients/charts/vertical-bar-grouped-test.js delete mode 100644 ui/tests/integration/components/clients/date-range-test.js create mode 100644 ui/tests/integration/components/clients/line-chart-test.js delete mode 100644 ui/tests/integration/components/clients/page-header-test.js delete mode 100644 ui/tests/integration/components/clients/page/overview-test.js create mode 100644 ui/tests/integration/components/date-dropdown-test.js delete mode 100644 ui/tests/integration/components/kv/kv-patch/editor/alerts-test.js delete mode 100644 ui/tests/integration/components/kv/kv-patch/editor/form-test.js delete mode 100644 ui/tests/integration/components/kv/kv-patch/editor/row-test.js delete mode 100644 ui/tests/integration/components/kv/kv-patch/json-form-test.js delete mode 100644 ui/tests/integration/components/kv/kv-paths-card-test.js delete mode 100644 ui/tests/integration/components/kv/kv-subkeys-card-test.js delete mode 100644 ui/tests/integration/components/kv/page/kv-page-overview-test.js delete mode 100644 ui/tests/integration/components/kv/page/kv-page-patch-test.js delete mode 100644 ui/tests/integration/components/replication-overview-mode-test.js delete mode 100644 ui/tests/integration/components/secret-engine/configuration-details-test.js delete mode 100644 ui/tests/integration/components/secret-engine/configure-aws-test.js delete mode 100644 ui/tests/integration/components/secret-engine/configure-ssh-test.js delete mode 100644 ui/tests/integration/components/tools/hash-test.js delete mode 100644 ui/tests/integration/components/tools/lookup-test.js delete mode 100644 ui/tests/integration/components/tools/random-test.js delete mode 100644 ui/tests/integration/components/tools/rewrap-test.js create mode 100644 ui/tests/integration/components/tools/tool-wrap-test.js delete mode 100644 ui/tests/integration/components/tools/unwrap-test.js delete mode 100644 ui/tests/integration/components/tools/wrap-test.js create mode 100644 ui/tests/pages/access/namespaces/index.js create mode 100644 ui/tests/pages/secrets/backend/pki/edit-role.js create mode 100644 ui/tests/pages/secrets/backend/pki/generate-cert.js create mode 100644 ui/tests/pages/secrets/backend/pki/show.js delete mode 100644 ui/tests/unit/models/generated-item-test.js delete mode 100644 ui/tests/unit/services/capabilities-test.js delete mode 100644 ui/tests/unit/services/path-help-test.js create mode 100644 ui/tests/unit/services/path-helper-test.js delete mode 100644 ui/tests/unit/utils/kmip-role-fields-test.js delete mode 100644 ui/tests/unit/utils/query-param-string-test.js rename ui/tests/unit/utils/{model-helpers => }/validators-test.js (64%) delete mode 100644 ui/types/vault/models/aws/lease-config.d.ts delete mode 100644 ui/types/vault/models/aws/root-config.d.ts delete mode 100644 ui/types/vault/models/identity/oidc/config.d.ts create mode 100644 vault/activity/test_fixtures/aug.csv create mode 100644 vault/activity/test_fixtures/aug.json create mode 100644 vault/activity/test_fixtures/aug_oct.csv create mode 100644 vault/activity/test_fixtures/aug_oct.json create mode 100644 vault/activity/test_fixtures/aug_sep.csv create mode 100644 vault/activity/test_fixtures/aug_sep.json create mode 100644 vault/activity/test_fixtures/full_history.csv create mode 100644 vault/activity/test_fixtures/full_history.json delete mode 100644 vault/census_manager.go create mode 100644 vault/census_stubs_oss.go delete mode 100644 vault/external_tests/activity/activity_util.go delete mode 100644 vault/external_tests/audit/audit_exclusion_test.go delete mode 100644 vault/external_tests/audit/audit_test.go delete mode 100644 vault/raft_test.go rename website/content/api-docs/secret/{pki/index.mdx => pki.mdx} (91%) delete mode 100644 website/content/api-docs/secret/pki/issuance.mdx delete mode 100644 website/content/docs/enterprise/audit/exclusion.mdx delete mode 100644 website/content/docs/platform/k8s/consul-to-raft.mdx delete mode 100644 website/content/docs/secrets/pki/cmpv2.mdx delete mode 100644 website/content/docs/upgrading/upgrade-to-1.18.x.mdx delete mode 100644 website/content/partials/audit/request-entry-json-schema.mdx delete mode 100644 website/content/partials/audit/response-entry-json-schema.mdx diff --git a/.github/docs/pull_request_template.md b/.github/docs/pull_request_template.md deleted file mode 100644 index 6b9d11b9a109..000000000000 --- a/.github/docs/pull_request_template.md +++ /dev/null @@ -1,8 +0,0 @@ -### Description -Why is this docs change needed? - -### TODO -- [ ] Preview the changes you made either locally or in the Vercel deployment - and make sure it looks correct. -- [ ] If you've added a new link to the sidebar navigation, make sure it's - sorted correctly. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index 4257adb67ed2..000000000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,17 +0,0 @@ -### Description -What does this PR do? - -### TODO only if you're a HashiCorp employee -- [ ] **Backport Labels:** If this PR is in the ENT repo and needs to be backported, backport - to N, N-1, and N-2, using the `backport/ent/x.x.x+ent` labels. If this PR is in the CE repo, you should only backport to N, using the `backport/x.x.x` label, not the enterprise labels. - - [ ] If this fixes a critical security vulnerability or [severity 1](https://www.hashicorp.com/customer-success/enterprise-support) bug, it will also need to be backported to the current [LTS versions](https://developer.hashicorp.com/vault/docs/enterprise/lts#why-is-there-a-risk-to-updating-to-a-non-lts-vault-enterprise-version) of Vault. To ensure this, use **all** available enterprise labels. -- [ ] **ENT Breakage:** If this PR either 1) removes a public function OR 2) changes the signature - of a public function, even if that change is in a CE file, _double check_ that - applying the patch for this PR to the ENT repo and running tests doesn't - break any tests. Sometimes ENT only tests rely on public functions in CE - files. -- [ ] **Jira:** If this change has an associated Jira, it's referenced either - in the PR description, commit message, or branch name. -- [ ] **RFC:** If this change has an associated RFC, please link it in the description. -- [ ] **ENT PR:** If this change has an associated ENT PR, please link it in the - description. Also, make sure the changelog is in this PR, _not_ in your ENT PR. diff --git a/.github/workflows/backport-ce.yml b/.github/workflows/backport-ce.yml index ef684918fa36..5a14cf18f445 100644 --- a/.github/workflows/backport-ce.yml +++ b/.github/workflows/backport-ce.yml @@ -13,7 +13,7 @@ jobs: backport-targeted-release-branch: if: github.event.pull_request.merged && github.repository == 'hashicorp/vault' runs-on: ubuntu-latest - container: hashicorpdev/backport-assistant:0.4.3 + container: hashicorpdev/backport-assistant:0.4.1 steps: - name: Backport changes to targeted release branch run: | diff --git a/.github/workflows/changelog-checker.yml b/.github/workflows/changelog-checker.yml index 23ab8246a710..44291fa8e085 100644 --- a/.github/workflows/changelog-checker.yml +++ b/.github/workflows/changelog-checker.yml @@ -48,8 +48,8 @@ jobs: echo "Not found." echo "" echo "Did not find a changelog entry named ${expected_changelog_file}" - echo "If your changelog file is correct, or this change does not need a changelog, skip this check with the 'pr/no-changelog' label" - echo "Reference - https://github.com/hashicorp/vault/blob/main/CONTRIBUTING.md#changelog-entries" + echo "If your changelog file is correct, skip this check with the 'pr/no-changelog' label" + echo "Reference - https://github.com/hashicorp/vault/pull/10363 and https://github.com/hashicorp/vault/pull/11894" exit 1 fi @@ -76,12 +76,6 @@ jobs: elif grep -q ':fix$' "$changelog_files"; then echo "Found invalid type (fix) in changelog - did you mean bug?" exit 1 - elif grep -q ':feature$' "$changelog_files"; then - if ! grep -q '^\*\*' "$changelog_files"; then - echo "Feature changelogs must be formatted like the following:" - echo "**Feature Name**: Feature description" - exit 1 - fi elif ! grep -q '```release-note:' "$changelog_files"; then # People often make changelog files like ```changelog:, which is incorrect. echo "Changelog file did not contain 'release-note' heading - check formatting." diff --git a/.github/workflows/do-not-merge-checker.yml b/.github/workflows/do-not-merge-checker.yml deleted file mode 100644 index 5cff45f5cd81..000000000000 --- a/.github/workflows/do-not-merge-checker.yml +++ /dev/null @@ -1,22 +0,0 @@ -# This workflow fails if a 'do-not-merge' label is applied to the PR. -name: Check do-not-merge - -on: - pull_request: - types: [reopened, labeled, unlabeled] - # Runs on PRs to main and release branches - branches: - - main - - release/** - -jobs: - # checks that a do-not-merge label is not present for a PR - do-not-merge-check: - # If there is a `do-not-merge` label we ignore this check - if: ${{ contains(github.event.pull_request.labels.*.name, 'do-not-merge') }} - runs-on: ubuntu-latest - steps: - - name: Fail if do-not-merge label is applied - run: | - echo "Cannot merge with do-not-merge label applied." - exit 1 diff --git a/.github/workflows/enos-release-testing-oss.yml b/.github/workflows/enos-release-testing-oss.yml index c648d5d2a9e3..7c5bbf818557 100644 --- a/.github/workflows/enos-release-testing-oss.yml +++ b/.github/workflows/enos-release-testing-oss.yml @@ -64,7 +64,7 @@ jobs: secrets: inherit save-metadata: - runs-on: ubuntu-latest + runs-on: linux if: always() needs: test steps: diff --git a/.github/workflows/plugin-update.yml b/.github/workflows/plugin-update.yml index 0e3f2551a9f7..00681a4cdc34 100644 --- a/.github/workflows/plugin-update.yml +++ b/.github/workflows/plugin-update.yml @@ -8,10 +8,6 @@ on: description: 'Full name of the plugin, e.g., vault-plugin-auth-kubernetes' required: true type: string - branch: - description: 'Git branch name to use' - required: true - type: string version: description: 'Version of the plugin with *NO* "v", e.g., 1.2.3' required: true @@ -25,7 +21,7 @@ jobs: plugin-update: runs-on: ubuntu-latest env: - VAULT_BRANCH: ${{ inputs.branch }} + VAULT_BRANCH: "update/${{ inputs.plugin }}/v${{ inputs.version }}" REVIEWER: ${{ inputs.reviewer || github.actor }} steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 @@ -39,19 +35,12 @@ jobs: cache: false # save cache space for vault builds: https://github.com/hashicorp/vault/pull/21764 go-version-file: .go-version - - name: Update plugin - if: github.repository == 'hashicorp/vault' + - name: update plugin run: | go get "github.com/hashicorp/${{ inputs.plugin }}@v${{ inputs.version }}" go mod tidy - - name: Update Enterprise-only plugin - if: github.repository == 'hashicorp/vault-enterprise' - run: | - (cd vault_ent && go get "github.com/hashicorp/${{ inputs.plugin }}@v${{ inputs.version }}" && go mod tidy) - go mod tidy - - - name: Detect changes + - name: detect changes run: | count=$(git status --porcelain=v1 2>/dev/null | wc -l) if [ "$count" -eq 0 ]; then @@ -59,7 +48,7 @@ jobs: exit 1 fi - - name: Commit and push + - name: commit/push run: | git config user.name hc-github-team-secure-vault-ecosystem git config user.email hc-github-team-secure-vault-ecosystem@users.noreply.github.com @@ -79,9 +68,8 @@ jobs: gh pr create \ --head "$VAULT_BRANCH" \ --reviewer "$REVIEWER" \ - --assignee "$REVIEWER" \ --title "Update ${{ inputs.plugin }} to v${{ inputs.version }}" \ - --body "This PR was generated by a GitHub Action. Full log: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + --body "This PR was generated by a GitHub Action. Full log: https://github.com/hashicorp/vault/actions/runs/${{ github.run_id }}" echo "vault_pr_num=$(gh pr list --head "$VAULT_BRANCH" --json number -q '.[0].number')" >> "$GITHUB_OUTPUT" echo "vault_pr_url=$(gh pr list --head "$VAULT_BRANCH" --json url -q '.[0].url')" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml index a396ed9314d2..2ca6fcf599c3 100644 --- a/.github/workflows/security-scan.yml +++ b/.github/workflows/security-scan.yml @@ -16,10 +16,10 @@ on: jobs: scan: runs-on: ${{ github.repository == 'hashicorp/vault' && 'ubuntu-latest' || fromJSON('["self-hosted","ondemand","os=linux","type=c6a.4xlarge"]') }} - # The first check ensures this doesn't run on community-contributed PRs, who won't have the - # permissions to run this job. + # The first check ensures this doesn't run on community-contributed PRs, who + # won't have the permissions to run this job. if: | - ! github.event.pull_request.head.repo.fork && + (startsWith(github.repository, 'hashicorp/vault') || (github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name)) && github.actor != 'dependabot[bot]' && github.actor != 'hc-github-team-secure-vault-core' steps: diff --git a/.github/workflows/test-enos-scenario-ui.yml b/.github/workflows/test-enos-scenario-ui.yml index 017d62640751..3aa49eb27a50 100644 --- a/.github/workflows/test-enos-scenario-ui.yml +++ b/.github/workflows/test-enos-scenario-ui.yml @@ -108,7 +108,7 @@ jobs: sudo apt install -y libnss3-dev libgdk-pixbuf2.0-dev libgtk-3-dev libxss-dev libasound2 - name: Install Chrome if: steps.chrome-check.outputs.chrome-version == 'not-installed' - uses: browser-actions/setup-chrome@facf10a55b9caf92e0cc749b4f82bf8220989148 # v1.7.2 + uses: browser-actions/setup-chrome@db1b524c26f20a8d1a10f7fc385c92387e2d0477 # v1.7.1 - name: Installed Chrome Version run: | echo "Installed Chrome Version = [$(chrome --version 2> /dev/null || google-chrome --version 2> /dev/null || google-chrome-stable --version 2> /dev/null)]" diff --git a/.release/versions.hcl b/.release/versions.hcl index 3cc6940eefeb..fa05b7c4c17a 100644 --- a/.release/versions.hcl +++ b/.release/versions.hcl @@ -5,17 +5,15 @@ schema = 1 active_versions { - version "1.18.x" { - ce_active = true - } - version "1.17.x" { - ce_active = true - } version "1.16.x" { - ce_active = false + ce_active = true lts = true } version "1.15.x" { - ce_active = false + ce_active = true + } + version "1.14.x" { + ce_active = true } + } diff --git a/CHANGELOG.md b/CHANGELOG.md index 82c8f74c0c42..04ef632a15a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,769 +2,6 @@ - [v1.0.0 - v1.9.10](CHANGELOG-pre-v1.10.md) - [v0.11.6 and earlier](CHANGELOG-v0.md) -## 1.18.0-rc1 -## September 18, 2024 - -CHANGES: - -* activity (enterprise): filter all fields in client count responses by the request namespace [[GH-27790](https://github.com/hashicorp/vault/pull/27790)] -* activity (enterprise): remove deprecated fields distinct_entities and non_entity_tokens [[GH-27830](https://github.com/hashicorp/vault/pull/27830)] -* activity log: Deprecated the field "default_report_months". Instead, the billing start time will be used to determine the start time -when querying the activity log endpoints. [[GH-27350](https://github.com/hashicorp/vault/pull/27350)] -* activity log: Deprecates the current_billing_period field for /sys/internal/counters/activity. The default start time -will automatically be set the billing period start date. [[GH-27426](https://github.com/hashicorp/vault/pull/27426)] -* activity: The [activity export API](https://developer.hashicorp.com/vault/api-docs/system/internal-counters#activity-export) now requires the `sudo` ACL capability. [[GH-27846](https://github.com/hashicorp/vault/pull/27846)] -* activity: The [activity export API](https://developer.hashicorp.com/vault/api-docs/system/internal-counters#activity-export) now responds with a status of 204 instead 400 when no data exists within the time range specified by `start_time` and `end_time`. [[GH-28064](https://github.com/hashicorp/vault/pull/28064)] -* activity: The startTime will be set to the start of the current billing period by default. -The endTime will be set to the end of the current month. This applies to /sys/internal/counters/activity, -/sys/internal/counters/activity/export, and the vault operator usage command that utilizes /sys/internal/counters/activity. [[GH-27379](https://github.com/hashicorp/vault/pull/27379)] -* api: Update backoff/v3 to backoff/v4.3.0 [[GH-26868](https://github.com/hashicorp/vault/pull/26868)] -* auth/alicloud: Update plugin to v0.19.0 [[GH-28263](https://github.com/hashicorp/vault/pull/28263)] -* auth/azure: Update plugin to v0.19.0 [[GH-28294](https://github.com/hashicorp/vault/pull/28294)] -* auth/cf: Update plugin to v0.18.0 [[GH-27724](https://github.com/hashicorp/vault/pull/27724)] -* auth/cf: Update plugin to v0.19.0 [[GH-28266](https://github.com/hashicorp/vault/pull/28266)] -* auth/gcp: Update plugin to v0.19.0 [[GH-28366](https://github.com/hashicorp/vault/pull/28366)] -* auth/jwt: Update plugin to v0.21.0 [[GH-27498](https://github.com/hashicorp/vault/pull/27498)] -* auth/jwt: Update plugin to v0.22.0 [[GH-28349](https://github.com/hashicorp/vault/pull/28349)] -* auth/kerberos: Update plugin to v0.13.0 [[GH-28264](https://github.com/hashicorp/vault/pull/28264)] -* auth/kubernetes: Update plugin to v0.20.0 [[GH-28289](https://github.com/hashicorp/vault/pull/28289)] -* auth/oci: Update plugin to v0.17.0 [[GH-28307](https://github.com/hashicorp/vault/pull/28307)] -* cli: The undocumented `-dev-three-node` and `-dev-four-cluster` CLI options have been removed. [[GH-27578](https://github.com/hashicorp/vault/pull/27578)] -* consul-template: updated to version 0.39.1 [[GH-27799](https://github.com/hashicorp/vault/pull/27799)] -* core(enterprise): Updated the following two control group related errors responses to respond with response code 400 instead of 500: `control group: could not find token`, and `control group: token is not a valid control group token`. -* core: Bump Go version to 1.22.7 -* database/couchbase: Update plugin to v0.12.0 [[GH-28327](https://github.com/hashicorp/vault/pull/28327)] -* database/elasticsearch: Update plugin to v0.16.0 [[GH-28277](https://github.com/hashicorp/vault/pull/28277)] -* database/mongodbatlas: Update plugin to v0.13.0 [[GH-28268](https://github.com/hashicorp/vault/pull/28268)] -* database/redis-elasticache: Update plugin to v0.5.0 [[GH-28293](https://github.com/hashicorp/vault/pull/28293)] -* database/redis: Update plugin to v0.4.0 [[GH-28404](https://github.com/hashicorp/vault/pull/28404)] -* database/snowflake: Update plugin to v0.12.0 [[GH-28275](https://github.com/hashicorp/vault/pull/28275)] -* sdk: Upgrade to go-secure-stdlib/plugincontainer@v0.4.0, which also bumps github.com/docker/docker to v26.1.5+incompatible [[GH-28269](https://github.com/hashicorp/vault/pull/28269)] -* secrets/ad: Update plugin to v0.19.0 [[GH-28361](https://github.com/hashicorp/vault/pull/28361)] -* secrets/alicloud: Update plugin to v0.18.0 [[GH-28271](https://github.com/hashicorp/vault/pull/28271)] -* secrets/azure: Update plugin to v0.19.2 [[GH-27652](https://github.com/hashicorp/vault/pull/27652)] -* secrets/azure: Update plugin to v0.20.0 [[GH-28267](https://github.com/hashicorp/vault/pull/28267)] -* secrets/gcp: Update plugin to v0.20.0 [[GH-28324](https://github.com/hashicorp/vault/pull/28324)] -* secrets/gcpkms: Update plugin to v0.18.0 [[GH-28300](https://github.com/hashicorp/vault/pull/28300)] -* secrets/gcpkms: Update plugin to v0.19.0 [[GH-28360](https://github.com/hashicorp/vault/pull/28360)] -* secrets/kubernetes: Update plugin to v0.9.0 [[GH-28287](https://github.com/hashicorp/vault/pull/28287)] -* secrets/kv: Update plugin to v0.20.0 [[GH-28334](https://github.com/hashicorp/vault/pull/28334)] -* secrets/mongodbatlas: Update plugin to v0.13.0 [[GH-28348](https://github.com/hashicorp/vault/pull/28348)] -* secrets/openldap: Update plugin to v0.14.0 [[GH-28325](https://github.com/hashicorp/vault/pull/28325)] -* secrets/terraform: Update plugin to v0.10.0 [[GH-28312](https://github.com/hashicorp/vault/pull/28312)] -* secrets/terraform: Update plugin to v0.9.0 [[GH-28016](https://github.com/hashicorp/vault/pull/28016)] -* ui: Uses the internal/counters/activity/export endpoint for client count export data. [[GH-27455](https://github.com/hashicorp/vault/pull/27455)] - -FEATURES: - -* **AWS secrets engine STS session tags support**: Adds support for setting STS -session tags when generating temporary credentials using the AWS secrets -engine. [[GH-27620](https://github.com/hashicorp/vault/pull/27620)] -* **Adaptive Overload Protection (enterprise)**: Enables Adaptive Overload Protection -for write requests as a GA feature (enabled by default) for Integrated Storage. -* **Audit Entry Exclusion**: Audit devices support excluding fields from entries being written to them, with expression-based rules (powered by go-bexpr) to determine when the specific fields are excluded. -* **Workload Identity Federation UI for AWS (enterprise)**: Add WIF fields to AWS secrets engine. [[GH-28148](https://github.com/hashicorp/vault/pull/28148)] -* **KV v2 Patch/Subkey (enterprise)**: Adds GUI support to read the subkeys of a KV v2 secret and patch (partially update) secret data. [[GH-28212](https://github.com/hashicorp/vault/pull/28212)] -* **Self-Managed Static Roles**: Self-Managed Static Roles are now supported for select SQL database engines (Postgres, Oracle). Requires Vault Enterprise. [[GH-28199](https://github.com/hashicorp/vault/pull/28199)] -* **Vault Minimal Version**: Add the ability to build a minimal version of Vault -with only core features using the BUILD_MINIMAL environment variable. [[GH-27394](https://github.com/hashicorp/vault/pull/27394)] -* **Vault PKI 3GPP CMPv2 Server (Enterprise)**: Support for the PKI 3GPP CMPv2 certificate management protocol has been added to the Vault PKI Plugin. This allows standard CMPv2 clients to request certificates from a Vault server with no knowledge of Vault APIs. - -IMPROVEMENTS: - -* activity log: Changes how new client counts in the current month are estimated, in order to return more -visibly sensible totals. [[GH-27547](https://github.com/hashicorp/vault/pull/27547)] -* activity: The [activity export API](https://developer.hashicorp.com/vault/api-docs/system/internal-counters#activity-export) can now be called in non-root namespaces. Resulting records will be filtered to include the requested namespace (via `X-Vault-Namespace` header or within the path) and all child namespaces. [[GH-27846](https://github.com/hashicorp/vault/pull/27846)] -* activity: The [activity export API](https://developer.hashicorp.com/vault/api-docs/system/internal-counters#activity-export) now includes identity metadata about entity clients. [[GH-28064](https://github.com/hashicorp/vault/pull/28064)] -* activity: `/sys/internal/counters/activity` will now include a warning if the specified usage period contains estimated client counts. [[GH-28068](https://github.com/hashicorp/vault/pull/28068)] -* agent/sink: Allow configuration of the user and group ID of the file sink. [[GH-27123](https://github.com/hashicorp/vault/pull/27123)] -* agent: Add metric (vault.agent.authenticated) that is set to 1 when vault agent has a valid token and zero if it does not. [[GH-26570](https://github.com/hashicorp/vault/pull/26570)] -* agent: Add the ability to dump pprof to the filesystem using SIGUSR2 [[GH-27510](https://github.com/hashicorp/vault/pull/27510)] -* audit: Adds TRACE logging to log request/response under certain circumstances, and further improvements to the audit subsystem. [[GH-28056](https://github.com/hashicorp/vault/pull/28056)] -* audit: Ensure that any underyling errors from audit devices are logged even if we consider auditing to be a success. [[GH-27809](https://github.com/hashicorp/vault/pull/27809)] -* audit: Internal implementation changes to the audit subsystem which improve performance. [[GH-27952](https://github.com/hashicorp/vault/pull/27952)] -* audit: Internal implementation changes to the audit subsystem which improve relability. [[GH-28286](https://github.com/hashicorp/vault/pull/28286)] -* audit: sinks (file, socket, syslog) will attempt to log errors to the server operational -log before returning (if there are errors to log, and the context is done). [[GH-27859](https://github.com/hashicorp/vault/pull/27859)] -* auth/cert: Cache full list of role trust information separately to avoid -eviction, and avoid duplicate loading during multiple simultaneous logins on -the same role. [[GH-27902](https://github.com/hashicorp/vault/pull/27902)] -* cli: Add a `--dev-no-kv` flag to prevent auto mounting a key-value secret backend when running a dev server [[GH-16974](https://github.com/hashicorp/vault/pull/16974)] -* cli: Allow vault CLI HTTP headers to be specified using the JSON-encoded VAULT_HEADERS environment variable [[GH-21993](https://github.com/hashicorp/vault/pull/21993)] -* cli: `vault operator usage` will now include a warning if the specified usage period contains estimated client counts. [[GH-28068](https://github.com/hashicorp/vault/pull/28068)] -* core/activity: Ensure client count queries that include the current month return consistent results by sorting the clients before performing estimation [[GH-28062](https://github.com/hashicorp/vault/pull/28062)] -* core/cli: Example 'help' pages for vault read / write docs improved. [[GH-19064](https://github.com/hashicorp/vault/pull/19064)] -* core/identity: allow identity backend to be tuned using standard secrets backend tuning parameters. [[GH-14723](https://github.com/hashicorp/vault/pull/14723)] -* core/metrics: ensure core HA metrics are always output to Prometheus. [[GH-27966](https://github.com/hashicorp/vault/pull/27966)] -* core: make authLock and mountsLock in Core configurable via the detect_deadlocks configuration parameter. [[GH-27633](https://github.com/hashicorp/vault/pull/27633)] -* database/postgres: Add new fields to the plugin's config endpoint for client certificate authentication. [[GH-28024](https://github.com/hashicorp/vault/pull/28024)] -* db/cassandra: Add `disable_host_initial_lookup` option to backend, allowing the disabling of initial host lookup. [[GH-9733](https://github.com/hashicorp/vault/pull/9733)] -* identity: alias metadata is now returned when listing entity aliases [[GH-26073](https://github.com/hashicorp/vault/pull/26073)] -* license utilization reporting (enterprise): Auto-roll billing start date. [[GH-27656](https://github.com/hashicorp/vault/pull/27656)] -* proxy/sink: Allow configuration of the user and group ID of the file sink. [[GH-27123](https://github.com/hashicorp/vault/pull/27123)] -* proxy: Add the ability to dump pprof to the filesystem using SIGUSR2 [[GH-27510](https://github.com/hashicorp/vault/pull/27510)] -* raft-snapshot (enterprise): add support for managed identity credentials for azure snapshots -* raft/autopilot: Persist Raft server versions so autopilot always knows the versions of all servers in the cluster. Include server versions in the Raft bootstrap challenge answer so autopilot immediately knows the versions of new nodes. [[GH-28186](https://github.com/hashicorp/vault/pull/28186)] -* sdk/helper: Allow setting environment variables when using NewTestDockerCluster [[GH-27457](https://github.com/hashicorp/vault/pull/27457)] -* secrets-sync (enterprise): add support for specifying the replication regions for secret storage within GCP Secret Manager destinations -* secrets-sync (enterprise): add support for syncing secrets to github environments within repositories -* secrets-sync (enterprise): add support for syncing secrets to github organizations (beta) -* secrets/database/hana: Update HANA db client to v1.10.1 [[GH-27950](https://github.com/hashicorp/vault/pull/27950)] -* secrets/database: Add support for GCP CloudSQL private IP's. [[GH-26828](https://github.com/hashicorp/vault/pull/26828)] -* secrets/pki: Key Usage can now be set on intermediate and root CAs, and CSRs generated by the PKI secret's engine. [[GH-28237](https://github.com/hashicorp/vault/pull/28237)] -* serviceregistration: Added support for Consul ServiceMeta tags from config file from the new `service_meta` config field. [[GH-11084](https://github.com/hashicorp/vault/pull/11084)] -* storage/azure: Updated metadata endpoint to `GetMSIEndpoint`, which supports more than just the metadata service. [[GH-10624](https://github.com/hashicorp/vault/pull/10624)] -* storage/dynamodb: Speed up list and delete of large directories by only requesting keys from DynamoDB [[GH-21159](https://github.com/hashicorp/vault/pull/21159)] -* storage/etcd: Update etcd3 client to v3.5.13 to allow use of TLSv1.3. [[GH-26660](https://github.com/hashicorp/vault/pull/26660)] -* storage/raft: Bump raft to v1.7.0 which includes pre-vote. This should make clusters more stable during network partitions. [[GH-27605](https://github.com/hashicorp/vault/pull/27605)] -* storage/raft: Improve autopilot logging on startup to show config values clearly and avoid spurious logs [[GH-27464](https://github.com/hashicorp/vault/pull/27464)] -* ui/secrets-sync: Hide Secrets Sync from the sidebar nav if user does not have access to the feature. [[GH-27262](https://github.com/hashicorp/vault/pull/27262)] -* ui: AWS credentials form sets credential_type from backing role [[GH-27405](https://github.com/hashicorp/vault/pull/27405)] -* ui: Creates separate section for updating sensitive creds for Secrets sync create/edit view. [[GH-27538](https://github.com/hashicorp/vault/pull/27538)] -* ui: For AWS and SSH secret engines hide mount configuration details in toggle and display configuration details or cta. [[GH-27831](https://github.com/hashicorp/vault/pull/27831)] -* ui: Mask obfuscated fields when creating/editing a Secrets sync destination. [[GH-27348](https://github.com/hashicorp/vault/pull/27348)] -* ui: Move secret-engine configuration create/edit from routing `vault/settings/secrets/configure/` to `vault/secrets//configuration/edit` [[GH-27918](https://github.com/hashicorp/vault/pull/27918)] -* ui: Remove deprecated `current_billing_period` from dashboard activity log request [[GH-27559](https://github.com/hashicorp/vault/pull/27559)] -* ui: Update the client count dashboard to use API namespace filtering and other UX improvements [[GH-28036](https://github.com/hashicorp/vault/pull/28036)] -* ui: remove initial start/end parameters on the activity call for client counts dashboard. [[GH-27816](https://github.com/hashicorp/vault/pull/27816)] -* ui: simplify the date range editing experience in the client counts dashboard. [[GH-27796](https://github.com/hashicorp/vault/pull/27796)] -* website/docs: Added API documentation for Azure Secrets Engine delete role [[GH-27883](https://github.com/hashicorp/vault/pull/27883)] -* website/docs: corrected invalid json in sample payload for azure secrets engine create/update role [[GH-28076](https://github.com/hashicorp/vault/pull/28076)] - -BUG FIXES: - -* activity: The sys/internal/counters/activity endpoint will return current month data when the end_date parameter is set to a future date. [[GH-28042](https://github.com/hashicorp/vault/pull/28042)] -* agent: Fixed an issue causing excessive CPU usage during normal operation [[GH-27518](https://github.com/hashicorp/vault/pull/27518)] -* auth/appid, auth/cert, auth/github, auth/ldap, auth/okta, auth/radius, auth/userpass: fixed an issue with policy name normalization that would prevent a token associated with a policy containing an uppercase character to be renewed. [[GH-16484](https://github.com/hashicorp/vault/pull/16484)] -* auth/aws: fixes an issue where not supplying an external id was interpreted as an empty external id [[GH-27858](https://github.com/hashicorp/vault/pull/27858)] -* auth/cert: Merge error messages returned in login failures and include error when present [[GH-27202](https://github.com/hashicorp/vault/pull/27202)] -* auth/cert: Use subject's serial number, not issuer's within error message text in OCSP request errors [[GH-27696](https://github.com/hashicorp/vault/pull/27696)] -* auth/cert: ocsp_ca_certificates field was not honored when validating OCSP responses signed by a CA that did not issue the certificate. [[GH-28309](https://github.com/hashicorp/vault/pull/28309)] -* auth/token: fixes an edge case bug that "identity_policies" is nil and causes cli vault login error [[GH-17007](https://github.com/hashicorp/vault/pull/17007)] -* cli: Fixed an erroneous warning appearing about `-address` not being set when it is. [[GH-27265](https://github.com/hashicorp/vault/pull/27265)] -* cli: Fixed issue with `vault hcp connect` where HCP resources with uppercase letters were inaccessible when entering the correct project name. [[GH-27694](https://github.com/hashicorp/vault/pull/27694)] -* command: The `vault secrets move` and `vault auth move` command will no longer attempt to write to storage on performance standby nodes. [[GH-28059](https://github.com/hashicorp/vault/pull/28059)] -* config: Vault TCP listener config now correctly supports the documented proxy_protocol_behavior -setting of 'deny_unauthorized' [[GH-27459](https://github.com/hashicorp/vault/pull/27459)] -* core (enterprise): Fix 500 errors that occurred querying `sys/internal/ui/mounts` for a mount prefixed by a namespace path when path filters are configured. [[GH-27939](https://github.com/hashicorp/vault/pull/27939)] -* core (enterprise): Fix HTTP redirects in namespaces to use the correct path and (in the case of event subscriptions) the correct URI scheme. [[GH-27660](https://github.com/hashicorp/vault/pull/27660)] -* core (enterprise): Fix deletion of MFA login-enforcement configurations on standby nodes -* core/audit: Audit logging a Vault request/response checks if the existing context -is cancelled and will now use a new context with a 5 second timeout. -If the existing context is cancelled a new context, will be used. [[GH-27531](https://github.com/hashicorp/vault/pull/27531)] -* core/config: fix issue when using `proxy_protocol_behavior` with `deny_unauthorized`, -which causes the Vault TCP listener to close after receiving an untrusted upstream proxy connection. [[GH-27589](https://github.com/hashicorp/vault/pull/27589)] -* core/identity: Fixed an issue where deleted/reassigned entity-aliases were not removed from in-memory database. [[GH-27750](https://github.com/hashicorp/vault/pull/27750)] -* core: Fixed an issue where maximum request duration timeout was not being added to all requests containing strings sys/monitor and sys/events. With this change, timeout is now added to all requests except monitor and events endpoint. [[GH-28230](https://github.com/hashicorp/vault/pull/28230)] -* core: Fixed an issue with performance standbys not being able to handle rotate root requests. [[GH-27631](https://github.com/hashicorp/vault/pull/27631)] -* helper/pkcs7: Fix parsing certain messages containing only certificates [[GH-27435](https://github.com/hashicorp/vault/pull/27435)] -* identity/oidc: prevent JWKS from being generated by multiple concurrent requests [[GH-27929](https://github.com/hashicorp/vault/pull/27929)] -* licensing (enterprise): fixed issue where billing start date might not be correctly updated on performance standbys -* proxy/cache (enterprise): Fixed an issue where Proxy with static secret caching enabled would not correctly handle requests to older secret versions for KVv2 secrets. Proxy's static secret cache now properly handles all requests relating to older versions for KVv2 secrets. [[GH-28207](https://github.com/hashicorp/vault/pull/28207)] -* proxy/cache (enterprise): Fixed an issue where Proxy would not correctly update KV secrets when talking to a perf standby. Proxy will now attempt to forward requests to update secrets triggered by events to the active node. Note that this requires `allow_forwarding_via_header` to be configured on the cluster. [[GH-27891](https://github.com/hashicorp/vault/pull/27891)] -* proxy/cache (enterprise): Fixed an issue where cached static secrets could fail to update if the secrets belonged to a non-root namespace. [[GH-27730](https://github.com/hashicorp/vault/pull/27730)] -* proxy: Fixed an issue causing excessive CPU usage during normal operation [[GH-27518](https://github.com/hashicorp/vault/pull/27518)] -* raft/autopilot: Fixed panic that may occur during shutdown [[GH-27726](https://github.com/hashicorp/vault/pull/27726)] -* replication (enterprise): fix cache invalidation issue leading to namespace custom metadata not being shown correctly on performance secondaries -* secrets-sync (enterprise): Destination set/remove operations will no longer be blocked as "purge in progress" after a purge job ended in failure. -* secrets-sync (enterprise): Normalize custom_tag keys and values for recoverable invalid characters. -* secrets-sync (enterprise): Normalize secret key names before storing the external_name in a secret association. -* secrets-sync (enterprise): Patching github sync destination credentials will properly update and save the new credentials. -* secrets-sync (enterprise): Properly remove tags from secrets in AWS when they are removed from the source association -* secrets-sync (enterprise): Return an error immediately on destination creation when providing invalid custom_tags based on destination type. -* secrets-sync (enterprise): Return more accurate error code for invalid connection details -* secrets-sync (enterprise): Secondary nodes in a cluster now properly check activation-flags values. -* secrets-sync (enterprise): Skip invalid GitHub repository names when creating destinations -* secrets-sync (enterprise): Validate corresponding GitHub app parameters `app_name` and `installation_id` are set -* secrets/database: Skip connection verification on reading existing DB connection configuration [[GH-28139](https://github.com/hashicorp/vault/pull/28139)] -* secrets/identity (enterprise): Fix a bug that can cause DR promotion to fail in rare cases where a PR secondary has inconsistent alias information in storage. -* secrets/pki: fix lack of serial number to a certificate read resulting in a server side error. [[GH-27681](https://github.com/hashicorp/vault/pull/27681)] -* secrets/transit (enterprise): Fix an issue that caused input data be returned as part of generated CMAC values. -* storage/azure: Fix invalid account name initialization bug [[GH-27563](https://github.com/hashicorp/vault/pull/27563)] -* storage/raft (enterprise): Fix issue with namespace cache not getting cleared on snapshot restore, resulting in namespaces not found in the snapshot being inaccurately represented by API responses. [[GH-27474](https://github.com/hashicorp/vault/pull/27474)] -* storage/raft: Fix auto_join not working with mDNS provider. [[GH-25080](https://github.com/hashicorp/vault/pull/25080)] -* sys: Fix a bug where mounts of external plugins that were registered before Vault v1.0.0 could not be tuned to -use versioned plugins. [[GH-27881](https://github.com/hashicorp/vault/pull/27881)] -* ui: Allow creation of session_token type roles for AWS secret backend [[GH-27424](https://github.com/hashicorp/vault/pull/27424)] -* ui: Display an error and force a timeout when TOTP passcode is incorrect [[GH-27574](https://github.com/hashicorp/vault/pull/27574)] -* ui: Ensure token expired banner displays when batch token expires [[GH-27479](https://github.com/hashicorp/vault/pull/27479)] -* ui: Fix UI improperly checking capabilities for enabling performance and dr replication [[GH-28371](https://github.com/hashicorp/vault/pull/28371)] -* ui: Fix cursor jump on KVv2 json editor that would occur after pressing ENTER. [[GH-27569](https://github.com/hashicorp/vault/pull/27569)] -* ui: fix issue where enabling then disabling "Tidy ACME" in PKI results in failed API call. [[GH-27742](https://github.com/hashicorp/vault/pull/27742)] -* ui: fix namespace picker not working when in small screen where the sidebar is collapsed by default. [[GH-27728](https://github.com/hashicorp/vault/pull/27728)] -* ui: fixes renew-self being called right after login for non-renewable tokens [[GH-28204](https://github.com/hashicorp/vault/pull/28204)] -* ui: fixes toast (flash) alert message saying "created" when deleting a kv v2 secret [[GH-28093](https://github.com/hashicorp/vault/pull/28093)] - -## 1.17.6 -### September 25, 2024 - -CHANGES: - -* core: Bump Go version to 1.22.7 -* secrets/ldap: Update vault-plugin-secrets-openldap to v0.13.1 [[GH-28478](https://github.com/hashicorp/vault/pull/28478)] -* secrets/ssh: Add a flag, `allow_empty_principals` to allow keys or certs to apply to any user/principal. [[GH-28466](https://github.com/hashicorp/vault/pull/28466)] - -IMPROVEMENTS: - -* audit: Internal implementation changes to the audit subsystem which improve relability. [[GH-28286](https://github.com/hashicorp/vault/pull/28286)] -* ui: Remove deprecated `current_billing_period` from dashboard activity log request [[GH-27559](https://github.com/hashicorp/vault/pull/27559)] - -BUG FIXES: - -* auth/aws: Fixed potential panic after step-down and the queue has not repopulated. [[GH-28330](https://github.com/hashicorp/vault/pull/28330)] -* auth/cert: During certificate validation, OCSP requests are debug logged even if Vault's log level is above DEBUG. [[GH-28450](https://github.com/hashicorp/vault/pull/28450)] -* auth/cert: ocsp_ca_certificates field was not honored when validating OCSP responses signed by a CA that did not issue the certificate. [[GH-28309](https://github.com/hashicorp/vault/pull/28309)] -* auth: Updated error handling for missing login credentials in AppRole and UserPass auth methods to return a 400 error instead of a 500 error. [[GH-28441](https://github.com/hashicorp/vault/pull/28441)] -* core: Fixed an issue where maximum request duration timeout was not being added to all requests containing strings sys/monitor and sys/events. With this change, timeout is now added to all requests except monitor and events endpoint. [[GH-28230](https://github.com/hashicorp/vault/pull/28230)] -* proxy/cache (enterprise): Fixed a data race that could occur while tracking capabilities in Proxy's static secret cache. [[GH-28494](https://github.com/hashicorp/vault/pull/28494)] -* secrets-sync (enterprise): Secondary nodes in a cluster now properly check activation-flags values. -* secrets-sync (enterprise): Validate corresponding GitHub app parameters `app_name` and `installation_id` are set - -## 1.17.5 -## August 30, 2024 - -SECURITY: - -core/audit: fix regression where client tokens and token accessors were being -displayed in the audit log in plaintext [HCSEC-2024-18](https://discuss.hashicorp.com/t/hcsec-2024-18-vault-leaks-client-token-and-token-accessor-in-audit-devices) - -BUG FIXES: - -* proxy/cache (enterprise): Fixed an issue where Proxy with static secret caching enabled would not correctly handle requests to older secret versions for KVv2 secrets. Proxy's static secret cache now properly handles all requests relating to older versions for KVv2 secrets. [[GH-28207](https://github.com/hashicorp/vault/pull/28207)] -* ui: fixes renew-self being called right after login for non-renewable tokens [[GH-28204](https://github.com/hashicorp/vault/pull/28204)] - -## 1.17.4 -### August 29, 2024 - -CHANGES: - -* activity (enterprise): filter all fields in client count responses by the request namespace [[GH-27790](https://github.com/hashicorp/vault/pull/27790)] -* core: Bump Go version to 1.22.6 -* secrets/terraform: Update plugin to v0.9.0 [[GH-28016](https://github.com/hashicorp/vault/pull/28016)] - -IMPROVEMENTS: - -* activity log: Changes how new client counts in the current month are estimated, in order to return more -visibly sensible totals. [[GH-27547](https://github.com/hashicorp/vault/pull/27547)] -* activity: `/sys/internal/counters/activity` will now include a warning if the specified usage period contains estimated client counts. [[GH-28068](https://github.com/hashicorp/vault/pull/28068)] -* audit: Adds TRACE logging to log request/response under certain circumstances, and further improvements to the audit subsystem. [[GH-28056](https://github.com/hashicorp/vault/pull/28056)] -* cli: `vault operator usage` will now include a warning if the specified usage period contains estimated client counts. [[GH-28068](https://github.com/hashicorp/vault/pull/28068)] -* core/activity: Ensure client count queries that include the current month return consistent results by sorting the clients before performing estimation [[GH-28062](https://github.com/hashicorp/vault/pull/28062)] -* raft-snapshot (enterprise): add support for managed identity credentials for azure snapshots - -BUG FIXES: - -* activity: The sys/internal/counters/activity endpoint will return current month data when the end_date parameter is set to a future date. [[GH-28042](https://github.com/hashicorp/vault/pull/28042)] -* auth/aws: fixes an issue where not supplying an external id was interpreted as an empty external id [[GH-27858](https://github.com/hashicorp/vault/pull/27858)] -* command: The `vault secrets move` and `vault auth move` command will no longer attempt to write to storage on performance standby nodes. [[GH-28059](https://github.com/hashicorp/vault/pull/28059)] -* core (enterprise): Fix deletion of MFA login-enforcement configurations on standby nodes -* secrets/database: Skip connection verification on reading existing DB connection configuration [[GH-28139](https://github.com/hashicorp/vault/pull/28139)] -* ui: fixes toast (flash) alert message saying "created" when deleting a kv v2 secret [[GH-28093](https://github.com/hashicorp/vault/pull/28093)] - -## 1.17.3 -### August 07, 2024 - -CHANGES: - -* auth/cf: Update plugin to v0.18.0 [[GH-27724](https://github.com/hashicorp/vault/pull/27724)] - -IMPROVEMENTS: - -* audit: Ensure that any underyling errors from audit devices are logged even if we consider auditing to be a success. [[GH-27809](https://github.com/hashicorp/vault/pull/27809)] -* audit: Internal implementation changes to the audit subsystem which improve performance. [[GH-27952](https://github.com/hashicorp/vault/pull/27952)] -* audit: sinks (file, socket, syslog) will attempt to log errors to the server operational -log before returning (if there are errors to log, and the context is done). [[GH-27859](https://github.com/hashicorp/vault/pull/27859)] -* auth/cert: Cache full list of role trust information separately to avoid -eviction, and avoid duplicate loading during multiple simultaneous logins on -the same role. [[GH-27902](https://github.com/hashicorp/vault/pull/27902)] -* license utilization reporting (enterprise): Auto-roll billing start date. [[GH-27656](https://github.com/hashicorp/vault/pull/27656)] -* website/docs: Added API documentation for Azure Secrets Engine delete role [[GH-27883](https://github.com/hashicorp/vault/pull/27883)] - -BUG FIXES: - -* auth/cert: Use subject's serial number, not issuer's within error message text in OCSP request errors [[GH-27696](https://github.com/hashicorp/vault/pull/27696)] -* core (enterprise): Fix 500 errors that occurred querying `sys/internal/ui/mounts` for a mount prefixed by a namespace path when path filters are configured. [[GH-27939](https://github.com/hashicorp/vault/pull/27939)] -* core/identity: Fixed an issue where deleted/reassigned entity-aliases were not removed from in-memory database. [[GH-27750](https://github.com/hashicorp/vault/pull/27750)] -* proxy/cache (enterprise): Fixed an issue where Proxy would not correctly update KV secrets when talking to a perf standby. Proxy will now attempt to forward requests to update secrets triggered by events to the active node. Note that this requires `allow_forwarding_via_header` to be configured on the cluster. [[GH-27891](https://github.com/hashicorp/vault/pull/27891)] -* proxy/cache (enterprise): Fixed an issue where cached static secrets could fail to update if the secrets belonged to a non-root namespace. [[GH-27730](https://github.com/hashicorp/vault/pull/27730)] -* raft/autopilot: Fixed panic that may occur during shutdown [[GH-27726](https://github.com/hashicorp/vault/pull/27726)] -* secrets-sync (enterprise): Destination set/remove operations will no longer be blocked as "purge in progress" after a purge job ended in failure. -* secrets-sync (enterprise): Normalize custom_tag keys and values for recoverable invalid characters. -* secrets-sync (enterprise): Normalize secret key names before storing the external_name in a secret association. -* secrets-sync (enterprise): Patching github sync destination credentials will properly update and save the new credentials. -* secrets-sync (enterprise): Return an error immediately on destination creation when providing invalid custom_tags based on destination type. -* secrets/identity (enterprise): Fix a bug that can cause DR promotion to fail in rare cases where a PR secondary has inconsistent alias information in storage. -* sys: Fix a bug where mounts of external plugins that were registered before Vault v1.0.0 could not be tuned to -use versioned plugins. [[GH-27881](https://github.com/hashicorp/vault/pull/27881)] -* ui: Fix cursor jump on KVv2 json editor that would occur after pressing ENTER. [[GH-27569](https://github.com/hashicorp/vault/pull/27569)] -* ui: fix issue where enabling then disabling "Tidy ACME" in PKI results in failed API call. [[GH-27742](https://github.com/hashicorp/vault/pull/27742)] -* ui: fix namespace picker not working when in small screen where the sidebar is collapsed by default. [[GH-27728](https://github.com/hashicorp/vault/pull/27728)] - - -## 1.17.2 -### July 10, 2024 - -CHANGES: - -* core: Bump Go version to 1.22.5 -* secrets/azure: Update plugin to v0.19.2 [[GH-27652](https://github.com/hashicorp/vault/pull/27652)] - -FEATURES: - -* **AWS secrets engine STS session tags support**: Adds support for setting STS -session tags when generating temporary credentials using the AWS secrets -engine. [[GH-27620](https://github.com/hashicorp/vault/pull/27620)] - -BUG FIXES: - -* cli: Fixed issue with `vault hcp connect` where HCP resources with uppercase letters were inaccessible when entering the correct project name. [[GH-27694](https://github.com/hashicorp/vault/pull/27694)] -* core (enterprise): Fix HTTP redirects in namespaces to use the correct path and (in the case of event subscriptions) the correct URI scheme. [[GH-27660](https://github.com/hashicorp/vault/pull/27660)] -* core/config: fix issue when using `proxy_protocol_behavior` with `deny_unauthorized`, -which causes the Vault TCP listener to close after receiving an untrusted upstream proxy connection. [[GH-27589](https://github.com/hashicorp/vault/pull/27589)] -* core: Fixed an issue with performance standbys not being able to handle rotate root requests. [[GH-27631](https://github.com/hashicorp/vault/pull/27631)] -* secrets/transit (enterprise): Fix an issue that caused input data be returned as part of generated CMAC values. -* ui: Display an error and force a timeout when TOTP passcode is incorrect [[GH-27574](https://github.com/hashicorp/vault/pull/27574)] -* ui: Ensure token expired banner displays when batch token expires [[GH-27479](https://github.com/hashicorp/vault/pull/27479)] - -## 1.17.1 -### June 26, 2024 - -CHANGES: - -* auth/jwt: Update plugin to v0.21.0 [[GH-27498](https://github.com/hashicorp/vault/pull/27498)] - -IMPROVEMENTS: - -* storage/raft: Improve autopilot logging on startup to show config values clearly and avoid spurious logs [[GH-27464](https://github.com/hashicorp/vault/pull/27464)] -* ui/secrets-sync: Hide Secrets Sync from the sidebar nav if user does not have access to the feature. [[GH-27262](https://github.com/hashicorp/vault/pull/27262)] - -BUG FIXES: - -* agent: Fixed an issue causing excessive CPU usage during normal operation [[GH-27518](https://github.com/hashicorp/vault/pull/27518)] -* config: Vault TCP listener config now correctly supports the documented proxy_protocol_behavior -setting of 'deny_unauthorized' [[GH-27459](https://github.com/hashicorp/vault/pull/27459)] -* core/audit: Audit logging a Vault request/response checks if the existing context -is cancelled and will now use a new context with a 5 second timeout. -If the existing context is cancelled a new context, will be used. [[GH-27531](https://github.com/hashicorp/vault/pull/27531)] -* helper/pkcs7: Fix parsing certain messages containing only certificates [[GH-27435](https://github.com/hashicorp/vault/pull/27435)] -* proxy: Fixed an issue causing excessive CPU usage during normal operation [[GH-27518](https://github.com/hashicorp/vault/pull/27518)] -* replication (enterprise): fix cache invalidation issue leading to namespace custom metadata not being shown correctly on performance secondaries -* secrets-sync (enterprise): Properly remove tags from secrets in AWS when they are removed from the source association -* secrets-sync (enterprise): Return more accurate error code for invalid connection details -* secrets-sync (enterprise): Skip invalid GitHub repository names when creating destinations -* storage/azure: Fix invalid account name initialization bug [[GH-27563](https://github.com/hashicorp/vault/pull/27563)] -* storage/raft (enterprise): Fix issue with namespace cache not getting cleared on snapshot restore, resulting in namespaces not found in the snapshot being inaccurately represented by API responses. [[GH-27474](https://github.com/hashicorp/vault/pull/27474)] -* ui: Allow creation of session_token type roles for AWS secret backend [[GH-27424](https://github.com/hashicorp/vault/pull/27424)] - -## 1.17.0 -### June 12, 2024 - -SECURITY: - -* auth/jwt: Update plugin to v0.20.3 that resolves a security issue with validing JWTs [[GH-26890](https://github.com/hashicorp/vault/pull/26890), [HCSEC-2024-11](https://discuss.hashicorp.com/t/hcsec-2024-11-vault-incorrectly-validated-json-web-tokens-jwt-audience-claims/67770)] - -CHANGES: - -* api: Upgrade from github.com/go-jose/go-jose/v3 v3.0.3 to github.com/go-jose/go-jose/v4 v4.0.1. [[GH-26527](https://github.com/hashicorp/vault/pull/26527)] -* audit: breaking change - Vault now allows audit logs to contain 'correlation-id' and 'x-correlation-id' headers when they -are present in the incoming request. By default they are not HMAC'ed (but can be configured to HMAC by Vault Operators). [[GH-26777](https://github.com/hashicorp/vault/pull/26777)] -* auth/alicloud: Update plugin to v0.18.0 [[GH-27133](https://github.com/hashicorp/vault/pull/27133)] -* auth/azure: Update plugin to v0.18.0 [[GH-27146](https://github.com/hashicorp/vault/pull/27146)] -* auth/centrify: Remove the deprecated Centrify auth method plugin [[GH-27130](https://github.com/hashicorp/vault/pull/27130)] -* auth/cf: Update plugin to v0.17.0 [[GH-27161](https://github.com/hashicorp/vault/pull/27161)] -* auth/gcp: Update plugin to v0.18.0 [[GH-27140](https://github.com/hashicorp/vault/pull/27140)] -* auth/jwt: Update plugin to v0.20.2 [[GH-26291](https://github.com/hashicorp/vault/pull/26291)] -* auth/kerberos: Update plugin to v0.12.0 [[GH-27177](https://github.com/hashicorp/vault/pull/27177)] -* auth/kubernetes: Update plugin to v0.19.0 [[GH-27186](https://github.com/hashicorp/vault/pull/27186)] -* auth/oci: Update plugin to v0.16.0 [[GH-27142](https://github.com/hashicorp/vault/pull/27142)] -* core (enterprise): Seal High Availability (HA) must be enabled by `enable_multiseal` in configuration. -* core/identity: improve performance for secondary nodes receiving identity related updates through replication [[GH-27184](https://github.com/hashicorp/vault/pull/27184)] -* core: Bump Go version to 1.22.4 -* core: return an additional "invalid token" error message in 403 response when the provided request token is expired, -exceeded the number of uses, or is a bogus value [[GH-25953](https://github.com/hashicorp/vault/pull/25953)] -* database/couchbase: Update plugin to v0.11.0 [[GH-27145](https://github.com/hashicorp/vault/pull/27145)] -* database/elasticsearch: Update plugin to v0.15.0 [[GH-27136](https://github.com/hashicorp/vault/pull/27136)] -* database/mongodbatlas: Update plugin to v0.12.0 [[GH-27143](https://github.com/hashicorp/vault/pull/27143)] -* database/redis-elasticache: Update plugin to v0.4.0 [[GH-27139](https://github.com/hashicorp/vault/pull/27139)] -* database/redis: Update plugin to v0.3.0 [[GH-27117](https://github.com/hashicorp/vault/pull/27117)] -* database/snowflake: Update plugin to v0.11.0 [[GH-27132](https://github.com/hashicorp/vault/pull/27132)] -* sdk: String templates now have a maximum size of 100,000 characters. [[GH-26110](https://github.com/hashicorp/vault/pull/26110)] -* secrets/ad: Update plugin to v0.18.0 [[GH-27172](https://github.com/hashicorp/vault/pull/27172)] -* secrets/alicloud: Update plugin to v0.17.0 [[GH-27134](https://github.com/hashicorp/vault/pull/27134)] -* secrets/azure: Update plugin to v0.17.1 [[GH-26528](https://github.com/hashicorp/vault/pull/26528)] -* secrets/azure: Update plugin to v0.19.0 [[GH-27141](https://github.com/hashicorp/vault/pull/27141)] -* secrets/gcp: Update plugin to v0.19.0 [[GH-27164](https://github.com/hashicorp/vault/pull/27164)] -* secrets/gcpkms: Update plugin to v0.17.0 [[GH-27163](https://github.com/hashicorp/vault/pull/27163)] -* secrets/keymgmt (enterprise): Removed `namespace` label on the `vault.kmse.key.count` metric. -* secrets/kmip (enterprise): Update plugin to v0.15.0 -* secrets/kubernetes: Update plugin to v0.8.0 [[GH-27187](https://github.com/hashicorp/vault/pull/27187)] -* secrets/kv: Update plugin to v0.18.0 [[GH-26877](https://github.com/hashicorp/vault/pull/26877)] -* secrets/kv: Update plugin to v0.19.0 [[GH-27159](https://github.com/hashicorp/vault/pull/27159)] -* secrets/mongodbatlas: Update plugin to v0.12.0 [[GH-27149](https://github.com/hashicorp/vault/pull/27149)] -* secrets/openldap: Update plugin to v0.13.0 [[GH-27137](https://github.com/hashicorp/vault/pull/27137)] -* secrets/pki: sign-intermediate API will truncate notAfter if calculated to go beyond the signing issuer's notAfter. Previously the notAfter was permitted to go beyond leading to invalid chains. [[GH-26796](https://github.com/hashicorp/vault/pull/26796)] -* secrets/terraform: Update plugin to v0.8.0 [[GH-27147](https://github.com/hashicorp/vault/pull/27147)] -* ui/kubernetes: Update the roles filter-input to use explicit search. [[GH-27178](https://github.com/hashicorp/vault/pull/27178)] -* ui: Update dependencies including D3 libraries [[GH-26346](https://github.com/hashicorp/vault/pull/26346)] -* ui: Upgrade Ember data from 4.11.3 to 4.12.4 [[GH-25272](https://github.com/hashicorp/vault/pull/25272)] -* ui: Upgrade Ember to version 5.4 [[GH-26708](https://github.com/hashicorp/vault/pull/26708)] -* ui: deleting a nested secret will no longer redirect you to the nearest path segment [[GH-26845](https://github.com/hashicorp/vault/pull/26845)] -* ui: flash messages render on right side of page [[GH-25459](https://github.com/hashicorp/vault/pull/25459)] - -FEATURES: - -* **PKI Certificate Metadata (enterprise)**: Add Certificate Metadata Functionality to Record and Return Client Information about a Certificate. -* **Adaptive Overload Protection (enterprise)**: Adds Adaptive Overload Protection -for write requests as a Beta feature (disabled by default). This automatically -prevents overloads caused by too many write requests while maintaining optimal -throughput for the hardware configuration and workload. -* **Audit Filtering (enterprise)** : Audit devices support expression-based filter rules (powered by go-bexpr) to determine which entries are written to the audit log. -* **LDAP Secrets engine hierarchical path support**: Hierarchical path handling is now supported for role and set APIs. [[GH-27203](https://github.com/hashicorp/vault/pull/27203)] -* **Plugin Identity Tokens**: Adds secret-less configuration of AWS auth engine using web identity federation. [[GH-26507](https://github.com/hashicorp/vault/pull/26507)] -* **Plugin Workload Identity** (enterprise): Vault can generate identity tokens for plugins to use in workload identity federation auth flows. -* **Transit AES-CMAC (enterprise)**: Added support to create and verify AES backed cipher-based message authentication codes - -IMPROVEMENTS: - -* activity (enterprise): Change minimum retention window in activity log to 48 months -* agent: Added a new config option, `lease_renewal_threshold`, that controls the refresh rate of non-renewable leases in Agent's template engine. [[GH-25212](https://github.com/hashicorp/vault/pull/25212)] -* agent: Agent will re-trigger auto auth if token used for rendering templates has been revoked, has exceeded the number of uses, or is a bogus value. [[GH-26172](https://github.com/hashicorp/vault/pull/26172)] -* api: Move CLI token helper functions to importable packages in `api` module. [[GH-25744](https://github.com/hashicorp/vault/pull/25744)] -* audit: timestamps across multiple audit devices for an audit entry will now match. [[GH-26088](https://github.com/hashicorp/vault/pull/26088)] -* auth/aws: Add inferred_hostname metadata for IAM AWS authentication method. [[GH-25418](https://github.com/hashicorp/vault/pull/25418)] -* auth/aws: add canonical ARN as entity alias option [[GH-22460](https://github.com/hashicorp/vault/pull/22460)] -* auth/aws: add support for external_ids in AWS assume-role [[GH-26628](https://github.com/hashicorp/vault/pull/26628)] -* auth/cert: Adds support for TLS certificate authenticaion through a reverse proxy that terminates the SSL connection [[GH-17272](https://github.com/hashicorp/vault/pull/17272)] -* cli: Add events subscriptions commands -* command/server: Removed environment variable requirement to generate pprof -files using SIGUSR2. Added CPU profile support. [[GH-25391](https://github.com/hashicorp/vault/pull/25391)] -* core (enterprise): persist seal rewrap status, so rewrap status API is consistent on secondary nodes. -* core/activity: Include ACME client metrics to precomputed queries [[GH-26519](https://github.com/hashicorp/vault/pull/26519)] -* core/activity: Include ACME clients in activity log responses [[GH-26020](https://github.com/hashicorp/vault/pull/26020)] -* core/activity: Include ACME clients in vault operator usage response [[GH-26525](https://github.com/hashicorp/vault/pull/26525)] -* core/config: reload service registration configuration on SIGHUP [[GH-17598](https://github.com/hashicorp/vault/pull/17598)] -* core: add deadlock detection in barrier and sealwrap -* license utilization reporting (enterprise): Add retention months to license utilization reports. -* proxy/cache (enterprise): Support new configuration parameter for static secret caching, `static_secret_token_capability_refresh_behavior`, to control the behavior when the capability refresh request receives an error from Vault. -* proxy: Proxy will re-trigger auto auth if the token used for requests has been revoked, has exceeded the number of uses, -or is an otherwise invalid value. [[GH-26307](https://github.com/hashicorp/vault/pull/26307)] -* raft/snapshotagent (enterprise): upgrade raft-snapshotagent to v0.0.0-20221104090112-13395acd02c5 -* replication (enterprise): Add replication heartbeat metric to telemetry -* replication (enterprise): Periodically write current time on the primary to storage, use that downstream to measure replication lag in time, expose that in health and replication status endpoints. [[GH-26406](https://github.com/hashicorp/vault/pull/26406)] -* sdk/decompression: DecompressWithCanary will now chunk the decompression in memory to prevent loading it all at once. [[GH-26464](https://github.com/hashicorp/vault/pull/26464)] -* sdk/helper/testcluster: add some new helpers, improve some error messages. [[GH-25329](https://github.com/hashicorp/vault/pull/25329)] -* sdk/helper/testhelpers: add namespace helpers [[GH-25270](https://github.com/hashicorp/vault/pull/25270)] -* secrets-sync (enterprise): Added global config path to the administrative namespace. -* secrets/pki (enterprise): Disable warnings about unknown parameters to the various CIEPS endpoints -* secrets/pki: Add a new ACME configuration parameter that allows increasing the maximum TTL for ACME leaf certificates [[GH-26797](https://github.com/hashicorp/vault/pull/26797)] -* secrets/transform (enterprise): Add delete by token and delete by plaintext operations to Tokenization. -* storage/azure: Perform validation on Azure account name and container name [[GH-26135](https://github.com/hashicorp/vault/pull/26135)] -* storage/raft (enterprise): add support for separate entry size limit for mount -and namespace table paths in storage to allow increased mount table size without -allowing other user storage entries to become larger. [[GH-25992](https://github.com/hashicorp/vault/pull/25992)] -* storage/raft: panic on unknown Raft operations [[GH-25991](https://github.com/hashicorp/vault/pull/25991)] -* ui (enterprise): Allow HVD users to access Secrets Sync. [[GH-26841](https://github.com/hashicorp/vault/pull/26841)] -* ui (enterprise): Update dashboard to make activity log query using the same start time as the metrics overview [[GH-26729](https://github.com/hashicorp/vault/pull/26729)] -* ui (enterprise): Update filters on the custom messages list view. [[GH-26653](https://github.com/hashicorp/vault/pull/26653)] -* ui: Allow users to wrap inputted data again instead of resetting form [[GH-27289](https://github.com/hashicorp/vault/pull/27289)] -* ui: Display ACME clients on a separate page in the UI. [[GH-26020](https://github.com/hashicorp/vault/pull/26020)] -* ui: Hide dashboard client count card if user does not have permission to view clients. [[GH-26848](https://github.com/hashicorp/vault/pull/26848)] -* ui: Show computed values from `sys/internal/ui/mounts` endpoint for auth mount configuration view [[GH-26663](https://github.com/hashicorp/vault/pull/26663)] -* ui: Update PGP display and show error for Generate Operation Token flow with PGP [[GH-26993](https://github.com/hashicorp/vault/pull/26993)] -* ui: Update language in Transit secret engine to reflect that not all keys are for encyryption [[GH-27346](https://github.com/hashicorp/vault/pull/27346)] -* ui: Update userpass user form to allow setting `password_hash` field. [[GH-26577](https://github.com/hashicorp/vault/pull/26577)] -* ui: fixes cases where inputs did not have associated labels [[GH-26263](https://github.com/hashicorp/vault/pull/26263)] -* ui: show banner instead of permission denied error when batch token is expired [[GH-26396](https://github.com/hashicorp/vault/pull/26396)] -* website/docs: Add note about eventual consietency with the MongoDB Atlas database secrets engine [[GH-24152](https://github.com/hashicorp/vault/pull/24152)] - -DEPRECATIONS: - -* Request Limiter Beta(enterprise): This Beta feature added in 1.16 has been -superseded by Adaptive Overload Protection and will be removed. -* secrets/azure: Deprecate field "password_policy" as we are not able to set it anymore with the new MS Graph API. [[GH-25637](https://github.com/hashicorp/vault/pull/25637)] - -BUG FIXES: - -* activity (enterprise): fix read-only storage error on upgrades -* agent: Correctly constructs kv-v2 secret paths in nested namespaces. [[GH-26863](https://github.com/hashicorp/vault/pull/26863)] -* agent: Fixes a high Vault load issue, by restarting the Conusl template server after backing off instead of immediately. [[GH-25497](https://github.com/hashicorp/vault/pull/25497)] -* agent: `vault.namespace` no longer gets incorrectly overridden by `auto_auth.namespace`, if set [[GH-26427](https://github.com/hashicorp/vault/pull/26427)] -* api: fixed a bug where LifetimeWatcher routines weren't respecting exponential backoff in the presence of unexpected errors [[GH-26383](https://github.com/hashicorp/vault/pull/26383)] -* audit: Operator changes to configured audit headers (via `/sys/config/auditing`) -will now force invalidation and be reloaded from storage when data is replicated -to other nodes. -* auth/ldap: Fix login error for group search anonymous bind. [[GH-26200](https://github.com/hashicorp/vault/pull/26200)] -* auth/ldap: Fix login error missing entity alias attribute value. [[GH-26200](https://github.com/hashicorp/vault/pull/26200)] -* auto-auth: Addressed issue where having no permissions to renew a renewable token caused auto-auth to attempt to renew constantly with no backoff [[GH-26844](https://github.com/hashicorp/vault/pull/26844)] -* cli/debug: Fix resource leak in CLI debug command. [[GH-26167](https://github.com/hashicorp/vault/pull/26167)] -* cli: fixed a bug where the Vault CLI would error out if -HOME was not set. [[GH-26243](https://github.com/hashicorp/vault/pull/26243)] -* core (enterprise): Fix 403s returned when forwarding invalid token to active node from secondary. -* core (enterprise): Fix an issue that prevented the seal re-wrap status from reporting that a re-wrap is in progress for up to a second. -* core (enterprise): fix bug where raft followers disagree with the seal type after returning to one seal from two. [[GH-26523](https://github.com/hashicorp/vault/pull/26523)] -* core (enterprise): fix issue where the Seal HA rewrap system may remain running when an active node steps down. -* core/audit: Audit logging a Vault request/response will now use a minimum 5 second context timeout. -If the existing context deadline occurs later than 5s in the future, it will be used, otherwise a -new context, separate from the original will be used. [[GH-26616](https://github.com/hashicorp/vault/pull/26616)] -* core/metrics: store cluster name in unencrypted storage to prevent blank cluster name [[GH-26878](https://github.com/hashicorp/vault/pull/26878)] -* core/namespace (enterprise): Privileged namespace paths provided in the `administrative_namespace_path` config will now be canonicalized. -* core/seal: During a seal reload through SIGHUP, only write updated seal barrier on an active node [[GH-26381](https://github.com/hashicorp/vault/pull/26381)] -* core/seal: allow overriding of VAULT_GCPCKMS_SEAL_KEY_RING and VAULT_GCPCKMS_SEAL_CRYPTO_KEY environment keys in seal-ha -* core: Add missing field delegated_auth_accessors to GET /sys/mounts/:path API response [[GH-26876](https://github.com/hashicorp/vault/pull/26876)] -* core: Address a data race updating a seal's last seen healthy time attribute [[GH-27014](https://github.com/hashicorp/vault/pull/27014)] -* core: Fix `redact_version` listener parameter being ignored for some OpenAPI related endpoints. [[GH-26607](https://github.com/hashicorp/vault/pull/26607)] -* core: Only reload seal configuration when enable_multiseal is set to true. [[GH-26166](https://github.com/hashicorp/vault/pull/26166)] -* core: when listener configuration `chroot_namespace` is active, Vault will no longer report that the configuration is invalid when Vault is sealed -* events (enterprise): Fix bug preventing subscribing and receiving events within a namepace. -* events (enterprise): Terminate WebSocket connection when token is revoked. -* openapi: Fixing approle reponse duration types [[GH-25510](https://github.com/hashicorp/vault/pull/25510)] -* openapi: added the missing migrate parameter for the unseal endpoint in vault/logical_system_paths.go [[GH-25550](https://github.com/hashicorp/vault/pull/25550)] -* pki: Fix error in cross-signing using ed25519 keys [[GH-27093](https://github.com/hashicorp/vault/pull/27093)] -* plugin/wif: fix a bug where the namespace was not set for external plugins using workload identity federation [[GH-26384](https://github.com/hashicorp/vault/pull/26384)] -* replication (enterprise): fix "given mount path is not in the same namespace as the request" error that can occur when enabling replication for the first time on a secondary cluster -* replication (enterprise): fixed data integrity issue with the processing of identity aliases causing duplicates to occur in rare cases -* router: Fix missing lock in MatchingSystemView. [[GH-25191](https://github.com/hashicorp/vault/pull/25191)] -* secret/database: Fixed race condition where database mounts may leak connections [[GH-26147](https://github.com/hashicorp/vault/pull/26147)] -* secrets-sync (enterprise): Fixed an issue with syncing to target projects in GCP -* secrets/azure: Update vault-plugin-secrets-azure to 0.17.2 to include a bug fix for azure role creation [[GH-26896](https://github.com/hashicorp/vault/pull/26896)] -* secrets/pki (enterprise): cert_role parameter within authenticators.cert EST configuration handler could not be set -* secrets/pki: fixed validation bug which rejected ldap schemed URLs in crl_distribution_points. [[GH-26477](https://github.com/hashicorp/vault/pull/26477)] -* secrets/transform (enterprise): Fix a bug preventing the use of alternate schemas on PostgreSQL token stores. -* secrets/transit: Use 'hash_algorithm' parameter if present in HMAC verify requests. Otherwise fall back to deprecated 'algorithm' parameter. [[GH-27211](https://github.com/hashicorp/vault/pull/27211)] -* storage/raft (enterprise): Fix a bug where autopilot automated upgrades could fail due to using the wrong upgrade version -* storage/raft (enterprise): Fix a regression introduced in 1.15.8 that causes -autopilot to fail to discover new server versions and so not trigger an upgrade. [[GH-27277](https://github.com/hashicorp/vault/pull/27277)] -* storage/raft: prevent writes from impeding leader transfers, e.g. during automated upgrades [[GH-25390](https://github.com/hashicorp/vault/pull/25390)] -* transform (enterprise): guard against a panic looking up a token in exportable mode with barrier storage. -* ui: Do not show resultant-ACL banner when ancestor namespace grants wildcard access. [[GH-27263](https://github.com/hashicorp/vault/pull/27263)] -* ui: Fix KVv2 cursor jumping inside json editor after initial input. [[GH-27120](https://github.com/hashicorp/vault/pull/27120)] -* ui: Fix KVv2 json editor to allow null values. [[GH-27094](https://github.com/hashicorp/vault/pull/27094)] -* ui: Fix a bug where disabling TTL on the AWS credential form would still send TTL value [[GH-27366](https://github.com/hashicorp/vault/pull/27366)] -* ui: Fix broken help link in console for the web command. [[GH-26858](https://github.com/hashicorp/vault/pull/26858)] -* ui: Fix configuration link from Secret Engine list view for Ember engines. [[GH-27131](https://github.com/hashicorp/vault/pull/27131)] -* ui: Fix link to v2 generic secrets engine from secrets list page. [[GH-27019](https://github.com/hashicorp/vault/pull/27019)] -* ui: Prevent perpetual loading screen when Vault needs initialization [[GH-26985](https://github.com/hashicorp/vault/pull/26985)] -* ui: Refresh model within a namespace on the Secrets Sync overview page. [[GH-26790](https://github.com/hashicorp/vault/pull/26790)] -* ui: Remove possibility of returning an undefined timezone from date-format helper [[GH-26693](https://github.com/hashicorp/vault/pull/26693)] -* ui: Resolved accessibility issues with Web REPL. Associated label and help text with input, added a conditional to show the console/ui-panel only when toggled open, added keyboard focus trap. [[GH-26872](https://github.com/hashicorp/vault/pull/26872)] -* ui: fix issue where a month without new clients breaks the client count dashboard [[GH-27352](https://github.com/hashicorp/vault/pull/27352)] -* ui: fixed a bug where the replication pages did not update display when navigating between DR and performance [[GH-26325](https://github.com/hashicorp/vault/pull/26325)] -* ui: fixes undefined start time in filename for downloaded client count attribution csv [[GH-26485](https://github.com/hashicorp/vault/pull/26485)] - -## 1.16.10 Enterprise -### September 25, 2024 - -**Enterprise LTS:** Vault Enterprise 1.16 is a [Long-Term Support (LTS)](https://developer.hashicorp.com/vault/docs/enterprise/lts) release. - -CHANGES: - -* core: Bump Go version to 1.22.7. -* secrets/ssh: Add a flag, `allow_empty_principals` to allow keys or certs to apply to any user/principal. [[GH-28466](https://github.com/hashicorp/vault/pull/28466)] - -IMPROVEMENTS: - -* audit: Internal implementation changes to the audit subsystem which improve relability. [[GH-28286](https://github.com/hashicorp/vault/pull/28286)] -* ui: Remove deprecated `current_billing_period` from dashboard activity log request [[GH-27559](https://github.com/hashicorp/vault/pull/27559)] - -BUG FIXES: - -* auth/aws: Fixed potential panic after step-down and the queue has not repopulated. [[GH-28330](https://github.com/hashicorp/vault/pull/28330)] -* auth/cert: During certificate validation, OCSP requests are debug logged even if Vault's log level is above DEBUG. [[GH-28450](https://github.com/hashicorp/vault/pull/28450)] -* auth/cert: ocsp_ca_certificates field was not honored when validating OCSP responses signed by a CA that did not issue the certificate. [[GH-28309](https://github.com/hashicorp/vault/pull/28309)] -* auth: Updated error handling for missing login credentials in AppRole and UserPass auth methods to return a 400 error instead of a 500 error. [[GH-28441](https://github.com/hashicorp/vault/pull/28441)] -* core: Fixed an issue where maximum request duration timeout was not being added to all requests containing strings sys/monitor and sys/events. With this change, timeout is now added to all requests except monitor and events endpoint. [[GH-28230](https://github.com/hashicorp/vault/pull/28230)] -* proxy/cache (enterprise): Fixed a data race that could occur while tracking capabilities in Proxy's static secret cache. [[GH-28494](https://github.com/hashicorp/vault/pull/28494)] -* secrets-sync (enterprise): Validate corresponding GitHub app parameters `app_name` and `installation_id` are set - -## 1.16.9 Enterprise -### August 30, 2024 - -**Enterprise LTS:** Vault Enterprise 1.16 is a [Long-Term Support (LTS)](https://developer.hashicorp.com/vault/docs/enterprise/lts) release. - -SECURITY: - -core/audit: fix regression where client tokens and token accessors were being -displayed in the audit log in plaintext [HCSEC-2024-18](https://discuss.hashicorp.com/t/hcsec-2024-18-vault-leaks-client-token-and-token-accessor-in-audit-devices) - -BUG FIXES: - -* proxy/cache (enterprise): Fixed an issue where Proxy with static secret caching enabled would not correctly handle requests to older secret versions for KVv2 secrets. Proxy's static secret cache now properly handles all requests relating to older versions for KVv2 secrets. [[GH-28207](https://github.com/hashicorp/vault/pull/28207)] -## 1.16.8 Enterprise -### August 29, 2024 - -**Enterprise LTS:** Vault Enterprise 1.16 is a [Long-Term Support (LTS)](https://developer.hashicorp.com/vault/docs/enterprise/lts) release. - -CHANGES: - -* activity (enterprise): filter all fields in client count responses by the request namespace [[GH-27790](https://github.com/hashicorp/vault/pull/27790)] -* core: Bump Go version to 1.22.6 - -IMPROVEMENTS: - -* activity log: Changes how new client counts in the current month are estimated, in order to return more -visibly sensible totals. [[GH-27547](https://github.com/hashicorp/vault/pull/27547)] -* activity: `/sys/internal/counters/activity` will now include a warning if the specified usage period contains estimated client counts. [[GH-28068](https://github.com/hashicorp/vault/pull/28068)] -* audit: Adds TRACE logging to log request/response under certain circumstances, and further improvements to the audit subsystem. [[GH-28056](https://github.com/hashicorp/vault/pull/28056)] -* cli: `vault operator usage` will now include a warning if the specified usage period contains estimated client counts. [[GH-28068](https://github.com/hashicorp/vault/pull/28068)] -* core/activity: Ensure client count queries that include the current month return consistent results by sorting the clients before performing estimation [[GH-28062](https://github.com/hashicorp/vault/pull/28062)] - -BUG FIXES: - -* activity: The sys/internal/counters/activity endpoint will return current month data when the end_date parameter is set to a future date. [[GH-28042](https://github.com/hashicorp/vault/pull/28042)] -* command: The `vault secrets move` and `vault auth move` command will no longer attempt to write to storage on performance standby nodes. [[GH-28059](https://github.com/hashicorp/vault/pull/28059)] -* core (enterprise): Fix deletion of MFA login-enforcement configurations on standby nodes -* secrets/database: Skip connection verification on reading existing DB connection configuration [[GH-28139](https://github.com/hashicorp/vault/pull/28139)] -* ui: fixes toast (flash) alert message saying "created" when deleting a kv v2 secret [[GH-28093](https://github.com/hashicorp/vault/pull/28093)] - -## 1.16.7 Enterprise -### August 07, 2024 - -**Enterprise LTS:** Vault Enterprise 1.16 is a [Long-Term Support (LTS)](https://developer.hashicorp.com/vault/docs/enterprise/lts) release. - -CHANGES: - -* auth/cf: Update plugin to v0.18.0 [[GH-27724](https://github.com/hashicorp/vault/pull/27724)] - -IMPROVEMENTS: - -* audit: Ensure that any underyling errors from audit devices are logged even if we consider auditing to be a success. [[GH-27809](https://github.com/hashicorp/vault/pull/27809)] -* audit: Internal implementation changes to the audit subsystem which improve performance. [[GH-27952](https://github.com/hashicorp/vault/pull/27952)] -* audit: sinks (file, socket, syslog) will attempt to log errors to the server operational -log before returning (if there are errors to log, and the context is done). [[GH-27859](https://github.com/hashicorp/vault/pull/27859)] -* auth/cert: Cache full list of role trust information separately to avoid -eviction, and avoid duplicate loading during multiple simultaneous logins on -the same role. [[GH-27902](https://github.com/hashicorp/vault/pull/27902)] -* license utilization reporting (enterprise): Auto-roll billing start date. [[GH-27656](https://github.com/hashicorp/vault/pull/27656)] - -BUG FIXES: - -* auth/cert: Use subject's serial number, not issuer's within error message text in OCSP request errors [[GH-27696](https://github.com/hashicorp/vault/pull/27696)] -* cli: Fixed issue with `vault hcp connect` where HCP resources with uppercase letters were inaccessible when entering the correct project name. [[GH-27694](https://github.com/hashicorp/vault/pull/27694)] -* core (enterprise): Fix 500 errors that occurred querying `sys/internal/ui/mounts` for a mount prefixed by a namespace path when path filters are configured. [[GH-27939](https://github.com/hashicorp/vault/pull/27939)] -* core/identity: Fixed an issue where deleted/reassigned entity-aliases were not removed from in-memory database. [[GH-27750](https://github.com/hashicorp/vault/pull/27750)] -* proxy/cache (enterprise): Fixed an issue where Proxy would not correctly update KV secrets when talking to a perf standby. Proxy will now attempt to forward requests to update secrets triggered by events to the active node. Note that this requires `allow_forwarding_via_header` to be configured on the cluster. [[GH-27891](https://github.com/hashicorp/vault/pull/27891)] -* raft/autopilot: Fixed panic that may occur during shutdown [[GH-27726](https://github.com/hashicorp/vault/pull/27726)] -* secrets-sync (enterprise): Destination set/remove operations will no longer be blocked as "purge in progress" after a purge job ended in failure. -* secrets-sync (enterprise): Normalize custom_tag keys and values for recoverable invalid characters. -* secrets-sync (enterprise): Normalize secret key names before storing the external_name in a secret association. -* secrets-sync (enterprise): Patching github sync destination credentials will properly update and save the new credentials. -* secrets-sync (enterprise): Return an error immediately on destination creation when providing invalid custom_tags based on destination type. -* secrets/identity (enterprise): Fix a bug that can cause DR promotion to fail in rare cases where a PR secondary has inconsistent alias information in storage. -* sys: Fix a bug where mounts of external plugins that were registered before Vault v1.0.0 could not be tuned to -use versioned plugins. [[GH-27881](https://github.com/hashicorp/vault/pull/27881)] -* ui: Fix cursor jump on KVv2 json editor that would occur after pressing ENTER. [[GH-27569](https://github.com/hashicorp/vault/pull/27569)] -* ui: fix issue where enabling then disabling "Tidy ACME" in PKI results in failed API call. [[GH-27742](https://github.com/hashicorp/vault/pull/27742)] -* ui: fix namespace picker not working when in small screen where the sidebar is collapsed by default. [[GH-27728](https://github.com/hashicorp/vault/pull/27728)] - - -## 1.16.6 Enterprise -### July 10, 2024 - -**Enterprise LTS:** Vault Enterprise 1.16 is a [Long-Term Support (LTS)](https://developer.hashicorp.com/vault/docs/enterprise/lts) release. - -CHANGES: - -* core: Bump Go version to 1.22.5. -* auth/jwt: Revert [GH-295](https://github.com/hashicorp/vault-plugin-auth-jwt/pull/295) which changed the way JWT `aud` claims were validated. - -BUG FIXES: - -* agent: Correctly constructs kv-v2 secret paths in nested namespaces. [[GH-26863](https://github.com/hashicorp/vault/pull/26863)] -* core (enterprise): Fix HTTP redirects in namespaces to use the correct path and (in the case of event subscriptions) the correct URI scheme. [[GH-27660](https://github.com/hashicorp/vault/pull/27660)] -* core/config: fix issue when using `proxy_protocol_behavior` with `deny_unauthorized`, -which causes the Vault TCP listener to close after receiving an untrusted upstream proxy connection. [[GH-27589](https://github.com/hashicorp/vault/pull/27589)] -* core: Fixed an issue with performance standbys not being able to handle rotate root requests. [[GH-27631](https://github.com/hashicorp/vault/pull/27631)] -* ui: Display an error and force a timeout when TOTP passcode is incorrect [[GH-27574](https://github.com/hashicorp/vault/pull/27574)] -* ui: Ensure token expired banner displays when batch token expires [[GH-27479](https://github.com/hashicorp/vault/pull/27479)] - -## 1.16.5 Enterprise -### June 26, 2024 - -**Enterprise LTS:** Vault Enterprise 1.16 is a [Long-Term Support (LTS)](https://developer.hashicorp.com/vault/docs/enterprise/lts) release. - -BUG FIXES: - -* cli/debug: Fix resource leak in CLI debug command. [[GH-26167](https://github.com/hashicorp/vault/pull/26167)] -* config: Vault TCP listener config now correctly supports the documented proxy_protocol_behavior -setting of 'deny_unauthorized' [[GH-27459](https://github.com/hashicorp/vault/pull/27459)] -* core/audit: Audit logging a Vault request/response checks if the existing context -is cancelled and will now use a new context with a 5 second timeout. -If the existing context is cancelled a new context, will be used. [[GH-27531](https://github.com/hashicorp/vault/pull/27531)] -* helper/pkcs7: Fix parsing certain messages containing only certificates [[GH-27435](https://github.com/hashicorp/vault/pull/27435)] -* replication (enterprise): fix cache invalidation issue leading to namespace custom metadata not being shown correctly on performance secondaries -* secrets-sync (enterprise): Properly remove tags from secrets in AWS when they are removed from the source association -* secrets-sync (enterprise): Return more accurate error code for invalid connection details -* secrets-sync (enterprise): Skip invalid GitHub repository names when creating destinations -* storage/raft (enterprise): Fix issue with namespace cache not getting cleared on snapshot restore, resulting in namespaces not found in the snapshot being inaccurately represented by API responses. [[GH-27474](https://github.com/hashicorp/vault/pull/27474)] -* ui: Allow creation of session_token type roles for AWS secret backend [[GH-27424](https://github.com/hashicorp/vault/pull/27424)] - -## 1.16.4 Enterprise -### June 12, 2024 - -**Enterprise LTS:** Vault Enterprise 1.16 is a [Long-Term Support (LTS)](https://developer.hashicorp.com/vault/docs/enterprise/lts) release. - -CHANGES: - -* core: Bump Go version to 1.22.4. -* ui/kubernetes: Update the roles filter-input to use explicit search. [[GH-27178](https://github.com/hashicorp/vault/pull/27178)] - -IMPROVEMENTS: - -* ui: Allow users to wrap inputted data again instead of resetting form [[GH-27289](https://github.com/hashicorp/vault/pull/27289)] -* ui: Update language in Transit secret engine to reflect that not all keys are for encyryption [[GH-27346](https://github.com/hashicorp/vault/pull/27346)] - -BUG FIXES: - -* secrets/transform (enterprise): Fix a bug preventing the use of alternate schemas on PostgreSQL token stores. -* storage/raft (enterprise): Fix a regression introduced in 1.15.8 that causes -autopilot to fail to discover new server versions and so not trigger an upgrade. [[GH-27277](https://github.com/hashicorp/vault/pull/27277)] -* ui: Do not show resultant-ACL banner when ancestor namespace grants wildcard access. [[GH-27263](https://github.com/hashicorp/vault/pull/27263)] -* ui: Fix a bug where disabling TTL on the AWS credential form would still send TTL value [[GH-27366](https://github.com/hashicorp/vault/pull/27366)] -* ui: fix issue where a month with total clients but no new clients breaks the client count dashboard [[GH-5962](https://github.com/hashicorp/vault/pull/5962)] - -## 1.16.3 -### May 30, 2024 - -**Enterprise LTS:** Vault Enterprise 1.16 is a [Long-Term Support (LTS)](https://developer.hashicorp.com/vault/docs/enterprise/lts) release. - -SECURITY: - -* auth/jwt: Update plugin to v0.20.3 that resolves a security issue with validing JWTs [[GH-26890](https://github.com/hashicorp/vault/pull/26890), [HCSEC-2024-11](https://discuss.hashicorp.com/t/hcsec-2024-11-vault-incorrectly-validated-json-web-tokens-jwt-audience-claims/67770)] - -CHANGES: - -* core/identity: improve performance for secondary nodes receiving identity related updates through replication [[GH-27184](https://github.com/hashicorp/vault/pull/27184)] -* core: Bump Go version to 1.22.2. - -IMPROVEMENTS: - -* secrets/pki (enterprise): Disable warnings about unknown parameters to the various CIEPS endpoints -* ui: Update PGP display and show error for Generate Operation Token flow with PGP [[GH-26993](https://github.com/hashicorp/vault/pull/26993)] - -BUG FIXES: - -* activity (enterprise): fix read-only storage error on upgrades -* auto-auth: Addressed issue where having no permissions to renew a renewable token caused auto-auth to attempt to renew constantly with no backoff [[GH-26844](https://github.com/hashicorp/vault/pull/26844)] -* core (enterprise): Fix an issue that prevented the seal re-wrap status from reporting that a re-wrap is in progress for up to a second. -* core/audit: Audit logging a Vault request/response will now use a minimum 5 second context timeout. -If the existing context deadline occurs later than 5s in the future, it will be used, otherwise a new context, separate from the original will be used. [[GH-26616](https://github.com/hashicorp/vault/pull/26616)] -* core: Add missing field delegated_auth_accessors to GET /sys/mounts/:path API response [[GH-26876](https://github.com/hashicorp/vault/pull/26876)] -* core: Address a data race updating a seal's last seen healthy time attribute [[GH-27014](https://github.com/hashicorp/vault/pull/27014)] -* core: Fix `redact_version` listener parameter being ignored for some OpenAPI related endpoints. [[GH-26607](https://github.com/hashicorp/vault/pull/26607)] -* events (enterprise): Fix bug preventing subscribing and receiving events within a namepace. -* pki: Fix error in cross-signing using ed25519 keys [[GH-27093](https://github.com/hashicorp/vault/pull/27093)] -* replication (enterprise): fix "given mount path is not in the same namespace as the request" error that can occur when enabling replication for the first time on a secondary cluster -* secrets-sync (enterprise): Secondary nodes in a cluster now properly check activation-flags values. -* secrets/azure: Update vault-plugin-secrets-azure to 0.17.2 to include a bug fix for azure role creation [[GH-26896](https://github.com/hashicorp/vault/pull/26896)] -* secrets/pki (enterprise): cert_role parameter within authenticators.cert EST configuration handler could not be set -* secrets/transit: Use 'hash_algorithm' parameter if present in HMAC verify requests. Otherwise fall back to deprecated 'algorithm' parameter. [[GH-27211](https://github.com/hashicorp/vault/pull/27211)] -* ui: Fix KVv2 cursor jumping inside json editor after initial input. [[GH-27120](https://github.com/hashicorp/vault/pull/27120)] -* ui: Fix KVv2 json editor to allow null values. [[GH-27094](https://github.com/hashicorp/vault/pull/27094)] -* ui: Fix broken help link in console for the web command. [[GH-26858](https://github.com/hashicorp/vault/pull/26858)] -* ui: Fix link to v2 generic secrets engine from secrets list page. [[GH-27019](https://github.com/hashicorp/vault/pull/27019)] -* ui: Prevent perpetual loading screen when Vault needs initialization [[GH-26985](https://github.com/hashicorp/vault/pull/26985)] -* ui: Refresh model within a namespace on the Secrets Sync overview page. [[GH-26790](https://github.com/hashicorp/vault/pull/26790)] - ## 1.16.2 ### April 24, 2024 @@ -1178,135 +415,6 @@ leading to failure to complete merkle sync without a full re-index. [[GH-23013]( * ui: remove user_lockout_config settings for unsupported methods [[GH-25867](https://github.com/hashicorp/vault/pull/25867)] * ui: show error from API when seal fails [[GH-23921](https://github.com/hashicorp/vault/pull/23921)] -## 1.15.15 Enterprise -### September 25, 2024 - -CHANGES: - -* core: Bump Go version to 1.22.7. -* secrets/ssh: Add a flag, `allow_empty_principals` to allow keys or certs to apply to any user/principal. [[GH-28466](https://github.com/hashicorp/vault/pull/28466)] - -BUG FIXES: - -* auth/aws: Fixed potential panic after step-down and the queue has not repopulated. [[GH-28330](https://github.com/hashicorp/vault/pull/28330)] -* auth/cert: During certificate validation, OCSP requests are debug logged even if Vault's log level is above DEBUG. [[GH-28450](https://github.com/hashicorp/vault/pull/28450)] -* auth/cert: ocsp_ca_certificates field was not honored when validating OCSP responses signed by a CA that did not issue the certificate. [[GH-28309](https://github.com/hashicorp/vault/pull/28309)] -* auth: Updated error handling for missing login credentials in AppRole and UserPass auth methods to return a 400 error instead of a 500 error. [[GH-28441](https://github.com/hashicorp/vault/pull/28441)] -* core: Fixed an issue where maximum request duration timeout was not being added to all requests containing strings sys/monitor and sys/events. With this change, timeout is now added to all requests except monitor and events endpoint. [[GH-28230](https://github.com/hashicorp/vault/pull/28230)] - -## 1.15.14 Enterprise -### August 29, 2024 - -CHANGES: - -* activity (enterprise): filter all fields in client count responses by the request namespace [[GH-27790](https://github.com/hashicorp/vault/pull/27790)] -* core: Bump Go version to 1.22.6 - -IMPROVEMENTS: - -* activity log: Changes how new client counts in the current month are estimated, in order to return more -visibly sensible totals. [[GH-27547](https://github.com/hashicorp/vault/pull/27547)] -* activity: `/sys/internal/counters/activity` will now include a warning if the specified usage period contains estimated client counts. [[GH-28068](https://github.com/hashicorp/vault/pull/28068)] -* cli: `vault operator usage` will now include a warning if the specified usage period contains estimated client counts. [[GH-28068](https://github.com/hashicorp/vault/pull/28068)] -* core/activity: Ensure client count queries that include the current month return consistent results by sorting the clients before performing estimation [[GH-28062](https://github.com/hashicorp/vault/pull/28062)] - -BUG FIXES: - -* activity: The sys/internal/counters/activity endpoint will return current month data when the end_date parameter is set to a future date. [[GH-28042](https://github.com/hashicorp/vault/pull/28042)] -* command: The `vault secrets move` and `vault auth move` command will no longer attempt to write to storage on performance standby nodes. [[GH-28059](https://github.com/hashicorp/vault/pull/28059)] -* core (enterprise): Fix deletion of MFA login-enforcement configurations on standby nodes - -## 1.15.13 Enterprise -### August 07, 2024 - -CHANGES: - -* auth/cf: Update plugin to v0.18.0 [[GH-27724](https://github.com/hashicorp/vault/pull/27724)] - -IMPROVEMENTS: - -* audit: Ensure that any underyling errors from audit devices are logged even if we consider auditing to be a success. [[GH-27809](https://github.com/hashicorp/vault/pull/27809)] -* auth/cert: Cache full list of role trust information separately to avoid -eviction, and avoid duplicate loading during multiple simultaneous logins on -the same role. [[GH-27902](https://github.com/hashicorp/vault/pull/27902)] - -BUG FIXES: - -* auth/cert: Use subject's serial number, not issuer's within error message text in OCSP request errors [[GH-27696](https://github.com/hashicorp/vault/pull/27696)] -* core (enterprise): Fix 500 errors that occurred querying `sys/internal/ui/mounts` for a mount prefixed by a namespace path when path filters are configured. [[GH-27939](https://github.com/hashicorp/vault/pull/27939)] -* raft/autopilot: Fixed panic that may occur during shutdown [[GH-27726](https://github.com/hashicorp/vault/pull/27726)] -* secrets/identity (enterprise): Fix a bug that can cause DR promotion to fail in rare cases where a PR secondary has inconsistent alias information in storage. -* ui: Fix cursor jump on KVv2 json editor that would occur after pressing ENTER. [[GH-27569](https://github.com/hashicorp/vault/pull/27569)] -* ui: fix issue where enabling then disabling "Tidy ACME" in PKI results in failed API call. [[GH-27742](https://github.com/hashicorp/vault/pull/27742)] -* ui: fix namespace picker not working when in small screen where the sidebar is collapsed by default. [[GH-27728](https://github.com/hashicorp/vault/pull/27728)] - - -## 1.15.12 Enterprise -### July 10, 2024 - -CHANGES: - -* core: Bump Go version to 1.22.5. -* auth/jwt: Revert [GH-295](https://github.com/hashicorp/vault-plugin-auth-jwt/pull/295) which changed the way JWT `aud` claims were validated. - -BUG FIXES: - -* core (enterprise): Fix HTTP redirects in namespaces to use the correct path and (in the case of event subscriptions) the correct URI scheme. [[GH-27660](https://github.com/hashicorp/vault/pull/27660)] -* core/config: fix issue when using `proxy_protocol_behavior` with `deny_unauthorized`, -which causes the Vault TCP listener to close after receiving an untrusted upstream proxy connection. [[GH-27589](https://github.com/hashicorp/vault/pull/27589)] -* core: Fixed an issue with performance standbys not being able to handle rotate root requests. [[GH-27631](https://github.com/hashicorp/vault/pull/27631)] -* ui: Display an error and force a timeout when TOTP passcode is incorrect [[GH-27574](https://github.com/hashicorp/vault/pull/27574)] -* ui: Ensure token expired banner displays when batch token expires [[GH-27479](https://github.com/hashicorp/vault/pull/27479)] - -## 1.15.11 Enterprise -### June 26, 2024 - -BUG FIXES: - -* cli/debug: Fix resource leak in CLI debug command. [[GH-26167](https://github.com/hashicorp/vault/pull/26167)] -* helper/pkcs7: Fix parsing certain messages containing only certificates [[GH-27435](https://github.com/hashicorp/vault/pull/27435)] -* replication (enterprise): fix cache invalidation issue leading to namespace custom metadata not being shown correctly on performance secondaries -* storage/raft (enterprise): Fix issue with namespace cache not getting cleared on snapshot restore, resulting in namespaces not found in the snapshot being inaccurately represented by API responses. [[GH-27474](https://github.com/hashicorp/vault/pull/27474)] - -## 1.15.10 Enterprise -### June 12, 2024 - -CHANGES: - -* core: Bump Go version to 1.22.4. - -IMPROVEMENTS: - -* ui: Allow users to wrap inputted data again instead of resetting form [[GH-27289](https://github.com/hashicorp/vault/pull/27289)] -* ui: Update language in Transit secret engine to reflect that not all keys are for encyryption [[GH-27346](https://github.com/hashicorp/vault/pull/27346)] - -BUG FIXES: - -* secrets/transform (enterprise): Fix a bug preventing the use of alternate schemas on PostgreSQL token stores. -* storage/raft (enterprise): Fix a regression introduced in 1.15.8 that causes -autopilot to fail to discover new server versions and so not trigger an upgrade. [[GH-27277](https://github.com/hashicorp/vault/pull/27277)] -* ui: Do not show resultant-ACL banner when ancestor namespace grants wildcard access. [[GH-27263](https://github.com/hashicorp/vault/pull/27263)] -* ui: Fix a bug where disabling TTL on the AWS credential form would still send TTL value [[GH-27366](https://github.com/hashicorp/vault/pull/27366)] - -## 1.15.9 Enterprise -### May 30, 2024 - -CHANGES: -* auth/jwt: Update plugin to v0.17.3 [[GH-27063](https://github.com/hashicorp/vault/pull/27063)] -* core: Bump Go version to 1.22.2. - -IMPROVEMENTS: -* secrets/pki (enterprise): Disable warnings about unknown parameters to the various CIEPS endpoints -* website/docs: Add note about eventual consietency with the MongoDB Atlas database secrets engine [[GH-24152](https://github.com/hashicorp/vault/pull/24152)] - -BUG FIXES: -* activity (enterprise): fix read-only storage error on upgrades -* core: Address a data race updating a seal's last seen healthy time attribute [[GH-27014](https://github.com/hashicorp/vault/pull/27014)] -* pki: Fix error in cross-signing using ed25519 keys [[GH-27093](https://github.com/hashicorp/vault/pull/27093)] -* replication (enterprise): fix "given mount path is not in the same namespace as the request" error that can occur when enabling replication for the first time on a secondary cluster -* secrets/transit: Use 'hash_algorithm' parameter if present in HMAC verify requests. Otherwise fall back to deprecated 'algorithm' parameter. [[GH-27211](https://github.com/hashicorp/vault/pull/27211)] -* ui: Fix KVv2 cursor jumping inside json editor after initial input. [[GH-27120](https://github.com/hashicorp/vault/pull/27120)] - ## 1.15.8 Enterprise ### April 24, 2024 @@ -1841,21 +949,6 @@ sdk/ldaputil: use EscapeLDAPValue implementation from cap/ldap [[GH-22249](https * ui: fixes model defaults overwriting input value when user tries to clear form input [[GH-22458](https://github.com/hashicorp/vault/pull/22458)] * ui: fixes text readability issue in revoke token confirmation dialog [[GH-22390](https://github.com/hashicorp/vault/pull/22390)] -## 1.14.13 Enterprise -### May 30, 2024 -CHANGES: -* auth/jwt: Update plugin to v0.16.1 [[GH-27122](https://github.com/hashicorp/vault/pull/27122)] -* core: Bump Go version to 1.22.2. - -IMPROVEMENTS: -* website/docs: Add note about eventual consietency with the MongoDB Atlas database secrets engine [[GH-24152](https://github.com/hashicorp/vault/pull/24152)] - -BUG FIXES: -* activity (enterprise): fix read-only storage error on upgrades -* pki: Fix error in cross-signing using ed25519 keys [[GH-27093](https://github.com/hashicorp/vault/pull/27093)] -* replication (enterprise): fix "given mount path is not in the same namespace as the request" error that can occur when enabling replication for the first time on a secondary cluster -* secrets/transit: Use 'hash_algorithm' parameter if present in HMAC verify requests. Otherwise fall back to deprecated 'algorithm' parameter. [[GH-27211](https://github.com/hashicorp/vault/pull/27211)] - ## 1.14.12 Enterprise ### April 24, 2024 @@ -2594,6 +1687,46 @@ BUG FIXES: * secrets/transit (enterprise): Apply hashing arguments and defaults to managed key sign/verify operations * secrets/transit: Do not allow auto rotation on managed_key key types [[GH-23723](https://github.com/hashicorp/vault/pull/23723)] +## 1.13.6 +### August 30, 2023 + +CHANGES: + +* core: Bump Go version to 1.20.7. + +IMPROVEMENTS: + +* core: Log rollback manager failures during unmount, remount to prevent replication failures on secondary clusters. [[GH-22235](https://github.com/hashicorp/vault/pull/22235)] +* replication (enterprise): Make reindex less disruptive by allowing writes during the flush phase. +* secrets/database: Improves error logging for static role rotations by including the database and role names. [[GH-22253](https://github.com/hashicorp/vault/pull/22253)] +* storage/raft: Cap the minimum dead_server_last_contact_threshold to 1m. [[GH-22040](https://github.com/hashicorp/vault/pull/22040)] +* ui: KV View Secret card will link to list view if input ends in "/" [[GH-22502](https://github.com/hashicorp/vault/pull/22502)] +* ui: enables create and update KV secret workflow when control group present [[GH-22471](https://github.com/hashicorp/vault/pull/22471)] + +BUG FIXES: + +* activity (enterprise): Fix misattribution of entities to no or child namespace auth methods [[GH-18809](https://github.com/hashicorp/vault/pull/18809)] +* api: Fix breakage with UNIX domain socket addresses introduced by newest Go versions as a security fix. [[GH-22523](https://github.com/hashicorp/vault/pull/22523)] +* core (enterprise): Remove MFA Configuration for namespace when deleting namespace +* core/quotas (enterprise): Fix a case where we were applying login roles to lease count quotas in a non-login context. +Also fix a related potential deadlock. [[GH-21110](https://github.com/hashicorp/vault/pull/21110)] +* core: Remove "expiration manager is nil on tokenstore" error log for unauth requests on DR secondary as they do not have expiration manager. [[GH-22137](https://github.com/hashicorp/vault/pull/22137)] +* core: Fix bug where background thread to update locked user entries runs on DR secondaries. [[GH-22355](https://github.com/hashicorp/vault/pull/22355)] +* core: Fix readonly errors that could occur while loading mounts/auths during unseal [[GH-22362](https://github.com/hashicorp/vault/pull/22362)] +* core: Fixed an instance where incorrect route entries would get tainted. We now pre-calculate namespace specific paths to avoid this. [[GH-21470](https://github.com/hashicorp/vault/pull/21470)] +* expiration: Fix a deadlock that could occur when a revocation failure happens while restoring leases on startup. [[GH-22374](https://github.com/hashicorp/vault/pull/22374)] +* license: Add autoloaded license path to the cache exempt list. This is to ensure the license changes on the active node is observed on the perfStandby node. [[GH-22363](https://github.com/hashicorp/vault/pull/22363)] +* replication (enterprise): Fix bug sync invalidate CoreReplicatedClusterInfoPath +* replication (enterprise): Fix panic when update-primary was called on demoted clusters using update_primary_addrs +* replication (enterprise): Fixing a bug by which the atomicity of a merkle diff result could be affected. This means it could be a source of a merkle-diff & sync process failing to switch into stream-wal mode afterwards. +* sdk/ldaputil: Properly escape user filters when using UPN domains +sdk/ldaputil: use EscapeLDAPValue implementation from cap/ldap [[GH-22249](https://github.com/hashicorp/vault/pull/22249)] +* secrets/ldap: Fix bug causing schema and password_policy to be overwritten in config. [[GH-22331](https://github.com/hashicorp/vault/pull/22331)] +* secrets/transform (enterprise): Tidy operations will be re-scheduled at a minimum of every minute, not a maximum of every minute +* ui: Fix blank page or ghost secret when canceling KV secret create [[GH-22541](https://github.com/hashicorp/vault/pull/22541)] +* ui: fixes `max_versions` default for secret metadata unintentionally overriding kv engine defaults [[GH-22394](https://github.com/hashicorp/vault/pull/22394)] +* ui: fixes model defaults overwriting input value when user tries to clear form input [[GH-22458](https://github.com/hashicorp/vault/pull/22458)] + ## 1.13.8 ### September 27, 2023 diff --git a/Makefile b/Makefile index ba499ad7407f..d3443a0e8b4d 100644 --- a/Makefile +++ b/Makefile @@ -22,12 +22,6 @@ ifneq ($(FDB_ENABLED), ) BUILD_TAGS+=foundationdb endif -# Set BUILD_MINIMAL to a non-empty value to build a minimal version of Vault with only core features. -BUILD_MINIMAL ?= -ifneq ($(strip $(BUILD_MINIMAL)),) - BUILD_TAGS+=minimal -endif - default: dev # bin generates the releasable binaries for Vault diff --git a/README.md b/README.md index 8139fa6d751a..109570940e09 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,8 @@ A modern system requires access to a multitude of secrets: database credentials, The key features of Vault are: -* **Secure Secret Storage**: Vault can store arbitrary key/value pairs. Vault encrypts data before writing it to persistent +* **Secure Secret Storage**: Arbitrary key/value secrets can be stored + in Vault. Vault encrypts these secrets prior to writing them to persistent storage, so gaining access to the raw storage isn't enough to access your secrets. Vault can write to disk, [Consul](https://www.consul.io), and more. @@ -38,8 +39,8 @@ The key features of Vault are: developers to store encrypted data in a location such as a SQL database without having to design their own encryption methods. -* **Leasing and Renewal**: Vault associates a **lease** with each secret. - At the end of the lease, Vault automatically revokes the +* **Leasing and Renewal**: All secrets in Vault have a _lease_ associated + with them. At the end of the lease, Vault will automatically revoke that secret. Clients are able to renew leases via built-in renew APIs. * **Revocation**: Vault has built-in support for secret revocation. Vault @@ -72,12 +73,9 @@ If you wish to work on Vault itself or any of its built-in systems, you'll first need [Go](https://www.golang.org) installed on your machine. For local dev first make sure Go is properly installed, including setting up a -[GOPATH](https://golang.org/doc/code.html#GOPATH), then setting the -[GOBIN](https://pkg.go.dev/cmd/go#hdr-Environment_variables) variable to `$GOPATH/bin`. -Ensure that `$GOPATH/bin` is in your path as some distributions bundle the old version -of build tools. - -Next, clone this repository. Vault uses [Go Modules](https://github.com/golang/go/wiki/Modules), +[GOPATH](https://golang.org/doc/code.html#GOPATH). Ensure that `$GOPATH/bin` is in +your path as some distributions bundle the old version of build tools. Next, clone this +repository. Vault uses [Go Modules](https://github.com/golang/go/wiki/Modules), so it is recommended that you clone the repository ***outside*** of the GOPATH. You can then download any required build tools by bootstrapping your environment: @@ -123,15 +121,6 @@ $ make test TEST=./vault ... ``` -### Troubleshooting - -If you encounter an error like `could not read Username for 'https://github.com'` you may need to adjust your git config like so: - -```sh -$ git config --global --add url."git@github.com:".insteadOf "https://github.com/" -``` - - ### Importing Vault This repository publishes two libraries that may be imported by other projects: diff --git a/api/auth/approle/LICENSE b/api/auth/approle/LICENSE deleted file mode 100644 index f4f97ee5853a..000000000000 --- a/api/auth/approle/LICENSE +++ /dev/null @@ -1,365 +0,0 @@ -Copyright (c) 2015 HashiCorp, Inc. - -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. - diff --git a/api/auth/approle/go.mod b/api/auth/approle/go.mod index 6196e6942f93..f5451d11f0b9 100644 --- a/api/auth/approle/go.mod +++ b/api/auth/approle/go.mod @@ -4,10 +4,10 @@ go 1.21 toolchain go1.22.2 -require github.com/hashicorp/vault/api v1.15.0 +require github.com/hashicorp/vault/api v1.14.0 require ( - github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cenkalti/backoff/v3 v3.0.0 // indirect github.com/go-jose/go-jose/v4 v4.0.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect diff --git a/api/auth/approle/go.sum b/api/auth/approle/go.sum index 84fd13507a68..00d28f04047b 100644 --- a/api/auth/approle/go.sum +++ b/api/auth/approle/go.sum @@ -1,7 +1,7 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= +github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -37,8 +37,8 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= 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/vault/api v1.15.0 h1:O24FYQCWwhwKnF7CuSqP30S51rTV7vz1iACXE/pj5DA= -github.com/hashicorp/vault/api v1.15.0/go.mod h1:+5YTO09JGn0u+b6ySD/LLVf8WkJCPLAL2Vkmrn2+CM8= +github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU= +github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= diff --git a/api/auth/aws/LICENSE b/api/auth/aws/LICENSE deleted file mode 100644 index f4f97ee5853a..000000000000 --- a/api/auth/aws/LICENSE +++ /dev/null @@ -1,365 +0,0 @@ -Copyright (c) 2015 HashiCorp, Inc. - -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. - diff --git a/api/auth/aws/go.mod b/api/auth/aws/go.mod index 9f0a2efdc629..507089ff649c 100644 --- a/api/auth/aws/go.mod +++ b/api/auth/aws/go.mod @@ -9,11 +9,11 @@ require ( github.com/hashicorp/go-hclog v1.6.3 github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6 github.com/hashicorp/go-uuid v1.0.2 - github.com/hashicorp/vault/api v1.15.0 + github.com/hashicorp/vault/api v1.14.0 ) require ( - github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cenkalti/backoff/v3 v3.0.0 // indirect github.com/fatih/color v1.16.0 // indirect github.com/go-jose/go-jose/v4 v4.0.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect diff --git a/api/auth/aws/go.sum b/api/auth/aws/go.sum index c03cee1af401..71ff425d86f6 100644 --- a/api/auth/aws/go.sum +++ b/api/auth/aws/go.sum @@ -3,8 +3,8 @@ github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZve github.com/aws/aws-sdk-go v1.49.22 h1:r01+cQJ3cORQI1PJxG8af0jzrZpUOL9L+/3kU2x1geU= github.com/aws/aws-sdk-go v1.49.22/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= +github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -48,8 +48,8 @@ github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2I github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 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/vault/api v1.15.0 h1:O24FYQCWwhwKnF7CuSqP30S51rTV7vz1iACXE/pj5DA= -github.com/hashicorp/vault/api v1.15.0/go.mod h1:+5YTO09JGn0u+b6ySD/LLVf8WkJCPLAL2Vkmrn2+CM8= +github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU= +github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= diff --git a/api/auth/azure/LICENSE b/api/auth/azure/LICENSE deleted file mode 100644 index f4f97ee5853a..000000000000 --- a/api/auth/azure/LICENSE +++ /dev/null @@ -1,365 +0,0 @@ -Copyright (c) 2015 HashiCorp, Inc. - -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. - diff --git a/api/auth/azure/azure.go b/api/auth/azure/azure.go index ecca535b43f0..b68219570115 100644 --- a/api/auth/azure/azure.go +++ b/api/auth/azure/azure.go @@ -7,7 +7,7 @@ import ( "context" "encoding/json" "fmt" - "io" + "io/ioutil" "net/http" "net/url" "time" @@ -175,7 +175,7 @@ func (a *AzureAuth) getJWT() (string, error) { } defer resp.Body.Close() - responseBytes, err := io.ReadAll(resp.Body) + responseBytes, err := ioutil.ReadAll(resp.Body) if err != nil { return "", fmt.Errorf("error reading response body from Azure token endpoint: %w", err) } @@ -222,7 +222,7 @@ func getMetadata() (metadataJSON, error) { } defer resp.Body.Close() - responseBytes, err := io.ReadAll(resp.Body) + responseBytes, err := ioutil.ReadAll(resp.Body) if err != nil { return metadataJSON{}, fmt.Errorf("error reading response body from metadata endpoint: %w", err) } diff --git a/api/auth/azure/go.mod b/api/auth/azure/go.mod index 5f45bcb710e1..d5c6d2856e3d 100644 --- a/api/auth/azure/go.mod +++ b/api/auth/azure/go.mod @@ -4,10 +4,10 @@ go 1.21 toolchain go1.22.2 -require github.com/hashicorp/vault/api v1.15.0 +require github.com/hashicorp/vault/api v1.14.0 require ( - github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cenkalti/backoff/v3 v3.0.0 // indirect github.com/go-jose/go-jose/v4 v4.0.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect diff --git a/api/auth/azure/go.sum b/api/auth/azure/go.sum index 84fd13507a68..00d28f04047b 100644 --- a/api/auth/azure/go.sum +++ b/api/auth/azure/go.sum @@ -1,7 +1,7 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= +github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -37,8 +37,8 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= 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/vault/api v1.15.0 h1:O24FYQCWwhwKnF7CuSqP30S51rTV7vz1iACXE/pj5DA= -github.com/hashicorp/vault/api v1.15.0/go.mod h1:+5YTO09JGn0u+b6ySD/LLVf8WkJCPLAL2Vkmrn2+CM8= +github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU= +github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= diff --git a/api/auth/gcp/LICENSE b/api/auth/gcp/LICENSE deleted file mode 100644 index f4f97ee5853a..000000000000 --- a/api/auth/gcp/LICENSE +++ /dev/null @@ -1,365 +0,0 @@ -Copyright (c) 2015 HashiCorp, Inc. - -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. - diff --git a/api/auth/gcp/gcp.go b/api/auth/gcp/gcp.go index 7f4f222c0c72..2d6ef842a4b4 100644 --- a/api/auth/gcp/gcp.go +++ b/api/auth/gcp/gcp.go @@ -7,7 +7,7 @@ import ( "context" "encoding/json" "fmt" - "io" + "io/ioutil" "net/http" "net/url" "time" @@ -181,7 +181,7 @@ func (a *GCPAuth) getJWTFromMetadataService(vaultAddress string) (string, error) defer resp.Body.Close() // get jwt from response - body, err := io.ReadAll(resp.Body) + body, err := ioutil.ReadAll(resp.Body) jwt := string(body) if err != nil { return "", fmt.Errorf("error reading response from metadata service: %w", err) diff --git a/api/auth/gcp/go.mod b/api/auth/gcp/go.mod index a1f61fa92415..1a75214a2fb7 100644 --- a/api/auth/gcp/go.mod +++ b/api/auth/gcp/go.mod @@ -7,14 +7,14 @@ toolchain go1.22.2 require ( cloud.google.com/go/compute/metadata v0.3.0 cloud.google.com/go/iam v1.1.8 - github.com/hashicorp/vault/api v1.15.0 + github.com/hashicorp/vault/api v1.14.0 google.golang.org/genproto v0.0.0-20240604185151-ef581f913117 ) require ( cloud.google.com/go/auth v0.3.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect - github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cenkalti/backoff/v3 v3.0.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-jose/go-jose/v4 v4.0.1 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/api/auth/gcp/go.sum b/api/auth/gcp/go.sum index 59fc4eb1228c..cb03d6d969c3 100644 --- a/api/auth/gcp/go.sum +++ b/api/auth/gcp/go.sum @@ -10,8 +10,8 @@ cloud.google.com/go/iam v1.1.8/go.mod h1:GvE6lyMmfxXauzNq8NbgJbeVQNspG+tcdL/W8QO github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= +github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -90,8 +90,8 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= 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/vault/api v1.15.0 h1:O24FYQCWwhwKnF7CuSqP30S51rTV7vz1iACXE/pj5DA= -github.com/hashicorp/vault/api v1.15.0/go.mod h1:+5YTO09JGn0u+b6ySD/LLVf8WkJCPLAL2Vkmrn2+CM8= +github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU= +github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= diff --git a/api/auth/kubernetes/LICENSE b/api/auth/kubernetes/LICENSE deleted file mode 100644 index f4f97ee5853a..000000000000 --- a/api/auth/kubernetes/LICENSE +++ /dev/null @@ -1,365 +0,0 @@ -Copyright (c) 2015 HashiCorp, Inc. - -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. - diff --git a/api/auth/kubernetes/go.mod b/api/auth/kubernetes/go.mod index f06c5c611ffb..0b6d1ef44675 100644 --- a/api/auth/kubernetes/go.mod +++ b/api/auth/kubernetes/go.mod @@ -4,10 +4,10 @@ go 1.21 toolchain go1.22.2 -require github.com/hashicorp/vault/api v1.15.0 +require github.com/hashicorp/vault/api v1.14.0 require ( - github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cenkalti/backoff/v3 v3.0.0 // indirect github.com/go-jose/go-jose/v4 v4.0.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect diff --git a/api/auth/kubernetes/go.sum b/api/auth/kubernetes/go.sum index 84fd13507a68..00d28f04047b 100644 --- a/api/auth/kubernetes/go.sum +++ b/api/auth/kubernetes/go.sum @@ -1,7 +1,7 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= +github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -37,8 +37,8 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= 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/vault/api v1.15.0 h1:O24FYQCWwhwKnF7CuSqP30S51rTV7vz1iACXE/pj5DA= -github.com/hashicorp/vault/api v1.15.0/go.mod h1:+5YTO09JGn0u+b6ySD/LLVf8WkJCPLAL2Vkmrn2+CM8= +github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU= +github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= diff --git a/api/auth/ldap/LICENSE b/api/auth/ldap/LICENSE deleted file mode 100644 index f4f97ee5853a..000000000000 --- a/api/auth/ldap/LICENSE +++ /dev/null @@ -1,365 +0,0 @@ -Copyright (c) 2015 HashiCorp, Inc. - -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. - diff --git a/api/auth/ldap/go.mod b/api/auth/ldap/go.mod index ba1fd3f02fb9..b97e5ad2330c 100644 --- a/api/auth/ldap/go.mod +++ b/api/auth/ldap/go.mod @@ -4,10 +4,10 @@ go 1.21 toolchain go1.22.2 -require github.com/hashicorp/vault/api v1.15.0 +require github.com/hashicorp/vault/api v1.14.0 require ( - github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cenkalti/backoff/v3 v3.0.0 // indirect github.com/go-jose/go-jose/v4 v4.0.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect diff --git a/api/auth/ldap/go.sum b/api/auth/ldap/go.sum index 84fd13507a68..00d28f04047b 100644 --- a/api/auth/ldap/go.sum +++ b/api/auth/ldap/go.sum @@ -1,7 +1,7 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= +github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -37,8 +37,8 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= 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/vault/api v1.15.0 h1:O24FYQCWwhwKnF7CuSqP30S51rTV7vz1iACXE/pj5DA= -github.com/hashicorp/vault/api v1.15.0/go.mod h1:+5YTO09JGn0u+b6ySD/LLVf8WkJCPLAL2Vkmrn2+CM8= +github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU= +github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= diff --git a/api/auth/userpass/LICENSE b/api/auth/userpass/LICENSE deleted file mode 100644 index f4f97ee5853a..000000000000 --- a/api/auth/userpass/LICENSE +++ /dev/null @@ -1,365 +0,0 @@ -Copyright (c) 2015 HashiCorp, Inc. - -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. - diff --git a/api/auth/userpass/go.mod b/api/auth/userpass/go.mod index 83d87488e41c..16cb26b3a632 100644 --- a/api/auth/userpass/go.mod +++ b/api/auth/userpass/go.mod @@ -4,10 +4,10 @@ go 1.21 toolchain go1.22.2 -require github.com/hashicorp/vault/api v1.15.0 +require github.com/hashicorp/vault/api v1.14.0 require ( - github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cenkalti/backoff/v3 v3.0.0 // indirect github.com/go-jose/go-jose/v4 v4.0.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect diff --git a/api/auth/userpass/go.sum b/api/auth/userpass/go.sum index 84fd13507a68..00d28f04047b 100644 --- a/api/auth/userpass/go.sum +++ b/api/auth/userpass/go.sum @@ -1,7 +1,7 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= +github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -37,8 +37,8 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= 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/vault/api v1.15.0 h1:O24FYQCWwhwKnF7CuSqP30S51rTV7vz1iACXE/pj5DA= -github.com/hashicorp/vault/api v1.15.0/go.mod h1:+5YTO09JGn0u+b6ySD/LLVf8WkJCPLAL2Vkmrn2+CM8= +github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU= +github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= diff --git a/api/client.go b/api/client.go index 0090321caa7f..52c991b1e2f6 100644 --- a/api/client.go +++ b/api/client.go @@ -10,7 +10,6 @@ import ( "crypto/tls" "encoding/base64" "encoding/hex" - "encoding/json" "fmt" "net" "net/http" @@ -42,7 +41,6 @@ const ( EnvVaultClientCert = "VAULT_CLIENT_CERT" EnvVaultClientKey = "VAULT_CLIENT_KEY" EnvVaultClientTimeout = "VAULT_CLIENT_TIMEOUT" - EnvVaultHeaders = "VAULT_HEADERS" EnvVaultSRVLookup = "VAULT_SRV_LOOKUP" EnvVaultSkipVerify = "VAULT_SKIP_VERIFY" EnvVaultNamespace = "VAULT_NAMESPACE" @@ -667,30 +665,6 @@ func NewClient(c *Config) (*Client, error) { client.setNamespace(namespace) } - if envHeaders := os.Getenv(EnvVaultHeaders); envHeaders != "" { - var result map[string]any - err := json.Unmarshal([]byte(envHeaders), &result) - if err != nil { - return nil, fmt.Errorf("could not unmarshal environment-supplied headers") - } - var forbiddenHeaders []string - for key, value := range result { - if strings.HasPrefix(key, "X-Vault-") { - forbiddenHeaders = append(forbiddenHeaders, key) - continue - } - - value, ok := value.(string) - if !ok { - return nil, fmt.Errorf("environment-supplied headers include non-string values") - } - client.AddHeader(key, value) - } - if len(forbiddenHeaders) > 0 { - return nil, fmt.Errorf("failed to setup Headers[%s]: Header starting by 'X-Vault-' are for internal usage only", strings.Join(forbiddenHeaders, ", ")) - } - } - return client, nil } @@ -731,7 +705,7 @@ func (c *Client) SetAddress(addr string) error { parsedAddr, err := c.config.ParseAddress(addr) if err != nil { - return fmt.Errorf("failed to set address: %w", err) + return errwrap.Wrapf("failed to set address: {{err}}", err) } c.addr = parsedAddr diff --git a/api/client_test.go b/api/client_test.go index 1ed4dfd3d359..3d75aabd6bda 100644 --- a/api/client_test.go +++ b/api/client_test.go @@ -374,61 +374,6 @@ func TestDefaulRetryPolicy(t *testing.T) { } } -func TestClientEnvHeaders(t *testing.T) { - oldHeaders := os.Getenv(EnvVaultHeaders) - - defer func() { - os.Setenv(EnvVaultHeaders, oldHeaders) - }() - - cases := []struct { - Input string - Valid bool - }{ - { - "{}", - true, - }, - { - "{\"foo\": \"bar\"}", - true, - }, - { - "{\"foo\": 1}", // Values must be strings - false, - }, - { - "{\"X-Vault-Foo\": \"bar\"}", // X-Vault-* not allowed - false, - }, - } - - for _, tc := range cases { - os.Setenv(EnvVaultHeaders, tc.Input) - config := DefaultConfig() - config.ReadEnvironment() - _, err := NewClient(config) - if err != nil { - if tc.Valid { - t.Fatalf("unexpected error reading headers from environment: %v", err) - } - } else { - if !tc.Valid { - t.Fatal("no error reading headers from environment when error was expected") - } - } - } - - os.Setenv(EnvVaultHeaders, "{\"foo\": \"bar\"}") - config := DefaultConfig() - config.ReadEnvironment() - cli, _ := NewClient(config) - - if !reflect.DeepEqual(cli.Headers().Values("foo"), []string{"bar"}) { - t.Error("Environment-supplied headers not set in CLI client") - } -} - func TestClientEnvSettings(t *testing.T) { cwd, _ := os.Getwd() diff --git a/api/go.mod b/api/go.mod index 2b273d8a06be..0971e7ee3186 100644 --- a/api/go.mod +++ b/api/go.mod @@ -10,7 +10,7 @@ go 1.21 toolchain go1.21.8 require ( - github.com/cenkalti/backoff/v4 v4.3.0 + github.com/cenkalti/backoff/v3 v3.0.0 github.com/go-jose/go-jose/v4 v4.0.1 github.com/go-test/deep v1.0.2 github.com/hashicorp/errwrap v1.1.0 diff --git a/api/go.sum b/api/go.sum index 03a463b4b439..8e7531e6dd15 100644 --- a/api/go.sum +++ b/api/go.sum @@ -1,7 +1,7 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= +github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/api/lifetime_watcher.go b/api/lifetime_watcher.go index bdb8fb64b3c9..4bc1390b93af 100644 --- a/api/lifetime_watcher.go +++ b/api/lifetime_watcher.go @@ -10,7 +10,7 @@ import ( "sync" "time" - "github.com/cenkalti/backoff/v4" + "github.com/cenkalti/backoff/v3" ) var ( diff --git a/api/request.go b/api/request.go index c0c8dea73449..a2d912c64dcf 100644 --- a/api/request.go +++ b/api/request.go @@ -7,6 +7,7 @@ import ( "bytes" "encoding/json" "io" + "io/ioutil" "net/http" "net/url" @@ -76,13 +77,13 @@ func (r *Request) ToHTTP() (*http.Request, error) { // No body case r.BodyBytes != nil: - req.Request.Body = io.NopCloser(bytes.NewReader(r.BodyBytes)) + req.Request.Body = ioutil.NopCloser(bytes.NewReader(r.BodyBytes)) default: if c, ok := r.Body.(io.ReadCloser); ok { req.Request.Body = c } else { - req.Request.Body = io.NopCloser(r.Body) + req.Request.Body = ioutil.NopCloser(r.Body) } } diff --git a/api/response.go b/api/response.go index 23246bf7165e..2842c125514a 100644 --- a/api/response.go +++ b/api/response.go @@ -8,6 +8,7 @@ import ( "encoding/json" "fmt" "io" + "io/ioutil" "net/http" ) @@ -43,7 +44,7 @@ func (r *Response) Error() error { } r.Body.Close() - r.Body = io.NopCloser(bodyBuf) + r.Body = ioutil.NopCloser(bodyBuf) ns := r.Header.Get(NamespaceHeaderName) // Build up the error object diff --git a/api/secret.go b/api/secret.go index 7df9f66a4da7..d37bf3cf06b0 100644 --- a/api/secret.go +++ b/api/secret.go @@ -159,10 +159,6 @@ TOKEN_DONE: goto DONE } - if s.Data["identity_policies"] == nil { - goto DONE - } - sList, ok := s.Data["identity_policies"].([]string) if ok { identityPolicies = sList diff --git a/api/sudo_paths.go b/api/sudo_paths.go index d458cbde0f45..24beb4bb1f2a 100644 --- a/api/sudo_paths.go +++ b/api/sudo_paths.go @@ -28,7 +28,6 @@ var sudoPaths = map[string]*regexp.Regexp{ "/sys/config/ui/headers": regexp.MustCompile(`^/sys/config/ui/headers/?$`), "/sys/config/ui/headers/{header}": regexp.MustCompile(`^/sys/config/ui/headers/.+$`), "/sys/internal/inspect/router/{tag}": regexp.MustCompile(`^/sys/internal/inspect/router/.+$`), - "/sys/internal/counters/activity/export": regexp.MustCompile(`^/sys/internal/counters/activity/export$`), "/sys/leases": regexp.MustCompile(`^/sys/leases$`), // This entry is a bit wrong... sys/leases/lookup does NOT require sudo. But sys/leases/lookup/ with a trailing // slash DOES require sudo. But the part of the Vault CLI that uses this logic doesn't pass operation-appropriate diff --git a/api/sys_raft.go b/api/sys_raft.go index f0e896271b39..699f6e9fd095 100644 --- a/api/sys_raft.go +++ b/api/sys_raft.go @@ -264,7 +264,7 @@ func (c *Sys) RaftSnapshotWithContext(ctx context.Context, snapWriter io.Writer) continue } var b []byte - b, err = io.ReadAll(t) + b, err = ioutil.ReadAll(t) if err != nil || len(b) == 0 { return } diff --git a/audit/backend.go b/audit/backend.go index 4bce4b6edb7d..49d46c8f0039 100644 --- a/audit/backend.go +++ b/audit/backend.go @@ -19,7 +19,6 @@ import ( const ( optionElideListResponses = "elide_list_responses" - optionExclude = "exclude" optionFallback = "fallback" optionFilter = "filter" optionFormat = "format" @@ -254,7 +253,6 @@ func HasInvalidOptions(options map[string]string) bool { // are only for use in the Enterprise version of Vault. func hasEnterpriseAuditOptions(options map[string]string) bool { enterpriseAuditOptions := []string{ - optionExclude, optionFallback, optionFilter, } diff --git a/audit/backend_test.go b/audit/backend_test.go index 000b827f6cc7..369ce97fc3cf 100644 --- a/audit/backend_test.go +++ b/audit/backend_test.go @@ -188,15 +188,6 @@ func TestBackend_hasEnterpriseAuditOptions(t *testing.T) { }, expected: true, }, - "ent-opt-exclude": { - input: map[string]string{ - "exclude": `{ - "condition": "\"/request/mount_type\" == transit", - "fields": [ "/request/data", "/response/data" ] - }`, - }, - expected: true, - }, } for name, tc := range tests { @@ -250,15 +241,6 @@ func TestBackend_hasInvalidAuditOptions(t *testing.T) { }, expected: !constants.IsEnterprise, }, - "ent-opt-exclude": { - input: map[string]string{ - "exclude": `{ - "condition": "\"/request/mount_type\" == transit", - "fields": [ "/request/data", "/response/data" ] - }`, - }, - expected: !constants.IsEnterprise, - }, } for name, tc := range tests { diff --git a/audit/entry_formatter.go b/audit/entry_formatter.go index 9ea6bdb92924..6ef95278df1a 100644 --- a/audit/entry_formatter.go +++ b/audit/entry_formatter.go @@ -132,17 +132,6 @@ func (f *entryFormatter) Process(ctx context.Context, e *eventlogger.Event) (_ * return nil, err } - // If this pipeline has been configured with (Enterprise-only) exclusions then - // attempt to exclude the fields from the audit entry. - if f.shouldExclude() { - m, err := f.excludeFields(entry) - if err != nil { - return nil, fmt.Errorf("unable to exclude %s audit data from %q: %w", a.Subtype, f.name, err) - } - - entry = m - } - result, err := jsonutil.EncodeJSON(entry) if err != nil { return nil, fmt.Errorf("unable to format %s: %w", a.Subtype, err) diff --git a/audit/entry_formatter_ce.go b/audit/entry_formatter_ce.go deleted file mode 100644 index 7c3f33212e69..000000000000 --- a/audit/entry_formatter_ce.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !enterprise - -package audit - -import ( - "errors" -) - -func (f *entryFormatter) shouldExclude() bool { - return false -} - -func (f *entryFormatter) excludeFields(entry any) (map[string]any, error) { - return nil, errors.New("enterprise-only feature: audit exclusion") -} diff --git a/audit/entry_formatter_ce_test.go b/audit/entry_formatter_ce_test.go deleted file mode 100644 index ffe181f4b882..000000000000 --- a/audit/entry_formatter_ce_test.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !enterprise - -package audit - -import ( - "testing" - - "github.com/hashicorp/go-hclog" - "github.com/stretchr/testify/require" -) - -// TestEntryFormatter_excludeFields tests that we can exclude data based on the -// pre-configured conditions/fields of the EntryFormatter. It covers some scenarios -// where we expect errors due to invalid input, which is unlikely to happen in reality. -func TestEntryFormatter_excludeFields(t *testing.T) { - // Create the formatter node. - cfg, err := newFormatterConfig(&testHeaderFormatter{}, nil) - require.NoError(t, err) - ss := newStaticSalt(t) - - // We intentionally create the EntryFormatter manually, as we wouldn't be - // able to set exclusions via NewEntryFormatter WithExclusions option. - formatter := &entryFormatter{ - config: cfg, - salter: ss, - logger: hclog.NewNullLogger(), - name: "juan", - } - - res, err := formatter.excludeFields(nil) - require.Error(t, err) - require.EqualError(t, err, "enterprise-only feature: audit exclusion") - require.Nil(t, res) -} diff --git a/audit/entry_formatter_config.go b/audit/entry_formatter_config.go index aa55a2ea2d2b..899dc17a736d 100644 --- a/audit/entry_formatter_config.go +++ b/audit/entry_formatter_config.go @@ -12,8 +12,6 @@ import ( // formatterConfig is used to provide basic configuration to a formatter. // Use newFormatterConfig to initialize the formatterConfig struct. type formatterConfig struct { - formatterConfigEnt - raw bool hmacAccessor bool @@ -103,13 +101,7 @@ func newFormatterConfig(headerFormatter HeaderFormatter, config map[string]strin return formatterConfig{}, err } - fmtCfgEnt, err := newFormatterConfigEnt(config) - if err != nil { - return formatterConfig{}, err - } - return formatterConfig{ - formatterConfigEnt: fmtCfgEnt, headerFormatter: headerFormatter, elideListResponses: opts.withElision, hmacAccessor: opts.withHMACAccessor, diff --git a/audit/entry_formatter_config_ce.go b/audit/entry_formatter_config_ce.go deleted file mode 100644 index 43b7307f4d71..000000000000 --- a/audit/entry_formatter_config_ce.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !enterprise - -package audit - -// formatterConfigEnt provides extensions to a formatterConfig which behave differently -// for Enterprise and community edition. -// NOTE: Use newFormatterConfigEnt to initialize the formatterConfigEnt struct. -type formatterConfigEnt struct{} - -// newFormatterConfigEnt should be used to create formatterConfigEnt. -func newFormatterConfigEnt(config map[string]string) (formatterConfigEnt, error) { - return formatterConfigEnt{}, nil -} diff --git a/builtin/credential/aws/backend_test.go b/builtin/credential/aws/backend_test.go index 5770b2c5ed36..771dc0e31140 100644 --- a/builtin/credential/aws/backend_test.go +++ b/builtin/credential/aws/backend_test.go @@ -8,7 +8,7 @@ import ( "encoding/base64" "encoding/json" "fmt" - "io" + "io/ioutil" "net/http" "os" "strings" @@ -1516,7 +1516,7 @@ func buildCallerIdentityLoginData(request *http.Request, roleName string) (map[s if err != nil { return nil, err } - requestBody, err := io.ReadAll(request.Body) + requestBody, err := ioutil.ReadAll(request.Body) if err != nil { return nil, err } diff --git a/builtin/credential/aws/client.go b/builtin/credential/aws/client.go index d06900b9f123..5931984ca743 100644 --- a/builtin/credential/aws/client.go +++ b/builtin/credential/aws/client.go @@ -9,8 +9,9 @@ import ( "strconv" "time" - "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" + + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials/stscreds" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" diff --git a/builtin/credential/aws/path_login.go b/builtin/credential/aws/path_login.go index fdb37da72b22..a0e5a96505ce 100644 --- a/builtin/credential/aws/path_login.go +++ b/builtin/credential/aws/path_login.go @@ -12,7 +12,7 @@ import ( "encoding/xml" "errors" "fmt" - "io" + "io/ioutil" "net/http" "net/url" "regexp" @@ -1803,7 +1803,7 @@ func submitCallerIdentityRequest(ctx context.Context, maxRetries int, method, en } // we check for status code afterwards to also print out response body - responseBody, err := io.ReadAll(response.Body) + responseBody, err := ioutil.ReadAll(response.Body) if err != nil { return nil, err } diff --git a/builtin/credential/cert/backend_test.go b/builtin/credential/cert/backend_test.go index e4affa3b5296..6260c368e8c0 100644 --- a/builtin/credential/cert/backend_test.go +++ b/builtin/credential/cert/backend_test.go @@ -843,7 +843,7 @@ func TestBackend_NonCAExpiry(t *testing.T) { time.Sleep(5 * time.Second) // Login attempt after certificate expiry should fail - _, err = b.HandleRequest(context.Background(), loginReq) + resp, err = b.HandleRequest(context.Background(), loginReq) if err == nil { t.Fatalf("expected error due to expired certificate") } @@ -2178,13 +2178,12 @@ func Test_Renew(t *testing.T) { Raw: map[string]interface{}{ "name": "test", "certificate": ca, - // Uppercase B should not cause an issue during renewal - "token_policies": "foo,Bar", + "policies": "foo,bar", }, Schema: pathCerts(b).Fields, } - _, err = b.pathCertWrite(context.Background(), req, fd) + resp, err := b.pathCertWrite(context.Background(), req, fd) if err != nil { t.Fatal(err) } @@ -2193,7 +2192,7 @@ func Test_Renew(t *testing.T) { Raw: map[string]interface{}{}, Schema: pathLogin(b).Fields, } - resp, err := b.pathLogin(context.Background(), req, empty_login_fd) + resp, err = b.pathLogin(context.Background(), req, empty_login_fd) if err != nil { t.Fatal(err) } @@ -2220,20 +2219,20 @@ func Test_Renew(t *testing.T) { } // Change the policies -- this should fail - fd.Raw["token_policies"] = "zip,zap" - _, err = b.pathCertWrite(context.Background(), req, fd) + fd.Raw["policies"] = "zip,zap" + resp, err = b.pathCertWrite(context.Background(), req, fd) if err != nil { t.Fatal(err) } - _, err = b.pathLoginRenew(context.Background(), req, empty_login_fd) + resp, err = b.pathLoginRenew(context.Background(), req, empty_login_fd) if err == nil { t.Fatal("expected error") } // Put the policies back, this should be okay - fd.Raw["token_policies"] = "bar,foo" - _, err = b.pathCertWrite(context.Background(), req, fd) + fd.Raw["policies"] = "bar,foo" + resp, err = b.pathCertWrite(context.Background(), req, fd) if err != nil { t.Fatal(err) } @@ -2252,7 +2251,7 @@ func Test_Renew(t *testing.T) { // Add period value to cert entry period := 350 * time.Second fd.Raw["period"] = period.String() - _, err = b.pathCertWrite(context.Background(), req, fd) + resp, err = b.pathCertWrite(context.Background(), req, fd) if err != nil { t.Fatal(err) } @@ -2273,7 +2272,7 @@ func Test_Renew(t *testing.T) { } // Delete CA, make sure we can't renew - _, err = b.pathCertDelete(context.Background(), req, fd) + resp, err = b.pathCertDelete(context.Background(), req, fd) if err != nil { t.Fatal(err) } diff --git a/builtin/credential/cert/path_login.go b/builtin/credential/cert/path_login.go index 53571b26185e..bf914d7baa8a 100644 --- a/builtin/credential/cert/path_login.go +++ b/builtin/credential/cert/path_login.go @@ -17,12 +17,13 @@ import ( "net/url" "strings" + "github.com/hashicorp/vault/sdk/helper/locksutil" + "github.com/hashicorp/errwrap" "github.com/hashicorp/go-multierror" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/helper/certutil" "github.com/hashicorp/vault/sdk/helper/cidrutil" - "github.com/hashicorp/vault/sdk/helper/locksutil" "github.com/hashicorp/vault/sdk/helper/ocsp" "github.com/hashicorp/vault/sdk/helper/policyutil" "github.com/hashicorp/vault/sdk/logical" @@ -35,8 +36,6 @@ type ParsedCert struct { Certificates []*x509.Certificate } -const certAuthFailMsg = "failed to match all constraints for this login certificate" - func pathLogin(b *backend) *framework.Path { return &framework.Path{ Pattern: "login", @@ -315,11 +314,10 @@ func (b *backend) verifyCredentials(ctx context.Context, req *logical.Request, d // If no trusted chain was found, client is not authenticated // This check happens after checking for a matching configured non-CA certs if len(trustedChains) == 0 { - if retErr != nil { - return nil, logical.ErrorResponse(fmt.Sprintf("%s; additionally got errors during verification: %v", certAuthFailMsg, retErr)), nil + if retErr == nil { + return nil, logical.ErrorResponse(fmt.Sprintf("invalid certificate or no client certificate supplied; additionally got errors during verification: %v", retErr)), nil } - - return nil, logical.ErrorResponse(certAuthFailMsg), nil + return nil, logical.ErrorResponse("invalid certificate or no client certificate supplied"), nil } // Search for a ParsedCert that intersects with the validated chains and any additional constraints @@ -354,10 +352,10 @@ func (b *backend) verifyCredentials(ctx context.Context, req *logical.Request, d } if retErr != nil { - return nil, logical.ErrorResponse(fmt.Sprintf("%s; additionally got errors during verification: %v", certAuthFailMsg, retErr)), nil + return nil, logical.ErrorResponse(fmt.Sprintf("no chain matching all constraints could be found for this login certificate; additionally got errors during verification: %v", retErr)), nil } - return nil, logical.ErrorResponse(certAuthFailMsg), nil + return nil, logical.ErrorResponse("no chain matching all constraints could be found for this login certificate"), nil } func (b *backend) matchesConstraints(ctx context.Context, clientCert *x509.Certificate, trustedChain []*x509.Certificate, diff --git a/builtin/credential/cert/path_login_test.go b/builtin/credential/cert/path_login_test.go index ad1030464f35..84e7c55f88e2 100644 --- a/builtin/credential/cert/path_login_test.go +++ b/builtin/credential/cert/path_login_test.go @@ -203,7 +203,7 @@ func testAccStepResolveRoleExpectRoleResolutionToFail(t *testing.T, connState tl t.Fatal("Error not part of response.") } - if !strings.Contains(errString, certAuthFailMsg) { + if !strings.Contains(errString, "invalid certificate") { t.Fatalf("Error was not due to invalid role name. Error: %s", errString) } return nil @@ -231,7 +231,7 @@ func testAccStepResolveRoleOCSPFail(t *testing.T, connState tls.ConnectionState, t.Fatal("Error not part of response.") } - if !strings.Contains(errString, certAuthFailMsg) { + if !strings.Contains(errString, "no chain matching") { t.Fatalf("Error was not due to OCSP failure. Error: %s", errString) } return nil diff --git a/builtin/credential/cert/test_responder.go b/builtin/credential/cert/test_responder.go index 56fb4727be1a..2052736d33cf 100644 --- a/builtin/credential/cert/test_responder.go +++ b/builtin/credential/cert/test_responder.go @@ -19,7 +19,7 @@ import ( "encoding/base64" "errors" "fmt" - "io" + "io/ioutil" "net/http" "net/url" "time" @@ -168,7 +168,7 @@ func (rs *Responder) ServeHTTP(response http.ResponseWriter, request *http.Reque return } case "POST": - requestBody, err = io.ReadAll(request.Body) + requestBody, err = ioutil.ReadAll(request.Body) if err != nil { rs.log.Log("Problem reading body of POST", err) response.WriteHeader(http.StatusBadRequest) diff --git a/builtin/logical/database/backend_test.go b/builtin/logical/database/backend_test.go index 1573d2146ac9..19f35824ed69 100644 --- a/builtin/logical/database/backend_test.go +++ b/builtin/logical/database/backend_test.go @@ -23,7 +23,6 @@ import ( "github.com/hashicorp/go-hclog" "github.com/hashicorp/vault/helper/builtinplugins" "github.com/hashicorp/vault/helper/namespace" - "github.com/hashicorp/vault/helper/testhelpers/certhelpers" "github.com/hashicorp/vault/helper/testhelpers/corehelpers" postgreshelper "github.com/hashicorp/vault/helper/testhelpers/postgresql" vaulthttp "github.com/hashicorp/vault/http" @@ -349,8 +348,6 @@ func TestBackend_config_connection(t *testing.T) { assert.Equal(t, "plugin-test", eventSender.Events[2].Event.Metadata.AsMap()["name"]) } -// TestBackend_BadConnectionString tests that an error response resulting from -// a failed connection does not expose the URL. The middleware should sanitize it. func TestBackend_BadConnectionString(t *testing.T) { cluster, sys := getClusterPostgresDB(t) defer cluster.Cleanup() @@ -365,7 +362,7 @@ func TestBackend_BadConnectionString(t *testing.T) { } defer b.Cleanup(context.Background()) - cleanup, _ := postgreshelper.PrepareTestContainer(t) + cleanup, _ := postgreshelper.PrepareTestContainer(t, "13.4-buster") defer cleanup() respCheck := func(req *logical.Request) { @@ -416,7 +413,7 @@ func TestBackend_basic(t *testing.T) { } defer b.Cleanup(context.Background()) - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "13.4-buster") defer cleanup() // Configure a connection @@ -664,7 +661,6 @@ func (s *singletonDBFactory) factory(context.Context, *logical.BackendConfig) (l } func TestBackend_connectionCrud(t *testing.T) { - t.Parallel() dbFactory := &singletonDBFactory{} cluster, sys := getClusterPostgresDBWithFactory(t, dbFactory.factory) defer cluster.Cleanup() @@ -672,7 +668,7 @@ func TestBackend_connectionCrud(t *testing.T) { dbFactory.sys = sys client := cluster.Cores[0].Client.Logical() - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "13.4-buster") defer cleanup() // Mount the database plugin. @@ -722,6 +718,7 @@ func TestBackend_connectionCrud(t *testing.T) { "allowed_roles": []string{"plugin-role-test"}, "username": "postgres", "password": "secret", + "private_key": "PRIVATE_KEY", }) if err != nil { t.Fatalf("err:%s resp:%#v\n", err, resp) @@ -742,6 +739,9 @@ func TestBackend_connectionCrud(t *testing.T) { if _, exists := returnedConnectionDetails["password"]; exists { t.Fatal("password should NOT be found in the returned config") } + if _, exists := returnedConnectionDetails["private_key"]; exists { + t.Fatal("private_key should NOT be found in the returned config") + } // Replace connection url with templated version templatedConnURL := strings.ReplaceAll(connURL, "postgres:secret", "{{username}}:{{password}}") @@ -751,6 +751,7 @@ func TestBackend_connectionCrud(t *testing.T) { "allowed_roles": []string{"plugin-role-test"}, "username": "postgres", "password": "secret", + "private_key": "PRIVATE_KEY", }) if err != nil { t.Fatalf("err:%s resp:%#v\n", err, resp) @@ -857,57 +858,6 @@ func TestBackend_connectionCrud(t *testing.T) { } } -func TestBackend_connectionSanitizePrivateKey(t *testing.T) { - t.Parallel() - dbFactory := &singletonDBFactory{} - cluster, sys := getClusterPostgresDBWithFactory(t, dbFactory.factory) - defer cluster.Cleanup() - - dbFactory.sys = sys - client := cluster.Cores[0].Client.Logical() - - cleanup, connURL := postgreshelper.PrepareTestContainer(t) - defer cleanup() - - // Mount the database plugin. - resp, err := client.Write("sys/mounts/database", map[string]interface{}{ - "type": "database", - }) - if err != nil { - t.Fatalf("err:%s resp:%#v\n", err, resp) - } - - caCert := certhelpers.NewCert(t, certhelpers.CommonName("ca"), certhelpers.IsCA(true), certhelpers.SelfSign()) - clientCert := certhelpers.NewCert(t, certhelpers.CommonName("postgres"), certhelpers.DNS("localhost"), certhelpers.Parent(caCert)) - - // Create a connection - resp, err = client.Write("database/config/plugin-test", map[string]interface{}{ - "connection_url": connURL, - "plugin_name": "postgresql-database-plugin", - "allowed_roles": []string{"plugin-role-test"}, - "username": "postgres", - "tls_certificate": string(clientCert.CombinedPEM()), - "private_key": string(clientCert.PrivateKeyPEM()), - "tls_ca": string(caCert.CombinedPEM()), - "verify_connection": false, - }) - if err != nil { - t.Fatalf("err:%s resp:%#v\n", err, resp) - } - - resp, err = client.Read("database/config/plugin-test") - if err != nil { - t.Fatalf("err:%s resp:%#v\n", err, resp) - } - returnedConnectionDetails := resp.Data["connection_details"].(map[string]interface{}) - if strings.Contains(returnedConnectionDetails["connection_url"].(string), "secret") { - t.Fatal("password should not be found in the connection url") - } - if _, exists := returnedConnectionDetails["private_key"]; exists { - t.Fatal("private_key should NOT be found in the returned config") - } -} - func TestBackend_roleCrud(t *testing.T) { cluster, sys := getClusterPostgresDB(t) defer cluster.Cleanup() @@ -926,7 +876,7 @@ func TestBackend_roleCrud(t *testing.T) { } defer b.Cleanup(context.Background()) - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "13.4-buster") defer cleanup() // Configure a connection @@ -1175,7 +1125,7 @@ func TestBackend_allowedRoles(t *testing.T) { } defer b.Cleanup(context.Background()) - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "13.4-buster") defer cleanup() // Configure a connection @@ -1372,7 +1322,7 @@ func TestBackend_RotateRootCredentials(t *testing.T) { } defer b.Cleanup(context.Background()) - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "13.4-buster") defer cleanup() connURL = strings.ReplaceAll(connURL, "postgres:secret", "{{username}}:{{password}}") @@ -1505,7 +1455,7 @@ func TestBackend_ConnectionURL_redacted(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - cleanup, u := postgreshelper.PrepareTestContainerWithPassword(t, tt.password) + cleanup, u := postgreshelper.PrepareTestContainerWithPassword(t, "13.4-buster", tt.password) t.Cleanup(cleanup) p, err := url.Parse(u) diff --git a/builtin/logical/database/path_roles.go b/builtin/logical/database/path_roles.go index a53988498000..e223018962fd 100644 --- a/builtin/logical/database/path_roles.go +++ b/builtin/logical/database/path_roles.go @@ -217,11 +217,6 @@ func staticFields() map[string]*framework.FieldSchema { this functionality. See the plugin's API page for more information on support and formatting for this parameter.`, }, - "self_managed_password": { - Type: framework.TypeString, - Description: `Used to connect to a self-managed static account. Must - be provided by the user when root credentials are not provided.`, - }, } return fields } @@ -633,10 +628,6 @@ func (b *databaseBackend) pathStaticRoleCreateUpdate(ctx context.Context, req *l } } - if smPasswordRaw, ok := data.GetOk("self_managed_password"); ok && createRole { - role.StaticAccount.SelfManagedPassword = smPasswordRaw.(string) - } - var credentialConfig map[string]string if raw, ok := data.GetOk("credential_config"); ok { credentialConfig = raw.(map[string]string) @@ -794,12 +785,6 @@ type staticAccount struct { // Username to create or assume management for static accounts Username string `json:"username"` - // SelfManagedPassword is used to make a dedicated connection to the DB - // user specified by Username. The credentials will leverage the existing - // static role mechanisms to handle password rotations. Required when root - // credentials are not provided. - SelfManagedPassword string `json:"self_managed_password"` - // Password is the current password credential for static accounts. As an input, // this is used/required when trying to assume management of an existing static // account. Returned on credential request if the role's credential type is diff --git a/builtin/logical/database/path_roles_test.go b/builtin/logical/database/path_roles_test.go index 41a2e99758aa..91737da2cf8b 100644 --- a/builtin/logical/database/path_roles_test.go +++ b/builtin/logical/database/path_roles_test.go @@ -222,7 +222,7 @@ func TestBackend_StaticRole_Config(t *testing.T) { } defer b.Cleanup(context.Background()) - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "") defer cleanup() // create the database user @@ -487,7 +487,7 @@ func TestBackend_StaticRole_ReadCreds(t *testing.T) { } defer b.Cleanup(context.Background()) - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "") defer cleanup() // create the database user @@ -667,7 +667,7 @@ func TestBackend_StaticRole_Updates(t *testing.T) { } defer b.Cleanup(context.Background()) - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "") defer cleanup() // create the database user @@ -966,7 +966,7 @@ func TestBackend_StaticRole_Role_name_check(t *testing.T) { } defer b.Cleanup(context.Background()) - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "") defer cleanup() // create the database user diff --git a/builtin/logical/database/rollback_test.go b/builtin/logical/database/rollback_test.go index 47c768374296..f60491a6662c 100644 --- a/builtin/logical/database/rollback_test.go +++ b/builtin/logical/database/rollback_test.go @@ -44,7 +44,7 @@ func TestBackend_RotateRootCredentials_WAL_rollback(t *testing.T) { } defer lb.Cleanup(context.Background()) - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "") defer cleanup() connURL = strings.ReplaceAll(connURL, "postgres:secret", "{{username}}:{{password}}") @@ -183,7 +183,7 @@ func TestBackend_RotateRootCredentials_WAL_no_rollback_1(t *testing.T) { } defer lb.Cleanup(context.Background()) - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "") defer cleanup() connURL = strings.ReplaceAll(connURL, "postgres:secret", "{{username}}:{{password}}") @@ -291,7 +291,7 @@ func TestBackend_RotateRootCredentials_WAL_no_rollback_2(t *testing.T) { } defer lb.Cleanup(context.Background()) - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "") defer cleanup() connURL = strings.ReplaceAll(connURL, "postgres:secret", "{{username}}:{{password}}") diff --git a/builtin/logical/database/rotation.go b/builtin/logical/database/rotation.go index d4d41cf570b5..0e5840bd30c2 100644 --- a/builtin/logical/database/rotation.go +++ b/builtin/logical/database/rotation.go @@ -413,11 +413,6 @@ func (b *databaseBackend) setStaticAccount(ctx context.Context, s logical.Storag Commands: input.Role.Statements.Rotation, } - // Add external password to request so we can use static account connection - if input.Role.StaticAccount.SelfManagedPassword != "" { - updateReq.SelfManagedPassword = input.Role.StaticAccount.SelfManagedPassword - } - // Use credential from input if available. This happens if we're restoring from // a WAL item or processing the rotation queue with an item that has a WAL // associated with it @@ -534,12 +529,6 @@ func (b *databaseBackend) setStaticAccount(ctx context.Context, s logical.Storag } modified = true - // static user password successfully updated in external system - // update self-managed password if available for future connections - if input.Role.StaticAccount.SelfManagedPassword != "" { - input.Role.StaticAccount.SelfManagedPassword = input.Role.StaticAccount.Password - } - // Store updated role information // lvr is the known LastVaultRotation lvr := time.Now() diff --git a/builtin/logical/database/rotation_test.go b/builtin/logical/database/rotation_test.go index 99fc3ddf004b..c9917cb37458 100644 --- a/builtin/logical/database/rotation_test.go +++ b/builtin/logical/database/rotation_test.go @@ -63,7 +63,7 @@ func TestBackend_StaticRole_Rotation_basic(t *testing.T) { b.schedule = &TestSchedule{} - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "") defer cleanup() // create the database user @@ -274,7 +274,7 @@ func TestBackend_StaticRole_Rotation_Schedule_ErrorRecover(t *testing.T) { b.schedule = &TestSchedule{} - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "") t.Cleanup(cleanup) // create the database user @@ -458,7 +458,7 @@ func TestBackend_StaticRole_Rotation_NonStaticError(t *testing.T) { } defer b.Cleanup(context.Background()) - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "") defer cleanup() // create the database user @@ -562,7 +562,7 @@ func TestBackend_StaticRole_Rotation_Revoke_user(t *testing.T) { } defer b.Cleanup(context.Background()) - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "") defer cleanup() // create the database user @@ -783,7 +783,7 @@ func TestBackend_StaticRole_Rotation_QueueWAL_discard_role_newer_rotation_date(t t.Fatal("could not convert to db backend") } - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "") defer cleanup() // create the database user @@ -952,7 +952,7 @@ func assertWALCount(t *testing.T, s logical.Storage, expected int, key string) { type userCreator func(t *testing.T, username, password string) func TestBackend_StaticRole_Rotation_PostgreSQL(t *testing.T) { - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "13.4-buster") defer cleanup() uc := userCreator(func(t *testing.T, username, password string) { createTestPGUser(t, connURL, username, password, testRoleStaticCreate) @@ -1246,7 +1246,7 @@ func TestBackend_StaticRole_Rotation_LockRegression(t *testing.T) { } defer b.Cleanup(context.Background()) - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "") defer cleanup() // Configure a connection @@ -1325,7 +1325,7 @@ func TestBackend_StaticRole_Rotation_Invalid_Role(t *testing.T) { } defer b.Cleanup(context.Background()) - cleanup, connURL := postgreshelper.PrepareTestContainer(t) + cleanup, connURL := postgreshelper.PrepareTestContainer(t, "") defer cleanup() // create the database user diff --git a/builtin/logical/database/secret_creds.go b/builtin/logical/database/secret_creds.go index b485f7ca46bb..e2130c1cf7da 100644 --- a/builtin/logical/database/secret_creds.go +++ b/builtin/logical/database/secret_creds.go @@ -34,9 +34,6 @@ func (b *databaseBackend) secretCredsRenew() framework.OperationFunc { return nil, fmt.Errorf("secret is missing username internal data") } username, ok := usernameRaw.(string) - if !ok { - return nil, fmt.Errorf("username not a string") - } roleNameRaw, ok := req.Secret.InternalData["role"] if !ok { @@ -101,9 +98,6 @@ func (b *databaseBackend) secretCredsRevoke() framework.OperationFunc { return nil, fmt.Errorf("secret is missing username internal data") } username, ok := usernameRaw.(string) - if !ok { - return nil, fmt.Errorf("username not a string") - } var resp *logical.Response diff --git a/builtin/logical/pki/acme_challenge_engine.go b/builtin/logical/pki/acme_challenge_engine.go index 96663f2e1cae..330a55b1ccd7 100644 --- a/builtin/logical/pki/acme_challenge_engine.go +++ b/builtin/logical/pki/acme_challenge_engine.go @@ -315,13 +315,13 @@ func (ace *ACMEChallengeEngine) AcceptChallenge(sc *storageContext, account stri func (ace *ACMEChallengeEngine) VerifyChallenge(runnerSc *storageContext, id string, validationQueueRetries int, finished chan bool, config *acmeConfigEntry) { sc, cancel := runnerSc.WithFreshTimeout(MaxChallengeTimeout) defer cancel() - runnerSc.Logger().Debug("Starting verification of challenge", "id", id) + runnerSc.Backend.Logger().Debug("Starting verification of challenge", "id", id) if retry, retryAfter, err := ace._verifyChallenge(sc, id, config); err != nil { // Because verification of this challenge failed, we need to retry // it in the future. Log the error and re-add the item to the queue // to try again later. - sc.Logger().Error(fmt.Sprintf("ACME validation failed for %v: %v", id, err)) + sc.Backend.Logger().Error(fmt.Sprintf("ACME validation failed for %v: %v", id, err)) if retry { validationQueueRetries++ @@ -331,10 +331,10 @@ func (ace *ACMEChallengeEngine) VerifyChallenge(runnerSc *storageContext, id str // we have a secondary check here to see if we are consistently looping within the validation // queue that is larger than the normal retry attempts we would allow. if validationQueueRetries > MaxRetryAttempts*2 { - sc.Logger().Warn("reached max error attempts within challenge queue: %v, giving up", id) + sc.Backend.Logger().Warn("reached max error attempts within challenge queue: %v, giving up", id) _, _, err = ace._verifyChallengeCleanup(sc, nil, id) if err != nil { - sc.Logger().Warn("Failed cleaning up challenge entry: %v", err) + sc.Backend.Logger().Warn("Failed cleaning up challenge entry: %v", err) } finished <- true return diff --git a/builtin/logical/pki/acme_state.go b/builtin/logical/pki/acme_state.go index 63962d933b99..aa0701058439 100644 --- a/builtin/logical/pki/acme_state.go +++ b/builtin/logical/pki/acme_state.go @@ -119,7 +119,7 @@ func (a *acmeState) reloadConfigIfRequired(sc *storageContext) error { return nil } - config, err := getAcmeConfig(sc) + config, err := sc.getAcmeConfig() if err != nil { return fmt.Errorf("failed reading ACME config: %w", err) } diff --git a/builtin/logical/pki/acme_wrappers.go b/builtin/logical/pki/acme_wrappers.go index 88a1cee1d075..febe48b9e430 100644 --- a/builtin/logical/pki/acme_wrappers.go +++ b/builtin/logical/pki/acme_wrappers.go @@ -17,13 +17,12 @@ import ( ) type acmeContext struct { - issuing.IssuerRoleContext - // baseUrl is the combination of the configured cluster local URL and the acmePath up to /acme/ baseUrl *url.URL clusterUrl *url.URL sc *storageContext - acmeState *acmeState + role *issuing.RoleEntry + issuer *issuing.IssuerEntry // acmeDirectory is a string that can distinguish the various acme directories we have configured // if something needs to remain locked into a directory path structure. acmeDirectory string @@ -33,7 +32,7 @@ type acmeContext struct { } func (c acmeContext) getAcmeState() *acmeState { - return c.acmeState + return c.sc.Backend.GetAcmeState() } type ( @@ -111,7 +110,7 @@ func (b *backend) acmeWrapper(opts acmeWrapperOpts, op acmeOperation) framework. return acmeErrorWrapper(func(ctx context.Context, r *logical.Request, data *framework.FieldData) (*logical.Response, error) { sc := b.makeStorageContext(ctx, r.Storage) - config, err := b.GetAcmeState().getConfigWithUpdate(sc) + config, err := sc.Backend.GetAcmeState().getConfigWithUpdate(sc) if err != nil { return nil, fmt.Errorf("failed to fetch ACME configuration: %w", err) } @@ -145,7 +144,7 @@ func (b *backend) acmeWrapper(opts acmeWrapperOpts, op acmeOperation) framework. return nil, err } - isCiepsEnabled, ciepsPolicy, err := getCiepsAcmeSettings(b, sc, opts, config, data) + isCiepsEnabled, ciepsPolicy, err := getCiepsAcmeSettings(sc, opts, config, data) if err != nil { return nil, err } @@ -161,15 +160,15 @@ func (b *backend) acmeWrapper(opts acmeWrapperOpts, op acmeOperation) framework. } acmeCtx := &acmeContext{ - IssuerRoleContext: issuing.NewIssuerRoleContext(ctx, issuer, role), - baseUrl: acmeBaseUrl, - clusterUrl: clusterBase, - sc: sc, - acmeState: b.acmeState, - acmeDirectory: acmeDirectory, - eabPolicy: eabPolicy, - ciepsPolicy: ciepsPolicy, - runtimeOpts: runtimeOpts, + baseUrl: acmeBaseUrl, + clusterUrl: clusterBase, + sc: sc, + role: role, + issuer: issuer, + acmeDirectory: acmeDirectory, + eabPolicy: eabPolicy, + ciepsPolicy: ciepsPolicy, + runtimeOpts: runtimeOpts, } return op(acmeCtx, r, data) @@ -456,7 +455,7 @@ func getAcmeRoleAndIssuer(sc *storageContext, data *framework.FieldData, config func getAndValidateAcmeRole(sc *storageContext, requestedRole string) (*issuing.RoleEntry, error) { var err error - role, err := sc.GetRole(requestedRole) + role, err := sc.Backend.GetRole(sc.Context, sc.Storage, requestedRole) if err != nil { return nil, fmt.Errorf("%w: err loading role", ErrServerInternal) } @@ -497,7 +496,7 @@ func isAcmeDisabled(sc *storageContext, config *acmeConfigEntry, policy EabPolic disableAcme, nonFatalErr := isPublicACMEDisabledByEnv() if nonFatalErr != nil { - sc.Logger().Warn(fmt.Sprintf("could not parse env var '%s'", disableAcmeEnvVar), "error", nonFatalErr) + sc.Backend.Logger().Warn(fmt.Sprintf("could not parse env var '%s'", disableAcmeEnvVar), "error", nonFatalErr) } // The OS environment if true will override any configuration option. diff --git a/builtin/logical/pki/acme_wrappers_test.go b/builtin/logical/pki/acme_wrappers_test.go index 569036deae6c..cabca180940f 100644 --- a/builtin/logical/pki/acme_wrappers_test.go +++ b/builtin/logical/pki/acme_wrappers_test.go @@ -82,12 +82,12 @@ func TestACMEIssuerRoleLoading(t *testing.T) { for _, tt := range tc { t.Run(tt.name, func(t *testing.T) { f := b.acmeWrapper(acmeWrapperOpts{}, func(acmeCtx *acmeContext, r *logical.Request, _ *framework.FieldData) (*logical.Response, error) { - if tt.roleName != acmeCtx.Role.Name { - return nil, fmt.Errorf("expected role %s but got %s", tt.roleName, acmeCtx.Role.Name) + if tt.roleName != acmeCtx.role.Name { + return nil, fmt.Errorf("expected role %s but got %s", tt.roleName, acmeCtx.role.Name) } - if tt.expectedIssuerName != acmeCtx.Issuer.Name { - return nil, fmt.Errorf("expected issuer %s but got %s", tt.expectedIssuerName, acmeCtx.Issuer.Name) + if tt.expectedIssuerName != acmeCtx.issuer.Name { + return nil, fmt.Errorf("expected issuer %s but got %s", tt.expectedIssuerName, acmeCtx.issuer.Name) } return nil, nil diff --git a/builtin/logical/pki/backend.go b/builtin/logical/pki/backend.go index 2b9044db4e16..96246c3d3f6e 100644 --- a/builtin/logical/pki/backend.go +++ b/builtin/logical/pki/backend.go @@ -5,7 +5,6 @@ package pki import ( "context" - "crypto/x509" "fmt" "strings" "sync" @@ -14,11 +13,9 @@ import ( "github.com/armon/go-metrics" "github.com/hashicorp/go-multierror" - "github.com/hashicorp/go-secure-stdlib/parseutil" "github.com/hashicorp/vault/builtin/logical/pki/issuing" "github.com/hashicorp/vault/builtin/logical/pki/managed_key" "github.com/hashicorp/vault/builtin/logical/pki/pki_backend" - "github.com/hashicorp/vault/builtin/logical/pki/revocation" "github.com/hashicorp/vault/helper/metricsutil" "github.com/hashicorp/vault/helper/namespace" "github.com/hashicorp/vault/sdk/framework" @@ -147,7 +144,7 @@ func Backend(conf *logical.BackendConfig) *backend { WriteForwardedStorage: []string{ crossRevocationPath, - revocation.UnifiedRevocationWritePathPrefix, + unifiedRevocationWritePathPrefix, unifiedDeltaWALPath, }, @@ -359,8 +356,6 @@ type BackendOps interface { pki_backend.SystemViewGetter pki_backend.MountInfo pki_backend.Logger - revocation.RevokerFactory - UseLegacyBundleCaStorage() bool CrlBuilder() *CrlBuilder GetRevokeStorageLock() *sync.RWMutex @@ -703,7 +698,7 @@ func (b *backend) periodicFunc(ctx context.Context, request *logical.Request) er } // Then attempt to rebuild the CRLs if required. - warnings, err := b.CrlBuilder().RebuildIfForced(sc) + warnings, err := b.CrlBuilder().rebuildIfForced(sc) if err != nil { return err } @@ -862,77 +857,3 @@ func (b *backend) initializeStoredCertificateCounts(ctx context.Context) error { certCounter.InitializeCountsFromStorage(entries, revokedEntries) return nil } - -var _ revocation.Revoker = &revoker{} - -type revoker struct { - backend *backend - storageContext *storageContext - crlConfig *pki_backend.CrlConfig -} - -func (r *revoker) RevokeCert(cert *x509.Certificate) (revocation.RevokeCertInfo, error) { - r.backend.GetRevokeStorageLock().Lock() - defer r.backend.GetRevokeStorageLock().Unlock() - resp, err := revokeCert(r.storageContext, r.crlConfig, cert) - return parseRevokeCertOutput(resp, err) -} - -func (r *revoker) RevokeCertBySerial(serial string) (revocation.RevokeCertInfo, error) { - // NOTE: tryRevokeCertBySerial grabs the revoke storage lock for us - resp, err := tryRevokeCertBySerial(r.storageContext, r.crlConfig, serial) - return parseRevokeCertOutput(resp, err) -} - -// There are a bunch of reasons that a certificate will/won't be revoked. Sadly we will need a further -// refactoring but for now handle the basics of the reasons/response objects back to a usable object -// that doesn't directly reply to the API request -func parseRevokeCertOutput(resp *logical.Response, err error) (revocation.RevokeCertInfo, error) { - if err != nil { - return revocation.RevokeCertInfo{}, err - } - - if resp == nil { - // nil, nil response, most likely means the certificate was missing, - // but *might* be other things such as a tainted mount - return revocation.RevokeCertInfo{}, nil - } - - if resp.IsError() { - // There are a few reasons we return a response error but not an error, - // such as UserError's or they tried to revoke the CA - return revocation.RevokeCertInfo{}, resp.Error() - } - - // It is possible we don't return the field for various reasons if just a bunch of warnings are set. - if revTimeRaw, ok := resp.Data["revocation_time"]; ok { - revTimeInt, err := parseutil.ParseInt(revTimeRaw) - if err != nil { - // Lets me lenient for now - revTimeInt = 0 - } - revTime := time.Unix(revTimeInt, 0) - return revocation.RevokeCertInfo{ - RevocationTime: revTime, - }, nil - } - - // Since we don't really know what went wrong if anything, for example the certificate might - // have been expired or close to expiry, lets punt on it for now - return revocation.RevokeCertInfo{ - Warnings: resp.Warnings, - }, nil -} - -func (b *backend) GetRevoker(ctx context.Context, s logical.Storage) (revocation.Revoker, error) { - sc := b.makeStorageContext(ctx, s) - crlConfig, err := b.CrlBuilder().GetConfigWithUpdate(sc) - if err != nil { - return nil, err - } - return &revoker{ - backend: b, - crlConfig: crlConfig, - storageContext: sc, - }, nil -} diff --git a/builtin/logical/pki/backend_test.go b/builtin/logical/pki/backend_test.go index af079b13f781..a12daec7076f 100644 --- a/builtin/logical/pki/backend_test.go +++ b/builtin/logical/pki/backend_test.go @@ -44,7 +44,6 @@ import ( "github.com/hashicorp/vault/builtin/credential/userpass" "github.com/hashicorp/vault/builtin/logical/pki/issuing" "github.com/hashicorp/vault/builtin/logical/pki/parsing" - "github.com/hashicorp/vault/builtin/logical/pki/pki_backend" "github.com/hashicorp/vault/helper/testhelpers" logicaltest "github.com/hashicorp/vault/helper/testhelpers/logical" "github.com/hashicorp/vault/helper/testhelpers/teststorage" @@ -4114,7 +4113,6 @@ func TestBackend_RevokePlusTidy_Intermediate(t *testing.T) { "tidy_revocation_queue": false, "tidy_cross_cluster_revoked_certs": false, "tidy_cert_metadata": false, - "tidy_cmpv2_nonce_store": false, "pause_duration": "0s", "state": "Finished", "error": nil, @@ -4137,7 +4135,6 @@ func TestBackend_RevokePlusTidy_Intermediate(t *testing.T) { "acme_account_deleted_count": json.Number("0"), "total_acme_account_count": json.Number("0"), "cert_metadata_deleted_count": json.Number("0"), - "cmpv2_nonce_deleted_count": json.Number("0"), } // Let's copy the times from the response so that we can use deep.Equal() timeStarted, ok := tidyStatus.Data["time_started"] @@ -6087,7 +6084,7 @@ func TestPKI_EmptyCRLConfigUpgraded(t *testing.T) { b, s := CreateBackendWithStorage(t) // Write an empty CRLConfig into storage. - crlConfigEntry, err := logical.StorageEntryJSON("config/crl", &pki_backend.CrlConfig{}) + crlConfigEntry, err := logical.StorageEntryJSON("config/crl", &crlConfig{}) require.NoError(t, err) err = s.Put(ctx, crlConfigEntry) require.NoError(t, err) @@ -6096,13 +6093,13 @@ func TestPKI_EmptyCRLConfigUpgraded(t *testing.T) { require.NoError(t, err) require.NotNil(t, resp) require.NotNil(t, resp.Data) - require.Equal(t, resp.Data["expiry"], pki_backend.DefaultCrlConfig.Expiry) - require.Equal(t, resp.Data["disable"], pki_backend.DefaultCrlConfig.Disable) - require.Equal(t, resp.Data["ocsp_disable"], pki_backend.DefaultCrlConfig.OcspDisable) - require.Equal(t, resp.Data["auto_rebuild"], pki_backend.DefaultCrlConfig.AutoRebuild) - require.Equal(t, resp.Data["auto_rebuild_grace_period"], pki_backend.DefaultCrlConfig.AutoRebuildGracePeriod) - require.Equal(t, resp.Data["enable_delta"], pki_backend.DefaultCrlConfig.EnableDelta) - require.Equal(t, resp.Data["delta_rebuild_interval"], pki_backend.DefaultCrlConfig.DeltaRebuildInterval) + require.Equal(t, resp.Data["expiry"], defaultCrlConfig.Expiry) + require.Equal(t, resp.Data["disable"], defaultCrlConfig.Disable) + require.Equal(t, resp.Data["ocsp_disable"], defaultCrlConfig.OcspDisable) + require.Equal(t, resp.Data["auto_rebuild"], defaultCrlConfig.AutoRebuild) + require.Equal(t, resp.Data["auto_rebuild_grace_period"], defaultCrlConfig.AutoRebuildGracePeriod) + require.Equal(t, resp.Data["enable_delta"], defaultCrlConfig.EnableDelta) + require.Equal(t, resp.Data["delta_rebuild_interval"], defaultCrlConfig.DeltaRebuildInterval) } func TestPKI_ListRevokedCerts(t *testing.T) { @@ -6767,14 +6764,12 @@ const ( shouldBeAuthed pathAuthChecker = iota shouldBeUnauthedReadList shouldBeUnauthedWriteOnly - shouldBeUnauthedReadWriteOnly ) var pathAuthChckerMap = map[pathAuthChecker]pathAuthCheckerFunc{ - shouldBeAuthed: pathShouldBeAuthed, - shouldBeUnauthedReadList: pathShouldBeUnauthedReadList, - shouldBeUnauthedWriteOnly: pathShouldBeUnauthedWriteOnly, - shouldBeUnauthedReadWriteOnly: pathShouldBeUnauthedWriteOnly, + shouldBeAuthed: pathShouldBeAuthed, + shouldBeUnauthedReadList: pathShouldBeUnauthedReadList, + shouldBeUnauthedWriteOnly: pathShouldBeUnauthedWriteOnly, } func TestProperAuthing(t *testing.T) { @@ -7068,10 +7063,6 @@ func TestProperAuthing(t *testing.T) { if hasGet || hasList { t.Fatalf("Unauthed write-only endpoints should not have GET/LIST capabilities: %v->%v", openapi_path, raw_path) } - } else if handler == shouldBeUnauthedReadWriteOnly { - if hasDelete || hasList { - t.Fatalf("Unauthed read-write-only endpoints should not have DELETE/LIST capabilities: %v->%v", openapi_path, raw_path) - } } } diff --git a/builtin/logical/pki/ca_util.go b/builtin/logical/pki/ca_util.go index 2d2478ab8e46..364bed9958d1 100644 --- a/builtin/logical/pki/ca_util.go +++ b/builtin/logical/pki/ca_util.go @@ -72,7 +72,6 @@ func getGenerationParams(sc *storageContext, data *framework.FieldData) (exporte PostalCode: data.Get("postal_code").([]string), NotBeforeDuration: time.Duration(data.Get("not_before_duration").(int)) * time.Second, CNValidations: []string{"disabled"}, - KeyUsage: data.Get("key_usage").([]string), } *role.AllowWildcardCertificates = true @@ -85,13 +84,14 @@ func getGenerationParams(sc *storageContext, data *framework.FieldData) (exporte func generateCABundle(sc *storageContext, input *inputBundle, data *certutil.CreationBundle, randomSource io.Reader) (*certutil.ParsedCertBundle, error) { ctx := sc.Context + b := sc.Backend if kmsRequested(input) { keyId, err := getManagedKeyId(input.apiData) if err != nil { return nil, err } - return managed_key.GenerateManagedKeyCABundle(ctx, sc.GetPkiManagedView(), keyId, data, randomSource) + return managed_key.GenerateManagedKeyCABundle(ctx, b, keyId, data, randomSource) } if existingKeyRequested(input) { @@ -110,7 +110,7 @@ func generateCABundle(sc *storageContext, input *inputBundle, data *certutil.Cre if err != nil { return nil, err } - return managed_key.GenerateManagedKeyCABundle(ctx, sc.GetPkiManagedView(), keyId, data, randomSource) + return managed_key.GenerateManagedKeyCABundle(ctx, b, keyId, data, randomSource) } return certutil.CreateCertificateWithKeyGenerator(data, randomSource, existingKeyGeneratorFromBytes(keyEntry)) @@ -121,6 +121,7 @@ func generateCABundle(sc *storageContext, input *inputBundle, data *certutil.Cre func generateCSRBundle(sc *storageContext, input *inputBundle, data *certutil.CreationBundle, addBasicConstraints bool, randomSource io.Reader) (*certutil.ParsedCSRBundle, error) { ctx := sc.Context + b := sc.Backend if kmsRequested(input) { keyId, err := getManagedKeyId(input.apiData) @@ -128,7 +129,7 @@ func generateCSRBundle(sc *storageContext, input *inputBundle, data *certutil.Cr return nil, err } - return managed_key.GenerateManagedKeyCSRBundle(ctx, sc.GetPkiManagedView(), keyId, data, addBasicConstraints, randomSource) + return managed_key.GenerateManagedKeyCSRBundle(ctx, b, keyId, data, addBasicConstraints, randomSource) } if existingKeyRequested(input) { @@ -147,7 +148,7 @@ func generateCSRBundle(sc *storageContext, input *inputBundle, data *certutil.Cr if err != nil { return nil, err } - return managed_key.GenerateManagedKeyCSRBundle(ctx, sc.GetPkiManagedView(), keyId, data, addBasicConstraints, randomSource) + return managed_key.GenerateManagedKeyCSRBundle(ctx, b, keyId, data, addBasicConstraints, randomSource) } return certutil.CreateCSRWithKeyGenerator(data, addBasicConstraints, randomSource, existingKeyGeneratorFromBytes(key)) @@ -156,8 +157,8 @@ func generateCSRBundle(sc *storageContext, input *inputBundle, data *certutil.Cr return certutil.CreateCSRWithRandomSource(data, addBasicConstraints, randomSource) } -func parseCABundle(ctx context.Context, mkv managed_key.PkiManagedKeyView, bundle *certutil.CertBundle) (*certutil.ParsedCertBundle, error) { - return issuing.ParseCABundle(ctx, mkv, bundle) +func parseCABundle(ctx context.Context, b *backend, bundle *certutil.CertBundle) (*certutil.ParsedCertBundle, error) { + return issuing.ParseCABundle(ctx, b, bundle) } func (sc *storageContext) getKeyTypeAndBitsForRole(data *framework.FieldData) (string, int, error) { @@ -189,7 +190,7 @@ func (sc *storageContext) getKeyTypeAndBitsForRole(data *framework.FieldData) (s return "", 0, errors.New("unable to determine managed key id: " + err.Error()) } - pubKeyManagedKey, err := managed_key.GetManagedKeyPublicKey(sc.Context, sc.GetPkiManagedView(), keyId) + pubKeyManagedKey, err := managed_key.GetManagedKeyPublicKey(sc.Context, sc.Backend, keyId) if err != nil { return "", 0, errors.New("failed to lookup public key from managed key: " + err.Error()) } @@ -221,7 +222,7 @@ func (sc *storageContext) getExistingPublicKey(data *framework.FieldData) (crypt if err != nil { return nil, err } - return getPublicKey(sc.Context, sc.GetPkiManagedView(), key) + return getPublicKey(sc.Context, sc.Backend, key) } func getKeyTypeAndBitsFromPublicKeyForRole(pubKey crypto.PublicKey) (certutil.PrivateKeyType, int, error) { diff --git a/builtin/logical/pki/cert_util.go b/builtin/logical/pki/cert_util.go index 5111699ab8c5..2a658f93ff35 100644 --- a/builtin/logical/pki/cert_util.go +++ b/builtin/logical/pki/cert_util.go @@ -22,7 +22,6 @@ import ( "github.com/hashicorp/vault/builtin/logical/pki/issuing" "github.com/hashicorp/vault/builtin/logical/pki/parsing" - "github.com/hashicorp/vault/builtin/logical/pki/pki_backend" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/helper/certutil" "github.com/hashicorp/vault/sdk/helper/errutil" @@ -140,9 +139,9 @@ func (sc *storageContext) fetchCAInfo(issuerRef string, usage issuing.IssuerUsag func (sc *storageContext) fetchCAInfoWithIssuer(issuerRef string, usage issuing.IssuerUsage) (*certutil.CAInfoBundle, issuing.IssuerID, error) { var issuerId issuing.IssuerID - if sc.UseLegacyBundleCaStorage() { + if sc.Backend.UseLegacyBundleCaStorage() { // We have not completed the migration so attempt to load the bundle from the legacy location - sc.Logger().Info("Using legacy CA bundle as PKI migration has not completed.") + sc.Backend.Logger().Info("Using legacy CA bundle as PKI migration has not completed.") issuerId = legacyBundleShimID } else { var err error @@ -164,24 +163,24 @@ func (sc *storageContext) fetchCAInfoWithIssuer(issuerRef string, usage issuing. // fetchCAInfoByIssuerId will fetch the CA info, will return an error if no ca info exists for the given issuerId. // This does support the loading using the legacyBundleShimID func (sc *storageContext) fetchCAInfoByIssuerId(issuerId issuing.IssuerID, usage issuing.IssuerUsage) (*certutil.CAInfoBundle, error) { - return issuing.FetchCAInfoByIssuerId(sc.Context, sc.Storage, sc.GetPkiManagedView(), issuerId, usage) + return issuing.FetchCAInfoByIssuerId(sc.Context, sc.Storage, sc.Backend, issuerId, usage) } func fetchCertBySerialBigInt(sc *storageContext, prefix string, serial *big.Int) (*logical.StorageEntry, error) { return fetchCertBySerial(sc, prefix, serialFromBigInt(serial)) } -// fetchCertBySerial allows fetching certificates from the backend; it handles the slightly +// Allows fetching certificates from the backend; it handles the slightly // separate pathing for CRL, and revoked certificates. // // Support for fetching CA certificates was removed, due to the new issuers // changes. -func fetchCertBySerial(sc pki_backend.StorageContext, prefix, serial string) (*logical.StorageEntry, error) { +func fetchCertBySerial(sc *storageContext, prefix, serial string) (*logical.StorageEntry, error) { var path, legacyPath string var err error var certEntry *logical.StorageEntry - hyphenSerial := parsing.NormalizeSerialForStorage(serial) + hyphenSerial := normalizeSerial(serial) colonSerial := strings.ReplaceAll(strings.ToLower(serial), "-", ":") switch { @@ -190,8 +189,8 @@ func fetchCertBySerial(sc pki_backend.StorageContext, prefix, serial string) (*l case strings.HasPrefix(prefix, "revoked/"): legacyPath = "revoked/" + colonSerial path = "revoked/" + hyphenSerial - case serial == issuing.LegacyCRLPath || serial == issuing.DeltaCRLPath || serial == issuing.UnifiedCRLPath || serial == issuing.UnifiedDeltaCRLPath: - warnings, err := sc.CrlBuilder().RebuildIfForced(sc) + case serial == legacyCRLPath || serial == deltaCRLPath || serial == unifiedCRLPath || serial == unifiedDeltaCRLPath: + warnings, err := sc.Backend.CrlBuilder().rebuildIfForced(sc) if err != nil { return nil, err } @@ -200,28 +199,28 @@ func fetchCertBySerial(sc pki_backend.StorageContext, prefix, serial string) (*l for index, warning := range warnings { msg = fmt.Sprintf("%v\n %d. %v", msg, index+1, warning) } - sc.Logger().Warn(msg) + sc.Backend.Logger().Warn(msg) } - unified := serial == issuing.UnifiedCRLPath || serial == issuing.UnifiedDeltaCRLPath - path, err = issuing.ResolveIssuerCRLPath(sc.GetContext(), sc.GetStorage(), sc.UseLegacyBundleCaStorage(), issuing.DefaultRef, unified) + unified := serial == unifiedCRLPath || serial == unifiedDeltaCRLPath + path, err = sc.resolveIssuerCRLPath(defaultRef, unified) if err != nil { return nil, err } - if serial == issuing.DeltaCRLPath || serial == issuing.UnifiedDeltaCRLPath { - if sc.UseLegacyBundleCaStorage() { + if serial == deltaCRLPath || serial == unifiedDeltaCRLPath { + if sc.Backend.UseLegacyBundleCaStorage() { return nil, fmt.Errorf("refusing to serve delta CRL with legacy CA bundle") } - path += issuing.DeltaCRLPathSuffix + path += deltaCRLPathSuffix } default: legacyPath = issuing.PathCerts + colonSerial path = issuing.PathCerts + hyphenSerial } - certEntry, err = sc.GetStorage().Get(sc.GetContext(), path) + certEntry, err = sc.Storage.Get(sc.Context, path) if err != nil { return nil, errutil.InternalError{Err: fmt.Sprintf("error fetching certificate %s: %s", serial, err)} } @@ -241,7 +240,7 @@ func fetchCertBySerial(sc pki_backend.StorageContext, prefix, serial string) (*l // always manifest on Windows, and thus the initial check for a revoked // cert fails would return an error when the cert isn't revoked, preventing // the happy path from working. - certEntry, _ = sc.GetStorage().Get(sc.GetContext(), legacyPath) + certEntry, _ = sc.Storage.Get(sc.Context, legacyPath) if certEntry == nil { return nil, nil } @@ -251,12 +250,12 @@ func fetchCertBySerial(sc pki_backend.StorageContext, prefix, serial string) (*l // Update old-style paths to new-style paths certEntry.Key = path - certCounter := sc.GetCertificateCounter() + certCounter := sc.Backend.GetCertificateCounter() certsCounted := certCounter.IsInitialized() - if err = sc.GetStorage().Put(sc.GetContext(), certEntry); err != nil { + if err = sc.Storage.Put(sc.Context, certEntry); err != nil { return nil, errutil.InternalError{Err: fmt.Sprintf("error saving certificate with serial %s to new location: %s", serial, err)} } - if err = sc.GetStorage().Delete(sc.GetContext(), legacyPath); err != nil { + if err = sc.Storage.Delete(sc.Context, legacyPath); err != nil { // If we fail here, we have an extra (copy) of a cert in storage, add to metrics: switch { case strings.HasPrefix(prefix, "revoked/"): @@ -328,6 +327,7 @@ func generateCert(sc *storageContext, randomSource io.Reader) (*certutil.ParsedCertBundle, []string, error, ) { ctx := sc.Context + b := sc.Backend if input.role == nil { return nil, nil, errutil.InternalError{Err: "no role found in data bundle"} @@ -337,7 +337,7 @@ func generateCert(sc *storageContext, return nil, nil, errutil.UserError{Err: "RSA keys < 2048 bits are unsafe and not supported"} } - data, warnings, err := generateCreationBundle(sc.System(), input, caSign, nil) + data, warnings, err := generateCreationBundle(b, input, caSign, nil) if err != nil { return nil, nil, err } @@ -402,7 +402,7 @@ func generateCert(sc *storageContext, // N.B.: This is only meant to be used for generating intermediate CAs. // It skips some sanity checks. func generateIntermediateCSR(sc *storageContext, input *inputBundle, randomSource io.Reader) (*certutil.ParsedCSRBundle, []string, error) { - creation, warnings, err := generateCreationBundle(sc.System(), input, nil, nil) + creation, warnings, err := generateCreationBundle(sc.Backend, input, nil, nil) if err != nil { return nil, nil, err } @@ -410,10 +410,6 @@ func generateIntermediateCSR(sc *storageContext, input *inputBundle, randomSourc return nil, nil, errutil.InternalError{Err: "nil parameters received from parameter bundle generation"} } - _, exists := input.apiData.GetOk("key_usage") - if !exists { - creation.Params.KeyUsage = 0 - } addBasicConstraints := input.apiData != nil && input.apiData.Get("add_basic_constraints").(bool) parsedBundle, err := generateCSRBundle(sc, input, creation, addBasicConstraints, randomSource) if err != nil { @@ -472,11 +468,7 @@ func (i SignCertInputFromDataFields) GetPermittedDomains() []string { return i.data.Get("permitted_dns_domains").([]string) } -func (i SignCertInputFromDataFields) IgnoreCSRSignature() bool { - return false -} - -func signCert(sysView logical.SystemView, data *inputBundle, caSign *certutil.CAInfoBundle, isCA bool, useCSRValues bool) (*certutil.ParsedCertBundle, []string, error) { +func signCert(b *backend, data *inputBundle, caSign *certutil.CAInfoBundle, isCA bool, useCSRValues bool) (*certutil.ParsedCertBundle, []string, error) { if data.role == nil { return nil, nil, errutil.InternalError{Err: "no role found in data bundle"} } @@ -484,7 +476,7 @@ func signCert(sysView logical.SystemView, data *inputBundle, caSign *certutil.CA entityInfo := issuing.NewEntityInfoFromReq(data.req) signCertInput := NewSignCertInputFromDataFields(data.apiData, isCA, useCSRValues) - return issuing.SignCert(sysView, data.role, entityInfo, caSign, signCertInput) + return issuing.SignCert(b.System(), data.role, entityInfo, caSign, signCertInput) } func getOtherSANsFromX509Extensions(exts []pkix.Extension) ([]certutil.OtherNameUtf8, error) { @@ -506,10 +498,6 @@ type CreationBundleInputFromFieldData struct { data *framework.FieldData } -func (cb CreationBundleInputFromFieldData) IgnoreCSRSignature() bool { - return false -} - func (cb CreationBundleInputFromFieldData) GetCommonName() string { return cb.data.Get("common_name").(string) } @@ -554,18 +542,18 @@ func (cb CreationBundleInputFromFieldData) GetUserIds() []string { // generateCreationBundle is a shared function that reads parameters supplied // from the various endpoints and generates a CreationParameters with the // parameters that can be used to issue or sign -func generateCreationBundle(sysView logical.SystemView, data *inputBundle, caSign *certutil.CAInfoBundle, csr *x509.CertificateRequest) (*certutil.CreationBundle, []string, error) { +func generateCreationBundle(b *backend, data *inputBundle, caSign *certutil.CAInfoBundle, csr *x509.CertificateRequest) (*certutil.CreationBundle, []string, error) { entityInfo := issuing.NewEntityInfoFromReq(data.req) creationBundleInput := NewCreationBundleInputFromFieldData(data.apiData) - return issuing.GenerateCreationBundle(sysView, data.role, entityInfo, creationBundleInput, caSign, csr) + return issuing.GenerateCreationBundle(b.System(), data.role, entityInfo, creationBundleInput, caSign, csr) } // getCertificateNotAfter compute a certificate's NotAfter date based on the mount ttl, role, signing bundle and input // api data being sent. Returns a NotAfter time, a set of warnings or an error. -func getCertificateNotAfter(sysView logical.SystemView, data *inputBundle, caSign *certutil.CAInfoBundle) (time.Time, []string, error) { +func getCertificateNotAfter(b *backend, data *inputBundle, caSign *certutil.CAInfoBundle) (time.Time, []string, error) { input := NewCertNotAfterInputFromFieldData(data.apiData) - return issuing.GetCertificateNotAfter(sysView, data.role, input, caSign) + return issuing.GetCertificateNotAfter(b.System(), data.role, input, caSign) } // applyIssuerLeafNotAfterBehavior resets a certificate's notAfter time or errors out based on the diff --git a/builtin/logical/pki/cert_util_test.go b/builtin/logical/pki/cert_util_test.go index 4f162aeb0946..c5edda91c19f 100644 --- a/builtin/logical/pki/cert_util_test.go +++ b/builtin/logical/pki/cert_util_test.go @@ -125,7 +125,7 @@ func TestPki_MultipleOUs(t *testing.T) { OU: []string{"Z", "E", "V"}, }, } - cb, _, err := generateCreationBundle(b.System(), input, nil, nil) + cb, _, err := generateCreationBundle(b, input, nil, nil) if err != nil { t.Fatalf("Error: %v", err) } @@ -245,7 +245,7 @@ func TestPki_PermitFQDNs(t *testing.T) { name := name testCase := testCase t.Run(name, func(t *testing.T) { - cb, _, err := generateCreationBundle(b.System(), testCase.input, nil, nil) + cb, _, err := generateCreationBundle(b, testCase.input, nil, nil) if err != nil { t.Fatalf("Error: %v", err) } diff --git a/builtin/logical/pki/cieps_util_oss.go b/builtin/logical/pki/cieps_util_oss.go index 7efb1151eeea..52524b9d4f58 100644 --- a/builtin/logical/pki/cieps_util_oss.go +++ b/builtin/logical/pki/cieps_util_oss.go @@ -20,6 +20,6 @@ func issueAcmeCertUsingCieps(_ *backend, _ *acmeContext, _ *logical.Request, _ * return nil, "", fmt.Errorf("cieps is an enterprise only feature") } -func getCiepsAcmeSettings(b *backend, sc *storageContext, opts acmeWrapperOpts, config *acmeConfigEntry, data *framework.FieldData) (bool, string, error) { +func getCiepsAcmeSettings(sc *storageContext, opts acmeWrapperOpts, config *acmeConfigEntry, data *framework.FieldData) (bool, string, error) { return false, "", nil } diff --git a/builtin/logical/pki/cmpv2_util_oss.go b/builtin/logical/pki/cmpv2_util_oss.go deleted file mode 100644 index 9e7574795d34..000000000000 --- a/builtin/logical/pki/cmpv2_util_oss.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !enterprise - -package pki - -import ( - "context" - - "github.com/hashicorp/vault/sdk/logical" -) - -func (b *backend) doTidyCMPV2NonceStore(_ context.Context, _ logical.Storage) error { - return nil -} diff --git a/builtin/logical/pki/crl_test.go b/builtin/logical/pki/crl_test.go index 3c7848db78de..7627a982c624 100644 --- a/builtin/logical/pki/crl_test.go +++ b/builtin/logical/pki/crl_test.go @@ -15,8 +15,6 @@ import ( "github.com/hashicorp/go-secure-stdlib/parseutil" "github.com/hashicorp/vault/api" "github.com/hashicorp/vault/builtin/logical/pki/issuing" - "github.com/hashicorp/vault/builtin/logical/pki/pki_backend" - "github.com/hashicorp/vault/builtin/logical/pki/revocation" "github.com/hashicorp/vault/helper/constants" vaulthttp "github.com/hashicorp/vault/http" "github.com/hashicorp/vault/sdk/helper/testhelpers/schema" @@ -63,10 +61,10 @@ func TestBackend_CRLConfigUpdate(t *testing.T) { require.Equal(t, "24h", resp.Data["expiry"]) require.Equal(t, false, resp.Data["disable"]) - require.Equal(t, pki_backend.DefaultCrlConfig.OcspDisable, resp.Data["ocsp_disable"]) - require.Equal(t, pki_backend.DefaultCrlConfig.OcspExpiry, resp.Data["ocsp_expiry"]) - require.Equal(t, pki_backend.DefaultCrlConfig.AutoRebuild, resp.Data["auto_rebuild"]) - require.Equal(t, pki_backend.DefaultCrlConfig.AutoRebuildGracePeriod, resp.Data["auto_rebuild_grace_period"]) + require.Equal(t, defaultCrlConfig.OcspDisable, resp.Data["ocsp_disable"]) + require.Equal(t, defaultCrlConfig.OcspExpiry, resp.Data["ocsp_expiry"]) + require.Equal(t, defaultCrlConfig.AutoRebuild, resp.Data["auto_rebuild"]) + require.Equal(t, defaultCrlConfig.AutoRebuildGracePeriod, resp.Data["auto_rebuild_grace_period"]) } func TestBackend_CRLConfig(t *testing.T) { @@ -418,7 +416,7 @@ func TestCrlRebuilder(t *testing.T) { cb := newCRLBuilder(true /* can rebuild and write CRLs */) // Force an initial build - warnings, err := cb.Rebuild(sc, true) + warnings, err := cb.rebuild(sc, true) require.NoError(t, err, "Failed to rebuild CRL") require.Empty(t, warnings, "unexpectedly got warnings rebuilding CRL") @@ -426,7 +424,7 @@ func TestCrlRebuilder(t *testing.T) { crl1 := parseCrlPemBytes(t, resp.Data["http_raw_body"].([]byte)) // We shouldn't rebuild within this call. - warnings, err = cb.RebuildIfForced(sc) + warnings, err = cb.rebuildIfForced(sc) require.NoError(t, err, "Failed to rebuild if forced CRL") require.Empty(t, warnings, "unexpectedly got warnings rebuilding CRL") @@ -445,7 +443,7 @@ func TestCrlRebuilder(t *testing.T) { // This should rebuild the CRL cb.requestRebuildIfActiveNode(b) - warnings, err = cb.RebuildIfForced(sc) + warnings, err = cb.rebuildIfForced(sc) require.NoError(t, err, "Failed to rebuild if forced CRL") require.Empty(t, warnings, "unexpectedly got warnings rebuilding CRL") resp = requestCrlFromBackend(t, s, b) @@ -976,13 +974,13 @@ func TestAutoRebuild(t *testing.T) { require.NoError(t, err) require.NotNil(t, resp) require.NotNil(t, resp.Data) - require.Equal(t, resp.Data["expiry"], pki_backend.DefaultCrlConfig.Expiry) - require.Equal(t, resp.Data["disable"], pki_backend.DefaultCrlConfig.Disable) - require.Equal(t, resp.Data["ocsp_disable"], pki_backend.DefaultCrlConfig.OcspDisable) - require.Equal(t, resp.Data["auto_rebuild"], pki_backend.DefaultCrlConfig.AutoRebuild) - require.Equal(t, resp.Data["auto_rebuild_grace_period"], pki_backend.DefaultCrlConfig.AutoRebuildGracePeriod) - require.Equal(t, resp.Data["enable_delta"], pki_backend.DefaultCrlConfig.EnableDelta) - require.Equal(t, resp.Data["delta_rebuild_interval"], pki_backend.DefaultCrlConfig.DeltaRebuildInterval) + require.Equal(t, resp.Data["expiry"], defaultCrlConfig.Expiry) + require.Equal(t, resp.Data["disable"], defaultCrlConfig.Disable) + require.Equal(t, resp.Data["ocsp_disable"], defaultCrlConfig.OcspDisable) + require.Equal(t, resp.Data["auto_rebuild"], defaultCrlConfig.AutoRebuild) + require.Equal(t, resp.Data["auto_rebuild_grace_period"], defaultCrlConfig.AutoRebuildGracePeriod) + require.Equal(t, resp.Data["enable_delta"], defaultCrlConfig.EnableDelta) + require.Equal(t, resp.Data["delta_rebuild_interval"], defaultCrlConfig.DeltaRebuildInterval) // Safety guard: we play with rebuild timing below. _, err = client.Logical().Write("pki/config/crl", map[string]interface{}{ @@ -1061,7 +1059,7 @@ func TestAutoRebuild(t *testing.T) { require.NotNil(t, resp.Data) require.NotEmpty(t, resp.Data["value"]) revEntryValue := resp.Data["value"].(string) - var revInfo revocation.RevocationInfo + var revInfo revocationInfo err = json.Unmarshal([]byte(revEntryValue), &revInfo) require.NoError(t, err) require.Equal(t, revInfo.CertificateIssuer, issuing.IssuerID(rootIssuer)) @@ -1234,7 +1232,7 @@ func TestTidyIssuerAssociation(t *testing.T) { require.NotNil(t, entry) require.NotNil(t, entry.Value) - var leafInfo revocation.RevocationInfo + var leafInfo revocationInfo err = entry.DecodeJSON(&leafInfo) require.NoError(t, err) require.Equal(t, rootID, leafInfo.CertificateIssuer) diff --git a/builtin/logical/pki/crl_util.go b/builtin/logical/pki/crl_util.go index def00a5f11c6..4085d597417b 100644 --- a/builtin/logical/pki/crl_util.go +++ b/builtin/logical/pki/crl_util.go @@ -17,9 +17,6 @@ import ( "github.com/hashicorp/go-secure-stdlib/parseutil" "github.com/hashicorp/vault/builtin/logical/pki/issuing" - "github.com/hashicorp/vault/builtin/logical/pki/parsing" - "github.com/hashicorp/vault/builtin/logical/pki/pki_backend" - "github.com/hashicorp/vault/builtin/logical/pki/revocation" "github.com/hashicorp/vault/sdk/helper/certutil" "github.com/hashicorp/vault/sdk/helper/consts" "github.com/hashicorp/vault/sdk/helper/errutil" @@ -27,7 +24,7 @@ import ( ) const ( - revokedPath = revocation.RevokedPath + revokedPath = "revoked/" crossRevocationPrefix = "cross-revocation-queue/" crossRevocationPath = crossRevocationPrefix + "{{clusterId}}/" deltaWALLastBuildSerialName = "last-build-serial" @@ -41,6 +38,13 @@ const ( unifiedDeltaWALLastRevokedSerial = unifiedDeltaWALPath + deltaWALLastRevokedSerialName ) +type revocationInfo struct { + CertificateBytes []byte `json:"certificate_bytes"` + RevocationTime int64 `json:"revocation_time"` + RevocationTimeUTC time.Time `json:"revocation_time_utc"` + CertificateIssuer issuing.IssuerID `json:"issuer_id"` +} + type revocationRequest struct { RequestedAt time.Time `json:"requested_at"` } @@ -93,7 +97,7 @@ type CrlBuilder struct { _config sync.RWMutex dirty *atomic.Bool - config pki_backend.CrlConfig + config crlConfig haveInitializedConfig bool // Whether to invalidate our LastModifiedTime due to write on the @@ -108,8 +112,6 @@ type CrlBuilder struct { crossQueue *revocationQueue } -var _ pki_backend.CrlBuilderType = (*CrlBuilder)(nil) - const ( _ignoreForceFlag = true _enforceForceFlag = false @@ -124,7 +126,7 @@ func newCRLBuilder(canRebuild bool) *CrlBuilder { // to stabilize. lastDeltaRebuildCheck: time.Now(), dirty: &atomic.Bool{}, - config: pki_backend.DefaultCrlConfig, + config: defaultCrlConfig, invalidate: &atomic.Bool{}, haveInitializedQueue: &atomic.Bool{}, revQueue: newRevocationQueue(), @@ -135,14 +137,6 @@ func newCRLBuilder(canRebuild bool) *CrlBuilder { return builder } -func (cb *CrlBuilder) SetLastDeltaRebuildCheckTime(t time.Time) { - cb.lastDeltaRebuildCheck = t -} - -func (cb *CrlBuilder) ShouldInvalidate() bool { - return cb.invalidate.Load() -} - func (cb *CrlBuilder) markConfigDirty() { cb.dirty.Store(true) } @@ -169,7 +163,7 @@ func (cb *CrlBuilder) reloadConfigIfRequired(sc *storageContext) error { if config != nil { cb.config = *config } else { - cb.config = pki_backend.DefaultCrlConfig + cb.config = defaultCrlConfig } // Updated the config; unset dirty. @@ -180,7 +174,7 @@ func (cb *CrlBuilder) reloadConfigIfRequired(sc *storageContext) error { triggerChangeNotification = false // do not trigger on the initial loading of configuration. } - // Certain things need to be triggered on all server types when CrlConfig is loaded. + // Certain things need to be triggered on all server types when crlConfig is loaded. if triggerChangeNotification { cb.notifyOnConfigChange(sc, previousConfig, cb.config) } @@ -189,12 +183,12 @@ func (cb *CrlBuilder) reloadConfigIfRequired(sc *storageContext) error { return nil } -func (cb *CrlBuilder) notifyOnConfigChange(sc *storageContext, priorConfig pki_backend.CrlConfig, newConfig pki_backend.CrlConfig) { +func (cb *CrlBuilder) notifyOnConfigChange(sc *storageContext, priorConfig crlConfig, newConfig crlConfig) { // If you need to hook into a CRL configuration change across different server types // such as primary clusters as well as performance replicas, it is easier to do here than // in two places (API layer and in invalidateFunc) if priorConfig.UnifiedCRL != newConfig.UnifiedCRL && newConfig.UnifiedCRL { - sc.GetUnifiedTransferStatus().forceRun() + sc.Backend.GetUnifiedTransferStatus().forceRun() } if priorConfig.UseGlobalQueue != newConfig.UseGlobalQueue && newConfig.UseGlobalQueue { @@ -202,10 +196,10 @@ func (cb *CrlBuilder) notifyOnConfigChange(sc *storageContext, priorConfig pki_b } } -func (cb *CrlBuilder) GetConfigWithUpdate(sc pki_backend.StorageContext) (*pki_backend.CrlConfig, error) { +func (cb *CrlBuilder) getConfigWithUpdate(sc *storageContext) (*crlConfig, error) { // Config may mutate immediately after accessing, but will be freshly // fetched if necessary. - if err := cb.reloadConfigIfRequired(sc.(*storageContext)); err != nil { + if err := cb.reloadConfigIfRequired(sc); err != nil { return nil, err } @@ -216,12 +210,12 @@ func (cb *CrlBuilder) GetConfigWithUpdate(sc pki_backend.StorageContext) (*pki_b return &configCopy, nil } -func (cb *CrlBuilder) getConfigWithForcedUpdate(sc *storageContext) (*pki_backend.CrlConfig, error) { +func (cb *CrlBuilder) getConfigWithForcedUpdate(sc *storageContext) (*crlConfig, error) { cb.markConfigDirty() - return cb.GetConfigWithUpdate(sc) + return cb.getConfigWithUpdate(sc) } -func (cb *CrlBuilder) writeConfig(sc *storageContext, config *pki_backend.CrlConfig) (*pki_backend.CrlConfig, error) { +func (cb *CrlBuilder) writeConfig(sc *storageContext, config *crlConfig) (*crlConfig, error) { cb._config.Lock() defer cb._config.Unlock() @@ -234,7 +228,7 @@ func (cb *CrlBuilder) writeConfig(sc *storageContext, config *pki_backend.CrlCon if config != nil { cb.config = *config } else { - cb.config = pki_backend.DefaultCrlConfig + cb.config = defaultCrlConfig } triggerChangeNotification := true @@ -243,7 +237,7 @@ func (cb *CrlBuilder) writeConfig(sc *storageContext, config *pki_backend.CrlCon triggerChangeNotification = false // do not trigger on the initial loading of configuration. } - // Certain things need to be triggered on all server types when CrlConfig is loaded. + // Certain things need to be triggered on all server types when crlConfig is loaded. if triggerChangeNotification { cb.notifyOnConfigChange(sc, previousConfig, cb.config) } @@ -252,7 +246,7 @@ func (cb *CrlBuilder) writeConfig(sc *storageContext, config *pki_backend.CrlCon } func (cb *CrlBuilder) checkForAutoRebuild(sc *storageContext) error { - cfg, err := cb.GetConfigWithUpdate(sc) + cfg, err := cb.getConfigWithUpdate(sc) if err != nil { return err } @@ -297,9 +291,9 @@ func (cb *CrlBuilder) checkForAutoRebuild(sc *storageContext) error { // This may occur if the duration is empty; in that case // assume the default. The default should be valid and shouldn't // error. - defaultPeriod, defaultErr := parseutil.ParseDurationSecond(pki_backend.DefaultCrlConfig.AutoRebuildGracePeriod) + defaultPeriod, defaultErr := parseutil.ParseDurationSecond(defaultCrlConfig.AutoRebuildGracePeriod) if defaultErr != nil { - return fmt.Errorf("error checking for auto-rebuild status: unable to parse duration from both config's grace period (%v) and default grace period (%v):\n- config: %v\n- default: %w\n", cfg.AutoRebuildGracePeriod, pki_backend.DefaultCrlConfig.AutoRebuildGracePeriod, err, defaultErr) + return fmt.Errorf("error checking for auto-rebuild status: unable to parse duration from both config's grace period (%v) and default grace period (%v):\n- config: %v\n- default: %w\n", cfg.AutoRebuildGracePeriod, defaultCrlConfig.AutoRebuildGracePeriod, err, defaultErr) } period = defaultPeriod @@ -343,19 +337,19 @@ func (cb *CrlBuilder) flushCRLBuildTimeInvalidation(sc *storageContext) error { return nil } -// RebuildIfForced is to be called by readers or periodic functions that might need to trigger +// rebuildIfForced is to be called by readers or periodic functions that might need to trigger // a refresh of the CRL before the read occurs. -func (cb *CrlBuilder) RebuildIfForced(sc pki_backend.StorageContext) ([]string, error) { +func (cb *CrlBuilder) rebuildIfForced(sc *storageContext) ([]string, error) { if cb.forceRebuild.Load() { - return cb._doRebuild(sc.(*storageContext), true, _enforceForceFlag) + return cb._doRebuild(sc, true, _enforceForceFlag) } return nil, nil } // rebuild is to be called by various write apis that know the CRL is to be updated and can be now. -func (cb *CrlBuilder) Rebuild(sc pki_backend.StorageContext, forceNew bool) ([]string, error) { - return cb._doRebuild(sc.(*storageContext), forceNew, _ignoreForceFlag) +func (cb *CrlBuilder) rebuild(sc *storageContext, forceNew bool) ([]string, error) { + return cb._doRebuild(sc, forceNew, _ignoreForceFlag) } // requestRebuildIfActiveNode will schedule a rebuild of the CRL from the next read or write api call assuming we are the active node of a cluster @@ -393,9 +387,9 @@ func (cb *CrlBuilder) _doRebuild(sc *storageContext, forceNew bool, ignoreForceF return nil, nil } -func (cb *CrlBuilder) _getPresentDeltaWALForClearing(sc pki_backend.StorageContext, path string) ([]string, error) { +func (cb *CrlBuilder) _getPresentDeltaWALForClearing(sc *storageContext, path string) ([]string, error) { // Clearing of the delta WAL occurs after a new complete CRL has been built. - walSerials, err := sc.GetStorage().List(sc.GetContext(), path) + walSerials, err := sc.Storage.List(sc.Context, path) if err != nil { return nil, fmt.Errorf("error fetching list of delta WAL certificates to clear: %w", err) } @@ -406,12 +400,12 @@ func (cb *CrlBuilder) _getPresentDeltaWALForClearing(sc pki_backend.StorageConte return walSerials, nil } -func (cb *CrlBuilder) GetPresentLocalDeltaWALForClearing(sc pki_backend.StorageContext) ([]string, error) { +func (cb *CrlBuilder) getPresentLocalDeltaWALForClearing(sc *storageContext) ([]string, error) { return cb._getPresentDeltaWALForClearing(sc, localDeltaWALPath) } -func (cb *CrlBuilder) GetPresentUnifiedDeltaWALForClearing(sc pki_backend.StorageContext) ([]string, error) { - walClusters, err := sc.GetStorage().List(sc.GetContext(), unifiedDeltaWALPrefix) +func (cb *CrlBuilder) getPresentUnifiedDeltaWALForClearing(sc *storageContext) ([]string, error) { + walClusters, err := sc.Storage.List(sc.Context, unifiedDeltaWALPrefix) if err != nil { return nil, fmt.Errorf("error fetching list of clusters with delta WAL entries: %w", err) } @@ -425,7 +419,7 @@ func (cb *CrlBuilder) GetPresentUnifiedDeltaWALForClearing(sc pki_backend.Storag } // Here, we don't want to include the unifiedDeltaWALPrefix because - // ClearUnifiedDeltaWAL handles that for us. Instead, just include + // clearUnifiedDeltaWAL handles that for us. Instead, just include // the cluster identifier. for _, clusterPath := range clusterPaths { allPaths = append(allPaths, cluster+clusterPath) @@ -435,7 +429,7 @@ func (cb *CrlBuilder) GetPresentUnifiedDeltaWALForClearing(sc pki_backend.Storag return allPaths, nil } -func (cb *CrlBuilder) _clearDeltaWAL(sc pki_backend.StorageContext, walSerials []string, path string) error { +func (cb *CrlBuilder) _clearDeltaWAL(sc *storageContext, walSerials []string, path string) error { // Clearing of the delta WAL occurs after a new complete CRL has been built. for _, serial := range walSerials { // Don't remove our special entries! @@ -443,7 +437,7 @@ func (cb *CrlBuilder) _clearDeltaWAL(sc pki_backend.StorageContext, walSerials [ continue } - if err := sc.GetStorage().Delete(sc.GetContext(), path+serial); err != nil { + if err := sc.Storage.Delete(sc.Context, path+serial); err != nil { return fmt.Errorf("error clearing delta WAL certificate: %w", err) } } @@ -451,11 +445,11 @@ func (cb *CrlBuilder) _clearDeltaWAL(sc pki_backend.StorageContext, walSerials [ return nil } -func (cb *CrlBuilder) ClearLocalDeltaWAL(sc pki_backend.StorageContext, walSerials []string) error { +func (cb *CrlBuilder) clearLocalDeltaWAL(sc *storageContext, walSerials []string) error { return cb._clearDeltaWAL(sc, walSerials, localDeltaWALPath) } -func (cb *CrlBuilder) ClearUnifiedDeltaWAL(sc pki_backend.StorageContext, walSerials []string) error { +func (cb *CrlBuilder) clearUnifiedDeltaWAL(sc *storageContext, walSerials []string) error { return cb._clearDeltaWAL(sc, walSerials, unifiedDeltaWALPrefix) } @@ -469,7 +463,7 @@ func (cb *CrlBuilder) rebuildDeltaCRLsIfForced(sc *storageContext, override bool // This guarantee means we can avoid checking delta CRL expiry. Thus, // we only need to rebuild the delta CRL when we have new revocations, // within our time window for updating it. - cfg, err := cb.GetConfigWithUpdate(sc) + cfg, err := cb.getConfigWithUpdate(sc) if err != nil { return nil, err } @@ -522,7 +516,7 @@ func (cb *CrlBuilder) rebuildDeltaCRLsIfForced(sc *storageContext, override bool } // Finally, we must've needed to do the rebuild. Execute! - return cb.RebuildDeltaCRLsHoldingLock(sc, false) + return cb.rebuildDeltaCRLsHoldingLock(sc, false) } func (cb *CrlBuilder) _shouldRebuildLocalCRLs(sc *storageContext, override bool) (bool, error) { @@ -573,9 +567,9 @@ func (cb *CrlBuilder) _shouldRebuildLocalCRLs(sc *storageContext, override bool) func (cb *CrlBuilder) _shouldRebuildUnifiedCRLs(sc *storageContext, override bool) (bool, error) { // Unified CRL can only be built by the main cluster. - sysView := sc.System() - if sysView.ReplicationState().HasState(consts.ReplicationDRSecondary|consts.ReplicationPerformanceStandby) || - (!sysView.LocalMount() && sysView.ReplicationState().HasState(consts.ReplicationPerformanceSecondary)) { + b := sc.Backend + if b.System().ReplicationState().HasState(consts.ReplicationDRSecondary|consts.ReplicationPerformanceStandby) || + (!b.System().LocalMount() && b.System().ReplicationState().HasState(consts.ReplicationPerformanceSecondary)) { return false, nil } @@ -649,11 +643,11 @@ func (cb *CrlBuilder) rebuildDeltaCRLs(sc *storageContext, forceNew bool) ([]str cb._builder.Lock() defer cb._builder.Unlock() - return cb.RebuildDeltaCRLsHoldingLock(sc, forceNew) + return cb.rebuildDeltaCRLsHoldingLock(sc, forceNew) } -func (cb *CrlBuilder) RebuildDeltaCRLsHoldingLock(sc pki_backend.StorageContext, forceNew bool) ([]string, error) { - return buildAnyCRLs(sc.(*storageContext), forceNew, true /* building delta */) +func (cb *CrlBuilder) rebuildDeltaCRLsHoldingLock(sc *storageContext, forceNew bool) ([]string, error) { + return buildAnyCRLs(sc, forceNew, true /* building delta */) } func (cb *CrlBuilder) addCertForRevocationCheck(cluster, serial string) { @@ -686,14 +680,14 @@ func (cb *CrlBuilder) maybeGatherQueueForFirstProcess(sc *storageContext, isNotP return nil } - sc.Logger().Debug(fmt.Sprintf("gathering first time existing revocations")) + sc.Backend.Logger().Debug(fmt.Sprintf("gathering first time existing revocations")) clusters, err := sc.Storage.List(sc.Context, crossRevocationPrefix) if err != nil { return fmt.Errorf("failed to list cross-cluster revocation queue participating clusters: %w", err) } - sc.Logger().Debug(fmt.Sprintf("found %v clusters: %v", len(clusters), clusters)) + sc.Backend.Logger().Debug(fmt.Sprintf("found %v clusters: %v", len(clusters), clusters)) for cIndex, cluster := range clusters { cluster = cluster[0 : len(cluster)-1] @@ -703,7 +697,7 @@ func (cb *CrlBuilder) maybeGatherQueueForFirstProcess(sc *storageContext, isNotP return fmt.Errorf("failed to list cross-cluster revocation queue entries for cluster %v (%v): %w", cluster, cIndex, err) } - sc.Logger().Debug(fmt.Sprintf("found %v serials for cluster %v: %v", len(serials), cluster, serials)) + sc.Backend.Logger().Debug(fmt.Sprintf("found %v serials for cluster %v: %v", len(serials), cluster, serials)) for _, serial := range serials { if serial[len(serial)-1] == '/' { @@ -737,10 +731,10 @@ func (cb *CrlBuilder) maybeGatherQueueForFirstProcess(sc *storageContext, isNotP } func (cb *CrlBuilder) processRevocationQueue(sc *storageContext) error { - sc.Logger().Debug(fmt.Sprintf("starting to process revocation requests")) + sc.Backend.Logger().Debug(fmt.Sprintf("starting to process revocation requests")) - isNotPerfPrimary := sc.System().ReplicationState().HasState(consts.ReplicationDRSecondary|consts.ReplicationPerformanceStandby) || - (!sc.System().LocalMount() && sc.System().ReplicationState().HasState(consts.ReplicationPerformanceSecondary)) + isNotPerfPrimary := sc.Backend.System().ReplicationState().HasState(consts.ReplicationDRSecondary|consts.ReplicationPerformanceStandby) || + (!sc.Backend.System().LocalMount() && sc.Backend.System().ReplicationState().HasState(consts.ReplicationPerformanceSecondary)) if err := cb.maybeGatherQueueForFirstProcess(sc, isNotPerfPrimary); err != nil { return fmt.Errorf("failed to gather first queue: %w", err) @@ -749,14 +743,14 @@ func (cb *CrlBuilder) processRevocationQueue(sc *storageContext) error { revQueue := cb.revQueue.Iterate() removalQueue := cb.removalQueue.Iterate() - sc.Logger().Debug(fmt.Sprintf("gathered %v revocations and %v confirmation entries", len(revQueue), len(removalQueue))) + sc.Backend.Logger().Debug(fmt.Sprintf("gathered %v revocations and %v confirmation entries", len(revQueue), len(removalQueue))) - crlConfig, err := cb.GetConfigWithUpdate(sc) + crlConfig, err := cb.getConfigWithUpdate(sc) if err != nil { return err } - ourClusterId, err := sc.System().ClusterID(sc.Context) + ourClusterId, err := sc.Backend.System().ClusterID(sc.Context) if err != nil { return fmt.Errorf("unable to fetch clusterID to ignore local revocation entries: %w", err) } @@ -818,7 +812,7 @@ func (cb *CrlBuilder) processRevocationQueue(sc *storageContext) error { } if isNotPerfPrimary { - sc.Logger().Debug(fmt.Sprintf("not on perf primary so ignoring any revocation confirmations")) + sc.Backend.Logger().Debug(fmt.Sprintf("not on perf primary so ignoring any revocation confirmations")) // See note in pki/backend.go; this should be empty. cb.removalQueue.RemoveAll() @@ -854,9 +848,9 @@ func (cb *CrlBuilder) processRevocationQueue(sc *storageContext) error { } func (cb *CrlBuilder) processCrossClusterRevocations(sc *storageContext) error { - sc.Logger().Debug(fmt.Sprintf("starting to process unified revocations")) + sc.Backend.Logger().Debug(fmt.Sprintf("starting to process unified revocations")) - crlConfig, err := cb.GetConfigWithUpdate(sc) + crlConfig, err := cb.getConfigWithUpdate(sc) if err != nil { return err } @@ -867,9 +861,9 @@ func (cb *CrlBuilder) processCrossClusterRevocations(sc *storageContext) error { } crossQueue := cb.crossQueue.Iterate() - sc.Logger().Debug(fmt.Sprintf("gathered %v unified revocations entries", len(crossQueue))) + sc.Backend.Logger().Debug(fmt.Sprintf("gathered %v unified revocations entries", len(crossQueue))) - ourClusterId, err := sc.System().ClusterID(sc.Context) + ourClusterId, err := sc.Backend.System().ClusterID(sc.Context) if err != nil { return fmt.Errorf("unable to fetch clusterID to ignore local unified revocation entries: %w", err) } @@ -915,12 +909,56 @@ func (cb *CrlBuilder) processCrossClusterRevocations(sc *storageContext) error { return nil } +// Helper function to fetch a map of IssuerID->parsed cert for revocation +// usage. Unlike other paths, this needs to handle the legacy bundle +// more gracefully than rejecting it outright. +func fetchIssuerMapForRevocationChecking(sc *storageContext) (map[issuing.IssuerID]*x509.Certificate, error) { + var err error + var issuers []issuing.IssuerID + + if !sc.Backend.UseLegacyBundleCaStorage() { + issuers, err = sc.listIssuers() + if err != nil { + return nil, fmt.Errorf("could not fetch issuers list: %w", err) + } + } else { + // Hack: this isn't a real IssuerID, but it works for fetchCAInfo + // since it resolves the reference. + issuers = []issuing.IssuerID{legacyBundleShimID} + } + + issuerIDCertMap := make(map[issuing.IssuerID]*x509.Certificate, len(issuers)) + for _, issuer := range issuers { + _, bundle, caErr := sc.fetchCertBundleByIssuerId(issuer, false) + if caErr != nil { + return nil, fmt.Errorf("error fetching CA certificate for issuer id %v: %w", issuer, caErr) + } + + if bundle == nil { + return nil, fmt.Errorf("faulty reference: %v - CA info not found", issuer) + } + + parsedBundle, err := parseCABundle(sc.Context, sc.Backend, bundle) + if err != nil { + return nil, errutil.InternalError{Err: err.Error()} + } + + if parsedBundle.Certificate == nil { + return nil, errutil.InternalError{Err: "stored CA information not able to be parsed"} + } + + issuerIDCertMap[issuer] = parsedBundle.Certificate + } + + return issuerIDCertMap, nil +} + // Revoke a certificate from a given serial number if it is present in local // storage. -func tryRevokeCertBySerial(sc *storageContext, config *pki_backend.CrlConfig, serial string) (*logical.Response, error) { +func tryRevokeCertBySerial(sc *storageContext, config *crlConfig, serial string) (*logical.Response, error) { // revokeCert requires us to hold these locks before calling it. - sc.GetRevokeStorageLock().Lock() - defer sc.GetRevokeStorageLock().Unlock() + sc.Backend.GetRevokeStorageLock().Lock() + defer sc.Backend.GetRevokeStorageLock().Unlock() certEntry, err := fetchCertBySerial(sc, issuing.PathCerts, serial) if err != nil { @@ -945,24 +983,24 @@ func tryRevokeCertBySerial(sc *storageContext, config *pki_backend.CrlConfig, se } // Revokes a cert, and tries to be smart about error recovery -func revokeCert(sc *storageContext, config *pki_backend.CrlConfig, cert *x509.Certificate) (*logical.Response, error) { +func revokeCert(sc *storageContext, config *crlConfig, cert *x509.Certificate) (*logical.Response, error) { // As this backend is self-contained and this function does not hook into // third parties to manage users or resources, if the mount is tainted, // revocation doesn't matter anyways -- the CRL that would be written will // be immediately blown away by the view being cleared. So we can simply // fast path a successful exit. - if sc.System().Tainted() { + if sc.Backend.System().Tainted() { return nil, nil } - colonSerial := parsing.SerialFromCert(cert) - hyphenSerial := parsing.NormalizeSerialForStorage(colonSerial) + colonSerial := serialFromCert(cert) + hyphenSerial := normalizeSerial(colonSerial) // Validate that no issuers match the serial number to be revoked. We need // to gracefully degrade to the legacy cert bundle when it is required, as // secondary PR clusters might not have been upgraded, but still need to // handle revoking certs. - issuerIDCertMap, err := revocation.FetchIssuerMapForRevocationChecking(sc) + issuerIDCertMap, err := fetchIssuerMapForRevocationChecking(sc) if err != nil { return nil, err } @@ -975,7 +1013,7 @@ func revokeCert(sc *storageContext, config *pki_backend.CrlConfig, cert *x509.Ce } } - curRevInfo, err := fetchRevocationInfo(sc, colonSerial) + curRevInfo, err := sc.fetchRevocationInfo(colonSerial) if err != nil { return nil, err } @@ -1002,7 +1040,7 @@ func revokeCert(sc *storageContext, config *pki_backend.CrlConfig, cert *x509.Ce } currTime := time.Now() - revInfo := revocation.RevocationInfo{ + revInfo := revocationInfo{ CertificateBytes: cert.Raw, RevocationTime: currTime.Unix(), RevocationTimeUTC: currTime.UTC(), @@ -1010,14 +1048,14 @@ func revokeCert(sc *storageContext, config *pki_backend.CrlConfig, cert *x509.Ce // We may not find an issuer with this certificate; that's fine so // ignore the return value. - revInfo.AssociateRevokedCertWithIsssuer(cert, issuerIDCertMap) + associateRevokedCertWithIsssuer(&revInfo, cert, issuerIDCertMap) revEntry, err := logical.StorageEntryJSON(revokedPath+hyphenSerial, revInfo) if err != nil { return nil, fmt.Errorf("error creating revocation entry: %w", err) } - certCounter := sc.GetCertificateCounter() + certCounter := sc.Backend.GetCertificateCounter() certsCounted := certCounter.IsInitialized() err = sc.Storage.Put(sc.Context, revEntry) if err != nil { @@ -1040,20 +1078,20 @@ func revokeCert(sc *storageContext, config *pki_backend.CrlConfig, cert *x509.Ce // the unified storage space through a periodic function. failedWritingUnifiedCRL := false if config.UnifiedCRL { - entry := &revocation.UnifiedRevocationEntry{ + entry := &unifiedRevocationEntry{ SerialNumber: colonSerial, CertExpiration: cert.NotAfter, RevocationTimeUTC: revInfo.RevocationTimeUTC, CertificateIssuer: revInfo.CertificateIssuer, } - ignoreErr := revocation.WriteUnifiedRevocationEntry(sc.GetContext(), sc.GetStorage(), entry) + ignoreErr := writeUnifiedRevocationEntry(sc, entry) if ignoreErr != nil { // Just log the error if we fail to write across clusters, a separate background // thread will reattempt it later on as we have the local write done. - sc.Logger().Error("Failed to write unified revocation entry, will re-attempt later", + sc.Backend.Logger().Error("Failed to write unified revocation entry, will re-attempt later", "serial_number", colonSerial, "error", ignoreErr) - sc.GetUnifiedTransferStatus().forceRun() + sc.Backend.GetUnifiedTransferStatus().forceRun() resp.AddWarning(fmt.Sprintf("Failed to write unified revocation entry, will re-attempt later: %v", err)) failedWritingUnifiedCRL = true @@ -1065,7 +1103,7 @@ func revokeCert(sc *storageContext, config *pki_backend.CrlConfig, cert *x509.Ce // already rebuilt the full CRL so the Delta WAL will be cleared // afterwards. Writing an entry only to immediately remove it // isn't necessary. - warnings, crlErr := sc.CrlBuilder().Rebuild(sc, false) + warnings, crlErr := sc.Backend.CrlBuilder().rebuild(sc, false) if crlErr != nil { switch crlErr.(type) { case errutil.UserError: @@ -1086,7 +1124,7 @@ func revokeCert(sc *storageContext, config *pki_backend.CrlConfig, cert *x509.Ce return resp, nil } -func writeRevocationDeltaWALs(sc *storageContext, config *pki_backend.CrlConfig, resp *logical.Response, failedWritingUnifiedCRL bool, hyphenSerial string, colonSerial string) error { +func writeRevocationDeltaWALs(sc *storageContext, config *crlConfig, resp *logical.Response, failedWritingUnifiedCRL bool, hyphenSerial string, colonSerial string) error { if err := writeSpecificRevocationDeltaWALs(sc, hyphenSerial, colonSerial, localDeltaWALPath); err != nil { return fmt.Errorf("failed to write local delta WAL entry: %w", err) } @@ -1108,9 +1146,9 @@ func writeRevocationDeltaWALs(sc *storageContext, config *pki_backend.CrlConfig, if ignoredErr := writeSpecificRevocationDeltaWALs(sc, hyphenSerial, colonSerial, unifiedDeltaWALPath); ignoredErr != nil { // Just log the error if we fail to write across clusters, a separate background // thread will reattempt it later on as we have the local write done. - sc.Logger().Error("Failed to write cross-cluster delta WAL entry, will re-attempt later", + sc.Backend.Logger().Error("Failed to write cross-cluster delta WAL entry, will re-attempt later", "serial_number", colonSerial, "error", ignoredErr) - sc.GetUnifiedTransferStatus().forceRun() + sc.Backend.GetUnifiedTransferStatus().forceRun() resp.AddWarning(fmt.Sprintf("Failed to write cross-cluster delta WAL entry, will re-attempt later: %v", ignoredErr)) } @@ -1205,7 +1243,8 @@ func buildAnyCRLs(sc *storageContext, forceNew bool, isDelta bool) ([]string, er var wasLegacy bool // First, fetch an updated copy of the CRL config. We'll pass this into buildCRL. - globalCRLConfig, err := sc.CrlBuilder().GetConfigWithUpdate(sc) + crlBuilder := sc.Backend.CrlBuilder() + globalCRLConfig, err := crlBuilder.getConfigWithUpdate(sc) if err != nil { return nil, fmt.Errorf("error building CRL: while updating config: %w", err) } @@ -1222,7 +1261,7 @@ func buildAnyCRLs(sc *storageContext, forceNew bool, isDelta bool) ([]string, er return nil, nil } - if !sc.UseLegacyBundleCaStorage() { + if !sc.Backend.UseLegacyBundleCaStorage() { issuers, err = sc.listIssuers() if err != nil { return nil, fmt.Errorf("error building CRL: while listing issuers: %w", err) @@ -1330,13 +1369,13 @@ func buildAnyCRLs(sc *storageContext, forceNew bool, isDelta bool) ([]string, er if !isDelta { // After we've confirmed the primary CRLs have built OK, go ahead and // clear the delta CRL WAL and rebuild it. - if err := sc.CrlBuilder().ClearLocalDeltaWAL(sc, currLocalDeltaSerials); err != nil { + if err := crlBuilder.clearLocalDeltaWAL(sc, currLocalDeltaSerials); err != nil { return nil, fmt.Errorf("error building CRLs: unable to clear Delta WAL: %w", err) } - if err := sc.CrlBuilder().ClearUnifiedDeltaWAL(sc, currUnifiedDeltaSerials); err != nil { + if err := crlBuilder.clearUnifiedDeltaWAL(sc, currUnifiedDeltaSerials); err != nil { return nil, fmt.Errorf("error building CRLs: unable to clear Delta WAL: %w", err) } - deltaWarnings, err := sc.CrlBuilder().RebuildDeltaCRLsHoldingLock(sc, forceNew) + deltaWarnings, err := crlBuilder.rebuildDeltaCRLsHoldingLock(sc, forceNew) if err != nil { return nil, fmt.Errorf("error building CRLs: unable to rebuild empty Delta WAL: %w", err) } @@ -1370,7 +1409,7 @@ func getLastWALSerial(sc *storageContext, path string) (string, error) { func buildAnyLocalCRLs( sc *storageContext, issuersConfig *issuing.IssuerConfigEntry, - globalCRLConfig *pki_backend.CrlConfig, + globalCRLConfig *crlConfig, issuers []issuing.IssuerID, issuerIDEntryMap map[issuing.IssuerID]*issuing.IssuerEntry, issuerIDCertMap map[issuing.IssuerID]*x509.Certificate, @@ -1400,7 +1439,7 @@ func buildAnyLocalCRLs( // visible now, should also be visible on the complete CRL we're writing. var currDeltaCerts []string if !isDelta { - currDeltaCerts, err = sc.CrlBuilder().GetPresentLocalDeltaWALForClearing(sc) + currDeltaCerts, err = sc.Backend.CrlBuilder().getPresentLocalDeltaWALForClearing(sc) if err != nil { return nil, nil, fmt.Errorf("error building CRLs: unable to get present delta WAL entries for removal: %w", err) } @@ -1464,7 +1503,7 @@ func buildAnyLocalCRLs( if isDelta { // Update our last build time here so we avoid checking for new certs // for a while. - sc.CrlBuilder().SetLastDeltaRebuildCheckTime(time.Now()) + sc.Backend.CrlBuilder().lastDeltaRebuildCheck = time.Now() if len(lastDeltaSerial) > 0 { // When we have a last delta serial, write out the relevant info @@ -1489,7 +1528,7 @@ func buildAnyLocalCRLs( func buildAnyUnifiedCRLs( sc *storageContext, issuersConfig *issuing.IssuerConfigEntry, - globalCRLConfig *pki_backend.CrlConfig, + globalCRLConfig *crlConfig, issuers []issuing.IssuerID, issuerIDEntryMap map[issuing.IssuerID]*issuing.IssuerEntry, issuerIDCertMap map[issuing.IssuerID]*x509.Certificate, @@ -1502,9 +1541,9 @@ func buildAnyUnifiedCRLs( var warnings []string // Unified CRL can only be built by the main cluster. - sysView := sc.System() - if sysView.ReplicationState().HasState(consts.ReplicationDRSecondary|consts.ReplicationPerformanceStandby) || - (!sysView.LocalMount() && sysView.ReplicationState().HasState(consts.ReplicationPerformanceSecondary)) { + b := sc.Backend + if b.System().ReplicationState().HasState(consts.ReplicationDRSecondary|consts.ReplicationPerformanceStandby) || + (!b.System().LocalMount() && b.System().ReplicationState().HasState(consts.ReplicationPerformanceSecondary)) { return nil, nil, nil } @@ -1543,7 +1582,7 @@ func buildAnyUnifiedCRLs( // visible now, should also be visible on the complete CRL we're writing. var currDeltaCerts []string if !isDelta { - currDeltaCerts, err = sc.CrlBuilder().GetPresentUnifiedDeltaWALForClearing(sc) + currDeltaCerts, err = sc.Backend.CrlBuilder().getPresentUnifiedDeltaWALForClearing(sc) if err != nil { return nil, nil, fmt.Errorf("error building CRLs: unable to get present delta WAL entries for removal: %w", err) } @@ -1607,7 +1646,7 @@ func buildAnyUnifiedCRLs( if isDelta { // Update our last build time here so we avoid checking for new certs // for a while. - sc.CrlBuilder().SetLastDeltaRebuildCheckTime(time.Now()) + sc.Backend.CrlBuilder().lastDeltaRebuildCheck = time.Now() // Persist all of our known last revoked serial numbers here, as the // last seen serial during build. This will allow us to detect if any @@ -1640,7 +1679,7 @@ func buildAnyUnifiedCRLs( func buildAnyCRLsWithCerts( sc *storageContext, issuersConfig *issuing.IssuerConfigEntry, - globalCRLConfig *pki_backend.CrlConfig, + globalCRLConfig *crlConfig, internalCRLConfig *issuing.InternalCRLConfigEntry, issuers []issuing.IssuerID, issuerIDEntryMap map[issuing.IssuerID]*issuing.IssuerEntry, @@ -1829,7 +1868,7 @@ func buildAnyCRLsWithCerts( return warnings, nil } -func isRevInfoIssuerValid(revInfo *revocation.RevocationInfo, issuerIDCertMap map[issuing.IssuerID]*x509.Certificate) bool { +func isRevInfoIssuerValid(revInfo *revocationInfo, issuerIDCertMap map[issuing.IssuerID]*x509.Certificate) bool { if len(revInfo.CertificateIssuer) > 0 { issuerId := revInfo.CertificateIssuer if _, issuerExists := issuerIDCertMap[issuerId]; issuerExists { @@ -1840,6 +1879,20 @@ func isRevInfoIssuerValid(revInfo *revocation.RevocationInfo, issuerIDCertMap ma return false } +func associateRevokedCertWithIsssuer(revInfo *revocationInfo, revokedCert *x509.Certificate, issuerIDCertMap map[issuing.IssuerID]*x509.Certificate) bool { + for issuerId, issuerCert := range issuerIDCertMap { + if bytes.Equal(revokedCert.RawIssuer, issuerCert.RawSubject) { + if err := revokedCert.CheckSignatureFrom(issuerCert); err == nil { + // Valid mapping. Add it to the specified entry. + revInfo.CertificateIssuer = issuerId + return true + } + } + } + + return false +} + func getLocalRevokedCertEntries(sc *storageContext, issuerIDCertMap map[issuing.IssuerID]*x509.Certificate, isDelta bool) ([]pkix.RevokedCertificate, map[issuing.IssuerID][]pkix.RevokedCertificate, error) { var unassignedCerts []pkix.RevokedCertificate revokedCertsMap := make(map[issuing.IssuerID][]pkix.RevokedCertificate) @@ -1867,7 +1920,7 @@ func getLocalRevokedCertEntries(sc *storageContext, issuerIDCertMap map[issuing. continue } - var revInfo revocation.RevocationInfo + var revInfo revocationInfo revokedEntry, err := sc.Storage.Get(sc.Context, revokedPath+serial) if err != nil { return nil, nil, errutil.InternalError{Err: fmt.Sprintf("unable to fetch revoked cert with serial %s: %s", serial, err)} @@ -1944,7 +1997,7 @@ func getLocalRevokedCertEntries(sc *storageContext, issuerIDCertMap map[issuing. } // Now we need to assign the revoked certificate to an issuer. - foundParent := revInfo.AssociateRevokedCertWithIsssuer(revokedCert, issuerIDCertMap) + foundParent := associateRevokedCertWithIsssuer(&revInfo, revokedCert, issuerIDCertMap) if !foundParent { // If the parent isn't found, add it to the unassigned bucket. unassignedCerts = append(unassignedCerts, newRevCert) @@ -2031,7 +2084,7 @@ func getUnifiedRevokedCertEntries(sc *storageContext, issuerIDCertMap map[issuin continue } - var xRevEntry revocation.UnifiedRevocationEntry + var xRevEntry unifiedRevocationEntry if err := entryRaw.DecodeJSON(&xRevEntry); err != nil { return nil, nil, fmt.Errorf("failed json decoding of unified revocation entry at path %v: %w ", serialPath, err) } @@ -2101,7 +2154,7 @@ func augmentWithRevokedIssuers(issuerIDEntryMap map[issuing.IssuerID]*issuing.Is // Builds a CRL by going through the list of revoked certificates and building // a new CRL with the stored revocation times and serial numbers. -func buildCRL(sc *storageContext, crlInfo *pki_backend.CrlConfig, forceNew bool, thisIssuerId issuing.IssuerID, revoked []pkix.RevokedCertificate, identifier issuing.CrlID, crlNumber int64, isUnified bool, isDelta bool, lastCompleteNumber int64) (*time.Time, error) { +func buildCRL(sc *storageContext, crlInfo *crlConfig, forceNew bool, thisIssuerId issuing.IssuerID, revoked []pkix.RevokedCertificate, identifier issuing.CrlID, crlNumber int64, isUnified bool, isDelta bool, lastCompleteNumber int64) (*time.Time, error) { var revokedCerts []pkix.RevokedCertificate crlLifetime, err := parseutil.ParseDurationSecond(crlInfo.Expiry) @@ -2193,6 +2246,6 @@ WRITE: // shouldLocalPathsUseUnified assuming a legacy path for a CRL/OCSP request, does our // configuration say we should be returning the unified response or not -func shouldLocalPathsUseUnified(cfg *pki_backend.CrlConfig) bool { +func shouldLocalPathsUseUnified(cfg *crlConfig) bool { return cfg.UnifiedCRL && cfg.UnifiedCRLOnExistingPaths } diff --git a/builtin/logical/pki/fields.go b/builtin/logical/pki/fields.go index dfeec9df4bb3..28884742689b 100644 --- a/builtin/logical/pki/fields.go +++ b/builtin/logical/pki/fields.go @@ -584,11 +584,6 @@ primary node.`, Description: `Set to true to enable tidying up certificate metadata`, } - fields["tidy_cmpv2_nonce_store"] = &framework.FieldSchema{ - Type: framework.TypeBool, - Description: `Set to true to enable tidying up the CMPv2 nonce store`, - } - return fields } @@ -661,33 +656,3 @@ RSA key-type issuer. Defaults to false.`, return fields } - -func addCACertKeyUsage(fields map[string]*framework.FieldSchema) map[string]*framework.FieldSchema { - fields["key_usage"] = &framework.FieldSchema{ // Same Name as Leaf-Cert Field, and CA CSR Field, but Description and Default Differ - Type: framework.TypeCommaStringSlice, - Default: []string{"CertSign", "CRLSign"}, - Description: `This list of key usages (not extended key usages) will be -added to the existing set of key usages, CRL,CertSign, on -the generated certificate. Valid values can be found at -https://golang.org/pkg/crypto/x509/#KeyUsage -- simply drop -the "KeyUsage" part of the name. To use the issuer for -CMPv2, DigitalSignature must be set.`, - } - - return fields -} - -func addCaCsrKeyUsage(fields map[string]*framework.FieldSchema) map[string]*framework.FieldSchema { - fields["key_usage"] = &framework.FieldSchema{ // Same Name as Leaf-Cert, CA-Cert Field, but Description and Default Differ - Type: framework.TypeCommaStringSlice, - Default: []string{}, - Description: `Specifies key_usage to encode in the certificate signing -request. This is a comma-separated string or list of key -usages (not extended key usages). Valid values can be found -at https://golang.org/pkg/crypto/x509/#KeyUsage -- simply -drop the "KeyUsage" part of the name. If not set, key -usage will not appear on the CSR.`, - } - - return fields -} diff --git a/builtin/logical/pki/issuing/context.go b/builtin/logical/pki/issuing/context.go deleted file mode 100644 index daa08a9ee70f..000000000000 --- a/builtin/logical/pki/issuing/context.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package issuing - -import "context" - -// IssuerRoleContext combines in a single struct an issuer and a role that we should -// leverage to issue a certificate along with the -type IssuerRoleContext struct { - context.Context - Role *RoleEntry - Issuer *IssuerEntry -} - -func NewIssuerRoleContext(ctx context.Context, issuer *IssuerEntry, role *RoleEntry) IssuerRoleContext { - return IssuerRoleContext{ - Context: ctx, - Role: role, - Issuer: issuer, - } -} diff --git a/builtin/logical/pki/issuing/issue_common.go b/builtin/logical/pki/issuing/issue_common.go index b1a67e2feb33..a2db75d58484 100644 --- a/builtin/logical/pki/issuing/issue_common.go +++ b/builtin/logical/pki/issuing/issue_common.go @@ -17,6 +17,7 @@ import ( "github.com/hashicorp/go-secure-stdlib/strutil" "github.com/hashicorp/vault/builtin/logical/pki/parsing" + "github.com/hashicorp/vault/builtin/logical/pki/pki_backend" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/helper/certutil" "github.com/hashicorp/vault/sdk/helper/errutil" @@ -63,12 +64,6 @@ type EntityInfo struct { EntityID string } -type CertificateCounter interface { - IsInitialized() bool - IncrementTotalCertificatesCount(certsCounted bool, newSerial string) - IncrementTotalRevokedCertificatesCount(certsCounted bool, newSerial string) -} - func NewEntityInfoFromReq(req *logical.Request) EntityInfo { if req == nil { return EntityInfo{} @@ -91,7 +86,6 @@ type CreationBundleInput interface { GetOptionalSkid() (interface{}, bool) IsUserIdInSchema() (interface{}, bool) GetUserIds() []string - IgnoreCSRSignature() bool } // GenerateCreationBundle is a shared function that reads parameters supplied @@ -429,7 +423,6 @@ func GenerateCreationBundle(b logical.SystemView, role *RoleEntry, entityInfo En NotBeforeDuration: role.NotBeforeDuration, ForceAppendCaChain: caSign != nil, SKID: skid, - IgnoreCSRSignature: cb.IgnoreCSRSignature(), }, SigningBundle: caSign, CSR: csr, @@ -1019,7 +1012,7 @@ func ApplyIssuerLeafNotAfterBehavior(caSign *certutil.CAInfoBundle, notAfter tim } // StoreCertificate given a certificate bundle that was signed, persist the certificate to storage -func StoreCertificate(ctx context.Context, s logical.Storage, certCounter CertificateCounter, certBundle *certutil.ParsedCertBundle) error { +func StoreCertificate(ctx context.Context, s logical.Storage, certCounter pki_backend.CertificateCounter, certBundle *certutil.ParsedCertBundle) error { hyphenSerialNumber := parsing.NormalizeSerialForStorageFromBigInt(certBundle.Certificate.SerialNumber) key := PathCerts + hyphenSerialNumber certsCounted := certCounter.IsInitialized() diff --git a/builtin/logical/pki/issuing/issuers.go b/builtin/logical/pki/issuing/issuers.go index 9ceff5b13cf2..a3e365815797 100644 --- a/builtin/logical/pki/issuing/issuers.go +++ b/builtin/logical/pki/issuing/issuers.go @@ -4,7 +4,6 @@ package issuing import ( - "bytes" "context" "crypto/x509" "fmt" @@ -44,13 +43,6 @@ const ( LegacyCertBundlePath = "config/ca_bundle" LegacyBundleShimID = IssuerID("legacy-entry-shim-id") LegacyBundleShimKeyID = KeyID("legacy-entry-shim-key-id") - - LegacyCRLPath = "crl" - DeltaCRLPath = "delta-crl" - DeltaCRLPathSuffix = "-delta" - UnifiedCRLPath = "unified-crl" - UnifiedDeltaCRLPath = "unified-delta-crl" - UnifiedCRLPathPrefix = "unified-" ) type IssuerID string @@ -139,10 +131,8 @@ type IssuerEntry struct { Version uint `json:"version"` } -// GetCertificate returns a x509.Certificate of the CA certificate -// represented by this issuer. func (i IssuerEntry) GetCertificate() (*x509.Certificate, error) { - cert, err := parsing.ParseCertificateFromString(i.Certificate) + cert, err := parsing.ParseCertificateFromBytes([]byte(i.Certificate)) if err != nil { return nil, errutil.InternalError{Err: fmt.Sprintf("unable to parse certificate from issuer: %s: %v", err.Error(), i.ID)} } @@ -150,32 +140,6 @@ func (i IssuerEntry) GetCertificate() (*x509.Certificate, error) { return cert, nil } -// GetFullCaChain returns a slice of x509.Certificate values of this issuer full ca chain, -// which starts with the CA certificate represented by this issuer followed by the entire CA chain -func (i IssuerEntry) GetFullCaChain() ([]*x509.Certificate, error) { - var chains []*x509.Certificate - issuerCert, err := i.GetCertificate() - if err != nil { - return nil, err - } - - chains = append(chains, issuerCert) - - for rangeI, chainVal := range i.CAChain { - parsedChainVal, err := parsing.ParseCertificateFromString(chainVal) - if err != nil { - return nil, fmt.Errorf("error parsing issuer %s ca chain index value [%d]: %w", i.ID, rangeI, err) - } - - if bytes.Equal(parsedChainVal.Raw, issuerCert.Raw) { - continue - } - chains = append(chains, parsedChainVal) - } - - return chains, nil -} - func (i IssuerEntry) EnsureUsage(usage IssuerUsage) error { // We want to spit out a nice error message about missing usages. if i.Usage.HasUsage(usage) { @@ -245,29 +209,6 @@ func (i IssuerEntry) CanMaybeSignWithAlgo(algo x509.SignatureAlgorithm) error { return fmt.Errorf("unable to use issuer of type %v to sign with %v key type", cert.PublicKeyAlgorithm.String(), algo.String()) } -// ResolveAndFetchIssuerForIssuance takes a name or uuid referencing an issuer, loads the issuer -// and validates that we have the associated private key and is allowed to perform issuance operations. -func ResolveAndFetchIssuerForIssuance(ctx context.Context, s logical.Storage, issuerName string) (*IssuerEntry, error) { - if len(issuerName) == 0 { - return nil, fmt.Errorf("unable to fetch pki issuer: empty issuer name") - } - issuerId, err := ResolveIssuerReference(ctx, s, issuerName) - if err != nil { - return nil, fmt.Errorf("failed to resolve issuer %s: %w", issuerName, err) - } - - issuer, err := FetchIssuerById(ctx, s, issuerId) - if err != nil { - return nil, fmt.Errorf("failed to load issuer %s: %w", issuerName, err) - } - - if issuer.Usage.HasUsage(IssuanceUsage) && len(issuer.KeyID) > 0 { - return issuer, nil - } - - return nil, fmt.Errorf("issuer %s missing proper issuance usage or doesn't have associated key", issuerName) -} - func ResolveIssuerReference(ctx context.Context, s logical.Storage, reference string) (IssuerID, error) { if reference == DefaultRef { // Handle fetching the default issuer. @@ -551,38 +492,3 @@ func GetLegacyCertBundle(ctx context.Context, s logical.Storage) (*IssuerEntry, return issuer, cb, nil } - -func ResolveIssuerCRLPath(ctx context.Context, storage logical.Storage, useLegacyBundleCaStorage bool, reference string, unified bool) (string, error) { - if useLegacyBundleCaStorage { - return "crl", nil - } - - issuer, err := ResolveIssuerReference(ctx, storage, reference) - if err != nil { - return "crl", err - } - - var crlConfig *InternalCRLConfigEntry - if unified { - crlConfig, err = GetUnifiedCRLConfig(ctx, storage) - if err != nil { - return "crl", err - } - } else { - crlConfig, err = GetLocalCRLConfig(ctx, storage) - if err != nil { - return "crl", err - } - } - - if crlId, ok := crlConfig.IssuerIDCRLMap[issuer]; ok && len(crlId) > 0 { - path := fmt.Sprintf("crls/%v", crlId) - if unified { - path = ("unified-") + path - } - - return path, nil - } - - return "crl", fmt.Errorf("unable to find CRL for issuer: id:%v/ref:%v", issuer, reference) -} diff --git a/builtin/logical/pki/issuing/keys.go b/builtin/logical/pki/issuing/keys.go index c0088117435d..0e703ddc6cad 100644 --- a/builtin/logical/pki/issuing/keys.go +++ b/builtin/logical/pki/issuing/keys.go @@ -5,8 +5,6 @@ package issuing import ( "context" - "crypto" - "encoding/pem" "fmt" "github.com/hashicorp/vault/builtin/logical/pki/managed_key" @@ -152,34 +150,3 @@ func GetManagedKeyUUID(key *KeyEntry) (managed_key.UUIDKey, error) { } return managed_key.ExtractManagedKeyId([]byte(key.PrivateKey)) } - -func GetSignerFromKeyEntry(ctx context.Context, mkv managed_key.PkiManagedKeyView, keyEntry *KeyEntry) (crypto.Signer, certutil.PrivateKeyType, error) { - if keyEntry.PrivateKeyType == certutil.UnknownPrivateKey { - return nil, certutil.UnknownPrivateKey, fmt.Errorf("unsupported unknown private key type for key: %s (%s)", keyEntry.ID, keyEntry.Name) - } - - if keyEntry.IsManagedPrivateKey() { - managedKeyId, err := GetManagedKeyUUID(keyEntry) - if err != nil { - return nil, certutil.UnknownPrivateKey, fmt.Errorf("unable to get managed key uuid: %w", err) - } - bundle, actualKeyType, err := managed_key.CreateKmsKeyBundle(ctx, mkv, managedKeyId) - if err != nil { - return nil, certutil.UnknownPrivateKey, fmt.Errorf("failed to create kms key bundle from managed key uuid %s: %w", managedKeyId, err) - } - - // The bundle's PrivateKeyType value is set to a ManagedKeyType so use the actual key type value - return bundle.PrivateKey, actualKeyType, nil - } - - pemBlock, _ := pem.Decode([]byte(keyEntry.PrivateKey)) - if pemBlock == nil { - return nil, certutil.UnknownPrivateKey, fmt.Errorf("no data found in PEM block") - } - - signer, _, err := certutil.ParseDERKey(pemBlock.Bytes) - if err != nil { - return nil, certutil.UnknownPrivateKey, fmt.Errorf("failed to parse PEM block: %w", err) - } - return signer, keyEntry.PrivateKeyType, nil -} diff --git a/builtin/logical/pki/issuing/sign_cert.go b/builtin/logical/pki/issuing/sign_cert.go index c6548f69521e..773e8b2a96d2 100644 --- a/builtin/logical/pki/issuing/sign_cert.go +++ b/builtin/logical/pki/issuing/sign_cert.go @@ -23,26 +23,20 @@ type SignCertInput interface { GetPermittedDomains() []string } -func NewBasicSignCertInput(csr *x509.CertificateRequest, isCA, useCSRValues bool) BasicSignCertInput { - return NewBasicSignCertInputWithIgnore(csr, isCA, useCSRValues, false) -} - -func NewBasicSignCertInputWithIgnore(csr *x509.CertificateRequest, isCA, useCSRValues, ignoreCsrSignature bool) BasicSignCertInput { +func NewBasicSignCertInput(csr *x509.CertificateRequest, isCA bool, useCSRValues bool) BasicSignCertInput { return BasicSignCertInput{ - isCA: isCA, - useCSRValues: useCSRValues, - csr: csr, - ignoreCsrSignature: ignoreCsrSignature, + isCA: isCA, + useCSRValues: useCSRValues, + csr: csr, } } var _ SignCertInput = BasicSignCertInput{} type BasicSignCertInput struct { - isCA bool - useCSRValues bool - csr *x509.CertificateRequest - ignoreCsrSignature bool + isCA bool + useCSRValues bool + csr *x509.CertificateRequest } func (b BasicSignCertInput) GetTTL() int { @@ -97,10 +91,6 @@ func (b BasicSignCertInput) GetCSR() (*x509.CertificateRequest, error) { return b.csr, nil } -func (b BasicSignCertInput) IgnoreCSRSignature() bool { - return b.ignoreCsrSignature -} - func (b BasicSignCertInput) IsCA() bool { return b.isCA } diff --git a/builtin/logical/pki/key_util.go b/builtin/logical/pki/key_util.go index 6fe17d41e1cd..c8538908aafe 100644 --- a/builtin/logical/pki/key_util.go +++ b/builtin/logical/pki/key_util.go @@ -17,7 +17,7 @@ import ( ) func comparePublicKey(sc *storageContext, key *issuing.KeyEntry, publicKey crypto.PublicKey) (bool, error) { - publicKeyForKeyEntry, err := getPublicKey(sc.Context, sc.GetPkiManagedView(), key) + publicKeyForKeyEntry, err := getPublicKey(sc.Context, sc.Backend, key) if err != nil { return false, err } @@ -25,9 +25,9 @@ func comparePublicKey(sc *storageContext, key *issuing.KeyEntry, publicKey crypt return certutil.ComparePublicKeysAndType(publicKeyForKeyEntry, publicKey) } -func getPublicKey(ctx context.Context, mkv managed_key.PkiManagedKeyView, key *issuing.KeyEntry) (crypto.PublicKey, error) { +func getPublicKey(ctx context.Context, b *backend, key *issuing.KeyEntry) (crypto.PublicKey, error) { if key.PrivateKeyType == certutil.ManagedPrivateKey { - return managed_key.GetPublicKeyFromKeyBytes(ctx, mkv, []byte(key.PrivateKey)) + return managed_key.GetPublicKeyFromKeyBytes(ctx, b, []byte(key.PrivateKey)) } signer, _, _, err := getSignerFromKeyEntryBytes(key) diff --git a/builtin/logical/pki/parsing/certificate.go b/builtin/logical/pki/parsing/certificate.go index 9cd52af46e52..c8f68b98e933 100644 --- a/builtin/logical/pki/parsing/certificate.go +++ b/builtin/logical/pki/parsing/certificate.go @@ -12,14 +12,6 @@ import ( "github.com/hashicorp/vault/sdk/helper/certutil" ) -func SerialFromCert(cert *x509.Certificate) string { - return SerialFromBigInt(cert.SerialNumber) -} - -func SerialFromBigInt(serial *big.Int) string { - return strings.TrimSpace(certutil.GetHexFormatted(serial.Bytes(), ":")) -} - // NormalizeSerialForStorageFromBigInt given a serial number, format it as a string // that is safe to store within a filesystem func NormalizeSerialForStorageFromBigInt(serial *big.Int) string { diff --git a/builtin/logical/pki/path_acme_order.go b/builtin/logical/pki/path_acme_order.go index 197b7d09161f..c0375e21bfbe 100644 --- a/builtin/logical/pki/path_acme_order.go +++ b/builtin/logical/pki/path_acme_order.go @@ -271,7 +271,7 @@ func (b *backend) acmeFinalizeOrderHandler(ac *acmeContext, r *logical.Request, return nil, err } - err = issuing.StoreCertificate(ac.sc.Context, ac.sc.Storage, ac.sc.GetCertificateCounter(), signedCertBundle) + err = issuing.StoreCertificate(ac.sc.Context, ac.sc.Storage, ac.sc.Backend.GetCertificateCounter(), signedCertBundle) if err != nil { return nil, err } @@ -476,7 +476,7 @@ func removeDuplicatesAndSortIps(ipIdentifiers []net.IP) []net.IP { func maybeAugmentReqDataWithSuitableCN(ac *acmeContext, csr *x509.CertificateRequest, data *framework.FieldData) { // Role doesn't require a CN, so we don't care. - if !ac.Role.RequireCN { + if !ac.role.RequireCN { return } @@ -522,9 +522,9 @@ func issueCertFromCsr(ac *acmeContext, csr *x509.CertificateRequest) (*certutil. // (TLS) clients are mostly verifying against server's DNS SANs. maybeAugmentReqDataWithSuitableCN(ac, csr, data) - signingBundle, issuerId, err := ac.sc.fetchCAInfoWithIssuer(ac.Issuer.ID.String(), issuing.IssuanceUsage) + signingBundle, issuerId, err := ac.sc.fetchCAInfoWithIssuer(ac.issuer.ID.String(), issuing.IssuanceUsage) if err != nil { - return nil, "", fmt.Errorf("failed loading CA %s: %w", ac.Issuer.ID.String(), err) + return nil, "", fmt.Errorf("failed loading CA %s: %w", ac.issuer.ID.String(), err) } // ACME issued cert will override the TTL values to truncate to the issuer's @@ -536,17 +536,17 @@ func issueCertFromCsr(ac *acmeContext, csr *x509.CertificateRequest) (*certutil. input := &inputBundle{ req: &logical.Request{}, apiData: data, - role: ac.Role, + role: ac.role, } - normalNotAfter, _, err := getCertificateNotAfter(ac.sc.System(), input, signingBundle) + normalNotAfter, _, err := getCertificateNotAfter(ac.sc.Backend, input, signingBundle) if err != nil { return nil, "", fmt.Errorf("failed computing certificate TTL from role/mount: %v: %w", err, ErrMalformed) } // We only allow ServerAuth key usage from ACME issued certs // when configuration does not allow usage of ExtKeyusage field. - config, err := ac.acmeState.getConfigWithUpdate(ac.sc) + config, err := ac.sc.Backend.GetAcmeState().getConfigWithUpdate(ac.sc) if err != nil { return nil, "", fmt.Errorf("failed to fetch ACME configuration: %w", err) } @@ -573,7 +573,7 @@ func issueCertFromCsr(ac *acmeContext, csr *x509.CertificateRequest) (*certutil. // unit, we have no way of validating this (via ACME here, without perhaps // an external policy engine), and thus should not be setting it on our // final issued certificate. - parsedBundle, _, err := signCert(ac.sc.System(), input, signingBundle, false /* is_ca=false */, false /* use_csr_values */) + parsedBundle, _, err := signCert(ac.sc.Backend, input, signingBundle, false /* is_ca=false */, false /* use_csr_values */) if err != nil { return nil, "", fmt.Errorf("%w: refusing to sign CSR: %s", ErrBadCSR, err.Error()) } @@ -730,7 +730,7 @@ func (b *backend) acmeNewOrderHandler(ac *acmeContext, _ *logical.Request, _ *fr return nil, err } - err = b.validateIdentifiersAgainstRole(ac.Role, identifiers) + err = b.validateIdentifiersAgainstRole(ac.role, identifiers) if err != nil { return nil, err } diff --git a/builtin/logical/pki/path_acme_revoke.go b/builtin/logical/pki/path_acme_revoke.go index 70d700d7d4b9..8b4a90529c30 100644 --- a/builtin/logical/pki/path_acme_revoke.go +++ b/builtin/logical/pki/path_acme_revoke.go @@ -12,7 +12,6 @@ import ( "time" "github.com/hashicorp/vault/builtin/logical/pki/issuing" - "github.com/hashicorp/vault/builtin/logical/pki/pki_backend" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/logical" ) @@ -84,7 +83,7 @@ func (b *backend) acmeRevocationHandler(acmeCtx *acmeContext, _ *logical.Request // Fetch the CRL config as we need it to ultimately do the // revocation. This should be cached and thus relatively fast. - config, err := b.CrlBuilder().GetConfigWithUpdate(acmeCtx.sc) + config, err := b.CrlBuilder().getConfigWithUpdate(acmeCtx.sc) if err != nil { return nil, fmt.Errorf("unable to revoke certificate: failed reading revocation config: %v: %w", err, ErrServerInternal) } @@ -135,7 +134,7 @@ func (b *backend) acmeRevocationHandler(acmeCtx *acmeContext, _ *logical.Request return b.acmeRevocationByAccount(acmeCtx, userCtx, cert, config) } -func (b *backend) acmeRevocationByPoP(acmeCtx *acmeContext, userCtx *jwsCtx, cert *x509.Certificate, config *pki_backend.CrlConfig) (*logical.Response, error) { +func (b *backend) acmeRevocationByPoP(acmeCtx *acmeContext, userCtx *jwsCtx, cert *x509.Certificate, config *crlConfig) (*logical.Response, error) { // Since this account does not exist, ensure we've gotten a private key // matching the certificate's public key. This private key isn't // explicitly provided, but instead provided by proxy (public key, @@ -161,7 +160,7 @@ func (b *backend) acmeRevocationByPoP(acmeCtx *acmeContext, userCtx *jwsCtx, cer return revokeCert(acmeCtx.sc, config, cert) } -func (b *backend) acmeRevocationByAccount(acmeCtx *acmeContext, userCtx *jwsCtx, cert *x509.Certificate, config *pki_backend.CrlConfig) (*logical.Response, error) { +func (b *backend) acmeRevocationByAccount(acmeCtx *acmeContext, userCtx *jwsCtx, cert *x509.Certificate, config *crlConfig) (*logical.Response, error) { // Fetch the account; disallow revocations from non-valid-status accounts. _, err := requireValidAcmeAccount(acmeCtx, userCtx) if err != nil { diff --git a/builtin/logical/pki/path_config_acme.go b/builtin/logical/pki/path_config_acme.go index 2a233cad7425..ac021a4e9b56 100644 --- a/builtin/logical/pki/path_config_acme.go +++ b/builtin/logical/pki/path_config_acme.go @@ -57,7 +57,7 @@ var ( rolePrefixLength = len(rolePrefix) ) -func getAcmeConfig(sc *storageContext) (*acmeConfigEntry, error) { +func (sc *storageContext) getAcmeConfig() (*acmeConfigEntry, error) { entry, err := sc.Storage.Get(sc.Context, storageAcmeConfig) if err != nil { return nil, err diff --git a/builtin/logical/pki/path_config_crl.go b/builtin/logical/pki/path_config_crl.go index 81815ff21592..cd28643f4a7e 100644 --- a/builtin/logical/pki/path_config_crl.go +++ b/builtin/logical/pki/path_config_crl.go @@ -9,13 +9,46 @@ import ( "net/http" "github.com/hashicorp/go-secure-stdlib/parseutil" - "github.com/hashicorp/vault/builtin/logical/pki/pki_backend" "github.com/hashicorp/vault/helper/constants" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/helper/errutil" "github.com/hashicorp/vault/sdk/logical" ) +const latestCrlConfigVersion = 1 + +// CRLConfig holds basic CRL configuration information +type crlConfig struct { + Version int `json:"version"` + Expiry string `json:"expiry"` + Disable bool `json:"disable"` + OcspDisable bool `json:"ocsp_disable"` + AutoRebuild bool `json:"auto_rebuild"` + AutoRebuildGracePeriod string `json:"auto_rebuild_grace_period"` + OcspExpiry string `json:"ocsp_expiry"` + EnableDelta bool `json:"enable_delta"` + DeltaRebuildInterval string `json:"delta_rebuild_interval"` + UseGlobalQueue bool `json:"cross_cluster_revocation"` + UnifiedCRL bool `json:"unified_crl"` + UnifiedCRLOnExistingPaths bool `json:"unified_crl_on_existing_paths"` +} + +// Implicit default values for the config if it does not exist. +var defaultCrlConfig = crlConfig{ + Version: latestCrlConfigVersion, + Expiry: "72h", + Disable: false, + OcspDisable: false, + OcspExpiry: "12h", + AutoRebuild: false, + AutoRebuildGracePeriod: "12h", + EnableDelta: false, + DeltaRebuildInterval: "15m", + UseGlobalQueue: false, + UnifiedCRL: false, + UnifiedCRLOnExistingPaths: false, +} + func pathConfigCRL(b *backend) *framework.Path { return &framework.Path{ Pattern: "config/crl", @@ -391,7 +424,7 @@ func (b *backend) pathCRLWrite(ctx context.Context, req *logical.Request, d *fra // auto-rebuild and we aren't now or equivalently, we changed our // mind about delta CRLs and need a new complete one or equivalently, // we changed our mind about unified CRLs), rotate the CRLs. - warnings, crlErr := b.CrlBuilder().Rebuild(sc, true) + warnings, crlErr := b.CrlBuilder().rebuild(sc, true) if crlErr != nil { switch crlErr.(type) { case errutil.UserError: @@ -408,7 +441,7 @@ func (b *backend) pathCRLWrite(ctx context.Context, req *logical.Request, d *fra return resp, nil } -func genResponseFromCrlConfig(config *pki_backend.CrlConfig) *logical.Response { +func genResponseFromCrlConfig(config *crlConfig) *logical.Response { return &logical.Response{ Data: map[string]interface{}{ "expiry": config.Expiry, diff --git a/builtin/logical/pki/path_fetch.go b/builtin/logical/pki/path_fetch.go index c18c73a1cebb..646998c9c7ec 100644 --- a/builtin/logical/pki/path_fetch.go +++ b/builtin/logical/pki/path_fetch.go @@ -12,7 +12,6 @@ import ( "time" "github.com/hashicorp/vault/builtin/logical/pki/issuing" - "github.com/hashicorp/vault/builtin/logical/pki/revocation" "github.com/hashicorp/vault/helper/constants" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/helper/errutil" @@ -307,7 +306,7 @@ func (b *backend) pathFetchRead(ctx context.Context, req *logical.Request, data contentType = "application/pkix-cert" } case req.Path == "crl" || req.Path == "crl/pem" || req.Path == "crl/delta" || req.Path == "crl/delta/pem" || req.Path == "cert/crl" || req.Path == "cert/crl/raw" || req.Path == "cert/crl/raw/pem" || req.Path == "cert/delta-crl" || req.Path == "cert/delta-crl/raw" || req.Path == "cert/delta-crl/raw/pem" || req.Path == "unified-crl" || req.Path == "unified-crl/pem" || req.Path == "unified-crl/delta" || req.Path == "unified-crl/delta/pem" || req.Path == "cert/unified-crl" || req.Path == "cert/unified-crl/raw" || req.Path == "cert/unified-crl/raw/pem" || req.Path == "cert/unified-delta-crl" || req.Path == "cert/unified-delta-crl/raw" || req.Path == "cert/unified-delta-crl/raw/pem": - config, err := b.CrlBuilder().GetConfigWithUpdate(sc) + config, err := b.CrlBuilder().getConfigWithUpdate(sc) if err != nil { retErr = err goto reply @@ -361,9 +360,7 @@ func (b *backend) pathFetchRead(ctx context.Context, req *logical.Request, data contentType = "application/pem-certificate-chain" } default: - if ser, ok := data.GetOk("serial"); ok { - serial = ser.(string) - } + serial = data.Get("serial").(string) pemType = "CERTIFICATE" } if len(serial) == 0 { @@ -455,7 +452,7 @@ func (b *backend) pathFetchRead(ctx context.Context, req *logical.Request, data } } if revokedEntry != nil { - var revInfo revocation.RevocationInfo + var revInfo revocationInfo err := revokedEntry.DecodeJSON(&revInfo) if err != nil { return logical.ErrorResponse(fmt.Sprintf("Error decoding revocation entry for serial %s: %s", serial, err)), nil diff --git a/builtin/logical/pki/path_fetch_issuers.go b/builtin/logical/pki/path_fetch_issuers.go index 6e6cf42010aa..bd5d8e63560b 100644 --- a/builtin/logical/pki/path_fetch_issuers.go +++ b/builtin/logical/pki/path_fetch_issuers.go @@ -1121,7 +1121,7 @@ func (b *backend) pathDeleteIssuer(ctx context.Context, req *logical.Request, da // Finally, we need to rebuild both the local and the unified CRLs. This // will free up any now unnecessary space used in both the CRL config // and for the underlying CRL. - warnings, err := b.CrlBuilder().Rebuild(sc, true) + warnings, err := b.CrlBuilder().rebuild(sc, true) if err != nil { return nil, err } @@ -1231,7 +1231,7 @@ func (b *backend) pathGetIssuerCRL(ctx context.Context, req *logical.Request, da } sc := b.makeStorageContext(ctx, req.Storage) - warnings, err := b.CrlBuilder().RebuildIfForced(sc) + warnings, err := b.CrlBuilder().rebuildIfForced(sc) if err != nil { return nil, err } @@ -1271,7 +1271,7 @@ func (b *backend) pathGetIssuerCRL(ctx context.Context, req *logical.Request, da return response, nil } - crlPath, err := issuing.ResolveIssuerCRLPath(sc.GetContext(), sc.GetStorage(), sc.UseLegacyBundleCaStorage(), issuerName, isUnified) + crlPath, err := sc.resolveIssuerCRLPath(issuerName, isUnified) if err != nil { return nil, err } diff --git a/builtin/logical/pki/path_fetch_keys.go b/builtin/logical/pki/path_fetch_keys.go index b0d1d9d680a6..0cf826d6f263 100644 --- a/builtin/logical/pki/path_fetch_keys.go +++ b/builtin/logical/pki/path_fetch_keys.go @@ -267,7 +267,7 @@ func (b *backend) pathGetKeyHandler(ctx context.Context, req *logical.Request, d return nil, errutil.InternalError{Err: fmt.Sprintf("failed fetching managed key info from key id %s (%s): %v", key.ID, key.Name, err)} } - pkForSkid, err = managed_key.GetManagedKeyPublicKey(sc.Context, sc.GetPkiManagedView(), managedKeyUUID) + pkForSkid, err = managed_key.GetManagedKeyPublicKey(sc.Context, sc.Backend, managedKeyUUID) if err != nil { return nil, err } diff --git a/builtin/logical/pki/path_issue_sign.go b/builtin/logical/pki/path_issue_sign.go index 57ae2caef766..f27548a3404d 100644 --- a/builtin/logical/pki/path_issue_sign.go +++ b/builtin/logical/pki/path_issue_sign.go @@ -417,7 +417,7 @@ func (b *backend) pathIssueSignCert(ctx context.Context, req *logical.Request, d var parsedBundle *certutil.ParsedCertBundle var warnings []string if useCSR { - parsedBundle, warnings, err = signCert(b.System(), input, signingBundle, false, useCSRValues) + parsedBundle, warnings, err = signCert(b, input, signingBundle, false, useCSRValues) } else { parsedBundle, warnings, err = generateCert(sc, input, signingBundle, false, rand.Reader) } diff --git a/builtin/logical/pki/path_manage_issuers.go b/builtin/logical/pki/path_manage_issuers.go index 01c0d6653063..e5bb0450310a 100644 --- a/builtin/logical/pki/path_manage_issuers.go +++ b/builtin/logical/pki/path_manage_issuers.go @@ -14,7 +14,6 @@ import ( "time" "github.com/hashicorp/vault/builtin/logical/pki/issuing" - "github.com/hashicorp/vault/builtin/logical/pki/revocation" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/helper/errutil" "github.com/hashicorp/vault/sdk/logical" @@ -117,7 +116,6 @@ func buildPathGenerateRoot(b *backend, pattern string, displayAttrs *framework.D ret.Fields = addCACommonFields(map[string]*framework.FieldSchema{}) ret.Fields = addCAKeyGenerationFields(ret.Fields) ret.Fields = addCAIssueFields(ret.Fields) - ret.Fields = addCACertKeyUsage(ret.Fields) return ret } @@ -198,7 +196,6 @@ extension with CA: true. Only needed as a workaround in some compatibility scenarios with Active Directory Certificate Services.`, } - ret.Fields = addCaCsrKeyUsage(ret.Fields) // At this time Go does not support signing CSRs using PSS signatures, see // https://github.com/golang/go/issues/45990 @@ -410,7 +407,7 @@ func (b *backend) pathImportIssuers(ctx context.Context, req *logical.Request, d } if len(createdIssuers) > 0 { - warnings, err := b.CrlBuilder().Rebuild(sc, true) + warnings, err := b.CrlBuilder().rebuild(sc, true) if err != nil { // Before returning, check if the error message includes the // string "PSS". If so, it indicates we might've wanted to modify @@ -680,7 +677,7 @@ func (b *backend) pathRevokeIssuer(ctx context.Context, req *logical.Request, da // Now, if the parent issuer exists within this mount, we'd have written // a storage entry for this certificate, making it appear as any other - // leaf. We need to add a RevocationInfo entry for this into storage, + // leaf. We need to add a revocationInfo entry for this into storage, // so that it appears as if it was revoked. // // This is a _necessary_ but not necessarily _sufficient_ step to @@ -715,7 +712,7 @@ func (b *backend) pathRevokeIssuer(ctx context.Context, req *logical.Request, da // // We'll let a cleanup pass or CRL build identify the issuer for // us. - revInfo := revocation.RevocationInfo{ + revInfo := revocationInfo{ CertificateBytes: issuerCert.Raw, RevocationTime: issuer.RevocationTime, RevocationTimeUTC: issuer.RevocationTimeUTC, @@ -734,7 +731,7 @@ func (b *backend) pathRevokeIssuer(ctx context.Context, req *logical.Request, da } // Rebuild the CRL to include the newly revoked issuer. - warnings, crlErr := b.CrlBuilder().Rebuild(sc, false) + warnings, crlErr := b.CrlBuilder().rebuild(sc, false) if crlErr != nil { switch crlErr.(type) { case errutil.UserError: diff --git a/builtin/logical/pki/path_ocsp.go b/builtin/logical/pki/path_ocsp.go index ea93b5da4ac3..2a5a1b8dc7bf 100644 --- a/builtin/logical/pki/path_ocsp.go +++ b/builtin/logical/pki/path_ocsp.go @@ -19,11 +19,8 @@ import ( "strings" "time" - "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-secure-stdlib/parseutil" "github.com/hashicorp/vault/builtin/logical/pki/issuing" - "github.com/hashicorp/vault/builtin/logical/pki/pki_backend" - "github.com/hashicorp/vault/builtin/logical/pki/revocation" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/helper/certutil" "github.com/hashicorp/vault/sdk/helper/errutil" @@ -159,7 +156,7 @@ func buildOcspPostWithPath(b *backend, pattern string, displayAttrs *framework.D func (b *backend) ocspHandler(ctx context.Context, request *logical.Request, data *framework.FieldData) (*logical.Response, error) { sc := b.makeStorageContext(ctx, request.Storage) - cfg, err := b.CrlBuilder().GetConfigWithUpdate(sc) + cfg, err := b.CrlBuilder().getConfigWithUpdate(sc) if err != nil || cfg.OcspDisable || (isUnifiedOcspPath(request) && !cfg.UnifiedCRL) { return OcspUnauthorizedResponse, nil } @@ -178,7 +175,7 @@ func (b *backend) ocspHandler(ctx context.Context, request *logical.Request, dat ocspStatus, err := getOcspStatus(sc, ocspReq, useUnifiedStorage) if err != nil { - return logAndReturnInternalError(b.Logger(), err), nil + return logAndReturnInternalError(b, err), nil } caBundle, issuer, err := lookupOcspIssuer(sc, ocspReq, ocspStatus.issuerID) @@ -196,12 +193,12 @@ func (b *backend) ocspHandler(ctx context.Context, request *logical.Request, dat // https://www.rfc-editor.org/rfc/rfc5019#section-2.2.3 return OcspUnauthorizedResponse, nil } - return logAndReturnInternalError(b.Logger(), err), nil + return logAndReturnInternalError(b, err), nil } byteResp, err := genResponse(cfg, caBundle, ocspStatus, ocspReq.HashAlgorithm, issuer.RevocationSigAlg) if err != nil { - return logAndReturnInternalError(b.Logger(), err), nil + return logAndReturnInternalError(b, err), nil } return &logical.Response{ @@ -213,7 +210,7 @@ func (b *backend) ocspHandler(ctx context.Context, request *logical.Request, dat }, nil } -func canUseUnifiedStorage(req *logical.Request, cfg *pki_backend.CrlConfig) bool { +func canUseUnifiedStorage(req *logical.Request, cfg *crlConfig) bool { if isUnifiedOcspPath(req) { return true } @@ -227,13 +224,13 @@ func isUnifiedOcspPath(req *logical.Request) bool { return strings.HasPrefix(req.Path, "unified-ocsp") } -func generateUnknownResponse(cfg *pki_backend.CrlConfig, sc *storageContext, ocspReq *ocsp.Request) *logical.Response { +func generateUnknownResponse(cfg *crlConfig, sc *storageContext, ocspReq *ocsp.Request) *logical.Response { // Generate an Unknown OCSP response, signing with the default issuer from the mount as we did // not match the request's issuer. If no default issuer can be used, return with Unauthorized as there // isn't much else we can do at this point. config, err := sc.getIssuersConfig() if err != nil { - return logAndReturnInternalError(sc.Logger(), err) + return logAndReturnInternalError(sc.Backend, err) } if config.DefaultIssuerId == "" { @@ -248,7 +245,7 @@ func generateUnknownResponse(cfg *pki_backend.CrlConfig, sc *storageContext, ocs // no way to sign a response so Unauthorized it is. return OcspUnauthorizedResponse } - return logAndReturnInternalError(sc.Logger(), err) + return logAndReturnInternalError(sc.Backend, err) } if !issuer.Usage.HasUsage(issuing.OCSPSigningUsage) { @@ -263,7 +260,7 @@ func generateUnknownResponse(cfg *pki_backend.CrlConfig, sc *storageContext, ocs byteResp, err := genResponse(cfg, caBundle, info, ocspReq.HashAlgorithm, issuer.RevocationSigAlg) if err != nil { - return logAndReturnInternalError(sc.Logger(), err) + return logAndReturnInternalError(sc.Backend, err) } return &logical.Response{ @@ -316,12 +313,12 @@ func fetchDerEncodedRequest(request *logical.Request, data *framework.FieldData) } } -func logAndReturnInternalError(logger hclog.Logger, err error) *logical.Response { +func logAndReturnInternalError(b *backend, err error) *logical.Response { // Since OCSP might be a high traffic endpoint, we will log at debug level only // any internal errors we do get. There is no way for us to return to the end-user // errors, so we rely on the log statement to help in debugging possible // issues in the field. - logger.Debug("OCSP internal error", "error", err) + b.Logger().Debug("OCSP internal error", "error", err) return OcspInternalErrorResponse } @@ -337,7 +334,7 @@ func getOcspStatus(sc *storageContext, ocspReq *ocsp.Request, useUnifiedStorage } if revEntryRaw != nil { - var revEntry revocation.RevocationInfo + var revEntry revocationInfo if err := revEntryRaw.DecodeJSON(&revEntry); err != nil { return nil, err } @@ -436,7 +433,7 @@ func getOcspIssuerParsedBundle(sc *storageContext, issuerId issuing.IssuerID) (* return nil, nil, ErrIssuerHasNoKey } - caBundle, err := parseCABundle(sc.Context, sc.GetPkiManagedView(), bundle) + caBundle, err := parseCABundle(sc.Context, sc.Backend, bundle) if err != nil { return nil, nil, err } @@ -449,7 +446,7 @@ func lookupIssuerIds(sc *storageContext, optRevokedIssuer issuing.IssuerID) ([]i return []issuing.IssuerID{optRevokedIssuer}, nil } - if sc.UseLegacyBundleCaStorage() { + if sc.Backend.UseLegacyBundleCaStorage() { return []issuing.IssuerID{legacyBundleShimID}, nil } @@ -477,7 +474,7 @@ func doesRequestMatchIssuer(parsedBundle *certutil.ParsedCertBundle, req *ocsp.R return bytes.Equal(req.IssuerKeyHash, issuerKeyHash) && bytes.Equal(req.IssuerNameHash, issuerNameHash), nil } -func genResponse(cfg *pki_backend.CrlConfig, caBundle *certutil.ParsedCertBundle, info *ocspRespInfo, reqHash crypto.Hash, revSigAlg x509.SignatureAlgorithm) ([]byte, error) { +func genResponse(cfg *crlConfig, caBundle *certutil.ParsedCertBundle, info *ocspRespInfo, reqHash crypto.Hash, revSigAlg x509.SignatureAlgorithm) ([]byte, error) { curTime := time.Now() duration, err := parseutil.ParseDurationSecond(cfg.OcspExpiry) if err != nil { diff --git a/builtin/logical/pki/path_ocsp_test.go b/builtin/logical/pki/path_ocsp_test.go index 517b55de79d7..baeb49cb1dc9 100644 --- a/builtin/logical/pki/path_ocsp_test.go +++ b/builtin/logical/pki/path_ocsp_test.go @@ -19,8 +19,6 @@ import ( "github.com/hashicorp/go-secure-stdlib/parseutil" "github.com/hashicorp/vault/builtin/logical/pki/issuing" - "github.com/hashicorp/vault/builtin/logical/pki/pki_backend" - "github.com/hashicorp/vault/builtin/logical/pki/revocation" vaulthttp "github.com/hashicorp/vault/http" "github.com/hashicorp/vault/sdk/helper/testhelpers/schema" "github.com/hashicorp/vault/sdk/logical" @@ -165,7 +163,7 @@ func TestOcsp_InvalidIssuerIdInRevocationEntry(t *testing.T) { // Twiddle the entry so that the issuer id is no longer valid. storagePath := revokedPath + normalizeSerial(serial) - var revInfo revocation.RevocationInfo + var revInfo revocationInfo revEntry, err := s.Get(ctx, storagePath) require.NoError(t, err, "failed looking up storage path: %s", storagePath) err = revEntry.DecodeJSON(&revInfo) @@ -209,7 +207,7 @@ func TestOcsp_UnknownIssuerIdWithDefaultHavingOcspUsageRemoved(t *testing.T) { // Twiddle the entry so that the issuer id is no longer valid. storagePath := revokedPath + normalizeSerial(serial) - var revInfo revocation.RevocationInfo + var revInfo revocationInfo revEntry, err := s.Get(ctx, storagePath) require.NoError(t, err, "failed looking up storage path: %s", storagePath) err = revEntry.DecodeJSON(&revInfo) @@ -609,7 +607,7 @@ func runOcspRequestTest(t *testing.T, requestType string, caKeyType string, nextUpdateDiff := nextUpdate.Sub(thisUpdate) require.Equal(t, expectedDiff, nextUpdateDiff, fmt.Sprintf("the delta between thisUpdate %s and nextUpdate: %s should have been around: %s but was %s", - thisUpdate, nextUpdate, pki_backend.DefaultCrlConfig.OcspExpiry, nextUpdateDiff)) + thisUpdate, nextUpdate, defaultCrlConfig.OcspExpiry, nextUpdateDiff)) } else { // With the config value set to 0, we shouldn't have a NextUpdate field set require.True(t, ocspResp.NextUpdate.IsZero(), "nextUpdate value was not zero as expected was: %v", ocspResp.NextUpdate) diff --git a/builtin/logical/pki/path_resign_crls.go b/builtin/logical/pki/path_resign_crls.go index 65563dc7f77a..6c2810db8252 100644 --- a/builtin/logical/pki/path_resign_crls.go +++ b/builtin/logical/pki/path_resign_crls.go @@ -22,7 +22,6 @@ import ( "github.com/hashicorp/go-secure-stdlib/parseutil" "github.com/hashicorp/vault/builtin/logical/pki/issuing" - "github.com/hashicorp/vault/builtin/logical/pki/pki_backend" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/helper/certutil" "github.com/hashicorp/vault/sdk/logical" @@ -74,7 +73,7 @@ to the issuer.`, Type: framework.TypeString, Description: `The amount of time the generated CRL should be valid; defaults to 72 hours.`, - Default: pki_backend.DefaultCrlConfig.Expiry, + Default: defaultCrlConfig.Expiry, }, crlsParam: { Type: framework.TypeStringSlice, @@ -143,7 +142,7 @@ to the issuer.`, Type: framework.TypeString, Description: `The amount of time the generated CRL should be valid; defaults to 72 hours.`, - Default: pki_backend.DefaultCrlConfig.Expiry, + Default: defaultCrlConfig.Expiry, }, formatParam: { Type: framework.TypeString, diff --git a/builtin/logical/pki/path_revoke.go b/builtin/logical/pki/path_revoke.go index f6c35e67f732..a8dc789187de 100644 --- a/builtin/logical/pki/path_revoke.go +++ b/builtin/logical/pki/path_revoke.go @@ -18,7 +18,6 @@ import ( "time" "github.com/hashicorp/vault/builtin/logical/pki/issuing" - "github.com/hashicorp/vault/builtin/logical/pki/pki_backend" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/helper/certutil" "github.com/hashicorp/vault/sdk/helper/consts" @@ -498,7 +497,7 @@ func validatePublicKeyMatchesCert(verifier crypto.PublicKey, certReference *x509 return nil } -func (b *backend) maybeRevokeCrossCluster(sc *storageContext, config *pki_backend.CrlConfig, serial string, havePrivateKey bool) (*logical.Response, error) { +func (b *backend) maybeRevokeCrossCluster(sc *storageContext, config *crlConfig, serial string, havePrivateKey bool) (*logical.Response, error) { if !config.UseGlobalQueue { return logical.ErrorResponse(fmt.Sprintf("certificate with serial %s not found.", serial)), nil } @@ -564,7 +563,7 @@ func (b *backend) pathRevokeWrite(ctx context.Context, req *logical.Request, dat var cert *x509.Certificate var serial string - config, err := sc.CrlBuilder().GetConfigWithUpdate(sc) + config, err := sc.Backend.CrlBuilder().getConfigWithUpdate(sc) if err != nil { return nil, fmt.Errorf("error revoking serial: %s: failed reading config: %w", serial, err) } @@ -659,7 +658,7 @@ func (b *backend) pathRotateCRLRead(ctx context.Context, req *logical.Request, _ defer b.GetRevokeStorageLock().RUnlock() sc := b.makeStorageContext(ctx, req.Storage) - warnings, crlErr := b.CrlBuilder().Rebuild(sc, false) + warnings, crlErr := b.CrlBuilder().rebuild(sc, false) if crlErr != nil { switch crlErr.(type) { case errutil.UserError: @@ -685,7 +684,7 @@ func (b *backend) pathRotateCRLRead(ctx context.Context, req *logical.Request, _ func (b *backend) pathRotateDeltaCRLRead(ctx context.Context, req *logical.Request, _ *framework.FieldData) (*logical.Response, error) { sc := b.makeStorageContext(ctx, req.Storage) - cfg, err := b.CrlBuilder().GetConfigWithUpdate(sc) + cfg, err := b.CrlBuilder().getConfigWithUpdate(sc) if err != nil { return nil, fmt.Errorf("error fetching CRL configuration: %w", err) } diff --git a/builtin/logical/pki/path_root.go b/builtin/logical/pki/path_root.go index 625bcb2946e3..53b8c81389ad 100644 --- a/builtin/logical/pki/path_root.go +++ b/builtin/logical/pki/path_root.go @@ -293,7 +293,7 @@ func (b *backend) pathCAGenerateRoot(ctx context.Context, req *logical.Request, } // Build a fresh CRL - warnings, err = b.CrlBuilder().Rebuild(sc, true) + warnings, err = b.CrlBuilder().rebuild(sc, true) if err != nil { return nil, err } @@ -356,7 +356,6 @@ func (b *backend) pathIssuerSignIntermediate(ctx context.Context, req *logical.R NotAfter: data.Get("not_after").(string), NotBeforeDuration: time.Duration(data.Get("not_before_duration").(int)) * time.Second, CNValidations: []string{"disabled"}, - KeyUsage: data.Get("key_usage").([]string), } *role.AllowWildcardCertificates = true @@ -400,7 +399,7 @@ func (b *backend) pathIssuerSignIntermediate(ctx context.Context, req *logical.R apiData: data, role: role, } - parsedBundle, warnings, err := signCert(b.System(), input, signingBundle, true, useCSRValues) + parsedBundle, warnings, err := signCert(b, input, signingBundle, true, useCSRValues) if err != nil { switch err.(type) { case errutil.UserError: diff --git a/builtin/logical/pki/path_sign_issuers.go b/builtin/logical/pki/path_sign_issuers.go index b620ac4bbfb0..d139e968ec95 100644 --- a/builtin/logical/pki/path_sign_issuers.go +++ b/builtin/logical/pki/path_sign_issuers.go @@ -110,7 +110,7 @@ certs signed by this path; for instance, the non-repudiation flag; 3) Extensions requested in the CSR will be copied into the issued certificate.`, - } // TODO: Re-Write This (!) + } fields["signature_bits"] = &framework.FieldSchema{ Type: framework.TypeInt, @@ -149,8 +149,6 @@ in the above RFC section.`, RSA key-type issuer. Defaults to false.`, } - fields = addCACertKeyUsage(fields) - return path } diff --git a/builtin/logical/pki/path_tidy.go b/builtin/logical/pki/path_tidy.go index a8971832c2b1..7a6f2b8456be 100644 --- a/builtin/logical/pki/path_tidy.go +++ b/builtin/logical/pki/path_tidy.go @@ -17,7 +17,6 @@ import ( "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-secure-stdlib/parseutil" "github.com/hashicorp/vault/builtin/logical/pki/issuing" - "github.com/hashicorp/vault/builtin/logical/pki/revocation" "github.com/hashicorp/vault/helper/constants" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/helper/consts" @@ -54,7 +53,6 @@ type tidyStatus struct { tidyCrossRevokedCerts bool tidyAcme bool tidyCertMetadata bool - tidyCMPV2NonceStore bool pauseDuration string // Status @@ -72,7 +70,6 @@ type tidyStatus struct { revQueueDeletedCount uint crossRevokedDeletedCount uint certMetadataDeletedCount uint - cmpv2NonceDeletedCount uint acmeAccountsCount uint acmeAccountsRevokedCount uint @@ -97,7 +94,6 @@ type tidyConfig struct { CrossRevokedCerts bool `json:"tidy_cross_cluster_revoked_certs"` TidyAcme bool `json:"tidy_acme"` CertMetadata bool `json:"tidy_cert_metadata"` - CMPV2NonceStore bool `json:"tidy_cmpv2_nonce_store"` // Safety Buffers SafetyBuffer time.Duration `json:"safety_buffer"` @@ -112,7 +108,7 @@ type tidyConfig struct { } func (tc *tidyConfig) IsAnyTidyEnabled() bool { - return tc.CertStore || tc.RevokedCerts || tc.IssuerAssocs || tc.ExpiredIssuers || tc.BackupBundle || tc.TidyAcme || tc.CrossRevokedCerts || tc.RevocationQueue || tc.CertMetadata || tc.CMPV2NonceStore + return tc.CertStore || tc.RevokedCerts || tc.IssuerAssocs || tc.ExpiredIssuers || tc.BackupBundle || tc.TidyAcme || tc.CrossRevokedCerts || tc.RevocationQueue || tc.CertMetadata } func (tc *tidyConfig) AnyTidyConfig() string { @@ -153,7 +149,6 @@ var defaultTidyConfig = tidyConfig{ QueueSafetyBuffer: 48 * time.Hour, CrossRevokedCerts: false, CertMetadata: false, - CMPV2NonceStore: false, } func pathTidy(b *backend) *framework.Path { @@ -250,11 +245,6 @@ func pathTidyCancel(b *backend) *framework.Path { Description: `Tidy cert metadata`, Required: false, }, - "tidy_cmpv2_nonce_store": { - Type: framework.TypeBool, - Description: `Tidy CMPv2 nonce store`, - Required: false, - }, "pause_duration": { Type: framework.TypeString, Description: `Duration to pause between tidying certificates`, @@ -364,11 +354,6 @@ func pathTidyCancel(b *backend) *framework.Path { Description: `The number of metadata entries removed`, Required: false, }, - "cmpv2_nonce_deleted_count": { - Type: framework.TypeInt, - Description: `The number of CMPv2 nonces removed`, - Required: false, - }, }, }}, }, @@ -452,11 +437,6 @@ func pathTidyStatus(b *backend) *framework.Path { Description: `Tidy cert metadata`, Required: true, }, - "tidy_cmpv2_nonce_store": { - Type: framework.TypeBool, - Description: `Tidy CMPv2 nonce store`, - Required: true, - }, "pause_duration": { Type: framework.TypeString, Description: `Duration to pause between tidying certificates`, @@ -562,11 +542,6 @@ func pathTidyStatus(b *backend) *framework.Path { Description: `The number of metadata entries removed`, Required: false, }, - "cmpv2_nonce_deleted_count": { - Type: framework.TypeInt, - Description: `The number of CMPv2 nonces removed`, - Required: false, - }, }, }}, }, @@ -630,11 +605,6 @@ func pathConfigAutoTidy(b *backend) *framework.Path { Description: `Tidy cert metadata`, Required: true, }, - "tidy_cmpv2_nonce_store": { - Type: framework.TypeBool, - Description: `Tidy CMPv2 nonce store`, - Required: true, - }, "safety_buffer": { Type: framework.TypeInt, Description: `Safety buffer time duration`, @@ -655,16 +625,15 @@ func pathConfigAutoTidy(b *backend) *framework.Path { Description: `Duration to pause between tidying certificates`, Required: true, }, - "tidy_cross_cluster_revoked_certs": { - Type: framework.TypeBool, - Description: `Tidy the cross-cluster revoked certificate store`, - Required: true, + "tidy_move_legacy_ca_bundle": { + Type: framework.TypeBool, + Required: true, }, - "tidy_revocation_queue": { + "tidy_cross_cluster_revoked_certs": { Type: framework.TypeBool, Required: true, }, - "tidy_move_legacy_ca_bundle": { + "tidy_revocation_queue": { Type: framework.TypeBool, Required: true, }, @@ -681,6 +650,7 @@ func pathConfigAutoTidy(b *backend) *framework.Path { Required: true, }, } + return &framework.Path{ Pattern: "config/auto-tidy", DisplayAttrs: &framework.DisplayAttributes{ @@ -773,7 +743,6 @@ func (b *backend) pathTidyWrite(ctx context.Context, req *logical.Request, d *fr tidyAcme := d.Get("tidy_acme").(bool) acmeAccountSafetyBuffer := d.Get("acme_account_safety_buffer").(int) tidyCertMetadata := d.Get("tidy_cert_metadata").(bool) - tidyCMPV2NonceStore := d.Get("tidy_cmpv2_nonce_store").(bool) if safetyBuffer < 1 { return logical.ErrorResponse("safety_buffer must be greater than zero"), nil @@ -830,7 +799,6 @@ func (b *backend) pathTidyWrite(ctx context.Context, req *logical.Request, d *fr TidyAcme: tidyAcme, AcmeAccountSafetyBuffer: acmeAccountSafetyBufferDuration, CertMetadata: tidyCertMetadata, - CMPV2NonceStore: tidyCMPV2NonceStore, } if !atomic.CompareAndSwapUint32(b.tidyCASGuard, 0, 1) { @@ -972,17 +940,6 @@ func (b *backend) startTidyOperation(req *logical.Request, config *tidyConfig) { } } - // Check for cancel before continuing. - if atomic.CompareAndSwapUint32(b.tidyCancelCAS, 1, 0) { - return tidyCancelledError - } - - if config.CMPV2NonceStore { - if err := b.doTidyCMPV2NonceStore(ctx, req.Storage); err != nil { - return err - } - } - return nil } @@ -1074,7 +1031,7 @@ func (b *backend) doTidyRevocationStore(ctx context.Context, req *logical.Reques // Fetch and parse our issuers so we can associate them if necessary. sc := b.makeStorageContext(ctx, req.Storage) - issuerIDCertMap, err := revocation.FetchIssuerMapForRevocationChecking(sc) + issuerIDCertMap, err := fetchIssuerMapForRevocationChecking(sc) if err != nil { return err } @@ -1091,7 +1048,7 @@ func (b *backend) doTidyRevocationStore(ctx context.Context, req *logical.Reques fixedIssuers := 0 - var revInfo revocation.RevocationInfo + var revInfo revocationInfo for i, serial := range revokedSerials { b.tidyStatusMessage(fmt.Sprintf("Tidying revoked certificates: checking certificate %d of %d", i, len(revokedSerials))) metrics.SetGauge([]string{"secrets", "pki", "tidy", "revoked_cert_current_entry"}, float32(i)) @@ -1150,7 +1107,7 @@ func (b *backend) doTidyRevocationStore(ctx context.Context, req *logical.Reques b.tidyStatusIncMissingIssuerCertCount() revInfo.CertificateIssuer = issuing.IssuerID("") storeCert = true - if revInfo.AssociateRevokedCertWithIsssuer(revokedCert, issuerIDCertMap) { + if associateRevokedCertWithIsssuer(&revInfo, revokedCert, issuerIDCertMap) { fixedIssuers += 1 } } @@ -1206,7 +1163,7 @@ func (b *backend) doTidyRevocationStore(ctx context.Context, req *logical.Reques } if !config.AutoRebuild { - warnings, err := b.CrlBuilder().Rebuild(sc, false) + warnings, err := b.CrlBuilder().rebuild(sc, false) if err != nil { return err } @@ -1245,7 +1202,7 @@ func (b *backend) doTidyExpiredIssuers(ctx context.Context, req *logical.Request // Fetch and parse our issuers so we have their expiration date. sc := b.makeStorageContext(ctx, req.Storage) - issuerIDCertMap, err := revocation.FetchIssuerMapForRevocationChecking(sc) + issuerIDCertMap, err := fetchIssuerMapForRevocationChecking(sc) if err != nil { return err } @@ -1318,7 +1275,7 @@ func (b *backend) doTidyExpiredIssuers(ctx context.Context, req *logical.Request b.GetRevokeStorageLock().Lock() defer b.GetRevokeStorageLock().Unlock() - warnings, err := b.CrlBuilder().Rebuild(sc, false) + warnings, err := b.CrlBuilder().rebuild(sc, false) if err != nil { return err } @@ -1567,7 +1524,7 @@ func (b *backend) doTidyCrossRevocationStore(ctx context.Context, req *logical.R continue } - var details revocation.UnifiedRevocationEntry + var details unifiedRevocationEntry if err := entry.DecodeJSON(&details); err != nil { return fmt.Errorf("error decoding cross-cluster revocation entry (%v) to tidy: %w", ePath, err) } @@ -1702,7 +1659,6 @@ func (b *backend) pathTidyStatusRead(_ context.Context, _ *logical.Request, _ *f "tidy_cross_cluster_revoked_certs": nil, "tidy_acme": nil, "tidy_cert_metadata": nil, - "tidy_cmpv2_nonce_store": nil, "pause_duration": nil, "state": "Inactive", "error": nil, @@ -1723,7 +1679,6 @@ func (b *backend) pathTidyStatusRead(_ context.Context, _ *logical.Request, _ *f "acme_orders_deleted_count": nil, "acme_account_safety_buffer": nil, "cert_metadata_deleted_count": nil, - "cmpv2_nonce_deleted_count": nil, "last_auto_tidy_finished": b.getLastAutoTidyTime(), }, } @@ -1759,7 +1714,6 @@ func (b *backend) pathTidyStatusRead(_ context.Context, _ *logical.Request, _ *f resp.Data["tidy_cross_cluster_revoked_certs"] = b.tidyStatus.tidyCrossRevokedCerts resp.Data["tidy_acme"] = b.tidyStatus.tidyAcme resp.Data["tidy_cert_metadata"] = b.tidyStatus.tidyCertMetadata - resp.Data["tidy_cmpv2_nonce_store"] = b.tidyStatus.tidyCMPV2NonceStore resp.Data["pause_duration"] = b.tidyStatus.pauseDuration resp.Data["time_started"] = b.tidyStatus.timeStarted resp.Data["message"] = b.tidyStatus.message @@ -1775,7 +1729,6 @@ func (b *backend) pathTidyStatusRead(_ context.Context, _ *logical.Request, _ *f resp.Data["acme_orders_deleted_count"] = b.tidyStatus.acmeOrdersDeletedCount resp.Data["acme_account_safety_buffer"] = b.tidyStatus.acmeAccountSafetyBuffer resp.Data["cert_metadata_deleted_count"] = b.tidyStatus.certMetadataDeletedCount - resp.Data["cmpv2_nonce_deleted_count"] = b.tidyStatus.cmpv2NonceDeletedCount switch b.tidyStatus.state { case tidyStatusStarted: @@ -2104,13 +2057,6 @@ func (b *backend) tidyStatusIncCertMetadataCount() { b.tidyStatus.certMetadataDeletedCount++ } -func (b *backend) tidyStatusIncCMPV2NonceDeletedCount() { - b.tidyStatusLock.Lock() - defer b.tidyStatusLock.Unlock() - - b.tidyStatus.cmpv2NonceDeletedCount++ -} - // updateLastAutoTidyTime should be used to update b.lastAutoTidy as the required locks // are acquired and the auto tidy time is persisted to storage to work across restarts func (b *backend) updateLastAutoTidyTime(sc *storageContext, lastRunTime time.Time) error { @@ -2243,6 +2189,5 @@ func getTidyConfigData(config tidyConfig) map[string]interface{} { "revocation_queue_safety_buffer": int(config.QueueSafetyBuffer / time.Second), "tidy_cross_cluster_revoked_certs": config.CrossRevokedCerts, "tidy_cert_metadata": config.CertMetadata, - "tidy_cmpv2_nonce_store": config.CMPV2NonceStore, } } diff --git a/builtin/logical/pki/periodic.go b/builtin/logical/pki/periodic.go index 05c37b660eae..b5c6209b1459 100644 --- a/builtin/logical/pki/periodic.go +++ b/builtin/logical/pki/periodic.go @@ -10,7 +10,6 @@ import ( "sync/atomic" "time" - "github.com/hashicorp/vault/builtin/logical/pki/revocation" "github.com/hashicorp/vault/sdk/helper/consts" "github.com/hashicorp/vault/sdk/logical" ) @@ -37,18 +36,19 @@ func newUnifiedTransferStatus() *UnifiedTransferStatus { // send all missing local revocation entries to the unified space if the feature // is enabled. func runUnifiedTransfer(sc *storageContext) { - status := sc.GetUnifiedTransferStatus() + b := sc.Backend + status := b.GetUnifiedTransferStatus() - isPerfStandby := sc.System().ReplicationState().HasState(consts.ReplicationDRSecondary | consts.ReplicationPerformanceStandby) + isPerfStandby := b.System().ReplicationState().HasState(consts.ReplicationDRSecondary | consts.ReplicationPerformanceStandby) - if isPerfStandby || sc.System().LocalMount() { + if isPerfStandby || b.System().LocalMount() { // We only do this on active enterprise nodes, when we aren't a local mount return } - config, err := sc.CrlBuilder().GetConfigWithUpdate(sc) + config, err := b.CrlBuilder().getConfigWithUpdate(sc) if err != nil { - sc.Logger().Error("failed to retrieve crl config from storage for unified transfer background process", + b.Logger().Error("failed to retrieve crl config from storage for unified transfer background process", "error", err) return } @@ -58,15 +58,15 @@ func runUnifiedTransfer(sc *storageContext) { return } - clusterId, err := sc.System().ClusterID(sc.Context) + clusterId, err := b.System().ClusterID(sc.Context) if err != nil { - sc.Logger().Error("failed to fetch cluster id for unified transfer background process", + b.Logger().Error("failed to fetch cluster id for unified transfer background process", "error", err) return } if !status.isRunning.CompareAndSwap(false, true) { - sc.Logger().Debug("an existing unified transfer process is already running") + b.Logger().Debug("an existing unified transfer process is already running") return } defer status.isRunning.Store(false) @@ -91,13 +91,13 @@ func runUnifiedTransfer(sc *storageContext) { err = doUnifiedTransferMissingLocalSerials(sc, clusterId) if err != nil { - sc.Logger().Error("an error occurred running unified transfer", "error", err.Error()) + b.Logger().Error("an error occurred running unified transfer", "error", err.Error()) status.forceRerun.Store(true) } else { if config.EnableDelta { err = doUnifiedTransferMissingDeltaWALSerials(sc, clusterId) if err != nil { - sc.Logger().Error("an error occurred running unified transfer", "error", err.Error()) + b.Logger().Error("an error occurred running unified transfer", "error", err.Error()) status.forceRerun.Store(true) } } @@ -125,7 +125,7 @@ func doUnifiedTransferMissingLocalSerials(sc *storageContext, clusterId string) errCount := 0 for i, serialNum := range localRevokedSerialNums { if i%25 == 0 { - config, _ := sc.CrlBuilder().GetConfigWithUpdate(sc) + config, _ := sc.Backend.CrlBuilder().getConfigWithUpdate(sc) if config != nil && !config.UnifiedCRL { return errors.New("unified crl has been disabled after we started, stopping") } @@ -134,14 +134,14 @@ func doUnifiedTransferMissingLocalSerials(sc *storageContext, clusterId string) err := readRevocationEntryAndTransfer(sc, serialNum) if err != nil { errCount++ - sc.Logger().Error("Failed transferring local revocation to unified space", + sc.Backend.Logger().Error("Failed transferring local revocation to unified space", "serial", serialNum, "error", err) } } } if errCount > 0 { - sc.Logger().Warn(fmt.Sprintf("Failed transfering %d local serials to unified storage", errCount)) + sc.Backend.Logger().Warn(fmt.Sprintf("Failed transfering %d local serials to unified storage", errCount)) } return nil @@ -224,7 +224,7 @@ func doUnifiedTransferMissingDeltaWALSerials(sc *storageContext, clusterId strin errCount := 0 for index, serial := range localWALEntries { if index%25 == 0 { - config, _ := sc.CrlBuilder().GetConfigWithUpdate(sc) + config, _ := sc.Backend.CrlBuilder().getConfigWithUpdate(sc) if config != nil && (!config.UnifiedCRL || !config.EnableDelta) { return errors.New("unified or delta CRLs have been disabled after we started, stopping") } @@ -247,7 +247,7 @@ func doUnifiedTransferMissingDeltaWALSerials(sc *storageContext, clusterId strin if !isRevokedCopied { // We need to wait here to copy over. errCount += 1 - sc.Logger().Debug("Delta WAL exists locally, but corresponding cross-cluster full revocation entry is missing; skipping", "serial", serial) + sc.Backend.Logger().Debug("Delta WAL exists locally, but corresponding cross-cluster full revocation entry is missing; skipping", "serial", serial) continue } @@ -258,7 +258,7 @@ func doUnifiedTransferMissingDeltaWALSerials(sc *storageContext, clusterId strin entry, err := sc.Storage.Get(sc.Context, localPath) if err != nil || entry == nil { errCount += 1 - sc.Logger().Error("Failed reading local delta WAL entry to copy to cross-cluster", "serial", serial, "err", err) + sc.Backend.Logger().Error("Failed reading local delta WAL entry to copy to cross-cluster", "serial", serial, "err", err) continue } @@ -266,14 +266,14 @@ func doUnifiedTransferMissingDeltaWALSerials(sc *storageContext, clusterId strin err = sc.Storage.Put(sc.Context, entry) if err != nil { errCount += 1 - sc.Logger().Error("Failed sync local delta WAL entry to cross-cluster unified delta WAL location", "serial", serial, "err", err) + sc.Backend.Logger().Error("Failed sync local delta WAL entry to cross-cluster unified delta WAL location", "serial", serial, "err", err) continue } } if errCount > 0 { // See note above about why we don't fail here. - sc.Logger().Warn(fmt.Sprintf("Failed transfering %d local delta WAL serials to unified storage", errCount)) + sc.Backend.Logger().Warn(fmt.Sprintf("Failed transfering %d local delta WAL serials to unified storage", errCount)) return nil } @@ -295,17 +295,17 @@ func doUnifiedTransferMissingDeltaWALSerials(sc *storageContext, clusterId strin func readRevocationEntryAndTransfer(sc *storageContext, serial string) error { hyphenSerial := normalizeSerial(serial) - revInfo, err := fetchRevocationInfo(sc, hyphenSerial) + revInfo, err := sc.fetchRevocationInfo(hyphenSerial) if err != nil { return fmt.Errorf("failed loading revocation entry for serial: %s: %w", serial, err) } if revInfo == nil { - sc.Logger().Debug("no certificate revocation entry for serial", "serial", serial) + sc.Backend.Logger().Debug("no certificate revocation entry for serial", "serial", serial) return nil } cert, err := x509.ParseCertificate(revInfo.CertificateBytes) if err != nil { - sc.Logger().Debug("failed parsing certificate stored in revocation entry for serial", + sc.Backend.Logger().Debug("failed parsing certificate stored in revocation entry for serial", "serial", serial, "error", err) return nil } @@ -326,12 +326,12 @@ func readRevocationEntryAndTransfer(sc *storageContext, serial string) error { return nil } - entry := &revocation.UnifiedRevocationEntry{ + entry := &unifiedRevocationEntry{ SerialNumber: hyphenSerial, CertExpiration: cert.NotAfter, RevocationTimeUTC: revocationTime, CertificateIssuer: revInfo.CertificateIssuer, } - return revocation.WriteUnifiedRevocationEntry(sc.GetContext(), sc.GetStorage(), entry) + return writeUnifiedRevocationEntry(sc, entry) } diff --git a/builtin/logical/pki/pki_backend/common.go b/builtin/logical/pki/pki_backend/common.go index 6b7c642ada06..b34fda076199 100644 --- a/builtin/logical/pki/pki_backend/common.go +++ b/builtin/logical/pki/pki_backend/common.go @@ -4,13 +4,7 @@ package pki_backend import ( - "context" - "fmt" - "strings" - log "github.com/hashicorp/go-hclog" - "github.com/hashicorp/vault/builtin/logical/pki/issuing" - "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/logical" ) @@ -26,80 +20,7 @@ type Logger interface { Logger() log.Logger } -//go:generate enumer -type=RolePathPolicy -text -json -transform=kebab-case -type RolePathPolicy int - -const ( - RPPUnknown RolePathPolicy = iota - RPPSignVerbatim - RPPRole -) - -var ( - pathPolicyRolePrefix = "role:" - pathPolicyRolePrefixLength = len(pathPolicyRolePrefix) -) - -// GetRoleByPathOrPathPolicy loads an existing role based on if the data field data contains a 'role' parameter -// or by the values within the pathPolicy -func GetRoleByPathOrPathPolicy(ctx context.Context, s logical.Storage, data *framework.FieldData, pathPolicy string) (*issuing.RoleEntry, error) { - var role *issuing.RoleEntry - - // The role name from the path is the highest priority - if roleName, ok := getRoleNameFromPath(data); ok { - var err error - role, err = issuing.GetRole(ctx, s, roleName) - if err != nil { - return nil, err - } - } else { - policyType, policyVal, err := GetPathPolicyType(pathPolicy) - if err != nil { - return nil, err - } - - switch policyType { - case RPPRole: - role, err = issuing.GetRole(ctx, s, policyVal) - if err != nil { - return nil, err - } - case RPPSignVerbatim: - role = issuing.SignVerbatimRole() - default: - return nil, fmt.Errorf("unsupported policy type returned: %s from policy path: %s", policyType, pathPolicy) - } - } - - return role, nil -} - -func GetPathPolicyType(pathPolicy string) (RolePathPolicy, string, error) { - policy := strings.TrimSpace(pathPolicy) - - switch { - case policy == "sign-verbatim": - return RPPSignVerbatim, "", nil - case strings.HasPrefix(policy, pathPolicyRolePrefix): - if policy == pathPolicyRolePrefix { - return RPPUnknown, "", fmt.Errorf("no role specified by policy %v", pathPolicy) - } - roleName := pathPolicy[pathPolicyRolePrefixLength:] - return RPPRole, roleName, nil - default: - return RPPUnknown, "", fmt.Errorf("string %v was not a valid default path policy", pathPolicy) - } -} - -func getRoleNameFromPath(data *framework.FieldData) (string, bool) { - // If our schema doesn't include the parameter bail - if _, ok := data.Schema["role"]; !ok { - return "", false - } - - if roleName, ok := data.GetOk("role"); ok { - return roleName.(string), true - } - - return "", false +type CertificateCounter interface { + IsInitialized() bool + IncrementTotalCertificatesCount(certsCounted bool, newSerial string) } diff --git a/builtin/logical/pki/pki_backend/crl_builder.go b/builtin/logical/pki/pki_backend/crl_builder.go deleted file mode 100644 index 58c048094a59..000000000000 --- a/builtin/logical/pki/pki_backend/crl_builder.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package pki_backend - -import "time" - -type CrlBuilderType interface { - RebuildIfForced(sc StorageContext) ([]string, error) - Rebuild(sc StorageContext, forceNew bool) ([]string, error) - RebuildDeltaCRLsHoldingLock(sc StorageContext, forceNew bool) ([]string, error) - GetPresentLocalDeltaWALForClearing(sc StorageContext) ([]string, error) - GetPresentUnifiedDeltaWALForClearing(sc StorageContext) ([]string, error) - GetConfigWithUpdate(sc StorageContext) (*CrlConfig, error) - ClearLocalDeltaWAL(sc StorageContext, walSerials []string) error - ClearUnifiedDeltaWAL(sc StorageContext, walSerials []string) error - - SetLastDeltaRebuildCheckTime(t time.Time) - ShouldInvalidate() bool -} diff --git a/builtin/logical/pki/pki_backend/crl_config.go b/builtin/logical/pki/pki_backend/crl_config.go deleted file mode 100644 index f37fbbbb3321..000000000000 --- a/builtin/logical/pki/pki_backend/crl_config.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package pki_backend - -const latestCrlConfigVersion = 1 - -// CRLConfig holds basic CRL configuration information -type CrlConfig struct { - Version int `json:"version"` - Expiry string `json:"expiry"` - Disable bool `json:"disable"` - OcspDisable bool `json:"ocsp_disable"` - AutoRebuild bool `json:"auto_rebuild"` - AutoRebuildGracePeriod string `json:"auto_rebuild_grace_period"` - OcspExpiry string `json:"ocsp_expiry"` - EnableDelta bool `json:"enable_delta"` - DeltaRebuildInterval string `json:"delta_rebuild_interval"` - UseGlobalQueue bool `json:"cross_cluster_revocation"` - UnifiedCRL bool `json:"unified_crl"` - UnifiedCRLOnExistingPaths bool `json:"unified_crl_on_existing_paths"` -} - -// Implicit default values for the config if it does not exist. -var DefaultCrlConfig = CrlConfig{ - Version: latestCrlConfigVersion, - Expiry: "72h", - Disable: false, - OcspDisable: false, - OcspExpiry: "12h", - AutoRebuild: false, - AutoRebuildGracePeriod: "12h", - EnableDelta: false, - DeltaRebuildInterval: "15m", - UseGlobalQueue: false, - UnifiedCRL: false, - UnifiedCRLOnExistingPaths: false, -} diff --git a/builtin/logical/pki/pki_backend/rolepathpolicy_enumer.go b/builtin/logical/pki/pki_backend/rolepathpolicy_enumer.go deleted file mode 100644 index 305e34a6b547..000000000000 --- a/builtin/logical/pki/pki_backend/rolepathpolicy_enumer.go +++ /dev/null @@ -1,80 +0,0 @@ -// Code generated by "enumer -type=RolePathPolicy -text -json -transform=kebab-case"; DO NOT EDIT. - -package pki_backend - -import ( - "encoding/json" - "fmt" -) - -const _RolePathPolicyName = "RPPUnknownRPPSignVerbatimRPPRole" - -var _RolePathPolicyIndex = [...]uint8{0, 10, 25, 32} - -func (i RolePathPolicy) String() string { - if i < 0 || i >= RolePathPolicy(len(_RolePathPolicyIndex)-1) { - return fmt.Sprintf("RolePathPolicy(%d)", i) - } - return _RolePathPolicyName[_RolePathPolicyIndex[i]:_RolePathPolicyIndex[i+1]] -} - -var _RolePathPolicyValues = []RolePathPolicy{0, 1, 2} - -var _RolePathPolicyNameToValueMap = map[string]RolePathPolicy{ - _RolePathPolicyName[0:10]: 0, - _RolePathPolicyName[10:25]: 1, - _RolePathPolicyName[25:32]: 2, -} - -// RolePathPolicyString retrieves an enum value from the enum constants string name. -// Throws an error if the param is not part of the enum. -func RolePathPolicyString(s string) (RolePathPolicy, error) { - if val, ok := _RolePathPolicyNameToValueMap[s]; ok { - return val, nil - } - return 0, fmt.Errorf("%s does not belong to RolePathPolicy values", s) -} - -// RolePathPolicyValues returns all values of the enum -func RolePathPolicyValues() []RolePathPolicy { - return _RolePathPolicyValues -} - -// IsARolePathPolicy returns "true" if the value is listed in the enum definition. "false" otherwise -func (i RolePathPolicy) IsARolePathPolicy() bool { - for _, v := range _RolePathPolicyValues { - if i == v { - return true - } - } - return false -} - -// MarshalJSON implements the json.Marshaler interface for RolePathPolicy -func (i RolePathPolicy) MarshalJSON() ([]byte, error) { - return json.Marshal(i.String()) -} - -// UnmarshalJSON implements the json.Unmarshaler interface for RolePathPolicy -func (i *RolePathPolicy) UnmarshalJSON(data []byte) error { - var s string - if err := json.Unmarshal(data, &s); err != nil { - return fmt.Errorf("RolePathPolicy should be a string, got %s", data) - } - - var err error - *i, err = RolePathPolicyString(s) - return err -} - -// MarshalText implements the encoding.TextMarshaler interface for RolePathPolicy -func (i RolePathPolicy) MarshalText() ([]byte, error) { - return []byte(i.String()), nil -} - -// UnmarshalText implements the encoding.TextUnmarshaler interface for RolePathPolicy -func (i *RolePathPolicy) UnmarshalText(text []byte) error { - var err error - *i, err = RolePathPolicyString(string(text)) - return err -} diff --git a/builtin/logical/pki/pki_backend/storage_context.go b/builtin/logical/pki/pki_backend/storage_context.go deleted file mode 100644 index d05b53306221..000000000000 --- a/builtin/logical/pki/pki_backend/storage_context.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package pki_backend - -import ( - "context" - - "github.com/hashicorp/go-hclog" - "github.com/hashicorp/vault/builtin/logical/pki/issuing" - "github.com/hashicorp/vault/builtin/logical/pki/managed_key" - "github.com/hashicorp/vault/sdk/logical" -) - -type StorageContext interface { - GetContext() context.Context - GetStorage() logical.Storage - - UseLegacyBundleCaStorage() bool - GetPkiManagedView() managed_key.PkiManagedKeyView - CrlBuilder() CrlBuilderType - GetCertificateCounter() issuing.CertificateCounter - - Logger() hclog.Logger -} diff --git a/builtin/logical/pki/revocation/revocation_entry.go b/builtin/logical/pki/revocation/revocation_entry.go deleted file mode 100644 index bdbd3c389cac..000000000000 --- a/builtin/logical/pki/revocation/revocation_entry.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package revocation - -import ( - "context" - "time" - - "github.com/hashicorp/vault/builtin/logical/pki/issuing" - "github.com/hashicorp/vault/builtin/logical/pki/parsing" - "github.com/hashicorp/vault/sdk/logical" -) - -type UnifiedRevocationEntry struct { - SerialNumber string `json:"-"` - CertExpiration time.Time `json:"certificate_expiration_utc"` - RevocationTimeUTC time.Time `json:"revocation_time_utc"` - CertificateIssuer issuing.IssuerID `json:"issuer_id"` -} - -const ( - UnifiedRevocationReadPathPrefix = "unified-revocation/" - UnifiedRevocationWritePathPrefix = UnifiedRevocationReadPathPrefix + "{{clusterId}}/" -) - -func WriteUnifiedRevocationEntry(ctx context.Context, storage logical.Storage, ure *UnifiedRevocationEntry) error { - json, err := logical.StorageEntryJSON(UnifiedRevocationWritePathPrefix+parsing.NormalizeSerialForStorage(ure.SerialNumber), ure) - if err != nil { - return err - } - - return storage.Put(ctx, json) -} diff --git a/builtin/logical/pki/revocation/revoke.go b/builtin/logical/pki/revocation/revoke.go deleted file mode 100644 index deb786f7fad6..000000000000 --- a/builtin/logical/pki/revocation/revoke.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package revocation - -import ( - "bytes" - "context" - "crypto/x509" - "fmt" - "time" - - "github.com/hashicorp/vault/builtin/logical/pki/issuing" - "github.com/hashicorp/vault/builtin/logical/pki/pki_backend" - "github.com/hashicorp/vault/sdk/helper/errutil" - "github.com/hashicorp/vault/sdk/logical" -) - -const ( - RevokedPath = "revoked/" -) - -type RevokerFactory interface { - GetRevoker(context.Context, logical.Storage) (Revoker, error) -} - -type RevokeCertInfo struct { - RevocationTime time.Time - Warnings []string -} - -type Revoker interface { - RevokeCert(cert *x509.Certificate) (RevokeCertInfo, error) - RevokeCertBySerial(serial string) (RevokeCertInfo, error) -} - -type RevocationInfo struct { - CertificateBytes []byte `json:"certificate_bytes"` - RevocationTime int64 `json:"revocation_time"` - RevocationTimeUTC time.Time `json:"revocation_time_utc"` - CertificateIssuer issuing.IssuerID `json:"issuer_id"` -} - -func (ri *RevocationInfo) AssociateRevokedCertWithIsssuer(revokedCert *x509.Certificate, issuerIDCertMap map[issuing.IssuerID]*x509.Certificate) bool { - for issuerId, issuerCert := range issuerIDCertMap { - if bytes.Equal(revokedCert.RawIssuer, issuerCert.RawSubject) { - if err := revokedCert.CheckSignatureFrom(issuerCert); err == nil { - // Valid mapping. Add it to the specified entry. - ri.CertificateIssuer = issuerId - return true - } - } - } - - return false -} - -// FetchIssuerMapForRevocationChecking fetches a map of IssuerID->parsed cert for revocation -// usage. Unlike other paths, this needs to handle the legacy bundle -// more gracefully than rejecting it outright. -func FetchIssuerMapForRevocationChecking(sc pki_backend.StorageContext) (map[issuing.IssuerID]*x509.Certificate, error) { - var err error - var issuers []issuing.IssuerID - - if !sc.UseLegacyBundleCaStorage() { - issuers, err = issuing.ListIssuers(sc.GetContext(), sc.GetStorage()) - if err != nil { - return nil, fmt.Errorf("could not fetch issuers list: %w", err) - } - } else { - // Hack: this isn't a real IssuerID, but it works for fetchCAInfo - // since it resolves the reference. - issuers = []issuing.IssuerID{issuing.LegacyBundleShimID} - } - - issuerIDCertMap := make(map[issuing.IssuerID]*x509.Certificate, len(issuers)) - for _, issuer := range issuers { - _, bundle, caErr := issuing.FetchCertBundleByIssuerId(sc.GetContext(), sc.GetStorage(), issuer, false) - if caErr != nil { - return nil, fmt.Errorf("error fetching CA certificate for issuer id %v: %w", issuer, caErr) - } - - if bundle == nil { - return nil, fmt.Errorf("faulty reference: %v - CA info not found", issuer) - } - - parsedBundle, err := issuing.ParseCABundle(sc.GetContext(), sc.GetPkiManagedView(), bundle) - if err != nil { - return nil, errutil.InternalError{Err: err.Error()} - } - - if parsedBundle.Certificate == nil { - return nil, errutil.InternalError{Err: "stored CA information not able to be parsed"} - } - - issuerIDCertMap[issuer] = parsedBundle.Certificate - } - - return issuerIDCertMap, nil -} diff --git a/builtin/logical/pki/secret_certs.go b/builtin/logical/pki/secret_certs.go index 7f75203b1f46..0cf0ad0c6d1d 100644 --- a/builtin/logical/pki/secret_certs.go +++ b/builtin/logical/pki/secret_certs.go @@ -78,7 +78,7 @@ func (b *backend) secretCredsRevoke(ctx context.Context, req *logical.Request, _ return nil, nil } - config, err := sc.CrlBuilder().GetConfigWithUpdate(sc) + config, err := sc.Backend.CrlBuilder().getConfigWithUpdate(sc) if err != nil { return nil, fmt.Errorf("error revoking serial: %s: failed reading config: %w", serial, err) } diff --git a/builtin/logical/pki/storage.go b/builtin/logical/pki/storage.go index 43c4853ba34c..01e01965b590 100644 --- a/builtin/logical/pki/storage.go +++ b/builtin/logical/pki/storage.go @@ -11,15 +11,11 @@ import ( "errors" "fmt" "strings" - "sync" "time" - "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-uuid" "github.com/hashicorp/vault/builtin/logical/pki/issuing" "github.com/hashicorp/vault/builtin/logical/pki/managed_key" - "github.com/hashicorp/vault/builtin/logical/pki/pki_backend" - "github.com/hashicorp/vault/builtin/logical/pki/revocation" "github.com/hashicorp/vault/helper/constants" "github.com/hashicorp/vault/sdk/helper/certutil" "github.com/hashicorp/vault/sdk/helper/errutil" @@ -39,13 +35,12 @@ const ( legacyMigrationBundleLogKey = "config/legacyMigrationBundleLog" legacyCertBundlePath = issuing.LegacyCertBundlePath legacyCertBundleBackupPath = "config/ca_bundle.bak" - - legacyCRLPath = issuing.LegacyCRLPath - deltaCRLPath = issuing.DeltaCRLPath - deltaCRLPathSuffix = issuing.DeltaCRLPathSuffix - unifiedCRLPath = issuing.UnifiedCRLPath - unifiedDeltaCRLPath = issuing.UnifiedDeltaCRLPath - unifiedCRLPathPrefix = issuing.UnifiedCRLPathPrefix + legacyCRLPath = "crl" + deltaCRLPath = "delta-crl" + deltaCRLPathSuffix = "-delta" + unifiedCRLPath = "unified-crl" + unifiedDeltaCRLPath = "unified-delta-crl" + unifiedCRLPathPrefix = "unified-" autoTidyConfigPath = "config/auto-tidy" clusterConfigPath = "config/cluster" @@ -66,8 +61,6 @@ type storageContext struct { Backend *backend } -var _ pki_backend.StorageContext = (*storageContext)(nil) - func (b *backend) makeStorageContext(ctx context.Context, s logical.Storage) *storageContext { return &storageContext{ Context: ctx, @@ -85,50 +78,6 @@ func (sc *storageContext) WithFreshTimeout(timeout time.Duration) (*storageConte }, cancel } -func (sc *storageContext) GetContext() context.Context { - return sc.Context -} - -func (sc *storageContext) GetStorage() logical.Storage { - return sc.Storage -} - -func (sc *storageContext) Logger() hclog.Logger { - return sc.Backend.Logger() -} - -func (sc *storageContext) System() logical.SystemView { - return sc.Backend.System() -} - -func (sc *storageContext) CrlBuilder() pki_backend.CrlBuilderType { - return sc.Backend.CrlBuilder() -} - -func (sc *storageContext) GetUnifiedTransferStatus() *UnifiedTransferStatus { - return sc.Backend.GetUnifiedTransferStatus() -} - -func (sc *storageContext) GetPkiManagedView() managed_key.PkiManagedKeyView { - return sc.Backend -} - -func (sc *storageContext) GetCertificateCounter() issuing.CertificateCounter { - return sc.Backend.GetCertificateCounter() -} - -func (sc *storageContext) UseLegacyBundleCaStorage() bool { - return sc.Backend.UseLegacyBundleCaStorage() -} - -func (sc *storageContext) GetRevokeStorageLock() *sync.RWMutex { - return sc.Backend.GetRevokeStorageLock() -} - -func (sc *storageContext) GetRole(name string) (*issuing.RoleEntry, error) { - return sc.Backend.GetRole(sc.Context, sc.Storage, name) -} - func (sc *storageContext) listKeys() ([]issuing.KeyID, error) { return issuing.ListKeys(sc.Context, sc.Storage) } @@ -520,6 +469,41 @@ func (sc *storageContext) resolveIssuerReference(reference string) (issuing.Issu return issuing.ResolveIssuerReference(sc.Context, sc.Storage, reference) } +func (sc *storageContext) resolveIssuerCRLPath(reference string, unified bool) (string, error) { + if sc.Backend.UseLegacyBundleCaStorage() { + return legacyCRLPath, nil + } + + issuer, err := sc.resolveIssuerReference(reference) + if err != nil { + return legacyCRLPath, err + } + + var crlConfig *issuing.InternalCRLConfigEntry + if unified { + crlConfig, err = issuing.GetUnifiedCRLConfig(sc.Context, sc.Storage) + if err != nil { + return legacyCRLPath, err + } + } else { + crlConfig, err = issuing.GetLocalCRLConfig(sc.Context, sc.Storage) + if err != nil { + return legacyCRLPath, err + } + } + + if crlId, ok := crlConfig.IssuerIDCRLMap[issuer]; ok && len(crlId) > 0 { + path := fmt.Sprintf("crls/%v", crlId) + if unified { + path = unifiedCRLPathPrefix + path + } + + return path, nil + } + + return legacyCRLPath, fmt.Errorf("unable to find CRL for issuer: id:%v/ref:%v", issuer, reference) +} + // Builds a certutil.CertBundle from the specified issuer identifier, // optionally loading the key or not. This method supports loading legacy // bundles using the legacyBundleShimID issuerId, and if no entry is found will return an error. @@ -631,15 +615,15 @@ func (sc *storageContext) checkForRolesReferencing(issuerId string) (timeout boo return false, inUseBy, nil } -func (sc *storageContext) getRevocationConfig() (*pki_backend.CrlConfig, error) { +func (sc *storageContext) getRevocationConfig() (*crlConfig, error) { entry, err := sc.Storage.Get(sc.Context, "config/crl") if err != nil { return nil, err } - var result pki_backend.CrlConfig + var result crlConfig if entry == nil { - result = pki_backend.DefaultCrlConfig + result = defaultCrlConfig return &result, nil } @@ -649,15 +633,15 @@ func (sc *storageContext) getRevocationConfig() (*pki_backend.CrlConfig, error) if result.Version == 0 { // Automatically update existing configurations. - result.OcspDisable = pki_backend.DefaultCrlConfig.OcspDisable - result.OcspExpiry = pki_backend.DefaultCrlConfig.OcspExpiry - result.AutoRebuild = pki_backend.DefaultCrlConfig.AutoRebuild - result.AutoRebuildGracePeriod = pki_backend.DefaultCrlConfig.AutoRebuildGracePeriod + result.OcspDisable = defaultCrlConfig.OcspDisable + result.OcspExpiry = defaultCrlConfig.OcspExpiry + result.AutoRebuild = defaultCrlConfig.AutoRebuild + result.AutoRebuildGracePeriod = defaultCrlConfig.AutoRebuildGracePeriod result.Version = 1 } if result.Version == 1 { if result.DeltaRebuildInterval == "" { - result.DeltaRebuildInterval = pki_backend.DefaultCrlConfig.DeltaRebuildInterval + result.DeltaRebuildInterval = defaultCrlConfig.DeltaRebuildInterval } result.Version = 2 } @@ -665,13 +649,13 @@ func (sc *storageContext) getRevocationConfig() (*pki_backend.CrlConfig, error) // Depending on client version, it's possible that the expiry is unset. // This sets the default value to prevent issues in downstream code. if result.Expiry == "" { - result.Expiry = pki_backend.DefaultCrlConfig.Expiry + result.Expiry = defaultCrlConfig.Expiry } - isLocalMount := sc.System().LocalMount() + isLocalMount := sc.Backend.System().LocalMount() if (!constants.IsEnterprise || isLocalMount) && (result.UnifiedCRLOnExistingPaths || result.UnifiedCRL || result.UseGlobalQueue) { // An end user must have had Enterprise, enabled the unified config args and then downgraded to OSS. - sc.Logger().Warn("Not running Vault Enterprise or using a local mount, " + + sc.Backend.Logger().Warn("Not running Vault Enterprise or using a local mount, " + "disabling unified_crl, unified_crl_on_existing_paths and cross_cluster_revocation config flags.") result.UnifiedCRLOnExistingPaths = false result.UnifiedCRL = false @@ -681,7 +665,7 @@ func (sc *storageContext) getRevocationConfig() (*pki_backend.CrlConfig, error) return &result, nil } -func (sc *storageContext) setRevocationConfig(config *pki_backend.CrlConfig) error { +func (sc *storageContext) setRevocationConfig(config *crlConfig) error { entry, err := logical.StorageEntryJSON("config/crl", config) if err != nil { return fmt.Errorf("failed building storage entry JSON: %w", err) @@ -814,9 +798,9 @@ func (sc *storageContext) writeAutoTidyLastRun(lastRunTime time.Time) error { return nil } -func fetchRevocationInfo(sc pki_backend.StorageContext, serial string) (*revocation.RevocationInfo, error) { - var revInfo *revocation.RevocationInfo - revEntry, err := fetchCertBySerial(sc, revocation.RevokedPath, serial) +func (sc *storageContext) fetchRevocationInfo(serial string) (*revocationInfo, error) { + var revInfo *revocationInfo + revEntry, err := fetchCertBySerial(sc, revokedPath, serial) if err != nil { return nil, err } diff --git a/builtin/logical/pki/storage_test.go b/builtin/logical/pki/storage_test.go index f51ed6b496d3..3ace55e51c12 100644 --- a/builtin/logical/pki/storage_test.go +++ b/builtin/logical/pki/storage_test.go @@ -242,7 +242,6 @@ func genCertBundle(t *testing.T, b *backend, s logical.Storage) *certutil.CertBu fields := addCACommonFields(map[string]*framework.FieldSchema{}) fields = addCAKeyGenerationFields(fields) fields = addCAIssueFields(fields) - fields = addCACertKeyUsage(fields) apiData := &framework.FieldData{ Schema: fields, Raw: map[string]interface{}{ diff --git a/builtin/logical/pki/storage_unified.go b/builtin/logical/pki/storage_unified.go index 63f39f1c596a..c279c26191ed 100644 --- a/builtin/logical/pki/storage_unified.go +++ b/builtin/logical/pki/storage_unified.go @@ -6,15 +6,25 @@ package pki import ( "fmt" "strings" + "time" - "github.com/hashicorp/vault/builtin/logical/pki/revocation" + "github.com/hashicorp/vault/builtin/logical/pki/issuing" + "github.com/hashicorp/vault/sdk/logical" ) const ( - unifiedRevocationReadPathPrefix = revocation.UnifiedRevocationReadPathPrefix + unifiedRevocationReadPathPrefix = "unified-revocation/" + unifiedRevocationWritePathPrefix = unifiedRevocationReadPathPrefix + "{{clusterId}}/" ) -func getUnifiedRevocationBySerial(sc *storageContext, serial string) (*revocation.UnifiedRevocationEntry, error) { +type unifiedRevocationEntry struct { + SerialNumber string `json:"-"` + CertExpiration time.Time `json:"certificate_expiration_utc"` + RevocationTimeUTC time.Time `json:"revocation_time_utc"` + CertificateIssuer issuing.IssuerID `json:"issuer_id"` +} + +func getUnifiedRevocationBySerial(sc *storageContext, serial string) (*unifiedRevocationEntry, error) { clusterPaths, err := lookupUnifiedClusterPaths(sc) if err != nil { return nil, err @@ -28,7 +38,7 @@ func getUnifiedRevocationBySerial(sc *storageContext, serial string) (*revocatio } if entryRaw != nil { - var revEntry revocation.UnifiedRevocationEntry + var revEntry unifiedRevocationEntry if err := entryRaw.DecodeJSON(&revEntry); err != nil { return nil, fmt.Errorf("failed json decoding of unified entry at path %s: %w", serialPath, err) } @@ -40,6 +50,15 @@ func getUnifiedRevocationBySerial(sc *storageContext, serial string) (*revocatio return nil, nil } +func writeUnifiedRevocationEntry(sc *storageContext, ure *unifiedRevocationEntry) error { + json, err := logical.StorageEntryJSON(unifiedRevocationWritePathPrefix+normalizeSerial(ure.SerialNumber), ure) + if err != nil { + return err + } + + return sc.Storage.Put(sc.Context, json) +} + // listClusterSpecificUnifiedRevokedCerts returns a list of revoked certificates from a given cluster func listClusterSpecificUnifiedRevokedCerts(sc *storageContext, clusterId string) ([]string, error) { path := unifiedRevocationReadPathPrefix + clusterId + "/" diff --git a/builtin/logical/pki/util.go b/builtin/logical/pki/util.go index 76f7bfcefcd3..f2e7c534f197 100644 --- a/builtin/logical/pki/util.go +++ b/builtin/logical/pki/util.go @@ -17,6 +17,7 @@ import ( "github.com/hashicorp/vault/builtin/logical/pki/managed_key" "github.com/hashicorp/vault/builtin/logical/pki/parsing" "github.com/hashicorp/vault/sdk/framework" + "github.com/hashicorp/vault/sdk/helper/certutil" "github.com/hashicorp/vault/sdk/helper/errutil" "github.com/hashicorp/vault/sdk/logical" ) @@ -39,11 +40,11 @@ var ( ) func serialFromCert(cert *x509.Certificate) string { - return parsing.SerialFromCert(cert) + return serialFromBigInt(cert.SerialNumber) } func serialFromBigInt(serial *big.Int) string { - return parsing.SerialFromBigInt(serial) + return strings.TrimSpace(certutil.GetHexFormatted(serial.Bytes(), ":")) } func normalizeSerialFromBigInt(serial *big.Int) string { @@ -307,7 +308,7 @@ func (sc *storageContext) isIfModifiedSinceBeforeLastModified(helper *IfModified switch helper.reqType { case ifModifiedCRL, ifModifiedDeltaCRL: - if sc.CrlBuilder().ShouldInvalidate() { + if sc.Backend.CrlBuilder().invalidate.Load() { // When we see the CRL is invalidated, respond with false // regardless of what the local CRL state says. We've likely // renamed some issuers or are about to rebuild a new CRL.... @@ -327,7 +328,7 @@ func (sc *storageContext) isIfModifiedSinceBeforeLastModified(helper *IfModified lastModified = crlConfig.DeltaLastModified } case ifModifiedUnifiedCRL, ifModifiedUnifiedDeltaCRL: - if sc.CrlBuilder().ShouldInvalidate() { + if sc.Backend.CrlBuilder().invalidate.Load() { // When we see the CRL is invalidated, respond with false // regardless of what the local CRL state says. We've likely // renamed some issuers or are about to rebuild a new CRL.... diff --git a/builtin/logical/pkiext/nginx_test.go b/builtin/logical/pkiext/nginx_test.go index 70defe42e875..e7d3ab42ed7e 100644 --- a/builtin/logical/pkiext/nginx_test.go +++ b/builtin/logical/pkiext/nginx_test.go @@ -39,7 +39,7 @@ const ( func buildNginxContainer(t *testing.T, root string, crl string, chain string, private string) (func(), string, int, string, string, int) { containerfile := ` -FROM nginx:1.27.1 +FROM nginx:latest RUN mkdir /www /etc/nginx/ssl && rm /etc/nginx/conf.d/*.conf diff --git a/builtin/logical/rabbitmq/path_role_create.go b/builtin/logical/rabbitmq/path_role_create.go index c06e82442812..956a01672086 100644 --- a/builtin/logical/rabbitmq/path_role_create.go +++ b/builtin/logical/rabbitmq/path_role_create.go @@ -6,7 +6,7 @@ package rabbitmq import ( "context" "fmt" - "io" + "io/ioutil" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/helper/template" @@ -113,7 +113,7 @@ func (b *backend) pathCredsRead(ctx context.Context, req *logical.Request, d *fr } }() if !isIn200s(resp.StatusCode) { - body, _ := io.ReadAll(resp.Body) + body, _ := ioutil.ReadAll(resp.Body) return nil, fmt.Errorf("error creating user %s - %d: %s", username, resp.StatusCode, body) } @@ -128,7 +128,7 @@ func (b *backend) pathCredsRead(ctx context.Context, req *logical.Request, d *fr b.Logger().Error(fmt.Sprintf("deleting %s due to permissions being in an unknown state, but failed: %s", username, err)) } if !isIn200s(resp.StatusCode) { - body, _ := io.ReadAll(resp.Body) + body, _ := ioutil.ReadAll(resp.Body) b.Logger().Error(fmt.Sprintf("deleting %s due to permissions being in an unknown state, but error deleting: %d: %s", username, resp.StatusCode, body)) } }() @@ -151,7 +151,7 @@ func (b *backend) pathCredsRead(ctx context.Context, req *logical.Request, d *fr } }() if !isIn200s(resp.StatusCode) { - body, _ := io.ReadAll(resp.Body) + body, _ := ioutil.ReadAll(resp.Body) return fmt.Errorf("error updating vhost permissions for %s - %d: %s", vhost, resp.StatusCode, body) } return nil @@ -180,7 +180,7 @@ func (b *backend) pathCredsRead(ctx context.Context, req *logical.Request, d *fr } }() if !isIn200s(resp.StatusCode) { - body, _ := io.ReadAll(resp.Body) + body, _ := ioutil.ReadAll(resp.Body) return fmt.Errorf("error updating vhost permissions for %s - %d: %s", vhost, resp.StatusCode, body) } return nil diff --git a/changelog/10624.txt b/changelog/10624.txt deleted file mode 100644 index fdb473b80d09..000000000000 --- a/changelog/10624.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -storage/azure: Updated metadata endpoint to `GetMSIEndpoint`, which supports more than just the metadata service. -``` diff --git a/changelog/11084.txt b/changelog/11084.txt deleted file mode 100644 index 444c93da9955..000000000000 --- a/changelog/11084.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -serviceregistration: Added support for Consul ServiceMeta tags from config file from the new `service_meta` config field. -``` diff --git a/changelog/14723.txt b/changelog/14723.txt deleted file mode 100644 index 04953430d866..000000000000 --- a/changelog/14723.txt +++ /dev/null @@ -1,4 +0,0 @@ -```release-note:improvement -core/identity: allow identity backend to be tuned using standard secrets backend tuning parameters. -``` - diff --git a/changelog/16484.txt b/changelog/16484.txt deleted file mode 100644 index 055f214dabdc..000000000000 --- a/changelog/16484.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:bug -auth/appid, auth/cert, auth/github, auth/ldap, auth/okta, auth/radius, auth/userpass: fixed an issue with policy name normalization that would prevent a token associated with a policy containing an uppercase character to be renewed. -``` diff --git a/changelog/16974.txt b/changelog/16974.txt deleted file mode 100644 index 202670ea4364..000000000000 --- a/changelog/16974.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -cli: Add a `--dev-no-kv` flag to prevent auto mounting a key-value secret backend when running a dev server -``` diff --git a/changelog/17007.txt b/changelog/17007.txt deleted file mode 100644 index 6c2a2801b24c..000000000000 --- a/changelog/17007.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:bug -auth/token: fixes an edge case bug that "identity_policies" is nil and causes cli vault login error -``` diff --git a/changelog/19064.txt b/changelog/19064.txt deleted file mode 100644 index cf31525e25ee..000000000000 --- a/changelog/19064.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -core/cli: Example 'help' pages for vault read / write docs improved. -``` diff --git a/changelog/21159.txt b/changelog/21159.txt deleted file mode 100644 index 25c1e53d90d5..000000000000 --- a/changelog/21159.txt +++ /dev/null @@ -1,4 +0,0 @@ -```release-note:improvement -storage/dynamodb: Speed up list and delete of large directories by only requesting keys from DynamoDB -``` - diff --git a/changelog/21993.txt b/changelog/21993.txt deleted file mode 100644 index 856cfc9662e0..000000000000 --- a/changelog/21993.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -cli: Allow vault CLI HTTP headers to be specified using the JSON-encoded VAULT_HEADERS environment variable -``` \ No newline at end of file diff --git a/changelog/25080.txt b/changelog/25080.txt deleted file mode 100644 index ad43618d8281..000000000000 --- a/changelog/25080.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:bug -storage/raft: Fix auto_join not working with mDNS provider. -``` diff --git a/changelog/26073.txt b/changelog/26073.txt deleted file mode 100644 index 90a964db99c3..000000000000 --- a/changelog/26073.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -identity: alias metadata is now returned when listing entity aliases -``` diff --git a/changelog/26570.txt b/changelog/26570.txt deleted file mode 100644 index 79efe31414f9..000000000000 --- a/changelog/26570.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -agent: Add metric (vault.agent.authenticated) that is set to 1 when vault agent has a valid token and zero if it does not. -``` \ No newline at end of file diff --git a/changelog/26660.txt b/changelog/26660.txt deleted file mode 100644 index 9490cd0b6efa..000000000000 --- a/changelog/26660.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -storage/etcd: Update etcd3 client to v3.5.13 to allow use of TLSv1.3. -``` diff --git a/changelog/26828.txt b/changelog/26828.txt deleted file mode 100644 index 4c9a004c4601..000000000000 --- a/changelog/26828.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -secrets/database: Add support for GCP CloudSQL private IP's. -``` diff --git a/changelog/26868.txt b/changelog/26868.txt deleted file mode 100644 index 3a25d05efdbb..000000000000 --- a/changelog/26868.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -api: Update backoff/v3 to backoff/v4.3.0 -``` \ No newline at end of file diff --git a/changelog/27033.txt b/changelog/27033.txt deleted file mode 100644 index a06152dedc2b..000000000000 --- a/changelog/27033.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -command/server: Add support for dumping pprof files during startup using CLI option `pprof-dump-dir` -``` diff --git a/changelog/27123.txt b/changelog/27123.txt deleted file mode 100644 index f23dd835c5ed..000000000000 --- a/changelog/27123.txt +++ /dev/null @@ -1,6 +0,0 @@ -```release-note:improvement -agent/sink: Allow configuration of the user and group ID of the file sink. -``` -```release-note:improvement -proxy/sink: Allow configuration of the user and group ID of the file sink. -``` diff --git a/changelog/27202.txt b/changelog/27202.txt deleted file mode 100644 index 224f976bba09..000000000000 --- a/changelog/27202.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:bug -auth/cert: Merge error messages returned in login failures and include error when present -``` diff --git a/changelog/27265.txt b/changelog/27265.txt deleted file mode 100644 index 926b2c7a07d8..000000000000 --- a/changelog/27265.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:bug -cli: Fixed an erroneous warning appearing about `-address` not being set when it is. -``` diff --git a/changelog/27348.txt b/changelog/27348.txt deleted file mode 100644 index ec7ece0b851a..000000000000 --- a/changelog/27348.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -ui: Mask obfuscated fields when creating/editing a Secrets sync destination. -``` diff --git a/changelog/27350.txt b/changelog/27350.txt deleted file mode 100644 index ddf95bc0052b..000000000000 --- a/changelog/27350.txt +++ /dev/null @@ -1,4 +0,0 @@ -```release-note:change -activity log: Deprecated the field "default_report_months". Instead, the billing start time will be used to determine the start time -when querying the activity log endpoints. -``` \ No newline at end of file diff --git a/changelog/27379.txt b/changelog/27379.txt deleted file mode 100644 index 1744873c2839..000000000000 --- a/changelog/27379.txt +++ /dev/null @@ -1,5 +0,0 @@ -```release-note:change -activity: The startTime will be set to the start of the current billing period by default. -The endTime will be set to the end of the current month. This applies to /sys/internal/counters/activity, -/sys/internal/counters/activity/export, and the vault operator usage command that utilizes /sys/internal/counters/activity. -``` diff --git a/changelog/27394.txt b/changelog/27394.txt deleted file mode 100644 index 81a04305f487..000000000000 --- a/changelog/27394.txt +++ /dev/null @@ -1,4 +0,0 @@ -```release-note:feature -**Vault Minimal Version**: Add the ability to build a minimal version of Vault -with only core features using the BUILD_MINIMAL environment variable. -``` diff --git a/changelog/27405.txt b/changelog/27405.txt deleted file mode 100644 index ac5162e8010e..000000000000 --- a/changelog/27405.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -ui: AWS credentials form sets credential_type from backing role -``` diff --git a/changelog/27426.txt b/changelog/27426.txt deleted file mode 100644 index ac18d438622d..000000000000 --- a/changelog/27426.txt +++ /dev/null @@ -1,4 +0,0 @@ -```release-note:change -activity log: Deprecates the current_billing_period field for /sys/internal/counters/activity. The default start time -will automatically be set the billing period start date. -``` \ No newline at end of file diff --git a/changelog/27455.txt b/changelog/27455.txt deleted file mode 100644 index 38b7c92ae6db..000000000000 --- a/changelog/27455.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -ui: Uses the internal/counters/activity/export endpoint for client count export data. -``` \ No newline at end of file diff --git a/changelog/27457.txt b/changelog/27457.txt deleted file mode 100644 index e3cf89a76524..000000000000 --- a/changelog/27457.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -sdk/helper: Allow setting environment variables when using NewTestDockerCluster -``` diff --git a/changelog/27510.txt b/changelog/27510.txt deleted file mode 100644 index af574898b604..000000000000 --- a/changelog/27510.txt +++ /dev/null @@ -1,6 +0,0 @@ -```release-note:improvement -agent: Add the ability to dump pprof to the filesystem using SIGUSR2 -``` -```release-note:improvement -proxy: Add the ability to dump pprof to the filesystem using SIGUSR2 -``` diff --git a/changelog/27538.txt b/changelog/27538.txt deleted file mode 100644 index e1d14481502c..000000000000 --- a/changelog/27538.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -ui: Creates separate section for updating sensitive creds for Secrets sync create/edit view. -``` diff --git a/changelog/27578.txt b/changelog/27578.txt deleted file mode 100644 index 3a1b62a2a512..000000000000 --- a/changelog/27578.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -cli: The undocumented `-dev-three-node` and `-dev-four-cluster` CLI options have been removed. -``` diff --git a/changelog/27605.txt b/changelog/27605.txt deleted file mode 100644 index b449daf78920..000000000000 --- a/changelog/27605.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -storage/raft: Bump raft to v1.7.0 which includes pre-vote. This should make clusters more stable during network partitions. -``` diff --git a/changelog/27633.txt b/changelog/27633.txt deleted file mode 100644 index 1f5156b3bdcb..000000000000 --- a/changelog/27633.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -core: make authLock and mountsLock in Core configurable via the detect_deadlocks configuration parameter. -``` \ No newline at end of file diff --git a/changelog/27681.txt b/changelog/27681.txt deleted file mode 100644 index 13f5f829d523..000000000000 --- a/changelog/27681.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:bug -secrets/pki: fix lack of serial number to a certificate read resulting in a server side error. -``` \ No newline at end of file diff --git a/changelog/27796.txt b/changelog/27796.txt deleted file mode 100644 index 7a1e7ebac3b0..000000000000 --- a/changelog/27796.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -ui: simplify the date range editing experience in the client counts dashboard. -``` \ No newline at end of file diff --git a/changelog/27799.txt b/changelog/27799.txt deleted file mode 100644 index 217f6d78d91c..000000000000 --- a/changelog/27799.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -consul-template: updated to version 0.39.1 -``` \ No newline at end of file diff --git a/changelog/27816.txt b/changelog/27816.txt deleted file mode 100644 index 92dd2d7bb90c..000000000000 --- a/changelog/27816.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -ui: remove initial start/end parameters on the activity call for client counts dashboard. -``` \ No newline at end of file diff --git a/changelog/27830.txt b/changelog/27830.txt deleted file mode 100644 index 6a3d7e3041f7..000000000000 --- a/changelog/27830.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -activity (enterprise): remove deprecated fields distinct_entities and non_entity_tokens -``` \ No newline at end of file diff --git a/changelog/27831.txt b/changelog/27831.txt deleted file mode 100644 index 27224ef7db66..000000000000 --- a/changelog/27831.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -ui: For AWS and SSH secret engines hide mount configuration details in toggle and display configuration details or cta. -``` \ No newline at end of file diff --git a/changelog/27846.txt b/changelog/27846.txt deleted file mode 100644 index 50cba99062fb..000000000000 --- a/changelog/27846.txt +++ /dev/null @@ -1,7 +0,0 @@ -```release-note:change -activity: The [activity export API](https://developer.hashicorp.com/vault/api-docs/system/internal-counters#activity-export) now requires the `sudo` ACL capability. -``` - -```release-note:improvement -activity: The [activity export API](https://developer.hashicorp.com/vault/api-docs/system/internal-counters#activity-export) can now be called in non-root namespaces. Resulting records will be filtered to include the requested namespace (via `X-Vault-Namespace` header or within the path) and all child namespaces. -``` diff --git a/changelog/27918.txt b/changelog/27918.txt deleted file mode 100644 index bdf34609efe3..000000000000 --- a/changelog/27918.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -ui: Move secret-engine configuration create/edit from routing `vault/settings/secrets/configure/` to `vault/secrets//configuration/edit` -``` \ No newline at end of file diff --git a/changelog/27920.txt b/changelog/27920.txt deleted file mode 100644 index 6cb687731630..000000000000 --- a/changelog/27920.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:bug -core/api: Added missing LICENSE files to API sub-modules to ensure Go module tooling recognizes MPL-2.0 license. -``` diff --git a/changelog/27927.txt b/changelog/27927.txt deleted file mode 100644 index afc37a7acbd3..000000000000 --- a/changelog/27927.txt +++ /dev/null @@ -1,6 +0,0 @@ -```release-note:improvement -storage/s3: Pass context to AWS SDK calls -``` -```release-note:improvement -storage/dynamodb: Pass context to AWS SDK calls -``` diff --git a/changelog/27929.txt b/changelog/27929.txt deleted file mode 100644 index d957bcace4d8..000000000000 --- a/changelog/27929.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:bug -identity/oidc: prevent JWKS from being generated by multiple concurrent requests -``` diff --git a/changelog/27950.txt b/changelog/27950.txt deleted file mode 100644 index 27a1e53b1743..000000000000 --- a/changelog/27950.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -secrets/database/hana: Update HANA db client to v1.10.1 -``` diff --git a/changelog/27966.txt b/changelog/27966.txt deleted file mode 100644 index 616bfe5c8acf..000000000000 --- a/changelog/27966.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -core/metrics: ensure core HA metrics are always output to Prometheus. -``` \ No newline at end of file diff --git a/changelog/28024.txt b/changelog/28024.txt deleted file mode 100644 index 8d1fbaa0e2a5..000000000000 --- a/changelog/28024.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -database/postgres: Add new fields to the plugin's config endpoint for client certificate authentication. -``` diff --git a/changelog/28036.txt b/changelog/28036.txt deleted file mode 100644 index f47891e46c8d..000000000000 --- a/changelog/28036.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -ui: Update the client count dashboard to use API namespace filtering and other UX improvements -``` \ No newline at end of file diff --git a/changelog/28064.txt b/changelog/28064.txt deleted file mode 100644 index 6f18843cad3a..000000000000 --- a/changelog/28064.txt +++ /dev/null @@ -1,7 +0,0 @@ -```release-note:improvement -activity: The [activity export API](https://developer.hashicorp.com/vault/api-docs/system/internal-counters#activity-export) now includes identity metadata about entity clients. -``` - -```release-note:change -activity: The [activity export API](https://developer.hashicorp.com/vault/api-docs/system/internal-counters#activity-export) now responds with a status of 204 instead 400 when no data exists within the time range specified by `start_time` and `end_time`. -``` diff --git a/changelog/28076.txt b/changelog/28076.txt deleted file mode 100644 index bb9adb94294e..000000000000 --- a/changelog/28076.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -website/docs: corrected invalid json in sample payload for azure secrets engine create/update role -``` \ No newline at end of file diff --git a/changelog/28148.txt b/changelog/28148.txt deleted file mode 100644 index 141e6a0129d2..000000000000 --- a/changelog/28148.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:feature -**Feature Name**: Add WIF fields to AWS secrets engine. -``` diff --git a/changelog/28186.txt b/changelog/28186.txt deleted file mode 100644 index ee17101e4b5d..000000000000 --- a/changelog/28186.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -raft/autopilot: Persist Raft server versions so autopilot always knows the versions of all servers in the cluster. Include server versions in the Raft bootstrap challenge answer so autopilot immediately knows the versions of new nodes. -``` \ No newline at end of file diff --git a/changelog/28199.txt b/changelog/28199.txt deleted file mode 100644 index 9b94d97f8c5f..000000000000 --- a/changelog/28199.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:feature -**Self-Managed Static Roles**: Self-Managed Static Roles are now supported for select SQL database engines (Postgres, Oracle). Requires Vault Enterprise. -``` \ No newline at end of file diff --git a/changelog/28212.txt b/changelog/28212.txt deleted file mode 100644 index a5e1a2b19a04..000000000000 --- a/changelog/28212.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:feature -**KV v2 Patch/Subkey (enterprise)**: Adds GUI support to read the subkeys of a KV v2 secret and patch (partially update) secret data. -``` diff --git a/changelog/28237.txt b/changelog/28237.txt deleted file mode 100644 index 8b5728f3f434..000000000000 --- a/changelog/28237.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -secrets/pki: Key Usage can now be set on intermediate and root CAs, and CSRs generated by the PKI secret's engine. -``` diff --git a/changelog/28263.txt b/changelog/28263.txt deleted file mode 100644 index 704ff2bb30a9..000000000000 --- a/changelog/28263.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -auth/alicloud: Update plugin to v0.19.0 -``` diff --git a/changelog/28264.txt b/changelog/28264.txt deleted file mode 100644 index 03a508fa8808..000000000000 --- a/changelog/28264.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -auth/kerberos: Update plugin to v0.13.0 -``` diff --git a/changelog/28266.txt b/changelog/28266.txt deleted file mode 100644 index 084977f1851c..000000000000 --- a/changelog/28266.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -auth/cf: Update plugin to v0.19.0 -``` diff --git a/changelog/28267.txt b/changelog/28267.txt deleted file mode 100644 index def6986c7d63..000000000000 --- a/changelog/28267.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -secrets/azure: Update plugin to v0.20.0 -``` diff --git a/changelog/28268.txt b/changelog/28268.txt deleted file mode 100644 index b622284ade72..000000000000 --- a/changelog/28268.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -database/mongodbatlas: Update plugin to v0.13.0 -``` diff --git a/changelog/28269.txt b/changelog/28269.txt deleted file mode 100644 index 336e88a44014..000000000000 --- a/changelog/28269.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -sdk: Upgrade to go-secure-stdlib/plugincontainer@v0.4.0, which also bumps github.com/docker/docker to v26.1.5+incompatible -``` diff --git a/changelog/28271.txt b/changelog/28271.txt deleted file mode 100644 index 6cc6148f3d20..000000000000 --- a/changelog/28271.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -secrets/alicloud: Update plugin to v0.18.0 -``` diff --git a/changelog/28275.txt b/changelog/28275.txt deleted file mode 100644 index 85564eed28af..000000000000 --- a/changelog/28275.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -database/snowflake: Update plugin to v0.12.0 -``` diff --git a/changelog/28277.txt b/changelog/28277.txt deleted file mode 100644 index 60985a1d9c25..000000000000 --- a/changelog/28277.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -database/elasticsearch: Update plugin to v0.16.0 -``` diff --git a/changelog/28287.txt b/changelog/28287.txt deleted file mode 100644 index 7e6a6b8e750b..000000000000 --- a/changelog/28287.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -secrets/kubernetes: Update plugin to v0.9.0 -``` diff --git a/changelog/28289.txt b/changelog/28289.txt deleted file mode 100644 index e203556fb134..000000000000 --- a/changelog/28289.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -auth/kubernetes: Update plugin to v0.20.0 -``` diff --git a/changelog/28293.txt b/changelog/28293.txt deleted file mode 100644 index 4db93f90dcf1..000000000000 --- a/changelog/28293.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -database/redis-elasticache: Update plugin to v0.5.0 -``` diff --git a/changelog/28294.txt b/changelog/28294.txt deleted file mode 100644 index 13168cf2d746..000000000000 --- a/changelog/28294.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -auth/azure: Update plugin to v0.19.0 -``` diff --git a/changelog/28300.txt b/changelog/28300.txt deleted file mode 100644 index 4357135fb9ef..000000000000 --- a/changelog/28300.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -secrets/gcpkms: Update plugin to v0.18.0 -``` diff --git a/changelog/28307.txt b/changelog/28307.txt deleted file mode 100644 index 9f1f3be31624..000000000000 --- a/changelog/28307.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -auth/oci: Update plugin to v0.17.0 -``` diff --git a/changelog/28312.txt b/changelog/28312.txt deleted file mode 100644 index e2959b09ac22..000000000000 --- a/changelog/28312.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -secrets/terraform: Update plugin to v0.10.0 -``` diff --git a/changelog/28324.txt b/changelog/28324.txt deleted file mode 100644 index a38b971b6b1c..000000000000 --- a/changelog/28324.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -secrets/gcp: Update plugin to v0.20.0 -``` diff --git a/changelog/28325.txt b/changelog/28325.txt deleted file mode 100644 index b00c20b19227..000000000000 --- a/changelog/28325.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -secrets/openldap: Update plugin to v0.14.0 -``` diff --git a/changelog/28327.txt b/changelog/28327.txt deleted file mode 100644 index 4d77459f3568..000000000000 --- a/changelog/28327.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -database/couchbase: Update plugin to v0.12.0 -``` diff --git a/changelog/28334.txt b/changelog/28334.txt deleted file mode 100644 index 6a126a0e02a5..000000000000 --- a/changelog/28334.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -secrets/kv: Update plugin to v0.20.0 -``` diff --git a/changelog/28348.txt b/changelog/28348.txt deleted file mode 100644 index 7b8177491b8c..000000000000 --- a/changelog/28348.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -secrets/mongodbatlas: Update plugin to v0.13.0 -``` diff --git a/changelog/28349.txt b/changelog/28349.txt deleted file mode 100644 index c81df34fc003..000000000000 --- a/changelog/28349.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -auth/jwt: Update plugin to v0.22.0 -``` diff --git a/changelog/28360.txt b/changelog/28360.txt deleted file mode 100644 index 722c8361eaaa..000000000000 --- a/changelog/28360.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -secrets/gcpkms: Update plugin to v0.19.0 -``` diff --git a/changelog/28361.txt b/changelog/28361.txt deleted file mode 100644 index 075bb21414f3..000000000000 --- a/changelog/28361.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -secrets/ad: Update plugin to v0.19.0 -``` diff --git a/changelog/28366.txt b/changelog/28366.txt deleted file mode 100644 index 5f2d65783986..000000000000 --- a/changelog/28366.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -auth/gcp: Update plugin to v0.19.0 -``` diff --git a/changelog/28371.txt b/changelog/28371.txt deleted file mode 100644 index c719c4be56c0..000000000000 --- a/changelog/28371.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:bug -ui: Fix UI improperly checking capabilities for enabling performance and dr replication -``` diff --git a/changelog/28404.txt b/changelog/28404.txt deleted file mode 100644 index cca52cce8b67..000000000000 --- a/changelog/28404.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -database/redis: Update plugin to v0.4.0 -``` diff --git a/changelog/28478.txt b/changelog/28478.txt new file mode 100644 index 000000000000..08e907339f37 --- /dev/null +++ b/changelog/28478.txt @@ -0,0 +1,3 @@ +```release-note:change +secrets/ldap: Update vault-plugin-secrets-openldap to v0.13.1 +``` diff --git a/changelog/28479.txt b/changelog/28479.txt deleted file mode 100644 index 4045d48837ec..000000000000 --- a/changelog/28479.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:change -secrets/openldap: Update plugin to v0.14.1 -``` diff --git a/changelog/28519.txt b/changelog/28519.txt deleted file mode 100644 index 9cd11f74ff36..000000000000 --- a/changelog/28519.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:bug -database/postgresql: Fix potential error revoking privileges in postgresql database secrets engine when a schema contains special characters -``` diff --git a/changelog/9733.txt b/changelog/9733.txt deleted file mode 100644 index f345cbd5278e..000000000000 --- a/changelog/9733.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:improvement -db/cassandra: Add `disable_host_initial_lookup` option to backend, allowing the disabling of initial host lookup. -``` diff --git a/changelog/_go-ver-1170.txt b/changelog/_go-ver-1170.txt index e06311e84e5b..407ab08f9db9 100644 --- a/changelog/_go-ver-1170.txt +++ b/changelog/_go-ver-1170.txt @@ -1,3 +1,3 @@ ```release-note:change -core: Bump Go version to 1.22.2 +core: Bump Go version to 1.22.4 ``` diff --git a/changelog/_go-ver-1172.txt b/changelog/_go-ver-1172.txt new file mode 100644 index 000000000000..43ae0c24493b --- /dev/null +++ b/changelog/_go-ver-1172.txt @@ -0,0 +1,3 @@ +```release-note:change +core: Bump Go version to 1.22.5 +``` diff --git a/changelog/_go-ver-1174.txt b/changelog/_go-ver-1174.txt new file mode 100644 index 000000000000..9943c24fb368 --- /dev/null +++ b/changelog/_go-ver-1174.txt @@ -0,0 +1,3 @@ +```release-note:change +core: Bump Go version to 1.22.6 +``` diff --git a/changelog/_go-ver-1180.txt b/changelog/_go-ver-1176.txt similarity index 100% rename from changelog/_go-ver-1180.txt rename to changelog/_go-ver-1176.txt diff --git a/command/agent.go b/command/agent.go index 2e5f550a55f9..7bab660ce313 100644 --- a/command/agent.go +++ b/command/agent.go @@ -13,7 +13,6 @@ import ( "net" "net/http" "os" - "path/filepath" "sort" "strings" "sync" @@ -75,7 +74,6 @@ type AgentCommand struct { ShutdownCh chan struct{} SighupCh chan struct{} - SigUSR2Ch chan struct{} tlsReloadFuncsLock sync.RWMutex tlsReloadFuncs []reloadutil.ReloadFunc @@ -760,16 +758,6 @@ func (c *AgentCommand) Run(args []string) int { case c.reloadedCh <- struct{}{}: default: } - case <-c.SigUSR2Ch: - pprofPath := filepath.Join(os.TempDir(), "vault-agent-pprof") - cpuProfileDuration := time.Second * 1 - err := WritePprofToFile(pprofPath, cpuProfileDuration) - if err != nil { - c.logger.Error(err.Error()) - continue - } - - c.logger.Info(fmt.Sprintf("Wrote pprof files to: %s", pprofPath)) case <-ctx.Done(): return nil } diff --git a/command/agent_test.go b/command/agent_test.go index 17c74fc316cc..235a8ede1a7b 100644 --- a/command/agent_test.go +++ b/command/agent_test.go @@ -91,7 +91,6 @@ func testAgentCommand(tb testing.TB, logger hclog.Logger) (*cli.MockUi, *AgentCo }, ShutdownCh: MakeShutdownCh(), SighupCh: MakeSighupCh(), - SigUSR2Ch: MakeSigUSR2Ch(), logger: logger, startedCh: make(chan struct{}, 5), reloadedCh: make(chan struct{}, 5), diff --git a/command/agentproxyshared/auth/auth.go b/command/agentproxyshared/auth/auth.go index 91e189ed2604..63d4ea0da08e 100644 --- a/command/agentproxyshared/auth/auth.go +++ b/command/agentproxyshared/auth/auth.go @@ -145,18 +145,12 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { backoffCfg := newAutoAuthBackoff(ah.minBackoff, ah.maxBackoff, ah.exitOnError) ah.logger.Info("starting auth handler") - - // Set unauthenticated when starting up - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0) - defer func() { am.Shutdown() close(ah.OutputCh) close(ah.TemplateTokenCh) close(ah.ExecTokenCh) ah.logger.Info("auth handler stopped") - // Set unauthenticated when shutting down - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0) }() credCh := am.NewCreds() @@ -223,8 +217,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { if err != nil { ah.logger.Error("error creating client for authentication call", "error", err, "backoff", backoffCfg) metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1) - // Set unauthenticated when authentication fails - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0) if backoffSleep(ctx, backoffCfg) { continue @@ -252,8 +244,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { if err != nil { ah.logger.Error("could not look up token", "err", err, "backoff", backoffCfg) metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1) - // Set unauthenticated when authentication fails - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0) if backoffSleep(ctx, backoffCfg) { continue @@ -274,8 +264,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { if err != nil { ah.logger.Error("error getting path or data from method", "error", err, "backoff", backoffCfg) metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1) - // Set unauthenticated when authentication fails - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0) if backoffSleep(ctx, backoffCfg) { continue @@ -289,7 +277,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { if err != nil { ah.logger.Error("error creating client for wrapped call", "error", err, "backoff", backoffCfg) metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1) - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0) if backoffSleep(ctx, backoffCfg) { continue @@ -313,11 +300,10 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { isTokenFileMethod = path == "auth/token/lookup-self" if isTokenFileMethod { token, _ := data["token"].(string) - // The error is called clientErr as to not shadow the other err above it. - lookupSelfClient, clientErr := clientToUse.CloneWithHeaders() - if clientErr != nil { + lookupSelfClient, err := clientToUse.CloneWithHeaders() + if err != nil { ah.logger.Error("failed to clone client to perform token lookup") - return clientErr + return err } lookupSelfClient.SetToken(token) secret, err = lookupSelfClient.Auth().Token().LookupSelf() @@ -329,8 +315,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { if err != nil { ah.logger.Error("error authenticating", "error", err, "backoff", backoffCfg) metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1) - // Set unauthenticated when authentication fails - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0) if backoffSleep(ctx, backoffCfg) { continue @@ -346,8 +330,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { if secret.WrapInfo == nil { ah.logger.Error("authentication returned nil wrap info", "backoff", backoffCfg) metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1) - // Set unauthenticated when authentication fails - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0) if backoffSleep(ctx, backoffCfg) { continue @@ -357,8 +339,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { if secret.WrapInfo.Token == "" { ah.logger.Error("authentication returned empty wrapped client token", "backoff", backoffCfg) metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1) - // Set unauthenticated when authentication fails - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0) if backoffSleep(ctx, backoffCfg) { continue @@ -369,8 +349,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { if err != nil { ah.logger.Error("failed to encode wrapinfo", "error", err, "backoff", backoffCfg) metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1) - // Set unauthenticated when authentication fails - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0) if backoffSleep(ctx, backoffCfg) { continue @@ -410,8 +388,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { if secret == nil || secret.Data == nil { ah.logger.Error("token file validation failed, token may be invalid", "backoff", backoffCfg) metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1) - // Set unauthenticated when authentication fails - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0) if backoffSleep(ctx, backoffCfg) { continue @@ -422,8 +398,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { if !ok || token == "" { ah.logger.Error("token file validation returned empty client token", "backoff", backoffCfg) metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1) - // Set unauthenticated when authentication fails - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0) if backoffSleep(ctx, backoffCfg) { continue @@ -440,7 +414,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { Renewable: renewable, } ah.logger.Info("authentication successful, sending token to sinks") - ah.OutputCh <- token if ah.enableTemplateTokenCh { ah.TemplateTokenCh <- token @@ -457,8 +430,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { if secret == nil || secret.Auth == nil { ah.logger.Error("authentication returned nil auth info", "backoff", backoffCfg) metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1) - // Set unauthenticated when authentication fails - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0) if backoffSleep(ctx, backoffCfg) { continue @@ -468,8 +439,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { if secret.Auth.ClientToken == "" { ah.logger.Error("authentication returned empty client token", "backoff", backoffCfg) metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1) - // Set unauthenticated when authentication fails - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0) if backoffSleep(ctx, backoffCfg) { continue @@ -502,8 +471,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { if err != nil { ah.logger.Error("error creating lifetime watcher", "error", err, "backoff", backoffCfg) metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1) - // Set unauthenticated when authentication fails - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0) if backoffSleep(ctx, backoffCfg) { continue @@ -512,7 +479,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { } metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "success"}, 1) - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 1) // We don't want to trigger the renewal process for the root token if isRootToken(leaseDuration, isTokenFileMethod, secret) { ah.logger.Info("not starting token renewal process, as token is root token") @@ -534,8 +500,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { if err != nil { ah.logger.Error("error renewing token", "error", err, "backoff", backoffCfg) metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "failure"}, 1) - // Set unauthenticated when authentication fails - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 0) // Add some exponential backoff so that if auth is successful // but the watcher errors, we won't go into an immediate @@ -561,8 +525,6 @@ func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) error { case <-watcher.RenewCh(): metrics.IncrCounter([]string{ah.metricsSignifier, "auth", "success"}, 1) - // Set authenticated when authentication succeeds - metrics.SetGauge([]string{ah.metricsSignifier, "authenticated"}, 1) ah.logger.Info("renewed auth token") case <-credCh: ah.logger.Info("auth method found new credentials, re-authenticating") diff --git a/command/agentproxyshared/auth/gcp/gcp.go b/command/agentproxyshared/auth/gcp/gcp.go index aaaf21d16af0..5d913581bca5 100644 --- a/command/agentproxyshared/auth/gcp/gcp.go +++ b/command/agentproxyshared/auth/gcp/gcp.go @@ -8,7 +8,7 @@ import ( "encoding/json" "errors" "fmt" - "io" + "io/ioutil" "net/http" "time" @@ -151,7 +151,7 @@ func (g *gcpMethod) Authenticate(ctx context.Context, client *api.Client) (retPa return } defer resp.Body.Close() - jwtBytes, err := io.ReadAll(resp.Body) + jwtBytes, err := ioutil.ReadAll(resp.Body) if err != nil { retErr = fmt.Errorf("error reading instance token response body: %w", err) return diff --git a/command/agentproxyshared/auth/kubernetes/kubernetes.go b/command/agentproxyshared/auth/kubernetes/kubernetes.go index 6f16a2b9b414..639226505f25 100644 --- a/command/agentproxyshared/auth/kubernetes/kubernetes.go +++ b/command/agentproxyshared/auth/kubernetes/kubernetes.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "io" + "io/ioutil" "net/http" "os" "strings" @@ -122,7 +123,7 @@ func (k *kubernetesMethod) readJWT() (string, error) { } defer data.Close() - contentBytes, err := io.ReadAll(data) + contentBytes, err := ioutil.ReadAll(data) if err != nil { return "", err } diff --git a/command/agentproxyshared/cache/handler.go b/command/agentproxyshared/cache/handler.go index d1369831787f..5801c8ebde4e 100644 --- a/command/agentproxyshared/cache/handler.go +++ b/command/agentproxyshared/cache/handler.go @@ -11,6 +11,7 @@ import ( "errors" "fmt" "io" + "io/ioutil" "net/http" "strings" "sync/atomic" @@ -85,10 +86,6 @@ func ProxyHandler(ctx context.Context, logger hclog.Logger, proxier Proxier, inm logical.RespondError(w, http.StatusInternalServerError, fmt.Errorf("failed to get the response: %w", err)) } return - } else if resp == nil { - metrics.IncrCounter([]string{"agent", "proxy", "error"}, 1) - logical.RespondError(w, http.StatusInternalServerError, fmt.Errorf("failed to get the response: %w", err)) - return } err = sanitizeAutoAuthTokenResponse(ctx, logger, inmemSink, req, resp) @@ -221,7 +218,7 @@ func sanitizeAutoAuthTokenResponse(ctx context.Context, logger hclog.Logger, inm if resp.Response.Body != nil { resp.Response.Body.Close() } - resp.Response.Body = io.NopCloser(bytes.NewReader(bodyBytes)) + resp.Response.Body = ioutil.NopCloser(bytes.NewReader(bodyBytes)) resp.Response.ContentLength = int64(len(bodyBytes)) // Serialize and re-read the response diff --git a/command/agentproxyshared/cache/proxy.go b/command/agentproxyshared/cache/proxy.go index 231c5d9d203b..503d981d60e3 100644 --- a/command/agentproxyshared/cache/proxy.go +++ b/command/agentproxyshared/cache/proxy.go @@ -57,7 +57,7 @@ func NewSendResponse(apiResponse *api.Response, responseBody []byte) (*SendRespo } // If a response body is separately provided we set that as the SendResponse.ResponseBody, - // otherwise we will do an io.ReadAll to extract the response body from apiResponse. + // otherwise we will do an ioutil.ReadAll to extract the response body from apiResponse. switch { case len(responseBody) > 0: resp.ResponseBody = responseBody diff --git a/command/agentproxyshared/sink/file/file_sink.go b/command/agentproxyshared/sink/file/file_sink.go index 6e1b71aa2e58..bf26a86b3c7b 100644 --- a/command/agentproxyshared/sink/file/file_sink.go +++ b/command/agentproxyshared/sink/file/file_sink.go @@ -19,8 +19,6 @@ import ( type fileSink struct { path string mode os.FileMode - owner int - group int logger hclog.Logger } @@ -35,8 +33,6 @@ func NewFileSink(conf *sink.SinkConfig) (sink.Sink, error) { f := &fileSink{ logger: conf.Logger, mode: 0o640, - owner: os.Getuid(), - group: os.Getgid(), } pathRaw, ok := conf.Config["path"] @@ -65,31 +61,11 @@ func NewFileSink(conf *sink.SinkConfig) (sink.Sink, error) { f.mode = os.FileMode(mode) } - if modeRaw, ok := conf.Config["owner"]; ok { - owner, typeOK := modeRaw.(int) - if !typeOK { - return nil, errors.New("could not parse 'owner' as integer") - } - - f.logger.Debug("overriding default file sink", "owner", owner) - f.owner = owner - } - - if modeRaw, ok := conf.Config["group"]; ok { - group, typeOK := modeRaw.(int) - if !typeOK { - return nil, errors.New("could not parse 'group' as integer") - } - - f.logger.Debug("overriding default file sink", "group", group) - f.group = group - } - if err := f.WriteToken(""); err != nil { return nil, fmt.Errorf("error during write check: %w", err) } - f.logger.Info("file sink configured", "path", f.path, "mode", f.mode, "owner", f.owner, "group", f.group) + f.logger.Info("file sink configured", "path", f.path, "mode", f.mode) return f, nil } @@ -117,10 +93,6 @@ func (f *fileSink) WriteToken(token string) error { return fmt.Errorf("error opening temp file in dir %s for writing: %w", targetDir, err) } - if err := tmpFile.Chown(f.owner, f.group); err != nil { - return fmt.Errorf("error changing ownership of %s: %w", tmpFile.Name(), err) - } - valToWrite := token if token == "" { valToWrite = u diff --git a/command/agentproxyshared/sink/file/file_sink_test.go b/command/agentproxyshared/sink/file/file_sink_test.go index de7840748d14..e603c6a32d3d 100644 --- a/command/agentproxyshared/sink/file/file_sink_test.go +++ b/command/agentproxyshared/sink/file/file_sink_test.go @@ -4,9 +4,10 @@ package file import ( + "fmt" + "io/ioutil" "os" "path/filepath" - "syscall" "testing" hclog "github.com/hashicorp/go-hclog" @@ -15,8 +16,15 @@ import ( "github.com/hashicorp/vault/sdk/helper/logging" ) +const ( + fileServerTestDir = "vault-agent-file-test" +) + func testFileSink(t *testing.T, log hclog.Logger) (*sink.SinkConfig, string) { - tmpDir := t.TempDir() + tmpDir, err := ioutil.TempDir("", fmt.Sprintf("%s.", fileServerTestDir)) + if err != nil { + t.Fatal(err) + } path := filepath.Join(tmpDir, "token") @@ -66,7 +74,7 @@ func TestFileSink(t *testing.T) { t.Fatal(err) } - fileBytes, err := os.ReadFile(path) + fileBytes, err := ioutil.ReadFile(path) if err != nil { t.Fatal(err) } @@ -76,17 +84,19 @@ func TestFileSink(t *testing.T) { } } -func testFileSinkMode(t *testing.T, log hclog.Logger, gid int) (*sink.SinkConfig, string) { - tmpDir := t.TempDir() +func testFileSinkMode(t *testing.T, log hclog.Logger) (*sink.SinkConfig, string) { + tmpDir, err := ioutil.TempDir("", fmt.Sprintf("%s.", fileServerTestDir)) + if err != nil { + t.Fatal(err) + } path := filepath.Join(tmpDir, "token") config := &sink.SinkConfig{ Logger: log.Named("sink.file"), Config: map[string]interface{}{ - "path": path, - "mode": 0o644, - "group": gid, + "path": path, + "mode": 0o644, }, } @@ -102,65 +112,7 @@ func testFileSinkMode(t *testing.T, log hclog.Logger, gid int) (*sink.SinkConfig func TestFileSinkMode(t *testing.T) { log := logging.NewVaultLogger(hclog.Trace) - fs, tmpDir := testFileSinkMode(t, log, os.Getegid()) - defer os.RemoveAll(tmpDir) - - path := filepath.Join(tmpDir, "token") - - uuidStr, _ := uuid.GenerateUUID() - if err := fs.WriteToken(uuidStr); err != nil { - t.Fatal(err) - } - - file, err := os.Open(path) - if err != nil { - t.Fatal(err) - } - defer file.Close() - - fi, err := file.Stat() - if err != nil { - t.Fatal(err) - } - if fi.Mode() != os.FileMode(0o644) { - t.Fatalf("wrong file mode was detected at %s", path) - } - - fileBytes, err := os.ReadFile(path) - if err != nil { - t.Fatal(err) - } - - if string(fileBytes) != uuidStr { - t.Fatalf("expected %s, got %s", uuidStr, string(fileBytes)) - } -} - -// TestFileSinkMode_Ownership tests that the file is owned by the group specified -// in the configuration. This test requires the current user to be in at least two -// groups. If the user is not in two groups, the test will be skipped. -func TestFileSinkMode_Ownership(t *testing.T) { - groups, err := os.Getgroups() - if err != nil { - t.Fatal(err) - } - - if len(groups) < 2 { - t.Skip("not enough groups to test file ownership") - } - - // find a group that is not the current group - var gid int - for _, g := range groups { - if g != os.Getegid() { - gid = g - break - } - } - - log := logging.NewVaultLogger(hclog.Trace) - - fs, tmpDir := testFileSinkMode(t, log, gid) + fs, tmpDir := testFileSinkMode(t, log) defer os.RemoveAll(tmpDir) path := filepath.Join(tmpDir, "token") @@ -183,12 +135,8 @@ func TestFileSinkMode_Ownership(t *testing.T) { if fi.Mode() != os.FileMode(0o644) { t.Fatalf("wrong file mode was detected at %s", path) } - // check if file is owned by the group - if fi.Sys().(*syscall.Stat_t).Gid != uint32(gid) { - t.Fatalf("file is not owned by the group %d", gid) - } - fileBytes, err := os.ReadFile(path) + fileBytes, err := ioutil.ReadFile(path) if err != nil { t.Fatal(err) } diff --git a/command/base.go b/command/base.go index 47f7be04a8bc..1c1661841492 100644 --- a/command/base.go +++ b/command/base.go @@ -8,6 +8,7 @@ import ( "flag" "fmt" "io" + "io/ioutil" "net/http" "os" "regexp" @@ -211,7 +212,7 @@ func (c *BaseCommand) Client() (*api.Client, error) { } if c.addrWarning != "" && c.UI != nil { - if os.Getenv("VAULT_ADDR") == "" && !c.flags.hadAddressFlag { + if os.Getenv("VAULT_ADDR") == "" { if !c.flagNonInteractive && isatty.IsTerminal(os.Stdin.Fd()) { c.UI.Warn(wrapAtLength(c.addrWarning)) } @@ -626,10 +627,6 @@ type FlagSets struct { hiddens map[string]struct{} completions complete.Flags ui cli.Ui - // hadAddressFlag signals if the FlagSet had an -address - // flag set, for the purposes of warning (see also: - // BaseCommand::addrWarning). - hadAddressFlag bool } // NewFlagSets creates a new flag sets. @@ -638,7 +635,7 @@ func NewFlagSets(ui cli.Ui) *FlagSets { // Errors and usage are controlled by the CLI. mainSet.Usage = func() {} - mainSet.SetOutput(io.Discard) + mainSet.SetOutput(ioutil.Discard) return &FlagSets{ flagSets: make([]*FlagSet, 0, 6), @@ -672,15 +669,6 @@ type ( // Parse parses the given flags, returning any errors. // Warnings, if any, regarding the arguments format are sent to stdout func (f *FlagSets) Parse(args []string, opts ...ParseOptions) error { - // Before parsing, check to see if we have an address flag, for the - // purposes of warning later. This must be done now, as the argument - // will be removed during parsing. - for _, arg := range args { - if strings.HasPrefix(arg, "-address") { - f.hadAddressFlag = true - } - } - err := f.mainSet.Parse(args) displayFlagWarningsDisabled := false diff --git a/command/command_stubs_oss.go b/command/command_stubs_oss.go index 6e55082f30a6..bb199f373c0c 100644 --- a/command/command_stubs_oss.go +++ b/command/command_stubs_oss.go @@ -16,6 +16,11 @@ import ( func entInitCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions, commands map[string]cli.CommandFactory) { } +func entEnableFourClusterDev(c *ServerCommand, base *vault.CoreConfig, info map[string]string, infoKeys []string, tempDir string) int { + c.logger.Error("-dev-four-cluster only supported in enterprise Vault") + return 1 +} + func entAdjustCoreConfig(config *server.Config, coreConfig *vault.CoreConfig) { } @@ -30,5 +35,3 @@ func entGetFIPSInfoKey() string { func entGetRequestLimiterStatus(coreConfig vault.CoreConfig) string { return "" } - -func entExtendAddonHandlers(handlers *vaultHandlers) {} diff --git a/command/command_test.go b/command/command_test.go index def68c4fbc89..d4fb934ab48c 100644 --- a/command/command_test.go +++ b/command/command_test.go @@ -21,6 +21,7 @@ import ( "github.com/hashicorp/vault/builtin/logical/pki" "github.com/hashicorp/vault/builtin/logical/ssh" "github.com/hashicorp/vault/builtin/logical/transit" + "github.com/hashicorp/vault/helper/benchhelpers" "github.com/hashicorp/vault/helper/builtinplugins" vaulthttp "github.com/hashicorp/vault/http" "github.com/hashicorp/vault/sdk/logical" @@ -121,11 +122,10 @@ func testVaultServerWithKVVersion(tb testing.TB, kvVersion string) (*api.Client, func testVaultServerAllBackends(tb testing.TB) (*api.Client, func()) { tb.Helper() - handlers := newVaultHandlers() client, _, closer := testVaultServerCoreConfig(tb, &vault.CoreConfig{ - CredentialBackends: handlers.credentialBackends, - AuditBackends: handlers.auditBackends, - LogicalBackends: handlers.logicalBackends, + CredentialBackends: credentialBackends, + AuditBackends: auditBackends, + LogicalBackends: logicalBackends, BuiltinRegistry: builtinplugins.Registry, }) return client, closer @@ -189,12 +189,12 @@ func testVaultServerCoreConfig(tb testing.TB, coreConfig *vault.CoreConfig) (*ap func testVaultServerCoreConfigWithOpts(tb testing.TB, coreConfig *vault.CoreConfig, opts *vault.TestClusterOptions) (*api.Client, []string, func()) { tb.Helper() - cluster := vault.NewTestCluster(tb, coreConfig, opts) + cluster := vault.NewTestCluster(benchhelpers.TBtoT(tb), coreConfig, opts) cluster.Start() // Make it easy to get access to the active core := cluster.Cores[0].Core - vault.TestWaitActive(tb, core) + vault.TestWaitActive(benchhelpers.TBtoT(tb), core) // Get the client already setup for us! client := cluster.Cores[0].Client diff --git a/command/commands.go b/command/commands.go index a4253dd192d0..f549f38ebbbf 100644 --- a/command/commands.go +++ b/command/commands.go @@ -10,18 +10,48 @@ import ( "github.com/hashicorp/cli" hcpvlib "github.com/hashicorp/vault-hcp-lib" + credAliCloud "github.com/hashicorp/vault-plugin-auth-alicloud" + credCF "github.com/hashicorp/vault-plugin-auth-cf" + credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin" credOIDC "github.com/hashicorp/vault-plugin-auth-jwt" + credKerb "github.com/hashicorp/vault-plugin-auth-kerberos" + credOCI "github.com/hashicorp/vault-plugin-auth-oci" logicalKv "github.com/hashicorp/vault-plugin-secrets-kv" "github.com/hashicorp/vault/audit" + credAws "github.com/hashicorp/vault/builtin/credential/aws" credCert "github.com/hashicorp/vault/builtin/credential/cert" + credGitHub "github.com/hashicorp/vault/builtin/credential/github" + credLdap "github.com/hashicorp/vault/builtin/credential/ldap" + credOkta "github.com/hashicorp/vault/builtin/credential/okta" credToken "github.com/hashicorp/vault/builtin/credential/token" credUserpass "github.com/hashicorp/vault/builtin/credential/userpass" logicalDb "github.com/hashicorp/vault/builtin/logical/database" "github.com/hashicorp/vault/builtin/plugin" _ "github.com/hashicorp/vault/helper/builtinplugins" + physAerospike "github.com/hashicorp/vault/physical/aerospike" + physAliCloudOSS "github.com/hashicorp/vault/physical/alicloudoss" + physAzure "github.com/hashicorp/vault/physical/azure" + physCassandra "github.com/hashicorp/vault/physical/cassandra" + physCockroachDB "github.com/hashicorp/vault/physical/cockroachdb" + physConsul "github.com/hashicorp/vault/physical/consul" + physCouchDB "github.com/hashicorp/vault/physical/couchdb" + physDynamoDB "github.com/hashicorp/vault/physical/dynamodb" + physEtcd "github.com/hashicorp/vault/physical/etcd" + physFoundationDB "github.com/hashicorp/vault/physical/foundationdb" + physGCS "github.com/hashicorp/vault/physical/gcs" + physManta "github.com/hashicorp/vault/physical/manta" + physMSSQL "github.com/hashicorp/vault/physical/mssql" + physMySQL "github.com/hashicorp/vault/physical/mysql" + physOCI "github.com/hashicorp/vault/physical/oci" + physPostgreSQL "github.com/hashicorp/vault/physical/postgresql" physRaft "github.com/hashicorp/vault/physical/raft" + physS3 "github.com/hashicorp/vault/physical/s3" + physSpanner "github.com/hashicorp/vault/physical/spanner" + physSwift "github.com/hashicorp/vault/physical/swift" + physZooKeeper "github.com/hashicorp/vault/physical/zookeeper" "github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/sdk/physical" + physFile "github.com/hashicorp/vault/sdk/physical/file" physInmem "github.com/hashicorp/vault/sdk/physical/inmem" sr "github.com/hashicorp/vault/serviceregistration" csr "github.com/hashicorp/vault/serviceregistration/consul" @@ -129,69 +159,85 @@ const ( flagNameDelegatedAuthAccessors = "delegated-auth-accessors" ) -// vaultHandlers contains the handlers for creating the various Vault backends. -type vaultHandlers struct { - physicalBackends map[string]physical.Factory - loginHandlers map[string]LoginHandler - auditBackends map[string]audit.Factory - credentialBackends map[string]logical.Factory - logicalBackends map[string]logical.Factory - serviceRegistrations map[string]sr.Factory -} +var ( + auditBackends = map[string]audit.Factory{ + "file": audit.NewFileBackend, + "socket": audit.NewSocketBackend, + "syslog": audit.NewSyslogBackend, + } -// newMinimalVaultHandlers returns a new vaultHandlers that a minimal Vault would use. -func newMinimalVaultHandlers() *vaultHandlers { - return &vaultHandlers{ - physicalBackends: map[string]physical.Factory{ - "inmem_ha": physInmem.NewInmemHA, - "inmem_transactional_ha": physInmem.NewTransactionalInmemHA, - "inmem_transactional": physInmem.NewTransactionalInmem, - "inmem": physInmem.NewInmem, - "raft": physRaft.NewRaftBackend, - }, - loginHandlers: map[string]LoginHandler{ - "cert": &credCert.CLIHandler{}, - "oidc": &credOIDC.CLIHandler{}, - "token": &credToken.CLIHandler{}, - "userpass": &credUserpass.CLIHandler{ - DefaultMount: "userpass", - }, - }, - auditBackends: map[string]audit.Factory{ - "file": audit.NewFileBackend, - "socket": audit.NewSocketBackend, - "syslog": audit.NewSyslogBackend, - }, - credentialBackends: map[string]logical.Factory{ - "plugin": plugin.Factory, - }, - logicalBackends: map[string]logical.Factory{ - "plugin": plugin.Factory, - "database": logicalDb.Factory, - // This is also available in the plugin catalog, but is here due to the need to - // automatically mount it. - "kv": logicalKv.Factory, - }, - serviceRegistrations: map[string]sr.Factory{ - "consul": csr.NewServiceRegistration, - "kubernetes": ksr.NewServiceRegistration, - }, + credentialBackends = map[string]logical.Factory{ + "plugin": plugin.Factory, } -} -// newVaultHandlers returns a new vaultHandlers composed of newMinimalVaultHandlers() -// and any addon handlers from Vault CE and Vault Enterprise selected by Go build tags. -func newVaultHandlers() *vaultHandlers { - handlers := newMinimalVaultHandlers() - extendAddonHandlers(handlers) - entExtendAddonHandlers(handlers) + logicalBackends = map[string]logical.Factory{ + "plugin": plugin.Factory, + "database": logicalDb.Factory, + // This is also available in the plugin catalog, but is here due to the need to + // automatically mount it. + "kv": logicalKv.Factory, + } - return handlers -} + physicalBackends = map[string]physical.Factory{ + "aerospike": physAerospike.NewAerospikeBackend, + "alicloudoss": physAliCloudOSS.NewAliCloudOSSBackend, + "azure": physAzure.NewAzureBackend, + "cassandra": physCassandra.NewCassandraBackend, + "cockroachdb": physCockroachDB.NewCockroachDBBackend, + "consul": physConsul.NewConsulBackend, + "couchdb_transactional": physCouchDB.NewTransactionalCouchDBBackend, + "couchdb": physCouchDB.NewCouchDBBackend, + "dynamodb": physDynamoDB.NewDynamoDBBackend, + "etcd": physEtcd.NewEtcdBackend, + "file_transactional": physFile.NewTransactionalFileBackend, + "file": physFile.NewFileBackend, + "foundationdb": physFoundationDB.NewFDBBackend, + "gcs": physGCS.NewBackend, + "inmem_ha": physInmem.NewInmemHA, + "inmem_transactional_ha": physInmem.NewTransactionalInmemHA, + "inmem_transactional": physInmem.NewTransactionalInmem, + "inmem": physInmem.NewInmem, + "manta": physManta.NewMantaBackend, + "mssql": physMSSQL.NewMSSQLBackend, + "mysql": physMySQL.NewMySQLBackend, + "oci": physOCI.NewBackend, + "postgresql": physPostgreSQL.NewPostgreSQLBackend, + "s3": physS3.NewS3Backend, + "spanner": physSpanner.NewBackend, + "swift": physSwift.NewSwiftBackend, + "raft": physRaft.NewRaftBackend, + "zookeeper": physZooKeeper.NewZooKeeperBackend, + } -func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) map[string]cli.CommandFactory { - handlers := newVaultHandlers() + serviceRegistrations = map[string]sr.Factory{ + "consul": csr.NewServiceRegistration, + "kubernetes": ksr.NewServiceRegistration, + } + loginHandlers = map[string]LoginHandler{ + "alicloud": &credAliCloud.CLIHandler{}, + "aws": &credAws.CLIHandler{}, + "cert": &credCert.CLIHandler{}, + "cf": &credCF.CLIHandler{}, + "gcp": &credGcp.CLIHandler{}, + "github": &credGitHub.CLIHandler{}, + "kerberos": &credKerb.CLIHandler{}, + "ldap": &credLdap.CLIHandler{}, + "oci": &credOCI.CLIHandler{}, + "oidc": &credOIDC.CLIHandler{}, + "okta": &credOkta.CLIHandler{}, + "pcf": &credCF.CLIHandler{}, // Deprecated. + "radius": &credUserpass.CLIHandler{ + DefaultMount: "radius", + }, + "token": &credToken.CLIHandler{}, + "userpass": &credUserpass.CLIHandler{ + DefaultMount: "userpass", + }, + } +) + +func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) map[string]cli.CommandFactory { getBaseCommand := func() *BaseCommand { return &BaseCommand{ UI: ui, @@ -210,7 +256,6 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) map[string]cli.Co }, ShutdownCh: MakeShutdownCh(), SighupCh: MakeSighupCh(), - SigUSR2Ch: MakeSigUSR2Ch(), }, nil }, "agent generate-config": func() (cli.Command, error) { @@ -261,7 +306,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) map[string]cli.Co "auth help": func() (cli.Command, error) { return &AuthHelpCommand{ BaseCommand: getBaseCommand(), - Handlers: handlers.loginHandlers, + Handlers: loginHandlers, }, nil }, "auth list": func() (cli.Command, error) { @@ -318,7 +363,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) map[string]cli.Co "login": func() (cli.Command, error) { return &LoginCommand{ BaseCommand: getBaseCommand(), - Handlers: handlers.loginHandlers, + Handlers: loginHandlers, }, nil }, "namespace": func() (cli.Command, error) { @@ -389,7 +434,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) map[string]cli.Co "operator migrate": func() (cli.Command, error) { return &OperatorMigrateCommand{ BaseCommand: getBaseCommand(), - PhysicalBackends: handlers.physicalBackends, + PhysicalBackends: physicalBackends, ShutdownCh: MakeShutdownCh(), }, nil }, @@ -595,7 +640,6 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) map[string]cli.Co }, ShutdownCh: MakeShutdownCh(), SighupCh: MakeSighupCh(), - SigUSR2Ch: MakeSigUSR2Ch(), }, nil }, "policy": func() (cli.Command, error) { @@ -680,11 +724,12 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) map[string]cli.Co tokenHelper: runOpts.TokenHelper, flagAddress: runOpts.Address, }, - AuditBackends: handlers.auditBackends, - CredentialBackends: handlers.credentialBackends, - LogicalBackends: handlers.logicalBackends, - PhysicalBackends: handlers.physicalBackends, - ServiceRegistrations: handlers.serviceRegistrations, + AuditBackends: auditBackends, + CredentialBackends: credentialBackends, + LogicalBackends: logicalBackends, + PhysicalBackends: physicalBackends, + + ServiceRegistrations: serviceRegistrations, ShutdownCh: MakeShutdownCh(), SighupCh: MakeSighupCh(), diff --git a/command/commands_full.go b/command/commands_full.go deleted file mode 100644 index 8db22350cf89..000000000000 --- a/command/commands_full.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !minimal - -package command - -import ( - "maps" - - credAliCloud "github.com/hashicorp/vault-plugin-auth-alicloud" - credCF "github.com/hashicorp/vault-plugin-auth-cf" - credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin" - credKerb "github.com/hashicorp/vault-plugin-auth-kerberos" - credOCI "github.com/hashicorp/vault-plugin-auth-oci" - credAws "github.com/hashicorp/vault/builtin/credential/aws" - credGitHub "github.com/hashicorp/vault/builtin/credential/github" - credLdap "github.com/hashicorp/vault/builtin/credential/ldap" - credOkta "github.com/hashicorp/vault/builtin/credential/okta" - credUserpass "github.com/hashicorp/vault/builtin/credential/userpass" - _ "github.com/hashicorp/vault/helper/builtinplugins" - physAerospike "github.com/hashicorp/vault/physical/aerospike" - physAliCloudOSS "github.com/hashicorp/vault/physical/alicloudoss" - physAzure "github.com/hashicorp/vault/physical/azure" - physCassandra "github.com/hashicorp/vault/physical/cassandra" - physCockroachDB "github.com/hashicorp/vault/physical/cockroachdb" - physConsul "github.com/hashicorp/vault/physical/consul" - physCouchDB "github.com/hashicorp/vault/physical/couchdb" - physDynamoDB "github.com/hashicorp/vault/physical/dynamodb" - physEtcd "github.com/hashicorp/vault/physical/etcd" - physFoundationDB "github.com/hashicorp/vault/physical/foundationdb" - physGCS "github.com/hashicorp/vault/physical/gcs" - physManta "github.com/hashicorp/vault/physical/manta" - physMSSQL "github.com/hashicorp/vault/physical/mssql" - physMySQL "github.com/hashicorp/vault/physical/mysql" - physOCI "github.com/hashicorp/vault/physical/oci" - physPostgreSQL "github.com/hashicorp/vault/physical/postgresql" - physS3 "github.com/hashicorp/vault/physical/s3" - physSpanner "github.com/hashicorp/vault/physical/spanner" - physSwift "github.com/hashicorp/vault/physical/swift" - physZooKeeper "github.com/hashicorp/vault/physical/zookeeper" - "github.com/hashicorp/vault/sdk/physical" - physFile "github.com/hashicorp/vault/sdk/physical/file" -) - -func newFullAddonHandlers() (map[string]physical.Factory, map[string]LoginHandler) { - addonPhysicalBackends := map[string]physical.Factory{ - "aerospike": physAerospike.NewAerospikeBackend, - "alicloudoss": physAliCloudOSS.NewAliCloudOSSBackend, - "azure": physAzure.NewAzureBackend, - "cassandra": physCassandra.NewCassandraBackend, - "cockroachdb": physCockroachDB.NewCockroachDBBackend, - "consul": physConsul.NewConsulBackend, - "couchdb_transactional": physCouchDB.NewTransactionalCouchDBBackend, - "couchdb": physCouchDB.NewCouchDBBackend, - "dynamodb": physDynamoDB.NewDynamoDBBackend, - "etcd": physEtcd.NewEtcdBackend, - "file_transactional": physFile.NewTransactionalFileBackend, - "file": physFile.NewFileBackend, - "foundationdb": physFoundationDB.NewFDBBackend, - "gcs": physGCS.NewBackend, - "manta": physManta.NewMantaBackend, - "mssql": physMSSQL.NewMSSQLBackend, - "mysql": physMySQL.NewMySQLBackend, - "oci": physOCI.NewBackend, - "postgresql": physPostgreSQL.NewPostgreSQLBackend, - "s3": physS3.NewS3Backend, - "spanner": physSpanner.NewBackend, - "swift": physSwift.NewSwiftBackend, - "zookeeper": physZooKeeper.NewZooKeeperBackend, - } - addonLoginHandlers := map[string]LoginHandler{ - "alicloud": &credAliCloud.CLIHandler{}, - "aws": &credAws.CLIHandler{}, - "cf": &credCF.CLIHandler{}, - "gcp": &credGcp.CLIHandler{}, - "github": &credGitHub.CLIHandler{}, - "kerberos": &credKerb.CLIHandler{}, - "ldap": &credLdap.CLIHandler{}, - "oci": &credOCI.CLIHandler{}, - "okta": &credOkta.CLIHandler{}, - "pcf": &credCF.CLIHandler{}, // Deprecated. - "radius": &credUserpass.CLIHandler{ - DefaultMount: "radius", - }, - } - - return addonPhysicalBackends, addonLoginHandlers -} - -func extendAddonHandlers(handlers *vaultHandlers) { - addonPhysicalBackends, addonLoginHandlers := newFullAddonHandlers() - - maps.Copy(handlers.physicalBackends, addonPhysicalBackends) - maps.Copy(handlers.loginHandlers, addonLoginHandlers) -} diff --git a/command/commands_full_test.go b/command/commands_full_test.go deleted file mode 100644 index e22c0fc5f102..000000000000 --- a/command/commands_full_test.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !enterprise && !minimal - -package command - -import ( - "maps" - "testing" - - "github.com/stretchr/testify/require" -) - -// Test_extendAddonHandlers tests extendAddonHandlers() extends the minimal Vault handlers with handlers -// generated by newFullAddonHandlers() -func Test_extendAddonHandlers(t *testing.T) { - handlers := newMinimalVaultHandlers() - expMinPhysicalBackends := maps.Clone(handlers.physicalBackends) - expMinLoginHandlers := maps.Clone(handlers.loginHandlers) - - expAddonPhysicalBackends, expAddonLoginHandlers := newFullAddonHandlers() - - extendAddonHandlers(handlers) - - require.Equal(t, len(expMinPhysicalBackends)+len(expAddonPhysicalBackends), len(handlers.physicalBackends), - "extended total physical backends mismatch total of minimal and full addon physical backends") - require.Equal(t, len(expMinLoginHandlers)+len(expAddonLoginHandlers), len(handlers.loginHandlers), - "extended total login handlers mismatch total of minimal and full addon login handlers") - - for k := range expMinPhysicalBackends { - require.Contains(t, handlers.physicalBackends, k, "expected to contain minimal physical backend") - } - - for k := range expAddonPhysicalBackends { - require.Contains(t, handlers.physicalBackends, k, "expected to contain full addon physical backend") - } - - for k := range expMinLoginHandlers { - require.Contains(t, handlers.loginHandlers, k, "expected to contain minimal login handler") - } - - for k := range expAddonLoginHandlers { - require.Contains(t, handlers.loginHandlers, k, "expected to contain full addon login handler") - } -} diff --git a/command/commands_min.go b/command/commands_min.go deleted file mode 100644 index 812c37a40c9e..000000000000 --- a/command/commands_min.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build minimal - -package command - -import ( - _ "github.com/hashicorp/vault/helper/builtinplugins" -) - -func extendAddonHandlers(*vaultHandlers) { - // No-op -} diff --git a/command/commands_test.go b/command/commands_test.go index 681e62712599..ac057f737cce 100644 --- a/command/commands_test.go +++ b/command/commands_test.go @@ -25,9 +25,6 @@ func Test_Commands_HCPInit(t *testing.T) { } for n, tst := range tests { - n := n - tst := tst - t.Run(n, func(t *testing.T) { t.Parallel() diff --git a/command/operator_diagnose.go b/command/operator_diagnose.go index b530ada5f0cc..47b6183cc5de 100644 --- a/command/operator_diagnose.go +++ b/command/operator_diagnose.go @@ -203,19 +203,17 @@ func (c *OperatorDiagnoseCommand) RunWithParsedFlags() int { func (c *OperatorDiagnoseCommand) offlineDiagnostics(ctx context.Context) error { rloadFuncs := make(map[string][]reloadutil.ReloadFunc) - handlers := newVaultHandlers() - server := &ServerCommand{ // TODO: set up a different one? // In particular, a UI instance that won't output? BaseCommand: c.BaseCommand, // TODO: refactor to a common place? - AuditBackends: handlers.auditBackends, - CredentialBackends: handlers.credentialBackends, - LogicalBackends: handlers.logicalBackends, - PhysicalBackends: handlers.physicalBackends, - ServiceRegistrations: handlers.serviceRegistrations, + AuditBackends: auditBackends, + CredentialBackends: credentialBackends, + LogicalBackends: logicalBackends, + PhysicalBackends: physicalBackends, + ServiceRegistrations: serviceRegistrations, // TODO: other ServerCommand options? diff --git a/command/operator_migrate_test.go b/command/operator_migrate_test.go index 15190b2640f5..9a6c27196ebb 100644 --- a/command/operator_migrate_test.go +++ b/command/operator_migrate_test.go @@ -32,11 +32,10 @@ func init() { } func TestMigration(t *testing.T) { - handlers := newVaultHandlers() t.Run("Default", func(t *testing.T) { data := generateData() - fromFactory := handlers.physicalBackends["file"] + fromFactory := physicalBackends["file"] folder := t.TempDir() @@ -52,7 +51,7 @@ func TestMigration(t *testing.T) { t.Fatal(err) } - toFactory := handlers.physicalBackends["inmem"] + toFactory := physicalBackends["inmem"] confTo := map[string]string{} to, err := toFactory(confTo, nil) if err != nil { @@ -73,7 +72,7 @@ func TestMigration(t *testing.T) { t.Run("Concurrent migration", func(t *testing.T) { data := generateData() - fromFactory := handlers.physicalBackends["file"] + fromFactory := physicalBackends["file"] folder := t.TempDir() @@ -89,7 +88,7 @@ func TestMigration(t *testing.T) { t.Fatal(err) } - toFactory := handlers.physicalBackends["inmem"] + toFactory := physicalBackends["inmem"] confTo := map[string]string{} to, err := toFactory(confTo, nil) if err != nil { @@ -111,7 +110,7 @@ func TestMigration(t *testing.T) { t.Run("Start option", func(t *testing.T) { data := generateData() - fromFactory := handlers.physicalBackends["inmem"] + fromFactory := physicalBackends["inmem"] confFrom := map[string]string{} from, err := fromFactory(confFrom, nil) if err != nil { @@ -121,7 +120,7 @@ func TestMigration(t *testing.T) { t.Fatal(err) } - toFactory := handlers.physicalBackends["file"] + toFactory := physicalBackends["file"] folder := t.TempDir() confTo := map[string]string{ "path": folder, @@ -150,7 +149,7 @@ func TestMigration(t *testing.T) { t.Run("Start option (parallel)", func(t *testing.T) { data := generateData() - fromFactory := handlers.physicalBackends["inmem"] + fromFactory := physicalBackends["inmem"] confFrom := map[string]string{} from, err := fromFactory(confFrom, nil) if err != nil { @@ -160,7 +159,7 @@ func TestMigration(t *testing.T) { t.Fatal(err) } - toFactory := handlers.physicalBackends["file"] + toFactory := physicalBackends["file"] folder := t.TempDir() confTo := map[string]string{ "path": folder, @@ -270,7 +269,7 @@ storage_destination "dest_type2" { }) t.Run("DFS Scan", func(t *testing.T) { - s, _ := handlers.physicalBackends["inmem"](map[string]string{}, nil) + s, _ := physicalBackends["inmem"](map[string]string{}, nil) data := generateData() data["cc"] = []byte{} diff --git a/command/operator_usage.go b/command/operator_usage.go index e96b0ca33d92..1fac47784489 100644 --- a/command/operator_usage.go +++ b/command/operator_usage.go @@ -56,7 +56,7 @@ func (c *OperatorUsageCommand) Flags() *FlagSets { f.TimeVar(&TimeVar{ Name: "start-time", - Usage: "Start of report period. Defaults to billing start time", + Usage: "Start of report period. Defaults to 'default_reporting_period' before end time.", Target: &c.flagStartTime, Completion: complete.PredictNothing, Default: time.Time{}, @@ -64,7 +64,7 @@ func (c *OperatorUsageCommand) Flags() *FlagSets { }) f.TimeVar(&TimeVar{ Name: "end-time", - Usage: "End of report period. Defaults to end of the current month.", + Usage: "End of report period. Defaults to end of last month.", Target: &c.flagEndTime, Completion: complete.PredictNothing, Default: time.Time{}, @@ -132,7 +132,7 @@ func (c *OperatorUsageCommand) Run(args []string) int { c.outputTimestamps(resp.Data) out := []string{ - "Namespace path | Entity Clients | Non-Entity clients | Secret syncs | ACME clients | Active clients", + "Namespace path | Distinct entities | Non-Entity tokens | Secret syncs | ACME clients | Active clients", } out = append(out, c.namespacesOutput(resp.Data)...) @@ -239,14 +239,14 @@ func (c *OperatorUsageCommand) parseNamespaceCount(rawVal interface{}) (UsageRes return ret, errors.New("missing counts") } - ret.entityCount, ok = jsonNumberOK(counts, "entity_clients") + ret.entityCount, ok = jsonNumberOK(counts, "distinct_entities") if !ok { - return ret, errors.New("missing entity_clients") + return ret, errors.New("missing distinct_entities") } - ret.tokenCount, ok = jsonNumberOK(counts, "non_entity_clients") + ret.tokenCount, ok = jsonNumberOK(counts, "non_entity_tokens") if !ok { - return ret, errors.New("missing non_entity_clients") + return ret, errors.New("missing non_entity_tokens") } // don't error if the secret syncs key is missing @@ -317,15 +317,15 @@ func (c *OperatorUsageCommand) totalOutput(data map[string]interface{}) []string return out } - entityCount, ok := jsonNumberOK(total, "entity_clients") + entityCount, ok := jsonNumberOK(total, "distinct_entities") if !ok { - c.UI.Error("missing entity_clients in total") + c.UI.Error("missing distinct_entities in total") return out } - tokenCount, ok := jsonNumberOK(total, "non_entity_clients") + tokenCount, ok := jsonNumberOK(total, "non_entity_tokens") if !ok { - c.UI.Error("missing non_entity_clients in total") + c.UI.Error("missing non_entity_tokens in total") return out } // don't error if secret syncs key is missing diff --git a/command/pki_reissue_intermediate.go b/command/pki_reissue_intermediate.go index 7501d4c8622a..fa4dd38fbe77 100644 --- a/command/pki_reissue_intermediate.go +++ b/command/pki_reissue_intermediate.go @@ -113,10 +113,6 @@ func (c *PKIReIssueCACommand) Run(args []string) int { } templateData, err := parseTemplateCertificate(*certificate, useExistingKey, keyRef) - if err != nil { - c.UI.Error(fmt.Sprintf("Error fetching parsing template certificate: %v", err)) - return 1 - } data := updateTemplateWithData(templateData, userData) return pkiIssue(c.BaseCommand, parentIssuer, intermediateMount, c.flagNewIssuerName, c.flagKeyStorageSource, data) diff --git a/command/proxy.go b/command/proxy.go index 05a52398224f..71559695e014 100644 --- a/command/proxy.go +++ b/command/proxy.go @@ -12,7 +12,6 @@ import ( "net" "net/http" "os" - "path/filepath" "sort" "strings" "sync" @@ -72,7 +71,6 @@ type ProxyCommand struct { ShutdownCh chan struct{} SighupCh chan struct{} - SigUSR2Ch chan struct{} tlsReloadFuncsLock sync.RWMutex tlsReloadFuncs []reloadutil.ReloadFunc @@ -717,16 +715,6 @@ func (c *ProxyCommand) Run(args []string) int { case c.reloadedCh <- struct{}{}: default: } - case <-c.SigUSR2Ch: - pprofPath := filepath.Join(os.TempDir(), "vault-proxy-pprof") - cpuProfileDuration := time.Second * 1 - err := WritePprofToFile(pprofPath, cpuProfileDuration) - if err != nil { - c.logger.Error(err.Error()) - continue - } - - c.logger.Info(fmt.Sprintf("Wrote pprof files to: %s", pprofPath)) case <-ctx.Done(): return nil } diff --git a/command/proxy_test.go b/command/proxy_test.go index 3c2fdd001618..705224f2e800 100644 --- a/command/proxy_test.go +++ b/command/proxy_test.go @@ -44,7 +44,6 @@ func testProxyCommand(tb testing.TB, logger hclog.Logger) (*cli.MockUi, *ProxyCo }, ShutdownCh: MakeShutdownCh(), SighupCh: MakeSighupCh(), - SigUSR2Ch: MakeSigUSR2Ch(), logger: logger, startedCh: make(chan struct{}, 5), reloadedCh: make(chan struct{}, 5), diff --git a/command/read.go b/command/read.go index 67ee2d6d7cd5..742e03676381 100644 --- a/command/read.go +++ b/command/read.go @@ -36,17 +36,9 @@ Usage: vault read [options] PATH Reads data from Vault at the given path. This can be used to read secrets, generate dynamic credentials, get configuration details, and more. - Read details of your own token: + Read a secret from the static secrets engine: - $ vault read auth/token/lookup-self - - Read entity details of a given ID: - - $ vault read identity/entity/id/2f09126d-d161-abb8-2241-555886491d97 - - Generate credentials for my-role in an AWS secrets engine: - - $ vault read aws/creds/my-role + $ vault read secret/my-secret For a full list of examples and paths, please see the documentation that corresponds to the secrets engine in use. diff --git a/command/server.go b/command/server.go index 5aba92cbd36d..d08117bb2fe3 100644 --- a/command/server.go +++ b/command/server.go @@ -11,6 +11,7 @@ import ( "errors" "fmt" "io" + "io/ioutil" "net" "net/http" "net/url" @@ -46,6 +47,7 @@ import ( loghelper "github.com/hashicorp/vault/helper/logging" "github.com/hashicorp/vault/helper/metricsutil" "github.com/hashicorp/vault/helper/namespace" + "github.com/hashicorp/vault/helper/testhelpers/teststorage" "github.com/hashicorp/vault/helper/useragent" vaulthttp "github.com/hashicorp/vault/http" "github.com/hashicorp/vault/internalshared/configutil" @@ -62,6 +64,7 @@ import ( "github.com/hashicorp/vault/vault/plugincatalog" vaultseal "github.com/hashicorp/vault/vault/seal" "github.com/hashicorp/vault/version" + "github.com/mitchellh/go-testing-interface" "github.com/posener/complete" "github.com/sasha-s/go-deadlock" "go.uber.org/atomic" @@ -119,7 +122,6 @@ type ServerCommand struct { flagConfigs []string flagRecovery bool flagExperiments []string - flagCLIDump string flagDev bool flagDevTLS bool flagDevTLSCertDir string @@ -133,9 +135,10 @@ type ServerCommand struct { flagDevLatency int flagDevLatencyJitter int flagDevLeasedKV bool - flagDevNoKV bool flagDevKVV1 bool flagDevSkipInit bool + flagDevThreeNode bool + flagDevFourCluster bool flagDevTransactional bool flagDevAutoSeal bool flagDevClusterJson string @@ -222,13 +225,6 @@ func (c *ServerCommand) Flags() *FlagSets { "Valid experiments are: " + strings.Join(experiments.ValidExperiments(), ", "), }) - f.StringVar(&StringVar{ - Name: "pprof-dump-dir", - Target: &c.flagCLIDump, - Completion: complete.PredictDirs("*"), - Usage: "Directory where generated profiles are created. If left unset, files are not generated.", - }) - f = set.NewFlagSet("Dev Options") f.BoolVar(&BoolVar{ @@ -349,13 +345,6 @@ func (c *ServerCommand) Flags() *FlagSets { Hidden: true, }) - f.BoolVar(&BoolVar{ - Name: "dev-no-kv", - Target: &c.flagDevNoKV, - Default: false, - Hidden: true, - }) - f.BoolVar(&BoolVar{ Name: "dev-kv-v1", Target: &c.flagDevKVV1, @@ -377,6 +366,20 @@ func (c *ServerCommand) Flags() *FlagSets { Hidden: true, }) + f.BoolVar(&BoolVar{ + Name: "dev-three-node", + Target: &c.flagDevThreeNode, + Default: false, + Hidden: true, + }) + + f.BoolVar(&BoolVar{ + Name: "dev-four-cluster", + Target: &c.flagDevFourCluster, + Default: false, + Hidden: true, + }) + f.BoolVar(&BoolVar{ Name: "dev-consul", Target: &c.flagDevConsul, @@ -1028,7 +1031,7 @@ func (c *ServerCommand) Run(args []string) int { } // Automatically enable dev mode if other dev flags are provided. - if c.flagDevConsul || c.flagDevHA || c.flagDevTransactional || c.flagDevLeasedKV || c.flagDevAutoSeal || c.flagDevKVV1 || c.flagDevNoKV || c.flagDevTLS { + if c.flagDevConsul || c.flagDevHA || c.flagDevTransactional || c.flagDevLeasedKV || c.flagDevThreeNode || c.flagDevFourCluster || c.flagDevAutoSeal || c.flagDevKVV1 || c.flagDevTLS { c.flagDev = true } @@ -1092,6 +1095,11 @@ func (c *ServerCommand) Run(args []string) int { f.applyLogConfigOverrides(config.SharedConfig) + // Set 'trace' log level for the following 'dev' clusters + if c.flagDevThreeNode || c.flagDevFourCluster { + config.LogLevel = "trace" + } + l, err := c.configureLogging(config) if err != nil { c.UI.Error(err.Error()) @@ -1259,6 +1267,13 @@ func (c *ServerCommand) Run(args []string) int { }() coreConfig := createCoreConfig(c, config, backend, configSR, setSealResponse.barrierSeal, setSealResponse.unwrapSeal, metricsHelper, metricSink, secureRandomReader) + if c.flagDevThreeNode { + return c.enableThreeNodeDevCluster(&coreConfig, info, infoKeys, c.flagDevListenAddr, os.Getenv("VAULT_DEV_TEMP_DIR")) + } + + if c.flagDevFourCluster { + return entEnableFourClusterDev(c, &coreConfig, info, infoKeys, os.Getenv("VAULT_DEV_TEMP_DIR")) + } if allowPendingRemoval := os.Getenv(consts.EnvVaultAllowPendingRemovalMounts); allowPendingRemoval != "" { var err error @@ -1576,7 +1591,7 @@ func (c *ServerCommand) Run(args []string) int { clusterJson.CACertPath = fmt.Sprintf("%s/%s", certDir, server.VaultDevCAFilename) } - if c.flagDevClusterJson != "" { + if c.flagDevClusterJson != "" && !c.flagDevThreeNode { b, err := jsonutil.EncodeJSON(clusterJson) if err != nil { c.UI.Error(fmt.Sprintf("Error encoding cluster.json: %s", err)) @@ -1601,11 +1616,6 @@ func (c *ServerCommand) Run(args []string) int { coreShutdownDoneCh = core.ShutdownDone() } - cliDumpCh := make(chan struct{}) - if c.flagCLIDump != "" { - go func() { cliDumpCh <- struct{}{} }() - } - // Wait for shutdown shutdownTriggered := false retCode := 0 @@ -1720,6 +1730,7 @@ func (c *ServerCommand) Run(args []string) int { // Notify systemd that the server has completed reloading config c.notifySystemd(systemd.SdNotifyReady) + case <-c.SigUSR2Ch: logWriter := c.logger.StandardWriter(&hclog.StandardLoggerOptions{}) pprof.Lookup("goroutine").WriteTo(logWriter, 2) @@ -1763,23 +1774,6 @@ func (c *ServerCommand) Run(args []string) int { // into a state where it cannot process requests so we can get pprof outputs // via SIGUSR2. pprofPath := filepath.Join(os.TempDir(), "vault-pprof") - cpuProfileDuration := time.Second * 1 - err := WritePprofToFile(pprofPath, cpuProfileDuration) - if err != nil { - c.logger.Error(err.Error()) - continue - } - - c.logger.Info(fmt.Sprintf("Wrote pprof files to: %s", pprofPath)) - case <-cliDumpCh: - path := c.flagCLIDump - - if _, err := os.Stat(path); err != nil && !errors.Is(err, os.ErrNotExist) { - c.logger.Error("Checking cli dump path failed", "error", err) - continue - } - - pprofPath := filepath.Join(path, "vault-pprof") err := os.MkdirAll(pprofPath, os.ModePerm) if err != nil { c.logger.Error("Could not create temporary directory for pprof", "error", err) @@ -1815,7 +1809,7 @@ func (c *ServerCommand) Run(args []string) int { pFile.Close() } - c.logger.Info(fmt.Sprintf("Wrote startup pprof files to: %s", pprofPath)) + c.logger.Info(fmt.Sprintf("Wrote pprof files to: %s", pprofPath)) } } // Notify systemd that the server is shutting down @@ -2111,34 +2105,271 @@ func (c *ServerCommand) enableDev(core *vault.Core, coreConfig *vault.CoreConfig } } - if !c.flagDevNoKV { - kvVer := "2" - if c.flagDevKVV1 || c.flagDevLeasedKV { - kvVer = "1" + kvVer := "2" + if c.flagDevKVV1 || c.flagDevLeasedKV { + kvVer = "1" + } + req := &logical.Request{ + Operation: logical.UpdateOperation, + ClientToken: init.RootToken, + Path: "sys/mounts/secret", + Data: map[string]interface{}{ + "type": "kv", + "path": "secret/", + "description": "key/value secret storage", + "options": map[string]string{ + "version": kvVer, + }, + }, + } + resp, err := core.HandleRequest(ctx, req) + if err != nil { + return nil, fmt.Errorf("error creating default KV store: %w", err) + } + if resp.IsError() { + return nil, fmt.Errorf("failed to create default KV store: %w", resp.Error()) + } + + return init, nil +} + +func (c *ServerCommand) enableThreeNodeDevCluster(base *vault.CoreConfig, info map[string]string, infoKeys []string, devListenAddress, tempDir string) int { + conf, opts := teststorage.ClusterSetup(base, &vault.TestClusterOptions{ + HandlerFunc: vaulthttp.Handler, + BaseListenAddress: c.flagDevListenAddr, + Logger: c.logger, + TempDir: tempDir, + DefaultHandlerProperties: vault.HandlerProperties{ + ListenerConfig: &configutil.Listener{ + Profiling: configutil.ListenerProfiling{ + UnauthenticatedPProfAccess: true, + }, + Telemetry: configutil.ListenerTelemetry{ + UnauthenticatedMetricsAccess: true, + }, + }, + }, + }, nil) + testCluster := vault.NewTestCluster(&testing.RuntimeT{}, conf, opts) + defer c.cleanupGuard.Do(testCluster.Cleanup) + + if constants.IsEnterprise { + err := testcluster.WaitForActiveNodeAndPerfStandbys(context.Background(), testCluster) + if err != nil { + c.UI.Error(fmt.Sprintf("perf standbys didn't become ready: %v", err)) + return 1 } + } + + info["cluster parameters path"] = testCluster.TempDir + infoKeys = append(infoKeys, "cluster parameters path") + + for i, core := range testCluster.Cores { + info[fmt.Sprintf("node %d api address", i)] = fmt.Sprintf("https://%s", core.Listeners[0].Address.String()) + infoKeys = append(infoKeys, fmt.Sprintf("node %d api address", i)) + } + + infoKeys = append(infoKeys, "version") + verInfo := version.GetVersion() + info["version"] = verInfo.FullVersionNumber(false) + if verInfo.Revision != "" { + info["version sha"] = strings.Trim(verInfo.Revision, "'") + infoKeys = append(infoKeys, "version sha") + } + + infoKeys = append(infoKeys, "cgo") + info["cgo"] = "disabled" + if version.CgoEnabled { + info["cgo"] = "enabled" + } + + infoKeys = append(infoKeys, "go version") + info["go version"] = runtime.Version() + + fipsStatus := entGetFIPSInfoKey() + if fipsStatus != "" { + infoKeys = append(infoKeys, "fips") + info["fips"] = fipsStatus + } + + // Server configuration output + padding := 24 + + sort.Strings(infoKeys) + c.UI.Output("==> Vault server configuration:\n") + + for _, k := range infoKeys { + c.UI.Output(fmt.Sprintf( + "%s%s: %s", + strings.Repeat(" ", padding-len(k)), + strings.Title(k), + info[k])) + } + + c.UI.Output("") + + for _, core := range testCluster.Cores { + core.Server.Handler = vaulthttp.Handler.Handler(&vault.HandlerProperties{ + Core: core.Core, + ListenerConfig: &configutil.Listener{}, + }) + core.SetClusterHandler(core.Server.Handler) + } + + testCluster.Start() + + ctx := namespace.ContextWithNamespace(context.Background(), namespace.RootNamespace) + + if base.DevToken != "" { req := &logical.Request{ + ID: "dev-gen-root", Operation: logical.UpdateOperation, - ClientToken: init.RootToken, - Path: "sys/mounts/secret", + ClientToken: testCluster.RootToken, + Path: "auth/token/create", Data: map[string]interface{}{ - "type": "kv", - "path": "secret/", - "description": "key/value secret storage", - "options": map[string]string{ - "version": kvVer, - }, + "id": base.DevToken, + "policies": []string{"root"}, + "no_parent": true, + "no_default_policy": true, }, } - resp, err := core.HandleRequest(ctx, req) + resp, err := testCluster.Cores[0].HandleRequest(ctx, req) if err != nil { - return nil, fmt.Errorf("error creating default KV store: %w", err) + c.UI.Error(fmt.Sprintf("failed to create root token with ID %s: %s", base.DevToken, err)) + return 1 + } + if resp == nil { + c.UI.Error(fmt.Sprintf("nil response when creating root token with ID %s", base.DevToken)) + return 1 } - if resp.IsError() { - return nil, fmt.Errorf("failed to create default KV store: %w", resp.Error()) + if resp.Auth == nil { + c.UI.Error(fmt.Sprintf("nil auth when creating root token with ID %s", base.DevToken)) + return 1 + } + + testCluster.RootToken = resp.Auth.ClientToken + + req.ID = "dev-revoke-init-root" + req.Path = "auth/token/revoke-self" + req.Data = nil + _, err = testCluster.Cores[0].HandleRequest(ctx, req) + if err != nil { + c.UI.Output(fmt.Sprintf("failed to revoke initial root token: %s", err)) + return 1 } } - return init, nil + // Set the token + tokenHelper, err := c.TokenHelper() + if err != nil { + c.UI.Error(fmt.Sprintf("Error getting token helper: %s", err)) + return 1 + } + if err := tokenHelper.Store(testCluster.RootToken); err != nil { + c.UI.Error(fmt.Sprintf("Error storing in token helper: %s", err)) + return 1 + } + + if err := ioutil.WriteFile(filepath.Join(testCluster.TempDir, "root_token"), []byte(testCluster.RootToken), 0o600); err != nil { + c.UI.Error(fmt.Sprintf("Error writing token to tempfile: %s", err)) + return 1 + } + + c.UI.Output(fmt.Sprintf( + "==> Three node dev mode is enabled\n\n" + + "The unseal key and root token are reproduced below in case you\n" + + "want to seal/unseal the Vault or play with authentication.\n", + )) + + for i, key := range testCluster.BarrierKeys { + c.UI.Output(fmt.Sprintf( + "Unseal Key %d: %s", + i+1, base64.StdEncoding.EncodeToString(key), + )) + } + + c.UI.Output(fmt.Sprintf( + "\nRoot Token: %s\n", testCluster.RootToken, + )) + + c.UI.Output(fmt.Sprintf( + "\nUseful env vars:\n"+ + "VAULT_TOKEN=%s\n"+ + "VAULT_ADDR=%s\n"+ + "VAULT_CACERT=%s/ca_cert.pem\n", + testCluster.RootToken, + testCluster.Cores[0].Client.Address(), + testCluster.TempDir, + )) + + if c.flagDevClusterJson != "" { + clusterJson := testcluster.ClusterJson{ + Nodes: []testcluster.ClusterNode{}, + CACertPath: filepath.Join(testCluster.TempDir, "ca_cert.pem"), + RootToken: testCluster.RootToken, + } + for _, core := range testCluster.Cores { + clusterJson.Nodes = append(clusterJson.Nodes, testcluster.ClusterNode{ + APIAddress: core.Client.Address(), + }) + } + b, err := jsonutil.EncodeJSON(clusterJson) + if err != nil { + c.UI.Error(fmt.Sprintf("Error encoding cluster.json: %s", err)) + return 1 + } + err = os.WriteFile(c.flagDevClusterJson, b, 0o600) + if err != nil { + c.UI.Error(fmt.Sprintf("Error writing cluster.json %q: %s", c.flagDevClusterJson, err)) + return 1 + } + } + + // Output the header that the server has started + c.UI.Output("==> Vault server started! Log data will stream in below:\n") + + // Inform any tests that the server is ready + select { + case c.startedCh <- struct{}{}: + default: + } + + // Release the log gate. + c.flushLog() + + // Wait for shutdown + shutdownTriggered := false + + for !shutdownTriggered { + select { + case <-c.ShutdownCh: + c.UI.Output("==> Vault shutdown triggered") + + // Stop the listeners so that we don't process further client requests. + c.cleanupGuard.Do(testCluster.Cleanup) + + // Finalize will wait until after Vault is sealed, which means the + // request forwarding listeners will also be closed (and also + // waited for). + for _, core := range testCluster.Cores { + if err := core.Shutdown(); err != nil { + c.UI.Error(fmt.Sprintf("Error with core shutdown: %s", err)) + } + } + + shutdownTriggered = true + + case <-c.SighupCh: + c.UI.Output("==> Vault reload triggered") + for _, core := range testCluster.Cores { + if err := c.Reload(core.ReloadFuncsLock, core.ReloadFuncs, nil, core.Core); err != nil { + c.UI.Error(fmt.Sprintf("Error(s) were encountered during reload: %s", err)) + } + } + } + } + + return 0 } // addPlugin adds any plugins to the catalog @@ -3100,7 +3331,7 @@ func initDevCore(c *ServerCommand, coreConfig *vault.CoreConfig, config *server. func startHttpServers(c *ServerCommand, core *vault.Core, config *server.Config, lns []listenerutil.Listener) error { for _, ln := range lns { if ln.Config == nil { - return fmt.Errorf("found nil listener config after parsing") + return fmt.Errorf("Found nil listener config after parsing") } if err := config2.IsValidListener(ln.Config); err != nil { diff --git a/command/server/listener_tcp_test.go b/command/server/listener_tcp_test.go index 6508e7a8afa4..66fcfbe2c8d0 100644 --- a/command/server/listener_tcp_test.go +++ b/command/server/listener_tcp_test.go @@ -6,7 +6,9 @@ package server import ( "crypto/tls" "crypto/x509" + "fmt" "io/ioutil" + "math/rand" "net" "os" "testing" @@ -24,7 +26,9 @@ func TestTCPListener(t *testing.T) { Address: "127.0.0.1:0", TLSDisable: true, }, nil, cli.NewMockUi()) - require.NoError(t, err) + if err != nil { + t.Fatalf("err: %s", err) + } connFn := func(lnReal net.Listener) (net.Conn, error) { return net.Dial("tcp", ln.Addr().String()) @@ -38,13 +42,19 @@ func TestTCPListener_tls(t *testing.T) { wd, _ := os.Getwd() wd += "/test-fixtures/reload/" - // Setup initial certs - inBytes, err := os.ReadFile(wd + "reload_ca.pem") - require.NoError(t, err) + td, err := ioutil.TempDir("", fmt.Sprintf("vault-test-%d", rand.New(rand.NewSource(time.Now().Unix())).Int63())) + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(td) + // Setup initial certs + inBytes, _ := ioutil.ReadFile(wd + "reload_ca.pem") certPool := x509.NewCertPool() ok := certPool.AppendCertsFromPEM(inBytes) - require.True(t, ok, "not ok when appending CA cert") + if !ok { + t.Fatal("not ok when appending CA cert") + } ln, _, _, err := tcpListenerFactory(&configutil.Listener{ Address: "127.0.0.1:0", @@ -53,8 +63,9 @@ func TestTCPListener_tls(t *testing.T) { TLSRequireAndVerifyClientCert: true, TLSClientCAFile: wd + "reload_ca.pem", }, nil, cli.NewMockUi()) - require.NoError(t, err) - + if err != nil { + t.Fatalf("err: %s", err) + } cwd, _ := os.Getwd() clientCert, _ := tls.LoadX509KeyPair( @@ -90,7 +101,9 @@ func TestTCPListener_tls(t *testing.T) { TLSDisableClientCerts: true, TLSClientCAFile: wd + "reload_ca.pem", }, nil, cli.NewMockUi()) - require.Error(t, err, "expected error due to mutually exclusive client cert options") + if err == nil { + t.Fatal("expected error due to mutually exclusive client cert options") + } ln, _, _, err = tcpListenerFactory(&configutil.Listener{ Address: "127.0.0.1:0", @@ -99,7 +112,9 @@ func TestTCPListener_tls(t *testing.T) { TLSDisableClientCerts: true, TLSClientCAFile: wd + "reload_ca.pem", }, nil, cli.NewMockUi()) - require.NoError(t, err) + if err != nil { + t.Fatalf("err: %s", err) + } testListenerImpl(t, ln, connFn(false), "foo.example.com", 0, "127.0.0.1", false) } @@ -108,11 +123,19 @@ func TestTCPListener_tls13(t *testing.T) { wd, _ := os.Getwd() wd += "/test-fixtures/reload/" + td, err := ioutil.TempDir("", fmt.Sprintf("vault-test-%d", rand.New(rand.NewSource(time.Now().Unix())).Int63())) + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(td) + // Setup initial certs inBytes, _ := ioutil.ReadFile(wd + "reload_ca.pem") certPool := x509.NewCertPool() ok := certPool.AppendCertsFromPEM(inBytes) - require.True(t, ok, "not ok when appending CA cert") + if !ok { + t.Fatal("not ok when appending CA cert") + } ln, _, _, err := tcpListenerFactory(&configutil.Listener{ Address: "127.0.0.1:0", @@ -122,8 +145,9 @@ func TestTCPListener_tls13(t *testing.T) { TLSClientCAFile: wd + "reload_ca.pem", TLSMinVersion: "tls13", }, nil, cli.NewMockUi()) - require.NoError(t, err) - + if err != nil { + t.Fatalf("err: %s", err) + } cwd, _ := os.Getwd() clientCert, _ := tls.LoadX509KeyPair( @@ -160,7 +184,9 @@ func TestTCPListener_tls13(t *testing.T) { TLSClientCAFile: wd + "reload_ca.pem", TLSMinVersion: "tls13", }, nil, cli.NewMockUi()) - require.Error(t, err, "expected error due to mutually exclusive client cert options") + if err == nil { + t.Fatal("expected error due to mutually exclusive client cert options") + } ln, _, _, err = tcpListenerFactory(&configutil.Listener{ Address: "127.0.0.1:0", @@ -170,7 +196,9 @@ func TestTCPListener_tls13(t *testing.T) { TLSClientCAFile: wd + "reload_ca.pem", TLSMinVersion: "tls13", }, nil, cli.NewMockUi()) - require.NoError(t, err) + if err != nil { + t.Fatalf("err: %s", err) + } testListenerImpl(t, ln, connFn(false), "foo.example.com", tls.VersionTLS13, "127.0.0.1", false) @@ -182,7 +210,9 @@ func TestTCPListener_tls13(t *testing.T) { TLSClientCAFile: wd + "reload_ca.pem", TLSMaxVersion: "tls12", }, nil, cli.NewMockUi()) - require.NoError(t, err) + if err != nil { + t.Fatalf("err: %s", err) + } testListenerImpl(t, ln, connFn(false), "foo.example.com", tls.VersionTLS12, "127.0.0.1", false) } @@ -400,7 +430,9 @@ func TestTCPListener_proxyProtocol(t *testing.T) { proxyProtocolAuthorizedAddrs := []*sockaddr.SockAddrMarshaler{} if tc.AuthorizedAddr != "" { sockAddr, err := sockaddr.NewSockAddr(tc.AuthorizedAddr) - require.NoError(t, err) + if err != nil { + t.Fatal(err) + } proxyProtocolAuthorizedAddrs = append( proxyProtocolAuthorizedAddrs, &sockaddr.SockAddrMarshaler{SockAddr: sockAddr}, @@ -413,11 +445,12 @@ func TestTCPListener_proxyProtocol(t *testing.T) { ProxyProtocolBehavior: tc.Behavior, ProxyProtocolAuthorizedAddrs: proxyProtocolAuthorizedAddrs, }, nil, cli.NewMockUi()) - require.NoError(t, err) + if err != nil { + t.Fatalf("err: %s", err) + } connFn := func(lnReal net.Listener) (net.Conn, error) { - d := net.Dialer{Timeout: 3 * time.Second} - conn, err := d.Dial("tcp", lnReal.Addr().String()) + conn, err := net.Dial("tcp", ln.Addr().String()) if err != nil { return nil, err } diff --git a/command/util.go b/command/util.go index 55aa7778c21a..26fd38000b42 100644 --- a/command/util.go +++ b/command/util.go @@ -8,8 +8,6 @@ import ( "io" "net/http" "os" - "path/filepath" - "runtime/pprof" "testing" "time" @@ -203,40 +201,3 @@ func (r *recordingRoundTripper) RoundTrip(req *http.Request) (*http.Response, er StatusCode: 200, }, nil } - -// WritePprofToFile will create a temporary directory at the specified path -// and generate pprof files at that location. CPU requires polling over a -// duration. For most situations 1 second is enough. -func WritePprofToFile(path string, cpuProfileDuration time.Duration) error { - err := os.MkdirAll(path, os.ModePerm) - if err != nil { - return fmt.Errorf("could not create temporary directory for pprof: %v", err) - } - - dumps := []string{"goroutine", "heap", "allocs", "threadcreate", "profile"} - for _, dump := range dumps { - pFile, err := os.Create(filepath.Join(path, dump)) - if err != nil { - return fmt.Errorf("error creating pprof file %s: %v", dump, err) - } - - if dump != "profile" { - err = pprof.Lookup(dump).WriteTo(pFile, 0) - if err != nil { - pFile.Close() - return fmt.Errorf("error generating pprof data for %s: %v", dump, err) - } - } else { - // CPU profiles need to run for a duration so we're going to run it - // just for one second to avoid blocking here. - if err := pprof.StartCPUProfile(pFile); err != nil { - pFile.Close() - return fmt.Errorf("could not start CPU profile: %v", err) - } - time.Sleep(cpuProfileDuration) - pprof.StopCPUProfile() - } - pFile.Close() - } - return nil -} diff --git a/command/write.go b/command/write.go index 0b10ec46564b..33ee3be0f242 100644 --- a/command/write.go +++ b/command/write.go @@ -51,15 +51,13 @@ Usage: vault write [options] PATH [DATA K=V...] it is loaded from a file. If the value is "-", Vault will read the value from stdin. - Store an arbitrary secret in the token's cubbyhole. + Persist data in the generic secrets engine: - $ vault write cubbyhole/git-credentials username="student01" password="p@$$w0rd" + $ vault write secret/my-secret foo=bar Create a new encryption key in the transit secrets engine: - $ vault write -force transit/keys/my-key - - The -force / -f flag allows a write operation without any input data. + $ vault write -f transit/keys/my-key Upload an AWS IAM policy from a file on disk: @@ -69,10 +67,6 @@ Usage: vault write [options] PATH [DATA K=V...] $ echo $MY_TOKEN | vault write consul/config/access token=- - Create a token - - $ vault write auth/token/create policies="admin" policies="secops" ttl=8h num_uses=3 - For a full list of examples and paths, please see the documentation that corresponds to the secret engines in use. diff --git a/go.mod b/go.mod index 069716b0ece7..242831c3aef4 100644 --- a/go.mod +++ b/go.mod @@ -24,33 +24,33 @@ replace github.com/hashicorp/vault/sdk => ./sdk require ( cloud.google.com/go/cloudsqlconn v1.4.3 - cloud.google.com/go/monitoring v1.21.0 - cloud.google.com/go/spanner v1.67.0 - cloud.google.com/go/storage v1.43.0 - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 + cloud.google.com/go/monitoring v1.19.0 + cloud.google.com/go/spanner v1.62.0 + cloud.google.com/go/storage v1.41.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 github.com/Azure/azure-storage-blob-go v0.15.0 github.com/Azure/go-autorest/autorest v0.11.29 github.com/Azure/go-autorest/autorest/adal v0.9.23 github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 - github.com/SAP/go-hdb v1.10.1 + github.com/SAP/go-hdb v0.14.1 github.com/Sectorbob/mlab-ns2 v0.0.0-20171030222938-d3aa0c295a8a github.com/aerospike/aerospike-client-go/v5 v5.6.0 - github.com/aliyun/alibaba-cloud-sdk-go v1.63.12 + github.com/aliyun/alibaba-cloud-sdk-go v1.62.737 github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5 github.com/apple/foundationdb/bindings/go v0.0.0-20190411004307-cd5c9d91fad2 github.com/armon/go-metrics v0.4.1 github.com/armon/go-radix v1.0.0 github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 - github.com/aws/aws-sdk-go v1.55.5 - github.com/aws/aws-sdk-go-v2/config v1.27.11 + github.com/aws/aws-sdk-go v1.53.5 + github.com/aws/aws-sdk-go-v2/config v1.18.19 github.com/axiomhq/hyperloglog v0.0.0-20220105174342-98591331716a github.com/cenkalti/backoff/v3 v3.2.2 github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0 github.com/cockroachdb/cockroach-go/v2 v2.3.8 github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf github.com/denisenkom/go-mssqldb v0.12.3 - github.com/docker/docker v26.1.5+incompatible + github.com/docker/docker v25.0.6+incompatible github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74 github.com/dustin/go-humanize v1.0.1 github.com/fatih/color v1.17.0 @@ -74,8 +74,8 @@ require ( github.com/hashicorp/cap v0.7.0 github.com/hashicorp/cap/ldap v0.0.0-20240403125925-c0418810d10e github.com/hashicorp/cli v1.1.6 - github.com/hashicorp/consul-template v0.39.1 - github.com/hashicorp/consul/api v1.29.1 + github.com/hashicorp/consul-template v0.37.6 + github.com/hashicorp/consul/api v1.28.3 github.com/hashicorp/errwrap v1.1.0 github.com/hashicorp/eventlogger v0.2.10 github.com/hashicorp/go-bexpr v0.1.12 @@ -91,10 +91,10 @@ require ( github.com/hashicorp/go-kms-wrapping/wrappers/azurekeyvault/v2 v2.0.11 github.com/hashicorp/go-kms-wrapping/wrappers/gcpckms/v2 v2.0.12 github.com/hashicorp/go-kms-wrapping/wrappers/ocikms/v2 v2.0.7 - github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.12 + github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.11 github.com/hashicorp/go-memdb v1.3.4 github.com/hashicorp/go-multierror v1.1.1 - github.com/hashicorp/go-plugin v1.6.1 + github.com/hashicorp/go-plugin v1.6.0 github.com/hashicorp/go-raftchunking v0.6.3-0.20191002164813-7e9e8525653a github.com/hashicorp/go-retryablehttp v0.7.7 github.com/hashicorp/go-rootcerts v1.0.2 @@ -112,7 +112,7 @@ require ( github.com/hashicorp/go-sockaddr v1.0.6 github.com/hashicorp/go-syslog v1.0.0 github.com/hashicorp/go-uuid v1.0.3 - github.com/hashicorp/go-version v1.7.0 + github.com/hashicorp/go-version v1.6.0 github.com/hashicorp/golang-lru v1.0.2 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/hashicorp/hcl v1.0.1-vault-5 @@ -121,42 +121,42 @@ require ( github.com/hashicorp/hcp-scada-provider v0.2.2 github.com/hashicorp/hcp-sdk-go v0.101.0 github.com/hashicorp/nomad/api v0.0.0-20240213164230-c364cb57298d - github.com/hashicorp/raft v1.7.1 + github.com/hashicorp/raft v1.6.1 github.com/hashicorp/raft-autopilot v0.2.0 github.com/hashicorp/raft-boltdb/v2 v2.3.0 github.com/hashicorp/raft-snapshot v1.0.4 github.com/hashicorp/raft-wal v0.4.0 github.com/hashicorp/vault-hcp-lib v0.0.0-20240704151836-a5c058ac604c - github.com/hashicorp/vault-plugin-auth-alicloud v0.19.0 - github.com/hashicorp/vault-plugin-auth-azure v0.19.0 - github.com/hashicorp/vault-plugin-auth-cf v0.19.0 - github.com/hashicorp/vault-plugin-auth-gcp v0.19.0 - github.com/hashicorp/vault-plugin-auth-jwt v0.22.0 - github.com/hashicorp/vault-plugin-auth-kerberos v0.13.0 - github.com/hashicorp/vault-plugin-auth-kubernetes v0.20.0 - github.com/hashicorp/vault-plugin-auth-oci v0.17.0 - github.com/hashicorp/vault-plugin-database-couchbase v0.12.0 - github.com/hashicorp/vault-plugin-database-elasticsearch v0.16.0 - github.com/hashicorp/vault-plugin-database-mongodbatlas v0.13.0 - github.com/hashicorp/vault-plugin-database-redis v0.4.0 - github.com/hashicorp/vault-plugin-database-redis-elasticache v0.5.0 - github.com/hashicorp/vault-plugin-database-snowflake v0.12.0 + github.com/hashicorp/vault-plugin-auth-alicloud v0.18.0 + github.com/hashicorp/vault-plugin-auth-azure v0.18.0 + github.com/hashicorp/vault-plugin-auth-cf v0.18.0 + github.com/hashicorp/vault-plugin-auth-gcp v0.18.0 + github.com/hashicorp/vault-plugin-auth-jwt v0.21.1 + github.com/hashicorp/vault-plugin-auth-kerberos v0.12.0 + github.com/hashicorp/vault-plugin-auth-kubernetes v0.19.0 + github.com/hashicorp/vault-plugin-auth-oci v0.16.0 + github.com/hashicorp/vault-plugin-database-couchbase v0.11.0 + github.com/hashicorp/vault-plugin-database-elasticsearch v0.15.0 + github.com/hashicorp/vault-plugin-database-mongodbatlas v0.12.0 + github.com/hashicorp/vault-plugin-database-redis v0.3.0 + github.com/hashicorp/vault-plugin-database-redis-elasticache v0.4.0 + github.com/hashicorp/vault-plugin-database-snowflake v0.11.0 github.com/hashicorp/vault-plugin-mock v0.16.1 - github.com/hashicorp/vault-plugin-secrets-ad v0.19.0 - github.com/hashicorp/vault-plugin-secrets-alicloud v0.18.0 - github.com/hashicorp/vault-plugin-secrets-azure v0.20.0 - github.com/hashicorp/vault-plugin-secrets-gcp v0.20.0 - github.com/hashicorp/vault-plugin-secrets-gcpkms v0.19.0 - github.com/hashicorp/vault-plugin-secrets-kubernetes v0.9.0 - github.com/hashicorp/vault-plugin-secrets-kv v0.20.0 - github.com/hashicorp/vault-plugin-secrets-mongodbatlas v0.13.0 - github.com/hashicorp/vault-plugin-secrets-openldap v0.14.1 - github.com/hashicorp/vault-plugin-secrets-terraform v0.10.0 - github.com/hashicorp/vault-testing-stepwise v0.3.1 - github.com/hashicorp/vault/api v1.15.0 + github.com/hashicorp/vault-plugin-secrets-ad v0.18.0 + github.com/hashicorp/vault-plugin-secrets-alicloud v0.17.0 + github.com/hashicorp/vault-plugin-secrets-azure v0.19.2 + github.com/hashicorp/vault-plugin-secrets-gcp v0.19.0 + github.com/hashicorp/vault-plugin-secrets-gcpkms v0.17.0 + github.com/hashicorp/vault-plugin-secrets-kubernetes v0.8.0 + github.com/hashicorp/vault-plugin-secrets-kv v0.19.0 + github.com/hashicorp/vault-plugin-secrets-mongodbatlas v0.12.0 + github.com/hashicorp/vault-plugin-secrets-openldap v0.13.1 + github.com/hashicorp/vault-plugin-secrets-terraform v0.9.0 + github.com/hashicorp/vault-testing-stepwise v0.1.4 + github.com/hashicorp/vault/api v1.14.0 github.com/hashicorp/vault/api/auth/approle v0.1.0 github.com/hashicorp/vault/api/auth/userpass v0.1.0 - github.com/hashicorp/vault/sdk v0.14.0 + github.com/hashicorp/vault/sdk v0.13.0 github.com/hashicorp/vault/vault/hcp_link/proto v0.0.0-20230201201504-b741fa893d77 github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab github.com/jackc/pgx/v4 v4.18.3 @@ -173,6 +173,7 @@ require ( github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a github.com/mitchellh/copystructure v1.2.0 github.com/mitchellh/go-homedir v1.1.0 + github.com/mitchellh/go-testing-interface v1.14.1 github.com/mitchellh/go-wordwrap v1.0.1 github.com/mitchellh/mapstructure v1.5.0 github.com/mitchellh/reflectwalk v1.0.2 @@ -187,8 +188,8 @@ require ( github.com/pkg/errors v0.9.1 github.com/posener/complete v1.2.3 github.com/pquerna/otp v1.2.1-0.20191009055518-468c2dd2b58d - github.com/prometheus/client_golang v1.19.1 - github.com/prometheus/common v0.55.0 + github.com/prometheus/client_golang v1.19.0 + github.com/prometheus/common v0.49.0 github.com/rboyer/safeio v0.2.1 github.com/robfig/cron/v3 v3.0.1 github.com/ryanuber/columnize v2.1.2+incompatible @@ -198,62 +199,57 @@ require ( github.com/shirou/gopsutil/v3 v3.22.6 github.com/stretchr/testify v1.9.0 github.com/tink-crypto/tink-go/v2 v2.2.0 - go.etcd.io/bbolt v1.3.10 - go.etcd.io/etcd/client/pkg/v3 v3.5.13 + go.etcd.io/bbolt v1.3.7 + go.etcd.io/etcd/client/pkg/v3 v3.5.7 go.etcd.io/etcd/client/v2 v2.305.5 - go.etcd.io/etcd/client/v3 v3.5.13 - go.mongodb.org/atlas v0.37.0 - go.mongodb.org/mongo-driver v1.16.1 - go.opentelemetry.io/otel v1.30.0 - go.opentelemetry.io/otel/sdk v1.30.0 - go.opentelemetry.io/otel/trace v1.30.0 + go.etcd.io/etcd/client/v3 v3.5.7 + go.mongodb.org/atlas v0.36.0 + go.mongodb.org/mongo-driver v1.16.0 + go.opentelemetry.io/otel v1.28.0 + go.opentelemetry.io/otel/sdk v1.28.0 + go.opentelemetry.io/otel/trace v1.28.0 go.uber.org/atomic v1.11.0 go.uber.org/goleak v1.3.0 - golang.org/x/crypto v0.27.0 - golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 - golang.org/x/net v0.29.0 - golang.org/x/oauth2 v0.23.0 + golang.org/x/crypto v0.26.0 + golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 + golang.org/x/net v0.28.0 + golang.org/x/oauth2 v0.21.0 golang.org/x/sync v0.8.0 - golang.org/x/sys v0.25.0 - golang.org/x/term v0.24.0 - golang.org/x/text v0.18.0 + golang.org/x/sys v0.24.0 + golang.org/x/term v0.23.0 + golang.org/x/text v0.17.0 golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d - google.golang.org/api v0.197.0 - google.golang.org/grpc v1.66.1 + google.golang.org/api v0.181.0 + google.golang.org/grpc v1.65.0 google.golang.org/protobuf v1.34.2 gopkg.in/ory-am/dockertest.v3 v3.3.4 - k8s.io/apimachinery v0.31.0 - k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 + k8s.io/apimachinery v0.29.3 + k8s.io/utils v0.0.0-20230726121419-3b25d923346b layeh.com/radius v0.0.0-20231213012653-1006025d24f8 nhooyr.io/websocket v1.8.11 ) require ( cel.dev/expr v0.15.0 // indirect - cloud.google.com/go/longrunning v0.6.0 // indirect - github.com/containerd/containerd v1.7.20 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect + cloud.google.com/go/longrunning v0.5.7 // indirect github.com/hashicorp/go-secure-stdlib/httputil v0.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.14.1 // indirect - github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect - github.com/x448/float16 v0.8.4 // indirect - golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 // indirect + golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect + gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect ) require ( - cloud.google.com/go v0.115.1 // indirect - cloud.google.com/go/auth v0.9.3 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect - cloud.google.com/go/compute/metadata v0.5.0 // indirect - cloud.google.com/go/iam v1.2.0 // indirect - cloud.google.com/go/kms v1.19.0 // indirect; indirect\ - dario.cat/mergo v1.0.1 // indirect + cloud.google.com/go v0.113.0 // indirect + cloud.google.com/go/auth v0.4.1 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect + cloud.google.com/go/compute/metadata v0.3.0 // indirect + cloud.google.com/go/iam v1.1.8 // indirect + cloud.google.com/go/kms v1.17.0 // indirect; indirect\ + dario.cat/mergo v1.0.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.2 // indirect github.com/Azure/azure-pipeline-go v0.2.3 // indirect github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 v2.2.0 // indirect @@ -281,29 +277,29 @@ require ( github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/Masterminds/sprig/v3 v3.2.3 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/agext/levenshtein v1.2.1 // indirect github.com/apache/arrow/go/v15 v15.0.0 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect - github.com/aws/aws-sdk-go-v2 v1.26.1 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.11 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 // indirect - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.15 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.5 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.7 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.5 // indirect - github.com/aws/aws-sdk-go-v2/service/s3 v1.53.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 // indirect - github.com/aws/smithy-go v1.20.2 // indirect + github.com/aws/aws-sdk-go-v2 v1.23.4 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.13.18 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1 // indirect + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.59 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.7 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.7 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.12.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.18.7 // indirect + github.com/aws/smithy-go v1.18.1 // indirect github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect github.com/benbjohnson/immutable v0.4.0 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -320,18 +316,19 @@ require ( github.com/cloudflare/circl v1.3.7 // indirect github.com/cloudfoundry-community/go-cfclient v0.0.0-20220930021109-9c4e6c59ccf1 // indirect github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b // indirect - github.com/containerd/continuity v0.4.3 // indirect + github.com/containerd/containerd v1.7.12 // indirect + github.com/containerd/continuity v0.4.2 // indirect github.com/containerd/log v0.1.0 // indirect github.com/coreos/etcd v3.3.27+incompatible // indirect github.com/coreos/go-oidc/v3 v3.11.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf // indirect - github.com/couchbase/gocb/v2 v2.9.1 // indirect - github.com/couchbase/gocbcore/v10 v10.5.1 // indirect - github.com/couchbase/gocbcoreps v0.1.3 // indirect + github.com/couchbase/gocb/v2 v2.8.1 // indirect + github.com/couchbase/gocbcore/v10 v10.4.1 // indirect + github.com/couchbase/gocbcoreps v0.1.2 // indirect github.com/couchbase/goprotostellar v1.0.2 // indirect - github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20240607131231-fb385523de28 // indirect + github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20230515165046-68b522a21131 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect @@ -340,13 +337,13 @@ require ( github.com/digitalocean/godo v1.7.5 // indirect github.com/dimchansky/utfbom v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/cli v26.1.5+incompatible // indirect - github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/cli v25.0.5+incompatible // indirect + github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dvsekhvalnov/jose2go v1.6.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155 // indirect + github.com/envoyproxy/go-control-plane v0.12.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect @@ -384,23 +381,24 @@ require ( github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/s2a-go v0.1.8 // indirect + github.com/google/s2a-go v0.1.7 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect - github.com/googleapis/gax-go/v2 v2.13.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.4 // indirect github.com/gophercloud/gophercloud v0.1.0 // indirect github.com/gorilla/websocket v1.5.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect + github.com/hashicorp/consul/proto-public v0.6.1 // indirect github.com/hashicorp/cronexpr v1.1.2 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect - github.com/hashicorp/go-msgpack/v2 v2.1.2 // indirect + github.com/hashicorp/go-msgpack/v2 v2.1.1 // indirect github.com/hashicorp/go-secure-stdlib/fileutil v0.1.0 // indirect - github.com/hashicorp/go-secure-stdlib/plugincontainer v0.4.0 // indirect - github.com/hashicorp/go-slug v0.15.2 // indirect - github.com/hashicorp/go-tfe v1.64.2 // indirect + github.com/hashicorp/go-secure-stdlib/plugincontainer v0.3.0 // indirect + github.com/hashicorp/go-slug v0.15.0 // indirect + github.com/hashicorp/go-tfe v1.61.0 // indirect github.com/hashicorp/jsonapi v1.3.1 // indirect github.com/hashicorp/logutils v1.0.0 // indirect github.com/hashicorp/mdns v1.0.4 // indirect @@ -439,22 +437,22 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-ieproxy v0.0.1 // indirect github.com/mediocregopher/radix/v4 v4.1.4 // indirect - github.com/microsoft/kiota-abstractions-go v1.6.1 // indirect - github.com/microsoft/kiota-authentication-azure-go v1.1.0 // indirect - github.com/microsoft/kiota-http-go v1.4.4 // indirect + github.com/microsoft/kiota-abstractions-go v1.6.0 // indirect + github.com/microsoft/kiota-authentication-azure-go v1.0.2 // indirect + github.com/microsoft/kiota-http-go v1.3.1 // indirect github.com/microsoft/kiota-serialization-form-go v1.0.0 // indirect - github.com/microsoft/kiota-serialization-json-go v1.0.8 // indirect + github.com/microsoft/kiota-serialization-json-go v1.0.7 // indirect github.com/microsoft/kiota-serialization-multipart-go v1.0.0 // indirect github.com/microsoft/kiota-serialization-text-go v1.0.0 // indirect - github.com/microsoftgraph/msgraph-sdk-go v1.47.0 // indirect - github.com/microsoftgraph/msgraph-sdk-go-core v1.2.1 // indirect + github.com/microsoftgraph/msgraph-sdk-go v1.42.0 // indirect + github.com/microsoftgraph/msgraph-sdk-go-core v1.1.0 // indirect github.com/miekg/dns v1.1.50 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect github.com/mitchellh/hashstructure v1.1.0 // indirect github.com/mitchellh/pointerstructure v1.2.1 // indirect github.com/moby/patternmatcher v0.5.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect - github.com/moby/sys/user v0.2.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -466,7 +464,7 @@ require ( github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect github.com/opencontainers/runc v1.2.0-rc.1 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect github.com/oracle/oci-go-sdk/v59 v59.0.0 // indirect @@ -479,8 +477,8 @@ require ( github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/procfs v0.15.1 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/segmentio/fasthash v1.0.3 // indirect @@ -489,12 +487,12 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/skeema/knownhosts v1.2.1 // indirect github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect - github.com/snowflakedb/gosnowflake v1.11.0 // indirect + github.com/snowflakedb/gosnowflake v1.10.0 // indirect github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d // indirect github.com/sony/gobreaker v0.5.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/std-uritemplate/std-uritemplate/go v0.0.57 // indirect + github.com/std-uritemplate/std-uritemplate/go v0.0.55 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/tencentcloud/tencentcloud-sdk-go v1.0.162 // indirect github.com/tilinna/clock v1.1.0 // indirect @@ -514,18 +512,18 @@ require ( github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zclconf/go-cty v1.12.1 // indirect github.com/zeebo/xxh3 v1.0.2 // indirect - go.etcd.io/etcd/api/v3 v3.5.13 // indirect + go.etcd.io/etcd/api/v3 v3.5.7 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect - go.opentelemetry.io/otel/metric v1.30.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/time v0.6.0 // indirect - google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect; indirect\ + golang.org/x/mod v0.17.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/genproto v0.0.0-20240520151616-dc85e6b867a5 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240730163845-b1a4ccb954bf // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect; indirect\ gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/jcmturner/goidentity.v3 v3.0.0 // indirect @@ -533,13 +531,13 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.31.0 // indirect - k8s.io/client-go v0.31.0 // indirect - k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect + k8s.io/api v0.29.3 // indirect + k8s.io/client-go v0.29.3 // indirect + k8s.io/klog/v2 v2.110.1 // indirect + k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) replace github.com/ma314smith/signedxml v1.1.1 => github.com/moov-io/signedxml v1.1.1 diff --git a/go.sum b/go.sum index 23962f2bba1f..349809c0bdee 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,8 @@ cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRY cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= -cloud.google.com/go v0.115.1 h1:Jo0SM9cQnSkYfp44+v+NQXHpcHqlnRJk2qxh6yvxxxQ= -cloud.google.com/go v0.115.1/go.mod h1:DuujITeaufu3gL68/lOFIirVNJwQeyf5UXyi+Wbgknc= +cloud.google.com/go v0.113.0 h1:g3C70mn3lWfckKBiCVsAshabrDg01pQ0pnX1MNtnMkA= +cloud.google.com/go v0.113.0/go.mod h1:glEqlogERKYeePz6ZdkcLJ28Q2I6aERgDDErBg9GzO8= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= @@ -102,10 +102,10 @@ cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVo cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= -cloud.google.com/go/auth v0.9.3 h1:VOEUIAADkkLtyfr3BLa3R8Ed/j6w1jTBmARx+wb5w5U= -cloud.google.com/go/auth v0.9.3/go.mod h1:7z6VY+7h3KUdRov5F1i8NDP5ZzWKYmEPO842BgCsmTk= -cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= -cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= +cloud.google.com/go/auth v0.4.1 h1:Z7YNIhlWRtrnKlZke7z3GMqzvuYzdc2z98F9D1NV5Hg= +cloud.google.com/go/auth v0.4.1/go.mod h1:QVBuVEKpCn4Zp58hzRGvL0tjRGU0YqdRTdCHM1IHnro= +cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= +cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= @@ -187,8 +187,8 @@ cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZ cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= -cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= +cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= +cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= @@ -322,8 +322,8 @@ cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGE cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= -cloud.google.com/go/iam v1.2.0 h1:kZKMKVNk/IsSSc/udOb83K0hL/Yh/Gcqpz+oAkoIFN8= -cloud.google.com/go/iam v1.2.0/go.mod h1:zITGuWgsLZxd8OwAlX+eMFgZDXzBm7icj1PVTYG766Q= +cloud.google.com/go/iam v1.1.8 h1:r7umDwhj+BQyz0ScZMp4QrGXjSTI3ZINnpgU2nlB/K0= +cloud.google.com/go/iam v1.1.8/go.mod h1:GvE6lyMmfxXauzNq8NbgJbeVQNspG+tcdL/W8QO1+zE= cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= @@ -343,8 +343,8 @@ cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4 cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= -cloud.google.com/go/kms v1.19.0 h1:x0OVJDl6UH1BSX4THKlMfdcFWoE4ruh90ZHuilZekrU= -cloud.google.com/go/kms v1.19.0/go.mod h1:e4imokuPJUc17Trz2s6lEXFDt8bgDmvpVynH39bdrHM= +cloud.google.com/go/kms v1.17.0 h1:5sFDtixjw5CivNoiiCbtWTQmi7bav3oMO6NeNg2IunQ= +cloud.google.com/go/kms v1.17.0/go.mod h1:DCMnCF/apA6fZk5Cj4XsD979OyHAqFasPuA5Sd0kGlQ= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= @@ -358,8 +358,8 @@ cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeN cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= -cloud.google.com/go/longrunning v0.6.0 h1:mM1ZmaNsQsnb+5n1DNPeL0KwQd9jQRqSqSDEkBZr+aI= -cloud.google.com/go/longrunning v0.6.0/go.mod h1:uHzSZqW89h7/pasCWNYdUpwGz3PcVWhrWupreVPYLts= +cloud.google.com/go/longrunning v0.5.7 h1:WLbHekDbjK1fVFD3ibpFFVoyizlLRl73I7YKuAKilhU= +cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng= cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= @@ -383,8 +383,8 @@ cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhI cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= -cloud.google.com/go/monitoring v1.21.0 h1:EMc0tB+d3lUewT2NzKC/hr8cSR9WsUieVywzIHetGro= -cloud.google.com/go/monitoring v1.21.0/go.mod h1:tuJ+KNDdJbetSsbSGTqnaBvbauS5kr3Q/koy3Up6r+4= +cloud.google.com/go/monitoring v1.19.0 h1:NCXf8hfQi+Kmr56QJezXRZ6GPb80ZI7El1XztyUuLQI= +cloud.google.com/go/monitoring v1.19.0/go.mod h1:25IeMR5cQ5BoZ8j1eogHE5VPJLlReQ7zFp5OiLgiGZw= cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= @@ -531,8 +531,8 @@ cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+ cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= -cloud.google.com/go/spanner v1.67.0 h1:h8xfobxh5lQu4qJVMPH+wSiyU+ZM6ZTxRNqGeu9iIVA= -cloud.google.com/go/spanner v1.67.0/go.mod h1:Um+TNmxfcCHqNCKid4rmAMvoe/Iu1vdz6UfxJ9GPxRQ= +cloud.google.com/go/spanner v1.62.0 h1:AHjSLrsGYIEzVQLQkF/OBgObSbXlnMpdovai8x+owco= +cloud.google.com/go/spanner v1.62.0/go.mod h1:ej/7etuxlyxOhfudKk9nUXBVyxr4kK39LMbmSjOeDEM= cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= @@ -550,8 +550,8 @@ cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeL cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= -cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= -cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= +cloud.google.com/go/storage v1.41.0 h1:RusiwatSu6lHeEXe3kglxakAmAbfV+rhtPqA6i8RBx0= +cloud.google.com/go/storage v1.41.0/go.mod h1:J1WCa/Z2FcgdEDuPUY8DxT5I+d9mFKsCepp5vR6Sq80= cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= @@ -617,8 +617,8 @@ cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoIS cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= -dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= -dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= @@ -634,14 +634,14 @@ github.com/Azure/azure-sdk-for-go v44.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 h1:nyQWyZvwGTvunIMxi1Y9uXkcyr+I7TeNrr/foo4Kpk8= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo= github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 h1:U2rTu3Ef+7w9FHKIAXM6ZyqF3UOWJZ12zIm8zECAFfg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg= github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 h1:m/sWOGCREuSBqg2htVQTBY8nOZpyajYztF0vUvSZTuM= github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0/go.mod h1:Pu5Zksi2KrU7LPbZbNINx6fuVrUp/ffvpxdDj+i8LeE= github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 h1:FbH3BbSb4bvGluTesZZ+ttN/MDsnMmQP36OSnDuSXqw= @@ -740,10 +740,10 @@ github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYr github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/Microsoft/hcsshim v0.11.7 h1:vl/nj3Bar/CvJSYo7gIQPyRWc9f3c6IeSNavBTSZNZQ= -github.com/Microsoft/hcsshim v0.11.7/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= +github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= @@ -752,8 +752,8 @@ github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCv github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/SAP/go-hdb v1.10.1 h1:c9dGT5xHZNDwPL3NQcRpnNISn3MchwYaGoMZpCAllUs= -github.com/SAP/go-hdb v1.10.1/go.mod h1:vxYDca44L2eRudZv5JAI6T+IygOfxb7vOCFh/Kj0pug= +github.com/SAP/go-hdb v0.14.1 h1:hkw4ozGZ/i4eak7ZuGkY5e0hxiXFdNUBNhr4AvZVNFE= +github.com/SAP/go-hdb v0.14.1/go.mod h1:7fdQLVC2lER3urZLjZCm0AuMQfApof92n3aylBPEkMo= github.com/Sectorbob/mlab-ns2 v0.0.0-20171030222938-d3aa0c295a8a h1:KFHLI4QGttB0i7M3qOkAo8Zn/GSsxwwCnInFqBaYtkM= github.com/Sectorbob/mlab-ns2 v0.0.0-20171030222938-d3aa0c295a8a/go.mod h1:D73UAuEPckrDorYZdtlCu2ySOLuPB5W4rhIkmmc/XbI= github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af h1:DBNMBMuMiWYu0b+8KMJuWmfCkcxl09JwdlqwDZZ6U14= @@ -772,8 +772,8 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI= github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= -github.com/aliyun/alibaba-cloud-sdk-go v1.63.12 h1:O/lpYuNJlb5ed/QIJUDE1yJBh6zPF5ZFToiuGpq91Ds= -github.com/aliyun/alibaba-cloud-sdk-go v1.63.12/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.737 h1:ZJQHOp8O0RpldZ8XQwCSlpiDMkiYwcqi1rTAs/7oxQY= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.737/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5 h1:nWDRPCyCltiTsANwC/n3QZH7Vww33Npq9MKqlwRzI/c= github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= @@ -805,46 +805,50 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.25.41/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.34.0/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= -github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= -github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA= -github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2/go.mod h1:lPprDr1e6cJdyYeGXnRaJoP4Md+cDBvi2eOj00BlGmg= -github.com/aws/aws-sdk-go-v2/config v1.27.11 h1:f47rANd2LQEYHda2ddSCKYId18/8BhSRM4BULGmfgNA= -github.com/aws/aws-sdk-go-v2/config v1.27.11/go.mod h1:SMsV78RIOYdve1vf36z8LmnszlRWkwMQtomCAI0/mIE= -github.com/aws/aws-sdk-go-v2/credentials v1.17.11 h1:YuIB1dJNf1Re822rriUOTxopaHHvIq0l/pX3fwO+Tzs= -github.com/aws/aws-sdk-go-v2/credentials v1.17.11/go.mod h1:AQtFPsDH9bI2O+71anW6EKL+NcD7LG3dpKGMV4SShgo= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 h1:FVJ0r5XTHSmIHJV6KuDmdYhEpvlHpiSd38RQWhut5J4= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1/go.mod h1:zusuAeqezXzAB24LGuzuekqMAEgWkVYukBec3kr3jUg= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.15 h1:7Zwtt/lP3KNRkeZre7soMELMGNoBrutx8nobg1jKWmo= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.15/go.mod h1:436h2adoHb57yd+8W+gYPrrA9U/R/SuAuOO42Ushzhw= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5/go.mod h1:FSaRudD0dXiMPK2UjknVwwTYyZMRsHv3TtkabsZih5I= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 h1:PG1F3OD1szkuQPzDw3CIQsRIrtTlUC3lP84taWzHlq0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5/go.mod h1:jU1li6RFryMz+so64PpKtudI+QzbKoIEivqdf6LNpOc= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.5 h1:81KE7vaZzrl7yHBYHVEzYB8sypz11NMOZ40YlWvPxsU= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.5/go.mod h1:LIt2rg7Mcgn09Ygbdh/RdIm0rQ+3BNkbP1gyVMFtRK0= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.7 h1:ZMeFZ5yk+Ek+jNr1+uwCd2tG89t6oTS5yVWpa6yy2es= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.7/go.mod h1:mxV05U+4JiHqIpGqqYXOHLPKUC6bDXC44bsUhNjOEwY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 h1:ogRAwT1/gxJBcSWDMZlgyFUM962F51A5CRhDLbxLdmo= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7/go.mod h1:YCsIZhXfRPLFFCl5xxY+1T9RKzOKjCut+28JSX2DnAk= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.5 h1:f9RyWNtS8oH7cZlbn+/JNPpjUk5+5fLd5lM9M0i49Ys= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.5/go.mod h1:h5CoMZV2VF297/VLhRhO1WF+XYWOzXo+4HsObA4HjBQ= -github.com/aws/aws-sdk-go-v2/service/s3 v1.53.1 h1:6cnno47Me9bRykw9AEv9zkXE+5or7jz8TsskTTccbgc= -github.com/aws/aws-sdk-go-v2/service/s3 v1.53.1/go.mod h1:qmdkIIAC+GCLASF7R2whgNrJADz0QZPX+Seiw/i4S3o= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 h1:vN8hEbpRnL7+Hopy9dzmRle1xmDc7o8tmY0klsr175w= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.5/go.mod h1:qGzynb/msuZIE8I75DVRCUXw3o3ZyBmUvMwQ2t/BrGM= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 h1:Jux+gDDyi1Lruk+KHF91tK2KCuY61kzoCpvtvJJBtOE= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4/go.mod h1:mUYPBhaF2lGiukDEjJX2BLRRKTmoUSitGDUgM4tRxak= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 h1:cwIxeBttqPN3qkaAjcEcsh8NYr8n2HZPkcKgPAi1phU= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.6/go.mod h1:FZf1/nKNEkHdGGJP/cI2MoIMquumuRK6ol3QQJNDxmw= -github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= -github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/aws/aws-sdk-go v1.53.5 h1:1OcVWMjGlwt7EU5OWmmEEXqaYfmX581EK317QJZXItM= +github.com/aws/aws-sdk-go v1.53.5/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aws/aws-sdk-go-v2 v1.17.7/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= +github.com/aws/aws-sdk-go-v2 v1.23.4 h1:2P20ZjH0ouSAu/6yZep8oCmTReathLuEu6dwoqEgjts= +github.com/aws/aws-sdk-go-v2 v1.23.4/go.mod h1:t3szzKfP0NeRU27uBFczDivYJjsmSnqI8kIvKyWb9ds= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= +github.com/aws/aws-sdk-go-v2/config v1.18.19 h1:AqFK6zFNtq4i1EYu+eC7lcKHYnZagMn6SW171la0bGw= +github.com/aws/aws-sdk-go-v2/config v1.18.19/go.mod h1:XvTmGMY8d52ougvakOv1RpiTLPz9dlG/OQHsKU/cMmY= +github.com/aws/aws-sdk-go-v2/credentials v1.13.18 h1:EQMdtHwz0ILTW1hoP+EwuWhwCG1hD6l3+RWFQABET4c= +github.com/aws/aws-sdk-go-v2/credentials v1.13.18/go.mod h1:vnwlwjIe+3XJPBYKu1et30ZPABG3VaXJYr8ryohpIyM= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1 h1:gt57MN3liKiyGopcqgNzJb2+d9MJaKT/q1OksHNXVE4= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1/go.mod h1:lfUx8puBRdM5lVVMQlwt2v+ofiG/X6Ms+dy0UkG/kXw= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.59 h1:E3Y+OfzOK1+rmRo/K2G0ml8Vs+Xqk0kOnf4nS0kUtBc= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.59/go.mod h1:1M4PLSBUVfBI0aP+C9XI7SM6kZPCGYyI6izWz0TGprE= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31/go.mod h1:QT0BqUvX1Bh2ABdTGnjqEjvjzrCfIniM9Sc8zn9Yndo= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.7 h1:eMqD7ku6WGdmcWWXPYun9m6yk6feSULLhJlAtN6rYG4= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.7/go.mod h1:0oBIfcDV6LScxEW0VgOqxT3e4aqKRp+SYhB9wAd5E3Q= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25/go.mod h1:zBHOPwhBc3FlQjQJE/D3IfPWiWaQmT06Vq9aNukDo0k= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.7 h1:+XYhWhgWs5F3Zx8oa49CXzNvfXrItaDjZB/M172fcHQ= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.7/go.mod h1:L6tcSRyCGxcKfDWUrmv2jv8G1cLDU7d0FUpEFpG9bVE= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32 h1:p5luUImdIqywn6JpQsW3tq5GNOxKmOnEpybzPx+d1lk= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32/go.mod h1:XGhIBZDEgfqmFIugclZ6FU7v75nHhBDtzuB4xB/tEi4= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23 h1:DWYZIsyqagnWL00f8M/SOr9fN063OEQWn9LLTbdYXsk= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23/go.mod h1:uIiFgURZbACBEQJfqTZPb/jxO7R+9LeoHUFudtIdeQI= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 h1:y2+VQzC6Zh2ojtV2LoC0MNwHWc6qXv/j2vrQtlftkdA= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11/go.mod h1:iV4q2hsqtNECrfmlXyord9u4zyuFEJX9eLgLpSPzWA8= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26 h1:CeuSeq/8FnYpPtnuIeLQEEvDv9zUjneuYi8EghMBdwQ= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26/go.mod h1:2UqAAwMUXKeRkAHIlDJqvMVgOWkUi/AUXPk/YIe+Dg4= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25 h1:5LHn8JQ0qvjD9L9JhMtylnkcw7j05GDZqM9Oin6hpr0= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25/go.mod h1:/95IA+0lMnzW6XzqYJRpjjsAbKEORVeO0anQqjd2CNU= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0 h1:e2ooMhpYGhDnBfSvIyusvAwX7KexuZaHbQY2Dyei7VU= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0/go.mod h1:bh2E0CXKZsQN+faiKVqC40vfNMAWheoULBCnEgO9K+8= +github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0 h1:B1G2pSPvbAtQjilPq+Y7jLIzCOwKzuVEl+aBBaNG0AQ= +github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0/go.mod h1:ncltU6n4Nof5uJttDtcNQ537uNuwYqsZZQcpkd2/GUQ= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.6 h1:5V7DWLBd7wTELVz5bPpwzYy/sikk0gsgZfj40X+l5OI= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.6/go.mod h1:Y1VOmit/Fn6Tz1uFAeCO6Q7M2fmfXSCLeL5INVYsLuY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6 h1:B8cauxOH1W1v7rd8RdI/MWnoR4Ze0wIHWrb90qczxj4= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6/go.mod h1:Lh/bc9XUf8CfOY6Jp5aIkQtN+j1mc+nExc+KXj9jx2s= +github.com/aws/aws-sdk-go-v2/service/sts v1.18.7 h1:bWNgNdRko2x6gqa0blfATqAZKZokPIeM1vfmQt2pnvM= +github.com/aws/aws-sdk-go-v2/service/sts v1.18.7/go.mod h1:JuTnSoeePXmMVe9G8NcjjwgOKEfZ4cOjMuT2IBT/2eI= +github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/aws/smithy-go v1.18.1 h1:pOdBTUfXNazOlxLrgeYalVnuTpKreACHtc62xLwIB3c= +github.com/aws/smithy-go v1.18.1/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE= github.com/axiomhq/hyperloglog v0.0.0-20220105174342-98591331716a h1:eqjiAL3qooftPm8b9C1GsSSRcmlw7iOva8vdBTmV2PY= github.com/axiomhq/hyperloglog v0.0.0-20220105174342-98591331716a/go.mod h1:2stgcRjl6QmW+gU2h5E7BQXg4HU0gzxKWDuT5HviN9s= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA= @@ -925,10 +929,10 @@ github.com/cockroachdb/cockroach-go/v2 v2.3.8 h1:53yoUo4+EtrC1NrAEgnnad4AS3ntNvG github.com/cockroachdb/cockroach-go/v2 v2.3.8/go.mod h1:9uH5jK4yQ3ZQUT9IXe4I2fHzMIF5+JC/oOdzTRgJYJk= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= -github.com/containerd/containerd v1.7.20 h1:Sl6jQYk3TRavaU83h66QMbI2Nqg9Jm6qzwX57Vsn1SQ= -github.com/containerd/containerd v1.7.20/go.mod h1:52GsS5CwquuqPuLncsXwG0t2CiUce+KsNHJZQJvAgR0= -github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= -github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0= +github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk= +github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= +github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -951,18 +955,18 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf h1:GOPo6vn/vTN+3IwZBvXX0y5doJfSC7My0cdzelyOCsQ= github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/couchbase/gocb/v2 v2.9.1 h1:yB2ZhRLk782Y9sZlATaUwglZe9+2QpvFmItJXTX4stQ= -github.com/couchbase/gocb/v2 v2.9.1/go.mod h1:TMAeK34yUdcASdV4mGcYuwtkAWckRBYN5uvMCEgPfXo= -github.com/couchbase/gocbcore/v10 v10.5.1 h1:bwlV/zv/fSQLuO14M9k49K7yWgcWfjSgMyfRGhW1AyU= -github.com/couchbase/gocbcore/v10 v10.5.1/go.mod h1:rulbgUK70EuyRUiLQ0LhQAfSI/Rl+jWws8tTbHzvB6M= -github.com/couchbase/gocbcoreps v0.1.3 h1:fILaKGCjxFIeCgAUG8FGmRDSpdrRggohOMKEgO9CUpg= -github.com/couchbase/gocbcoreps v0.1.3/go.mod h1:hBFpDNPnRno6HH5cRXExhqXYRmTsFJlFHQx7vztcXPk= +github.com/couchbase/gocb/v2 v2.8.1 h1:syeJEVy36IvUy4wyzK/74M4wc4OJ2eWZ1d6yWG31Qno= +github.com/couchbase/gocb/v2 v2.8.1/go.mod h1:xI7kkiz4IhdrhBAAEcKC6R2oqVXxpMIV/ZkmxB+PWgM= +github.com/couchbase/gocbcore/v10 v10.4.1 h1:2vZjYRTbSCp1HEcL3iFQv+r4HwiI13VhdnbTku+E/+M= +github.com/couchbase/gocbcore/v10 v10.4.1/go.mod h1:rulbgUK70EuyRUiLQ0LhQAfSI/Rl+jWws8tTbHzvB6M= +github.com/couchbase/gocbcoreps v0.1.2 h1:wlGyyMnkWpCNOlTtfy8UG+8XZsFtqTJtPXz63+QKC58= +github.com/couchbase/gocbcoreps v0.1.2/go.mod h1:33hSdOKnrUVaBqw4+RiqW+2JoD8ylkbvqm89Wg81uXk= github.com/couchbase/goprotostellar v1.0.2 h1:yoPbAL9sCtcyZ5e/DcU5PRMOEFaJrF9awXYu3VPfGls= github.com/couchbase/goprotostellar v1.0.2/go.mod h1:5/yqVnZlW2/NSbAWu1hPJCFBEwjxgpe0PFFOlRixnp4= github.com/couchbaselabs/gocaves/client v0.0.0-20230404095311-05e3ba4f0259 h1:2TXy68EGEzIMHOx9UvczR5ApVecwCfQZ0LjkmwMI6g4= github.com/couchbaselabs/gocaves/client v0.0.0-20230404095311-05e3ba4f0259/go.mod h1:AVekAZwIY2stsJOMWLAS/0uA/+qdp7pjO8EHnl61QkY= -github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20240607131231-fb385523de28 h1:lhGOw8rNG6RAadmmaJAF3PJ7MNt7rFuWG7BHCYMgnGE= -github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20240607131231-fb385523de28/go.mod h1:o7T431UOfFVHDNvMBUmUxpHnhivwv7BziUao/nMl81E= +github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20230515165046-68b522a21131 h1:2EAfFswAfgYn3a05DVcegiw6DgMgn1Mv5eGz6IHt1Cw= +github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20230515165046-68b522a21131/go.mod h1:o7T431UOfFVHDNvMBUmUxpHnhivwv7BziUao/nMl81E= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -995,12 +999,12 @@ github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5 github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/docker/cli v26.1.5+incompatible h1:NxXGSdz2N+Ibdaw330TDO3d/6/f7MvHuiMbuFaIQDTk= -github.com/docker/cli v26.1.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v26.1.5+incompatible h1:NEAxTwEjxV6VbBMBoGG3zPqbiJosIApZjxlbrG9q3/g= -github.com/docker/docker v26.1.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/cli v25.0.5+incompatible h1:3Llw3kcE1gOScEojA247iDD+p1l9hHeC7H3vf3Zd5fk= +github.com/docker/cli v25.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v25.0.6+incompatible h1:5cPwbwriIcsua2REJe8HqQV+6WlWc1byg2QSXzBxBGg= +github.com/docker/docker v25.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= @@ -1031,8 +1035,8 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= -github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155 h1:IgJPqnrlY2Mr4pYB6oaMKvFvwJ9H+X6CCY5x1vCTcpc= -github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155/go.mod h1:5Wkq+JduFtdAXihLmeTJf+tRYIT4KBc2vPXDhwVo1pA= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= @@ -1061,8 +1065,6 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0= @@ -1116,6 +1118,7 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -1156,10 +1159,9 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= -github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= @@ -1299,12 +1301,11 @@ github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= -github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -1318,8 +1319,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= -github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -1331,8 +1332,8 @@ github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqE github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= -github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= +github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg= +github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= @@ -1375,15 +1376,15 @@ github.com/hashicorp/cap/ldap v0.0.0-20240403125925-c0418810d10e h1:IakB/NhT0YtM github.com/hashicorp/cap/ldap v0.0.0-20240403125925-c0418810d10e/go.mod h1:Ofp5fMLl1ImcwjNGu9FtEwNOdxA0LYoWpcWQE2vltuI= github.com/hashicorp/cli v1.1.6 h1:CMOV+/LJfL1tXCOKrgAX0uRKnzjj/mpmqNXloRSy2K8= github.com/hashicorp/cli v1.1.6/go.mod h1:MPon5QYlgjjo0BSoAiN0ESeT5fRzDjVRp+uioJ0piz4= -github.com/hashicorp/consul-template v0.39.1 h1:MfhPoNENzCVSEXtE7CnIm3JkCzM9K0I7rcJYofm1BYY= -github.com/hashicorp/consul-template v0.39.1/go.mod h1:AKqYCDerwwX2k9w7mTWIEC0bEUemSjyYl6Cy+NlqNYw= -github.com/hashicorp/consul/api v1.29.1 h1:UEwOjYJrd3lG1x5w7HxDRMGiAUPrb3f103EoeKuuEcc= -github.com/hashicorp/consul/api v1.29.1/go.mod h1:lumfRkY/coLuqMICkI7Fh3ylMG31mQSRZyef2c5YvJI= +github.com/hashicorp/consul-template v0.37.6 h1:7iz+BjuO4/LHQn/x04o3b+42UspILcIKZQk6DQJd59M= +github.com/hashicorp/consul-template v0.37.6/go.mod h1:tT9BVCw6W4JUxHJlv+onPuUzBTiYwvPRfXYPDgXDbIA= +github.com/hashicorp/consul/api v1.28.3 h1:IE06LST/knnCQ+cxcvzyXRF/DetkgGhJoaOFd4l9xkk= +github.com/hashicorp/consul/api v1.28.3/go.mod h1:7AGcUFu28HkgOKD/GmsIGIFzRTmN0L02AE9Thsr2OhU= github.com/hashicorp/consul/proto-public v0.6.1 h1:+uzH3olCrksXYWAYHKqK782CtK9scfqH+Unlw3UHhCg= github.com/hashicorp/consul/proto-public v0.6.1/go.mod h1:cXXbOg74KBNGajC+o8RlA502Esf0R9prcoJgiOX/2Tg= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.16.1 h1:V8TxTnImoPD5cj0U9Spl0TUxcytjcbbJeADFF07KdHg= -github.com/hashicorp/consul/sdk v0.16.1/go.mod h1:fSXvwxB2hmh1FMZCNl6PwX0Q/1wdWtHJcZ7Ea5tns0s= +github.com/hashicorp/consul/sdk v0.15.0 h1:2qK9nDrr4tiJKRoxPGhm6B7xJjLVIQqkjiab2M4aKjU= +github.com/hashicorp/consul/sdk v0.15.0/go.mod h1:r/OmRRPbHOe0yxNahLw7G9x5WG17E1BIECMtCjcPSNo= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -1429,22 +1430,22 @@ github.com/hashicorp/go-kms-wrapping/wrappers/gcpckms/v2 v2.0.12 h1:PCqWzT/Hii0K github.com/hashicorp/go-kms-wrapping/wrappers/gcpckms/v2 v2.0.12/go.mod h1:HSaOaX/lv3ShCdilUYbOTPnSvmoZ9xtQhgw+8hYcZkg= github.com/hashicorp/go-kms-wrapping/wrappers/ocikms/v2 v2.0.7 h1:KeG3QGrbxbr2qAqCJdf3NR4ijAYwdcWLTmwSbR0yusM= github.com/hashicorp/go-kms-wrapping/wrappers/ocikms/v2 v2.0.7/go.mod h1:rXxYzjjGw4HltEwxPp9zYSRIo6R+rBf1MSPk01bvodc= -github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.12 h1:E8pzzF7i44OZCYDol+U7VbTBmHe65/6dx1nYxS0P1k0= -github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.12/go.mod h1:YRqguGarF7kbHeojTPkanH3qvjbEP2pelq5b0ifaQ1M= +github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.11 h1:hdzSrDJ0CgHgGFx+1toaf7Z5bmQ2EYaFQ/dtWNXxu1I= +github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.11/go.mod h1:ywjP17x2t88pT3GA8gCc2vEH1vhvU1R9d5XwRQ0d7PQ= github.com/hashicorp/go-memdb v1.3.4 h1:XSL3NR682X/cVk2IeV0d70N4DZ9ljI885xAEU8IoK3c= github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs= github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4= -github.com/hashicorp/go-msgpack/v2 v2.1.2 h1:4Ee8FTp834e+ewB71RDrQ0VKpyFdrKOjvYtnQ/ltVj0= -github.com/hashicorp/go-msgpack/v2 v2.1.2/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= +github.com/hashicorp/go-msgpack/v2 v2.1.1 h1:xQEY9yB2wnHitoSzk/B9UjXWRQ67QKu5AOm8aFp8N3I= +github.com/hashicorp/go-msgpack/v2 v2.1.1/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= 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-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI= -github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= +github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= +github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/hashicorp/go-raftchunking v0.6.3-0.20191002164813-7e9e8525653a h1:FmnBDwGwlTgugDGbVxwV8UavqSMACbGrUpfc98yFLR4= github.com/hashicorp/go-raftchunking v0.6.3-0.20191002164813-7e9e8525653a/go.mod h1:xbXnmKqX9/+RhPkJ4zrEx4738HacP72aaUPlT2RZ4sU= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= @@ -1472,30 +1473,30 @@ github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8 h1:iBt4Ew4XEGLfh6/bPk4rSY github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8/go.mod h1:aiJI+PIApBRQG7FZTEBx5GiiX+HbOHilUdNxUZi4eV0= github.com/hashicorp/go-secure-stdlib/password v0.1.1 h1:6JzmBqXprakgFEHwBgdchsjaA9x3GyjdI568bXKxa60= github.com/hashicorp/go-secure-stdlib/password v0.1.1/go.mod h1:9hH302QllNwu1o2TGYtSk8I8kTAN0ca1EHpwhm5Mmzo= -github.com/hashicorp/go-secure-stdlib/plugincontainer v0.4.0 h1:7Yran48kl6X7jfUg3sfYDrFot1gD3LvzdC3oPu5l/qo= -github.com/hashicorp/go-secure-stdlib/plugincontainer v0.4.0/go.mod h1:9WJFu7L3d+Z4ViZmwUf+6/73/Uy7YMY1NXrB9wdElYE= +github.com/hashicorp/go-secure-stdlib/plugincontainer v0.3.0 h1:KMWpBsC65ZBXDpoxJ0n2/zVfZaZIW73k2d8cy5Dv/Kk= +github.com/hashicorp/go-secure-stdlib/plugincontainer v0.3.0/go.mod h1:qKYwSZ2EOpppko5ud+Sh9TrUgiTAZSaQCr8XWIYXsbM= github.com/hashicorp/go-secure-stdlib/reloadutil v0.1.1 h1:SMGUnbpAcat8rIKHkBPjfv81yC46a8eCNZ2hsR2l1EI= github.com/hashicorp/go-secure-stdlib/reloadutil v0.1.1/go.mod h1:Ch/bf00Qnx77MZd49JRgHYqHQjtEmTgGU2faufpVZb0= 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.3 h1:xbrxd0U9XQW8qL1BAz2XrAjAF/P2vcqUTAues9c24B8= github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.3/go.mod h1:LWq2Sy8UoKKuK4lFuCNWSjJj57MhNNf2zzBWMtkAIX4= -github.com/hashicorp/go-slug v0.15.2 h1:/ioIpE4bWVN/d7pG2qMrax0a7xe9vOA66S+fz7fZmGY= -github.com/hashicorp/go-slug v0.15.2/go.mod h1:THWVTAXwJEinbsp4/bBRcmbaO5EYNLTqxbG4tZ3gCYQ= +github.com/hashicorp/go-slug v0.15.0 h1:AhMnE6JIyW0KoDJlmRDwv4xd52a5ZK3VdioQ7SMmZhI= +github.com/hashicorp/go-slug v0.15.0/go.mod h1:THWVTAXwJEinbsp4/bBRcmbaO5EYNLTqxbG4tZ3gCYQ= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.6 h1:RSG8rKU28VTUTvEKghe5gIhIQpv8evvNpnDEyqO4u9I= github.com/hashicorp/go-sockaddr v1.0.6/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI= github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-tfe v1.64.2 h1:nbK9p5gA7k8/jbqgNpOzs7lG5cGfOhLVCki4bn7PmdQ= -github.com/hashicorp/go-tfe v1.64.2/go.mod h1:JIgzD8EKkwAqFJdtmo0X2k1NUTrozyniKijL1nVkJgE= +github.com/hashicorp/go-tfe v1.61.0 h1:KlLB/hbU2nnHWzzS1Z9UNGw5gjrfFh+XntcKrf4CLv0= +github.com/hashicorp/go-tfe v1.61.0/go.mod h1:XnTtBj3tVQ4uFkcFsv8Grn+O1CVcIcceL1uc2AgUcaU= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= -github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= @@ -1530,8 +1531,8 @@ github.com/hashicorp/nomad/api v0.0.0-20240213164230-c364cb57298d/go.mod h1:ijDw github.com/hashicorp/raft v1.0.1/go.mod h1:DVSAWItjLjTOkVbSpWQ0j0kUADIvDaCtBxIcbNAQLkI= github.com/hashicorp/raft v1.1.2-0.20191002163536-9c6bd3e3eb17/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8= github.com/hashicorp/raft v1.2.0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8= -github.com/hashicorp/raft v1.7.1 h1:ytxsNx4baHsRZrhUcbt3+79zc4ly8qm7pi0393pSchY= -github.com/hashicorp/raft v1.7.1/go.mod h1:hUeiEwQQR/Nk2iKDD0dkEhklSsu3jcAcqvPzPoZSAEM= +github.com/hashicorp/raft v1.6.1 h1:v/jm5fcYHvVkL0akByAp+IDdDSzCNCGhdO6VdB56HIM= +github.com/hashicorp/raft v1.6.1/go.mod h1:N1sKh6Vn47mrWvEArQgILTyng8GoDRNYlgKyK7PMjs0= github.com/hashicorp/raft-autopilot v0.2.0 h1:2/R2RPgamgRKgNWGQioULZvjeKXQZmDuw5Ty+6c+H7Y= github.com/hashicorp/raft-autopilot v0.2.0/go.mod h1:q6tZ8UAZ5xio2gv2JvjgmtOlh80M6ic8xQYBe2Egkg8= github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= @@ -1547,58 +1548,58 @@ github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= github.com/hashicorp/vault-hcp-lib v0.0.0-20240704151836-a5c058ac604c h1:LCwgi0iiq6pPIRWG80MWwZfPxO2xoHPYwShWfnhAhNI= github.com/hashicorp/vault-hcp-lib v0.0.0-20240704151836-a5c058ac604c/go.mod h1:Nb41BTPvmFbKB73D/+XpxIw6Nf2Rt+AOUvLzlDxwAGQ= -github.com/hashicorp/vault-plugin-auth-alicloud v0.19.0 h1:LgNFlAgUsOjt8THbhcnWDyfdiSwPIajfay6ltdg3d6I= -github.com/hashicorp/vault-plugin-auth-alicloud v0.19.0/go.mod h1:hkcOv6HSKRMWwZA/YZ6OgStW6iQXCv90KfSTJYbt5vc= -github.com/hashicorp/vault-plugin-auth-azure v0.19.0 h1:TdInvToRpn0tCl/+R4qqAAovMobq4YSuCezVvamWlPQ= -github.com/hashicorp/vault-plugin-auth-azure v0.19.0/go.mod h1:elSxwfldjnRJQsJIAfD305g7gvUnFDykGvuY5phNNgw= -github.com/hashicorp/vault-plugin-auth-cf v0.19.0 h1:/I084ZCypbhTO5ZiYjxhjzokuDqOWWLLxHatyViU9ss= -github.com/hashicorp/vault-plugin-auth-cf v0.19.0/go.mod h1:LiH/IttNxAgto2ooR9l2g6+CiXc5c/1uPE0pT0hILRg= -github.com/hashicorp/vault-plugin-auth-gcp v0.19.0 h1:mMTnAGDi6GigGmP9DlLjDzp5VRF8/sZzw8hlfOLFbbU= -github.com/hashicorp/vault-plugin-auth-gcp v0.19.0/go.mod h1:+0+ufeudu8nKVS448iHnzKp5SgLtMcs2U9E0nOUoL/Q= -github.com/hashicorp/vault-plugin-auth-jwt v0.22.0 h1:ihjx6HszRSt8Vfknc5t0AKXBQqFhqTQ4Wdd/PK+EboU= -github.com/hashicorp/vault-plugin-auth-jwt v0.22.0/go.mod h1:+Ne5sCgAza7aDIzxE4aruv6PeQI9ORWIvg/dFe2jlJU= -github.com/hashicorp/vault-plugin-auth-kerberos v0.13.0 h1:KN+nY7XJANb7IRILf0EnaCT04JI9ctiUhq/W9sgyJnk= -github.com/hashicorp/vault-plugin-auth-kerberos v0.13.0/go.mod h1:tJ4upLp8+7xxNHBFwpXQaQQQjkwSwI4P/Hic9EKkWvQ= -github.com/hashicorp/vault-plugin-auth-kubernetes v0.20.0 h1:C+3gSOE+M1JT/6K/CNbQXCAUAA2wFQ7IFpD9Y9IPXxU= -github.com/hashicorp/vault-plugin-auth-kubernetes v0.20.0/go.mod h1:5//ywSXEdrni78mPcOAE+BnF8XUnbvSMCIwMvmHSbzI= -github.com/hashicorp/vault-plugin-auth-oci v0.17.0 h1:t2PNAWSZNNm7sf+l2vK4wod0fQ4DckVZuCb3N9Dgark= -github.com/hashicorp/vault-plugin-auth-oci v0.17.0/go.mod h1:vCuIzHclwIyL+Vk6OfIoqjOomuvPmwRUbnnxlxHCyqM= -github.com/hashicorp/vault-plugin-database-couchbase v0.12.0 h1:WBPE3nsbM03HxmBBEa2dca2XR/6wZqm1eKZDo3NFxOg= -github.com/hashicorp/vault-plugin-database-couchbase v0.12.0/go.mod h1:Pp6qHuSRxSivKMNVGzxRhIjkVsdJ4LSj8B4n8uoD4XU= -github.com/hashicorp/vault-plugin-database-elasticsearch v0.16.0 h1:gArlFh8W0SVQA3OmYZ/IwD6H4RxLphAtKB71jOEKawE= -github.com/hashicorp/vault-plugin-database-elasticsearch v0.16.0/go.mod h1:IqiX9rT/8wCsriRogV4kOCIgAV21yEgjK1D+Oucda3Y= -github.com/hashicorp/vault-plugin-database-mongodbatlas v0.13.0 h1:QfqA3GYVtuVOBe02snoEoU1BS6u3hUkzObd27lVb6FQ= -github.com/hashicorp/vault-plugin-database-mongodbatlas v0.13.0/go.mod h1:4JKUfOniWUxWjnrsBKyPpy3u7dCxkncYAH6VM0BCPhg= -github.com/hashicorp/vault-plugin-database-redis v0.4.0 h1:caNySLrAoKnwYun2kLlwntMKDp+T4yFl/ToCI+ebu1A= -github.com/hashicorp/vault-plugin-database-redis v0.4.0/go.mod h1:OAKaJH4fj4t0MXPBU8FTb7Ca+DzyQD8wjvq4Dq7I8pU= -github.com/hashicorp/vault-plugin-database-redis-elasticache v0.5.0 h1:XCbJLn02bRf9+eyjoMVaEx5TPoIJD9YV7u+shjr4paU= -github.com/hashicorp/vault-plugin-database-redis-elasticache v0.5.0/go.mod h1:o1ac/VruWlSmjIaTx4GVCOiXw6+aUuXxHs3btG0XYjU= -github.com/hashicorp/vault-plugin-database-snowflake v0.12.0 h1:rykZv8cV7W6iSeR9vEAFB3FivLz/tTuO8s8mNd9Xrbw= -github.com/hashicorp/vault-plugin-database-snowflake v0.12.0/go.mod h1:grT3WmPmEiRY6zjEkJJ781jWq7h9Yg68jlU8G/BXuBU= +github.com/hashicorp/vault-plugin-auth-alicloud v0.18.0 h1:rGQ+zHJPSIFEpWJ/AEDrOCs7zWrVWIh/JDHRlccr8CI= +github.com/hashicorp/vault-plugin-auth-alicloud v0.18.0/go.mod h1:yTlbTm6u0wLBmS905Puz68d+SAc7MjN2D4BeELPUON8= +github.com/hashicorp/vault-plugin-auth-azure v0.18.0 h1:jQcbAWvEP2fFbmlomA6fnIGRhW5EZqat4NYNcmZUjOY= +github.com/hashicorp/vault-plugin-auth-azure v0.18.0/go.mod h1:ioz9EmeUGS+nIJkcfrnkGa1Bs/FtwT2BdnlgL0tKSUw= +github.com/hashicorp/vault-plugin-auth-cf v0.18.0 h1:UGfzrjgGS6kxpXLXx5ym1qkgyGHS2vn5r/LOBsRTNdA= +github.com/hashicorp/vault-plugin-auth-cf v0.18.0/go.mod h1:tibzfC+K4587UzHH9468DizyQRIlAFXq3EnEVyfX83c= +github.com/hashicorp/vault-plugin-auth-gcp v0.18.0 h1:chiaa1NLN/B2fcoN/WY/YWVxB8F+hE5koudzLWQcG2c= +github.com/hashicorp/vault-plugin-auth-gcp v0.18.0/go.mod h1:HtXlc4HKAmUe8/WE4hP0dirpkq4joxhvm8EZ/TvOZk0= +github.com/hashicorp/vault-plugin-auth-jwt v0.21.1 h1:SFk4j5AbXnKm3csXGCy61W7TrJmHK1vPnEwcH4GrMrg= +github.com/hashicorp/vault-plugin-auth-jwt v0.21.1/go.mod h1:ggLUt/LHQ+H8GbfvLWSmw+rmujHaUvZ5g9pu4JCBoz8= +github.com/hashicorp/vault-plugin-auth-kerberos v0.12.0 h1:zJF5jyIwDSqvze2QZ+ONE9k8p8GSql6+4aWSzDrCIUM= +github.com/hashicorp/vault-plugin-auth-kerberos v0.12.0/go.mod h1:SHMeHUVjgH5lmmCukxEQiVsib8dQnMuhGJgwv5So7oI= +github.com/hashicorp/vault-plugin-auth-kubernetes v0.19.0 h1:zJLrTPyVp62BEDrK3+ZimyELCx0ShBBQppFnloy/fJ8= +github.com/hashicorp/vault-plugin-auth-kubernetes v0.19.0/go.mod h1:JHa4MgsZh6PopoDW4kyRi1E/F9g8eYLavyvva7z0llU= +github.com/hashicorp/vault-plugin-auth-oci v0.16.0 h1:V8vz5b/rqo16cKuvczv8s6n5w6R3ebVEw71fSFlgbVs= +github.com/hashicorp/vault-plugin-auth-oci v0.16.0/go.mod h1:BFcFkE1w2uPvQG52a2ZT7XsFENr0W2N7y4FwTqvDk/c= +github.com/hashicorp/vault-plugin-database-couchbase v0.11.0 h1:SH+/CQUZayrmgqgozeyM8Ctz6i6ZkwT/q7fyB5OKFfg= +github.com/hashicorp/vault-plugin-database-couchbase v0.11.0/go.mod h1:R4KHWLLyQhHUACZuFJqlNFasbm3hoDyF/kruiUvTEmM= +github.com/hashicorp/vault-plugin-database-elasticsearch v0.15.0 h1:RGH87sxehWL74/JsEV8BacmErLeNRfxg6Pv1tudjGFU= +github.com/hashicorp/vault-plugin-database-elasticsearch v0.15.0/go.mod h1:LYqjVkcdXvGCPDdYNeOM0j3MqWSkMAWeZ4r++Xn+tS8= +github.com/hashicorp/vault-plugin-database-mongodbatlas v0.12.0 h1:SQLOOQcF/BuKXh/6AnVYTbCrwyK9MlqzP6AVaqZBAMA= +github.com/hashicorp/vault-plugin-database-mongodbatlas v0.12.0/go.mod h1:++CfUO0B7GQk2dy6nawWVMcNHKdA1nhxoZx6dbMbudI= +github.com/hashicorp/vault-plugin-database-redis v0.3.0 h1:chSbAsc7cYkn5ajQ/528nKoCm9ExGpJaDjTDos2IUa4= +github.com/hashicorp/vault-plugin-database-redis v0.3.0/go.mod h1:Tr6VELF9q/VAslIO7+ROykrzrvEONVaONrcsthX9qcY= +github.com/hashicorp/vault-plugin-database-redis-elasticache v0.4.0 h1:kU6zic2/iIo40kUKzRvTIj1TozcC1T0sqkWimV5e290= +github.com/hashicorp/vault-plugin-database-redis-elasticache v0.4.0/go.mod h1:KQmyYsR5CfoTPSjQqXq6TO9QqucESSga9f+bph+Rx74= +github.com/hashicorp/vault-plugin-database-snowflake v0.11.0 h1:LsBrVl6/bHtn2kCyPAU+ki33iHPBMrOFVzzRvDt3c1g= +github.com/hashicorp/vault-plugin-database-snowflake v0.11.0/go.mod h1:F4+eKtsa3yTdpGh0OfAvtpLodWt//NSIKZ7gDnqzqqc= github.com/hashicorp/vault-plugin-mock v0.16.1 h1:5QQvSUHxDjEEbrd2REOeacqyJnCLPD51IQzy71hx8P0= github.com/hashicorp/vault-plugin-mock v0.16.1/go.mod h1:83G4JKlOwUtxVourn5euQfze3ZWyXcUiLj2wqrKSDIM= -github.com/hashicorp/vault-plugin-secrets-ad v0.19.0 h1:jt5flxYYEaqXasCNzE8MUsA1qWe2FjOWhS1viRpqsbE= -github.com/hashicorp/vault-plugin-secrets-ad v0.19.0/go.mod h1:FlrqHh3gDEOx81OEMFRPGgle+IlnKJUs+3HPYL8bawc= -github.com/hashicorp/vault-plugin-secrets-alicloud v0.18.0 h1:LCaOtwItk9x4lYVKjNyj1+AG+8423O9jSYcw7NBeick= -github.com/hashicorp/vault-plugin-secrets-alicloud v0.18.0/go.mod h1:We2m27w9q7uQgF1UULA3TtcUH6LnA4ItuiujhvvAGOU= -github.com/hashicorp/vault-plugin-secrets-azure v0.20.0 h1:rWsyvZQzF2G1Wkvp624yNIoZHeB7gQ4/Nxk9WuA9HtA= -github.com/hashicorp/vault-plugin-secrets-azure v0.20.0/go.mod h1:PW7g5lgIcwudoZAthoc3xNqiumHHI1gvNw9en/iI3TQ= -github.com/hashicorp/vault-plugin-secrets-gcp v0.20.0 h1:yTRId8Y8rpf6LBUcnAEMQZfMBApiKFxPh7669RcE2zg= -github.com/hashicorp/vault-plugin-secrets-gcp v0.20.0/go.mod h1:FiAMuQ67Wyy2qvXZyezcMFo0ZCh/Prk5FtBABdc1cPc= -github.com/hashicorp/vault-plugin-secrets-gcpkms v0.19.0 h1:XMVCbZtI5UwJ19KoYZpg4Q6byVccRvUzm/I4SGaFJ4o= -github.com/hashicorp/vault-plugin-secrets-gcpkms v0.19.0/go.mod h1:3OEx2UIpLZ0f4biNj60hRZTULuTzJV43Tn6+jKj9xdY= -github.com/hashicorp/vault-plugin-secrets-kubernetes v0.9.0 h1:HEgEjYzG/DYBbCOrm3Pr43XPNwZWMool1EzcRFw3lgg= -github.com/hashicorp/vault-plugin-secrets-kubernetes v0.9.0/go.mod h1:I/CF2GdsKiZ3ZgPrNVF+bs3XD7pUxp24iSKTVV4pHeE= -github.com/hashicorp/vault-plugin-secrets-kv v0.20.0 h1:p1RVmd4x1rgGK0tN8DDu21J21bR3O93qBFXLGEdJSEo= -github.com/hashicorp/vault-plugin-secrets-kv v0.20.0/go.mod h1:bCpMggD3Z0+H+3dOmTCoQjBHC53jA08lPqOLmFrHBi8= -github.com/hashicorp/vault-plugin-secrets-mongodbatlas v0.13.0 h1:BeDS7luTeOW0braIbtuyairFF8SEz7k3nvi9e+mJ2Ok= -github.com/hashicorp/vault-plugin-secrets-mongodbatlas v0.13.0/go.mod h1:sprde+S70PBIbgOLUAKDxR+xNF714ksBBVh77O3hnWc= -github.com/hashicorp/vault-plugin-secrets-openldap v0.14.1 h1:5l7/83OCZsHL1PYkFJd8xjLtKQEz3vpbIbaEzHL5qeU= -github.com/hashicorp/vault-plugin-secrets-openldap v0.14.1/go.mod h1:wqOf/QJqrrNXjnm0eLUnm5Ju9s/LIZUl6wEKmnFL9Uo= -github.com/hashicorp/vault-plugin-secrets-terraform v0.10.0 h1:YzOJrpuDRNrw5SQ4i7IEjedF40I/7ejupQy+gAyQ6Zg= -github.com/hashicorp/vault-plugin-secrets-terraform v0.10.0/go.mod h1:j2nbB//xAQMD+5JivVDalwDEyzJY3AWzKIkw6k65xJQ= -github.com/hashicorp/vault-testing-stepwise v0.3.1 h1:SqItnMWOOknQfJJR49Fps34ZfBMWSqBFFTx6NoTHzNw= -github.com/hashicorp/vault-testing-stepwise v0.3.1/go.mod h1:BK7TOCyZ7idR7txAlPGEu+9ETJzlQsYQNdabSv3lyYY= +github.com/hashicorp/vault-plugin-secrets-ad v0.18.0 h1:amSAV4+W3wBWfuOQk1TA8lHETsrQ7c8PC2PDjroRQMI= +github.com/hashicorp/vault-plugin-secrets-ad v0.18.0/go.mod h1:Dz4s3LTMaZg1wZs41Zqe0vAW19c0HSUzQN36yGzzO+U= +github.com/hashicorp/vault-plugin-secrets-alicloud v0.17.0 h1:b8mTj3e/3JgkEpBFq3Qwp1gH1/YwU4vJHFohVJqWs08= +github.com/hashicorp/vault-plugin-secrets-alicloud v0.17.0/go.mod h1:9eT3ysHGq0jIarcJFcb9rZoaVbQoAsG3Iug8KM9H83w= +github.com/hashicorp/vault-plugin-secrets-azure v0.19.2 h1:/9eARO5fffhRh7/oLVgdKlylTl9mQuk5oXUVksvUjH8= +github.com/hashicorp/vault-plugin-secrets-azure v0.19.2/go.mod h1:R8CJArW9qdsp7ycyKndTaHo7Zj4vXjFMgMXchr/ct1s= +github.com/hashicorp/vault-plugin-secrets-gcp v0.19.0 h1:5FRAVA3JYpn7zDMebQ3V622NxMKtY6tJg3YDuvTzS3A= +github.com/hashicorp/vault-plugin-secrets-gcp v0.19.0/go.mod h1:/xdangTVszef3HQdZ0Ct2MmokRuYSpjx/SyX7aWxTbg= +github.com/hashicorp/vault-plugin-secrets-gcpkms v0.17.0 h1:GeARWON8OFWZFsulNOQqvDRG2H/38l9ye35VFk5MO1g= +github.com/hashicorp/vault-plugin-secrets-gcpkms v0.17.0/go.mod h1:IQl89mmTl+GISbF16Rxr2d8YCfUfEdLeZJkV2rjuZCQ= +github.com/hashicorp/vault-plugin-secrets-kubernetes v0.8.0 h1:PhLMvNO+VbTYzX04tZDkgQIrBxjDBYTbVFQsa7qbE84= +github.com/hashicorp/vault-plugin-secrets-kubernetes v0.8.0/go.mod h1:idMLjrXasvIFI1DclLprHkbz3KrJtTd2Cq5jOYMr6WE= +github.com/hashicorp/vault-plugin-secrets-kv v0.19.0 h1:vF38KPiu0pDK/WZYRPE4M9hmHd4EvO5Opkuokv+lkIE= +github.com/hashicorp/vault-plugin-secrets-kv v0.19.0/go.mod h1:CxMY+Q23bIbkFk5dj+D9yI5fJ2uHQfpUiua11xo6mHM= +github.com/hashicorp/vault-plugin-secrets-mongodbatlas v0.12.0 h1:zbddJmujV0YrtePRSeCsXxfloL0RbDyLhQsJ6l3yjrw= +github.com/hashicorp/vault-plugin-secrets-mongodbatlas v0.12.0/go.mod h1:SFCvcu7ypRUcsuSC3DPUu7BFFhGOTwmZfiIRz3zBinE= +github.com/hashicorp/vault-plugin-secrets-openldap v0.13.1 h1:cjwMAq1TNA3Iv9vaclSokCNw2NQdan0KDDqjJ6X0xS8= +github.com/hashicorp/vault-plugin-secrets-openldap v0.13.1/go.mod h1:s8mEVRoufS+ukZEPOgnmZbJia9LHibGZraGyvoF9B34= +github.com/hashicorp/vault-plugin-secrets-terraform v0.9.0 h1:fEzcmdwxVKJoPaF4kgrxX5/riEqaGEIluJ9AetCpsTM= +github.com/hashicorp/vault-plugin-secrets-terraform v0.9.0/go.mod h1:I/SuXxfo/J9YedVRAdT3MO7u4l3S8AsMKxvY0IAtGYk= +github.com/hashicorp/vault-testing-stepwise v0.1.4 h1:Lsv1KdpQyjhvmLgKeH65FG5MmY5hMkF5LoX3xIxurjg= +github.com/hashicorp/vault-testing-stepwise v0.1.4/go.mod h1:Ym1T/kMM2sT6qgCIIJ3an7uaSWCJ8O7ohsWB9UiB5tI= github.com/hashicorp/vault/vault/hcp_link/proto v0.0.0-20230201201504-b741fa893d77 h1:Y/+BtwxmRak3Us9jrByARvYW6uNeqZlEpMylIdXVIjY= github.com/hashicorp/vault/vault/hcp_link/proto v0.0.0-20230201201504-b741fa893d77/go.mod h1:a2crHoMWwY6aiL8GWT8hYj7vKD64uX0EdRPbnsHF5wU= github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443 h1:O/pT5C1Q3mVXMyuqg7yuAWUg/jMZR1/0QTzTRdNR6Uw= @@ -1813,24 +1814,24 @@ github.com/michaelklishin/rabbit-hole/v2 v2.12.0 h1:946p6jOYFcVJdtBBX8MwXvuBkpPj github.com/michaelklishin/rabbit-hole/v2 v2.12.0/go.mod h1:AN/3zyz7d++OHf+4WUo/LR0+Q5nlPHMaXasIsG/mPY0= github.com/microsoft/go-mssqldb v1.5.0 h1:CgENxkwtOBNj3Jg6T1X209y2blCfTTcwuOlznd2k9fk= github.com/microsoft/go-mssqldb v1.5.0/go.mod h1:lmWsjHD8XX/Txr0f8ZqgbEZSC+BZjmEQy/Ms+rLrvho= -github.com/microsoft/kiota-abstractions-go v1.6.1 h1:NXK50S3BwJn9Wj6bO0YFuAig7y2WVgdQ/ie1ktMl2J4= -github.com/microsoft/kiota-abstractions-go v1.6.1/go.mod h1:FI1I2OHg0E7bK5t8DPnw+9C/CHVyLP6XeqDBT+95pTE= -github.com/microsoft/kiota-authentication-azure-go v1.1.0 h1:HudH57Enel9zFQ4TEaJw6lMiyZ5RbBdrRHwdU0NP2RY= -github.com/microsoft/kiota-authentication-azure-go v1.1.0/go.mod h1:zfPFOiLdEqM77Hua5B/2vpcXrVaGqSWjHSRzlvAWEgc= -github.com/microsoft/kiota-http-go v1.4.4 h1:HM0KT/Q7o+JsGatFkkbTIqJL24Jzo5eMI5NNe9N4TQ4= -github.com/microsoft/kiota-http-go v1.4.4/go.mod h1:Kup5nMDD3a9sjdgRKHCqZWqtrv3FbprjcPaGjLR6FzM= +github.com/microsoft/kiota-abstractions-go v1.6.0 h1:qbGBNMU0/o5myKbikCBXJFohVCFrrpx2cO15Rta2WyA= +github.com/microsoft/kiota-abstractions-go v1.6.0/go.mod h1:7YH20ZbRWXGfHSSvdHkdztzgCB9mRdtFx13+hrYIEpo= +github.com/microsoft/kiota-authentication-azure-go v1.0.2 h1:tClGeyFZJ+4Bakf8u0euPM4wqy4ethycdOgx3jyH3pI= +github.com/microsoft/kiota-authentication-azure-go v1.0.2/go.mod h1:aTcti0bUJEcq7kBfQG4Sr4ElvRNuaalXcFEu4iEyQ6M= +github.com/microsoft/kiota-http-go v1.3.1 h1:S+ZDxE7Pc/Z06hbfqpFHkoq5xiC8/7d12iNovcgl+7o= +github.com/microsoft/kiota-http-go v1.3.1/go.mod h1:4QjB+as08swnZXZLx5I+ZHZ8U/tVy7Zu49RNTmWgw48= github.com/microsoft/kiota-serialization-form-go v1.0.0 h1:UNdrkMnLFqUCccQZerKjblsyVgifS11b3WCx+eFEsAI= github.com/microsoft/kiota-serialization-form-go v1.0.0/go.mod h1:h4mQOO6KVTNciMF6azi1J9QB19ujSw3ULKcSNyXXOMA= -github.com/microsoft/kiota-serialization-json-go v1.0.8 h1:+aViv9k6wqaw1Fx6P49fl5GIB1hN3b6CG0McNTcUYBc= -github.com/microsoft/kiota-serialization-json-go v1.0.8/go.mod h1:O8+v11U0EUwHlCz7hrW38KxDmdhKAHfv4Q89uvsBalY= +github.com/microsoft/kiota-serialization-json-go v1.0.7 h1:yMbckSTPrjZdM4EMXgzLZSA3CtDaUBI350u0VoYRz7Y= +github.com/microsoft/kiota-serialization-json-go v1.0.7/go.mod h1:1krrY7DYl3ivPIzl4xTaBpew6akYNa8/Tal8g+kb0cc= github.com/microsoft/kiota-serialization-multipart-go v1.0.0 h1:3O5sb5Zj+moLBiJympbXNaeV07K0d46IfuEd5v9+pBs= github.com/microsoft/kiota-serialization-multipart-go v1.0.0/go.mod h1:yauLeBTpANk4L03XD985akNysG24SnRJGaveZf+p4so= github.com/microsoft/kiota-serialization-text-go v1.0.0 h1:XOaRhAXy+g8ZVpcq7x7a0jlETWnWrEum0RhmbYrTFnA= github.com/microsoft/kiota-serialization-text-go v1.0.0/go.mod h1:sM1/C6ecnQ7IquQOGUrUldaO5wj+9+v7G2W3sQ3fy6M= -github.com/microsoftgraph/msgraph-sdk-go v1.47.0 h1:qXfmDij9md6mPsSAJjiDNmS4hxqKo0R489GiVMZVmmY= -github.com/microsoftgraph/msgraph-sdk-go v1.47.0/go.mod h1:Gnws5D7d/930uS9J4qlCm4BAR/zenqECMk9tgMDXeZQ= -github.com/microsoftgraph/msgraph-sdk-go-core v1.2.1 h1:P1wpmn3xxfPMFJHg+PJPcusErfRkl63h6OdAnpDbkS8= -github.com/microsoftgraph/msgraph-sdk-go-core v1.2.1/go.mod h1:vFmWQGWyLlhxCESNLv61vlE4qesBU+eWmEVH7DJSESA= +github.com/microsoftgraph/msgraph-sdk-go v1.42.0 h1:AJ/8hJl9lSIKSKaa/+8AxHslpt8QR5z03rHxw4GlsqM= +github.com/microsoftgraph/msgraph-sdk-go v1.42.0/go.mod h1:u/ciVhK5eBqzQvsVnTVdeEl+Jgy9WbUoUHHKgcw54hk= +github.com/microsoftgraph/msgraph-sdk-go-core v1.1.0 h1:NB7c/n4Knj+TLaLfjsahhSqoUqoN/CtyNB0XIe/nJnM= +github.com/microsoftgraph/msgraph-sdk-go-core v1.1.0/go.mod h1:M3w/5IFJ1u/DpwOyjsjNSVEA43y1rLOeX58suyfBhGk= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= @@ -1865,14 +1866,12 @@ github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8oh github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= -github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo= github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= -github.com/moby/sys/user v0.2.0 h1:OnpapJsRp25vkhw8TFG6OLJODNh/3rEwRWtJ3kakwRM= -github.com/moby/sys/user v0.2.0/go.mod h1:RYstrcWOJpVh+6qzUqp2bU3eaRpdiQeKGlKitaH0PM8= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -1920,20 +1919,20 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= -github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= +github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= +github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= -github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8= +github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/opencontainers/runc v1.2.0-rc.1 h1:SMjop2pxxYRTfKdsigna/8xRoaoCfIQfD2cVuOb64/o= github.com/opencontainers/runc v1.2.0-rc.1/go.mod h1:m9JwxfHzXz5YTTXBQr7EY9KTuazFAGPyMQx2nRR3vTw= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -1984,8 +1983,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= -github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -2001,29 +1998,29 @@ github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4 github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/common v0.49.0 h1:ToNTdK4zSnPVJmh698mGFkDor9wBI/iGaJy5dbH1EgI= +github.com/prometheus/common v0.49.0/go.mod h1:Kxm+EULxRbUkjGU6WFsQqo3ORzB4tyKvlWFOE9mB2sE= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rboyer/safeio v0.2.1 h1:05xhhdRNAdS3apYm7JRjOqngf4xruaW959jmRxGDuSU= github.com/rboyer/safeio v0.2.1/go.mod h1:Cq/cEPK+YXFn622lsQ0K4KsPZSPtaptHHEldsy7Fmig= @@ -2088,8 +2085,8 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykE github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/snowflakedb/gosnowflake v1.11.0 h1:qyqunGCVyq/Qyx40KQT+6sJ1CAGuuG2qv3WiCTLTctI= -github.com/snowflakedb/gosnowflake v1.11.0/go.mod h1:WFe+8mpsapDaQjHX6BqJBKtfQCGlGD3lHKeDsKfpx2A= +github.com/snowflakedb/gosnowflake v1.10.0 h1:5hBGKa/jJEhciokzgJcz5xmLNlJ8oUm8vhfu5tg82tM= +github.com/snowflakedb/gosnowflake v1.10.0/go.mod h1:WC4eGUOH3K9w3pLsdwZsdawIwtWgse4kZPPqNG0Ky/k= github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d h1:bVQRCxQvfjNUeRqaY/uT0tFuvuFY0ulgnczuR684Xic= github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d/go.mod h1:Cw4GTlQccdRGSEf6KiMju767x0NEHE0YIVPJSaXjlsw= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -2115,8 +2112,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/std-uritemplate/std-uritemplate/go v0.0.57 h1:GHGjptrsmazP4IVDlUprssiEf9ESVkbjx15xQXXzvq4= -github.com/std-uritemplate/std-uritemplate/go v0.0.57/go.mod h1:rG/bqh/ThY4xE5de7Rap3vaDkYUT76B0GPJ0loYeTTc= +github.com/std-uritemplate/std-uritemplate/go v0.0.55 h1:muSH037g97K7U2f94G9LUuE8tZlJsoSSrPsO9V281WY= +github.com/std-uritemplate/std-uritemplate/go v0.0.55/go.mod h1:rG/bqh/ThY4xE5de7Rap3vaDkYUT76B0GPJ0loYeTTc= github.com/streadway/amqp v1.0.0 h1:kuuDrUJFZL1QYL9hUNuCxNObNzB0bV/ZG5jV3RWAQgo= github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -2164,8 +2161,6 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/vmware/govmomi v0.18.0 h1:f7QxSmP7meCtoAmiKZogvVbLInT+CZx6Px6K5rYsJZo= github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= -github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= @@ -2205,22 +2200,22 @@ github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= -go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= +go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/etcd/api/v3 v3.5.5/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8= -go.etcd.io/etcd/api/v3 v3.5.13 h1:8WXU2/NBge6AUF1K1gOexB6e07NgsN1hXK0rSTtgSp4= -go.etcd.io/etcd/api/v3 v3.5.13/go.mod h1:gBqlqkcMMZMVTMm4NDZloEVJzxQOQIls8splbqBDa0c= +go.etcd.io/etcd/api/v3 v3.5.7 h1:sbcmosSVesNrWOJ58ZQFitHMdncusIifYcrBfwrlJSY= +go.etcd.io/etcd/api/v3 v3.5.7/go.mod h1:9qew1gCdDDLu+VwmeG+iFpL+QlpHTo7iubavdVDgCAA= go.etcd.io/etcd/client/pkg/v3 v3.5.5/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ= -go.etcd.io/etcd/client/pkg/v3 v3.5.13 h1:RVZSAnWWWiI5IrYAXjQorajncORbS0zI48LQlE2kQWg= -go.etcd.io/etcd/client/pkg/v3 v3.5.13/go.mod h1:XxHT4u1qU12E2+po+UVPrEeL94Um6zL58ppuJWXSAB8= +go.etcd.io/etcd/client/pkg/v3 v3.5.7 h1:y3kf5Gbp4e4q7egZdn5T7W9TSHUvkClN6u+Rq9mEOmg= +go.etcd.io/etcd/client/pkg/v3 v3.5.7/go.mod h1:o0Abi1MK86iad3YrWhgUsbGx1pmTS+hrORWc2CamuhY= go.etcd.io/etcd/client/v2 v2.305.5 h1:DktRP60//JJpnPC0VBymAN/7V71GHMdjDCBt4ZPXDjI= go.etcd.io/etcd/client/v2 v2.305.5/go.mod h1:zQjKllfqfBVyVStbt4FaosoX2iYd8fV/GRy/PbowgP4= -go.etcd.io/etcd/client/v3 v3.5.13 h1:o0fHTNJLeO0MyVbc7I3fsCf6nrOqn5d+diSarKnB2js= -go.etcd.io/etcd/client/v3 v3.5.13/go.mod h1:cqiAeY8b5DEEcpxvgWKsbLIWNM/8Wy2xJSDMtioMcoI= -go.mongodb.org/atlas v0.37.0 h1:zQnO1o5+bVP9IotpAYpres4UjMD2F4nwNEFTZhNL4ck= -go.mongodb.org/atlas v0.37.0/go.mod h1:DJYtM+vsEpPEMSkQzJnFHrT0sP7ev6cseZc/GGjJYG8= -go.mongodb.org/mongo-driver v1.16.1 h1:rIVLL3q0IHM39dvE+z2ulZLp9ENZKThVfuvN/IiN4l8= -go.mongodb.org/mongo-driver v1.16.1/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw= +go.etcd.io/etcd/client/v3 v3.5.7 h1:u/OhpiuCgYY8awOHlhIhmGIGpxfBU/GZBUP3m/3/Iz4= +go.etcd.io/etcd/client/v3 v3.5.7/go.mod h1:sOWmj9DZUMyAngS7QQwCyAXXAL6WhgTOPLNS/NabQgw= +go.mongodb.org/atlas v0.36.0 h1:m05S3AO7zkl+bcG1qaNsEKBnAqnKx2FDwLooHpIG3j4= +go.mongodb.org/atlas v0.36.0/go.mod h1:nfPldE9dSama6G2IbIzmEza02Ly7yFZjMMVscaM0uEc= +go.mongodb.org/mongo-driver v1.16.0 h1:tpRsfBJMROVHKpdGyc1BBEzzjDUWjItxbVSZ8Ls4BQ4= +go.mongodb.org/mongo-driver v1.16.0/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -2230,27 +2225,27 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= -go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= -go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 h1:lsInsfvhVIfOI6qHVyysXMNDnjO9Npvl7tlDPJFBVd4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0/go.mod h1:KQsVNh4OjgjTG0G6EiNi1jVpnaeeKsKMRwbLN+f1+8M= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0 h1:JAv0Jwtl01UFiyWZEMiJZBiTlv5A50zNs8lsthXqIio= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0/go.mod h1:QNKLmUEAq2QUbPQUfvw4fmv0bgbK7UlOSFCnXyfvSNc= -go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w= -go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ= -go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE= -go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg= -go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc= -go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= -go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -2309,8 +2304,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -2326,8 +2321,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= -golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= -golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -2370,8 +2365,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2451,8 +2446,8 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190130055435-99b60b757ec1/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -2483,8 +2478,8 @@ golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= -golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= -golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -2622,8 +2617,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= 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= @@ -2637,8 +2632,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2658,16 +2653,16 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= -golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -2756,8 +2751,8 @@ golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 h1:LLhsEBxRTBLuKlQxFBYUOU8xyFgXv6cOTp2HASDlsDk= -golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= @@ -2826,8 +2821,8 @@ google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/ google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= -google.golang.org/api v0.197.0 h1:x6CwqQLsFiA5JKAiGyGBjc2bNtHtLddhJCE2IKuhhcQ= -google.golang.org/api v0.197.0/go.mod h1:AuOuo20GoQ331nq7DquGHlU6d+2wN2fZ8O0ta60nRNw= +google.golang.org/api v0.181.0 h1:rPdjwnWgiPPOJx3IcSAQ2III5aX5tCer6wMpa/xmZi4= +google.golang.org/api v0.181.0/go.mod h1:MnQ+M0CFsfUwA5beZ+g/vCBCPXvtmZwRz2qzZk8ih1k= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2969,12 +2964,12 @@ google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOl google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= -google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 h1:BulPr26Jqjnd4eYDVe+YvyR7Yc2vJGkO5/0UxD0/jZU= -google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:hL97c3SYopEHblzpxRL4lSs523++l8DYxGM1FQiYmb4= -google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc= -google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto v0.0.0-20240520151616-dc85e6b867a5 h1:IGsMFz879l+GhhDJ9fN5rWnkVrGnoZv8oeYfpk82QZQ= +google.golang.org/genproto v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:ch5ZrEj5+9MCxUeR3Gp3mCJ4u0eVpusYAmSr/mvpMSk= +google.golang.org/genproto/googleapis/api v0.0.0-20240730163845-b1a4ccb954bf h1:GillM0Ef0pkZPIB+5iO6SDK+4T9pf6TpaYR6ICD5rVE= +google.golang.org/genproto/googleapis/api v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:OFMYQFHJ4TM3JRlWDZhJbZfra2uqc3WLBZiaaqP4DtU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -3019,8 +3014,8 @@ google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5v google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/grpc v1.66.1 h1:hO5qAXR19+/Z44hmvIM4dQFMSYX9XcWsByfoxutBpAM= -google.golang.org/grpc v1.66.1/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -3053,6 +3048,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs= +gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -3096,26 +3093,26 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= -k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo= -k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE= +k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= +k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= -k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc= -k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= +k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= -k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8= -k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU= +k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= +k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= +k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= layeh.com/radius v0.0.0-20231213012653-1006025d24f8 h1:orYXpi6BJZdvgytfHH4ybOe4wHnLbbS71Cmd8mWdZjs= layeh.com/radius v0.0.0-20231213012653-1006025d24f8/go.mod h1:QRf+8aRqXc019kHkpcs/CTgyWXFzf+bxlsyuo2nAl1o= lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= @@ -3166,5 +3163,5 @@ sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+s sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/helper/benchhelpers/benchhelpers.go b/helper/benchhelpers/benchhelpers.go new file mode 100644 index 000000000000..afb0d4a88a49 --- /dev/null +++ b/helper/benchhelpers/benchhelpers.go @@ -0,0 +1,22 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package benchhelpers + +import ( + "testing" + + testinginterface "github.com/mitchellh/go-testing-interface" +) + +type tbWrapper struct { + testing.TB +} + +func (b tbWrapper) Parallel() { + // no-op +} + +func TBtoT(tb testing.TB) testinginterface.T { + return tbWrapper{tb} +} diff --git a/helper/builtinplugins/registry.go b/helper/builtinplugins/registry.go index e5a6044e5f3c..feaa7a100d38 100644 --- a/helper/builtinplugins/registry.go +++ b/helper/builtinplugins/registry.go @@ -6,14 +6,54 @@ package builtinplugins import ( "context" + credAliCloud "github.com/hashicorp/vault-plugin-auth-alicloud" + credAzure "github.com/hashicorp/vault-plugin-auth-azure" + credCF "github.com/hashicorp/vault-plugin-auth-cf" + credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin" credJWT "github.com/hashicorp/vault-plugin-auth-jwt" + credKerb "github.com/hashicorp/vault-plugin-auth-kerberos" + credKube "github.com/hashicorp/vault-plugin-auth-kubernetes" + credOCI "github.com/hashicorp/vault-plugin-auth-oci" + dbCouchbase "github.com/hashicorp/vault-plugin-database-couchbase" + dbElastic "github.com/hashicorp/vault-plugin-database-elasticsearch" + dbMongoAtlas "github.com/hashicorp/vault-plugin-database-mongodbatlas" + dbRedis "github.com/hashicorp/vault-plugin-database-redis" + dbRedisElastiCache "github.com/hashicorp/vault-plugin-database-redis-elasticache" + dbSnowflake "github.com/hashicorp/vault-plugin-database-snowflake" + logicalAd "github.com/hashicorp/vault-plugin-secrets-ad/plugin" + logicalAlicloud "github.com/hashicorp/vault-plugin-secrets-alicloud" + logicalAzure "github.com/hashicorp/vault-plugin-secrets-azure" + logicalGcp "github.com/hashicorp/vault-plugin-secrets-gcp/plugin" + logicalGcpKms "github.com/hashicorp/vault-plugin-secrets-gcpkms" + logicalKube "github.com/hashicorp/vault-plugin-secrets-kubernetes" logicalKv "github.com/hashicorp/vault-plugin-secrets-kv" + logicalMongoAtlas "github.com/hashicorp/vault-plugin-secrets-mongodbatlas" + logicalLDAP "github.com/hashicorp/vault-plugin-secrets-openldap" + logicalTerraform "github.com/hashicorp/vault-plugin-secrets-terraform" credAppRole "github.com/hashicorp/vault/builtin/credential/approle" + credAws "github.com/hashicorp/vault/builtin/credential/aws" credCert "github.com/hashicorp/vault/builtin/credential/cert" + credGitHub "github.com/hashicorp/vault/builtin/credential/github" + credLdap "github.com/hashicorp/vault/builtin/credential/ldap" + credOkta "github.com/hashicorp/vault/builtin/credential/okta" + credRadius "github.com/hashicorp/vault/builtin/credential/radius" credUserpass "github.com/hashicorp/vault/builtin/credential/userpass" + logicalAws "github.com/hashicorp/vault/builtin/logical/aws" + logicalConsul "github.com/hashicorp/vault/builtin/logical/consul" + logicalNomad "github.com/hashicorp/vault/builtin/logical/nomad" logicalPki "github.com/hashicorp/vault/builtin/logical/pki" + logicalRabbit "github.com/hashicorp/vault/builtin/logical/rabbitmq" logicalSsh "github.com/hashicorp/vault/builtin/logical/ssh" + logicalTotp "github.com/hashicorp/vault/builtin/logical/totp" logicalTransit "github.com/hashicorp/vault/builtin/logical/transit" + dbCass "github.com/hashicorp/vault/plugins/database/cassandra" + dbHana "github.com/hashicorp/vault/plugins/database/hana" + dbInflux "github.com/hashicorp/vault/plugins/database/influxdb" + dbMongo "github.com/hashicorp/vault/plugins/database/mongodb" + dbMssql "github.com/hashicorp/vault/plugins/database/mssql" + dbMysql "github.com/hashicorp/vault/plugins/database/mysql" + dbPostgres "github.com/hashicorp/vault/plugins/database/postgresql" + dbRedshift "github.com/hashicorp/vault/plugins/database/redshift" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/helper/consts" "github.com/hashicorp/vault/sdk/logical" @@ -53,29 +93,104 @@ func removedFactory(ctx context.Context, config *logical.BackendConfig) (logical return removedBackend, nil } -func newMinimalRegistry() *registry { - return ®istry{ +func newRegistry() *registry { + reg := ®istry{ credentialBackends: map[string]credentialBackend{ - "approle": {Factory: credAppRole.Factory}, - "cert": {Factory: credCert.Factory}, - "jwt": {Factory: credJWT.Factory}, - "oidc": {Factory: credJWT.Factory}, + "alicloud": {Factory: credAliCloud.Factory}, + "app-id": { + Factory: removedFactory, + DeprecationStatus: consts.Removed, + }, + "approle": {Factory: credAppRole.Factory}, + "aws": {Factory: credAws.Factory}, + "azure": {Factory: credAzure.Factory}, + "cert": {Factory: credCert.Factory}, + "cf": {Factory: credCF.Factory}, + "gcp": {Factory: credGcp.Factory}, + "github": {Factory: credGitHub.Factory}, + "jwt": {Factory: credJWT.Factory}, + "kerberos": {Factory: credKerb.Factory}, + "kubernetes": {Factory: credKube.Factory}, + "ldap": {Factory: credLdap.Factory}, + "oci": {Factory: credOCI.Factory}, + "oidc": {Factory: credJWT.Factory}, + "okta": {Factory: credOkta.Factory}, + "pcf": { + Factory: credCF.Factory, + DeprecationStatus: consts.Deprecated, + }, + "radius": {Factory: credRadius.Factory}, "userpass": {Factory: credUserpass.Factory}, }, - databasePlugins: map[string]databasePlugin{}, + databasePlugins: map[string]databasePlugin{ + // These four plugins all use the same mysql implementation but with + // different username settings passed by the constructor. + "mysql-database-plugin": {Factory: dbMysql.New(dbMysql.DefaultUserNameTemplate)}, + "mysql-aurora-database-plugin": {Factory: dbMysql.New(dbMysql.DefaultLegacyUserNameTemplate)}, + "mysql-rds-database-plugin": {Factory: dbMysql.New(dbMysql.DefaultLegacyUserNameTemplate)}, + "mysql-legacy-database-plugin": {Factory: dbMysql.New(dbMysql.DefaultLegacyUserNameTemplate)}, + + "cassandra-database-plugin": {Factory: dbCass.New}, + "couchbase-database-plugin": {Factory: dbCouchbase.New}, + "elasticsearch-database-plugin": {Factory: dbElastic.New}, + "hana-database-plugin": {Factory: dbHana.New}, + "influxdb-database-plugin": {Factory: dbInflux.New}, + "mongodb-database-plugin": {Factory: dbMongo.New}, + "mongodbatlas-database-plugin": {Factory: dbMongoAtlas.New}, + "mssql-database-plugin": {Factory: dbMssql.New}, + "postgresql-database-plugin": {Factory: dbPostgres.New}, + "redshift-database-plugin": {Factory: dbRedshift.New}, + "redis-database-plugin": {Factory: dbRedis.New}, + "redis-elasticache-database-plugin": {Factory: dbRedisElastiCache.New}, + "snowflake-database-plugin": {Factory: dbSnowflake.New}, + }, logicalBackends: map[string]logicalBackend{ - "kv": {Factory: logicalKv.Factory}, - "pki": {Factory: logicalPki.Factory}, - "ssh": {Factory: logicalSsh.Factory}, - "transit": {Factory: logicalTransit.Factory}, + "ad": { + Factory: logicalAd.Factory, + DeprecationStatus: consts.Deprecated, + }, + "alicloud": {Factory: logicalAlicloud.Factory}, + "aws": {Factory: logicalAws.Factory}, + "azure": {Factory: logicalAzure.Factory}, + "cassandra": { + Factory: removedFactory, + DeprecationStatus: consts.Removed, + }, + "consul": {Factory: logicalConsul.Factory}, + "gcp": {Factory: logicalGcp.Factory}, + "gcpkms": {Factory: logicalGcpKms.Factory}, + "kubernetes": {Factory: logicalKube.Factory}, + "kv": {Factory: logicalKv.Factory}, + "mongodb": { + Factory: removedFactory, + DeprecationStatus: consts.Removed, + }, + // The mongodbatlas secrets engine is not the same as the database plugin equivalent + // (`mongodbatlas-database-plugin`), and thus will not be deprecated at this time. + "mongodbatlas": {Factory: logicalMongoAtlas.Factory}, + "mssql": { + Factory: removedFactory, + DeprecationStatus: consts.Removed, + }, + "mysql": { + Factory: removedFactory, + DeprecationStatus: consts.Removed, + }, + "nomad": {Factory: logicalNomad.Factory}, + "openldap": {Factory: logicalLDAP.Factory}, + "ldap": {Factory: logicalLDAP.Factory}, + "pki": {Factory: logicalPki.Factory}, + "postgresql": { + Factory: removedFactory, + DeprecationStatus: consts.Removed, + }, + "rabbitmq": {Factory: logicalRabbit.Factory}, + "ssh": {Factory: logicalSsh.Factory}, + "terraform": {Factory: logicalTerraform.Factory}, + "totp": {Factory: logicalTotp.Factory}, + "transit": {Factory: logicalTransit.Factory}, }, } -} - -func newRegistry() *registry { - reg := newMinimalRegistry() - - extendAddonPlugins(reg) entAddExtPlugins(reg) diff --git a/helper/builtinplugins/registry_full.go b/helper/builtinplugins/registry_full.go deleted file mode 100644 index 32bba4048796..000000000000 --- a/helper/builtinplugins/registry_full.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !minimal - -package builtinplugins - -import ( - "maps" - - credAliCloud "github.com/hashicorp/vault-plugin-auth-alicloud" - credAzure "github.com/hashicorp/vault-plugin-auth-azure" - credCF "github.com/hashicorp/vault-plugin-auth-cf" - credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin" - credKerb "github.com/hashicorp/vault-plugin-auth-kerberos" - credKube "github.com/hashicorp/vault-plugin-auth-kubernetes" - credOCI "github.com/hashicorp/vault-plugin-auth-oci" - dbCouchbase "github.com/hashicorp/vault-plugin-database-couchbase" - dbElastic "github.com/hashicorp/vault-plugin-database-elasticsearch" - dbMongoAtlas "github.com/hashicorp/vault-plugin-database-mongodbatlas" - dbRedis "github.com/hashicorp/vault-plugin-database-redis" - dbRedisElastiCache "github.com/hashicorp/vault-plugin-database-redis-elasticache" - dbSnowflake "github.com/hashicorp/vault-plugin-database-snowflake" - logicalAd "github.com/hashicorp/vault-plugin-secrets-ad/plugin" - logicalAlicloud "github.com/hashicorp/vault-plugin-secrets-alicloud" - logicalAzure "github.com/hashicorp/vault-plugin-secrets-azure" - logicalGcp "github.com/hashicorp/vault-plugin-secrets-gcp/plugin" - logicalGcpKms "github.com/hashicorp/vault-plugin-secrets-gcpkms" - logicalKube "github.com/hashicorp/vault-plugin-secrets-kubernetes" - logicalMongoAtlas "github.com/hashicorp/vault-plugin-secrets-mongodbatlas" - logicalLDAP "github.com/hashicorp/vault-plugin-secrets-openldap" - logicalTerraform "github.com/hashicorp/vault-plugin-secrets-terraform" - credAws "github.com/hashicorp/vault/builtin/credential/aws" - credGitHub "github.com/hashicorp/vault/builtin/credential/github" - credLdap "github.com/hashicorp/vault/builtin/credential/ldap" - credOkta "github.com/hashicorp/vault/builtin/credential/okta" - credRadius "github.com/hashicorp/vault/builtin/credential/radius" - logicalAws "github.com/hashicorp/vault/builtin/logical/aws" - logicalConsul "github.com/hashicorp/vault/builtin/logical/consul" - logicalNomad "github.com/hashicorp/vault/builtin/logical/nomad" - logicalRabbit "github.com/hashicorp/vault/builtin/logical/rabbitmq" - logicalTotp "github.com/hashicorp/vault/builtin/logical/totp" - dbCass "github.com/hashicorp/vault/plugins/database/cassandra" - dbHana "github.com/hashicorp/vault/plugins/database/hana" - dbInflux "github.com/hashicorp/vault/plugins/database/influxdb" - dbMongo "github.com/hashicorp/vault/plugins/database/mongodb" - dbMssql "github.com/hashicorp/vault/plugins/database/mssql" - dbMysql "github.com/hashicorp/vault/plugins/database/mysql" - dbPostgres "github.com/hashicorp/vault/plugins/database/postgresql" - dbRedshift "github.com/hashicorp/vault/plugins/database/redshift" - "github.com/hashicorp/vault/sdk/helper/consts" -) - -func newFullAddonRegistry() *registry { - return ®istry{ - credentialBackends: map[string]credentialBackend{ - "alicloud": {Factory: credAliCloud.Factory}, - "app-id": { - Factory: removedFactory, - DeprecationStatus: consts.Removed, - }, - "aws": {Factory: credAws.Factory}, - "azure": {Factory: credAzure.Factory}, - "cf": {Factory: credCF.Factory}, - "gcp": {Factory: credGcp.Factory}, - "github": {Factory: credGitHub.Factory}, - "kerberos": {Factory: credKerb.Factory}, - "kubernetes": {Factory: credKube.Factory}, - "ldap": {Factory: credLdap.Factory}, - "oci": {Factory: credOCI.Factory}, - "okta": {Factory: credOkta.Factory}, - "pcf": { - Factory: credCF.Factory, - DeprecationStatus: consts.Deprecated, - }, - "radius": {Factory: credRadius.Factory}, - }, - databasePlugins: map[string]databasePlugin{ - // These four plugins all use the same mysql implementation but with - // different username settings passed by the constructor. - "mysql-database-plugin": {Factory: dbMysql.New(dbMysql.DefaultUserNameTemplate)}, - "mysql-aurora-database-plugin": {Factory: dbMysql.New(dbMysql.DefaultLegacyUserNameTemplate)}, - "mysql-rds-database-plugin": {Factory: dbMysql.New(dbMysql.DefaultLegacyUserNameTemplate)}, - "mysql-legacy-database-plugin": {Factory: dbMysql.New(dbMysql.DefaultLegacyUserNameTemplate)}, - - "cassandra-database-plugin": {Factory: dbCass.New}, - "couchbase-database-plugin": {Factory: dbCouchbase.New}, - "elasticsearch-database-plugin": {Factory: dbElastic.New}, - "hana-database-plugin": {Factory: dbHana.New}, - "influxdb-database-plugin": {Factory: dbInflux.New}, - "mongodb-database-plugin": {Factory: dbMongo.New}, - "mongodbatlas-database-plugin": {Factory: dbMongoAtlas.New}, - "mssql-database-plugin": {Factory: dbMssql.New}, - "postgresql-database-plugin": {Factory: dbPostgres.New}, - "redshift-database-plugin": {Factory: dbRedshift.New}, - "redis-database-plugin": {Factory: dbRedis.New}, - "redis-elasticache-database-plugin": {Factory: dbRedisElastiCache.New}, - "snowflake-database-plugin": {Factory: dbSnowflake.New}, - }, - logicalBackends: map[string]logicalBackend{ - "ad": { - Factory: logicalAd.Factory, - DeprecationStatus: consts.Deprecated, - }, - "alicloud": {Factory: logicalAlicloud.Factory}, - "aws": {Factory: logicalAws.Factory}, - "azure": {Factory: logicalAzure.Factory}, - "cassandra": { - Factory: removedFactory, - DeprecationStatus: consts.Removed, - }, - "consul": {Factory: logicalConsul.Factory}, - "gcp": {Factory: logicalGcp.Factory}, - "gcpkms": {Factory: logicalGcpKms.Factory}, - "kubernetes": {Factory: logicalKube.Factory}, - "mongodb": { - Factory: removedFactory, - DeprecationStatus: consts.Removed, - }, - "mongodbatlas": {Factory: logicalMongoAtlas.Factory}, - "mssql": { - Factory: removedFactory, - DeprecationStatus: consts.Removed, - }, - "mysql": { - Factory: removedFactory, - DeprecationStatus: consts.Removed, - }, - "nomad": {Factory: logicalNomad.Factory}, - "openldap": {Factory: logicalLDAP.Factory}, - "ldap": {Factory: logicalLDAP.Factory}, - "postgresql": { - Factory: removedFactory, - DeprecationStatus: consts.Removed, - }, - "rabbitmq": {Factory: logicalRabbit.Factory}, - "terraform": {Factory: logicalTerraform.Factory}, - "totp": {Factory: logicalTotp.Factory}, - }, - } -} - -func extendAddonPlugins(reg *registry) { - addonReg := newFullAddonRegistry() - - maps.Copy(reg.credentialBackends, addonReg.credentialBackends) - maps.Copy(reg.databasePlugins, addonReg.databasePlugins) - maps.Copy(reg.logicalBackends, addonReg.logicalBackends) -} diff --git a/helper/builtinplugins/registry_full_test.go b/helper/builtinplugins/registry_full_test.go deleted file mode 100644 index 23626daf525b..000000000000 --- a/helper/builtinplugins/registry_full_test.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !enterprise && !minimal - -package builtinplugins - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -// Test_newRegistry tests that newRegistry() returns a registry with -// the expected minimal registry extended with full addon registry -func Test_newRegistry(t *testing.T) { - actual := newRegistry() - expMinimal := newMinimalRegistry() - expFullAddon := newFullAddonRegistry() - - require.Equal(t, len(expMinimal.credentialBackends)+len(expFullAddon.credentialBackends), len(actual.credentialBackends), - "newRegistry() total auth backends mismatch total of minimal and full addon registries") - require.Equal(t, len(expMinimal.databasePlugins)+len(expFullAddon.databasePlugins), len(actual.databasePlugins), - "newRegistry() total database plugins mismatch total of minimal and full addon registries") - require.Equal(t, len(expMinimal.logicalBackends)+len(expFullAddon.logicalBackends), len(actual.logicalBackends), - "newRegistry() total logical backends mismatch total of minimal and full addon registries") - - assertRegistrySubset(t, actual, expMinimal, "common") - assertRegistrySubset(t, actual, expFullAddon, "full addon") -} diff --git a/helper/builtinplugins/registry_min.go b/helper/builtinplugins/registry_min.go deleted file mode 100644 index 75b281f631b7..000000000000 --- a/helper/builtinplugins/registry_min.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build minimal - -package builtinplugins - -func extendAddonPlugins(_ *registry) { - // No-op -} diff --git a/helper/builtinplugins/registry_testing_util.go b/helper/builtinplugins/registry_testing_util.go deleted file mode 100644 index 78d0f938670b..000000000000 --- a/helper/builtinplugins/registry_testing_util.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package builtinplugins - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" -) - -func assertRegistrySubset(t *testing.T, r, subset *registry, subsetName string) { - t.Helper() - - for k := range subset.credentialBackends { - require.Contains(t, r.credentialBackends, k, fmt.Sprintf("expected to contain %s auth backend", subsetName)) - } - - for k := range subset.databasePlugins { - require.Contains(t, r.databasePlugins, k, fmt.Sprintf("expected to contain %s database plugin", subsetName)) - } - - for k := range subset.logicalBackends { - require.Contains(t, r.logicalBackends, k, fmt.Sprintf("expected to contain %s logical backend", subsetName)) - } -} diff --git a/helper/locking/core_locking.go b/helper/locking/core_locking.go deleted file mode 100644 index 7370fd907c91..000000000000 --- a/helper/locking/core_locking.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package locking - -import ( - "slices" - "strings" -) - -// ParseDetectDeadlockConfigParameter takes the detectDeadlockConfigParameter string -// and transforms it to a lowercase version of the string, then splits it into -// a slice of strings by interpreting commas as the element delimiters. -func ParseDetectDeadlockConfigParameter(detectDeadlockConfigParameter string) []string { - if detectDeadlockConfigParameter == "" { - // This doesn't seem necessary, since the companion functions that use - // this slice can handle an empty slice just the same as a nil slice, - // but for the sake of compatibility, this will be introduced for now - // until all occurrences that rely on Core.detectDeadlocks have been - // switched to using functions from this file to create their locks. - return nil - } - - result := strings.Split(strings.ToLower(detectDeadlockConfigParameter), ",") - for i := range result { - result[i] = strings.TrimSpace(result[i]) - } - - return result -} - -// CreateConfigurableRWMutex determines if the specified lock (identifier) should -// use a deadlock detecting implementation (DeadlockRWMutex) or simply a basic -// sync.RWMutex instance. This is done by splitting the deadlockDetectionLocks -// string into a slice of strings. If the slice contains the specified lock -// (identifier), then the deadlock detecting implementation is used, otherwise a -// sync.Mutex is returned. -func CreateConfigurableRWMutex(deadlockDetectionLocks []string, identifier string) RWMutex { - if slices.Contains(deadlockDetectionLocks, strings.ToLower(identifier)) { - return &DeadlockRWMutex{} - } - - return &SyncRWMutex{} -} diff --git a/helper/locking/core_locking_test.go b/helper/locking/core_locking_test.go deleted file mode 100644 index 55017812d3d6..000000000000 --- a/helper/locking/core_locking_test.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package locking - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -// TestParseDetectDeadlockConfigParameter verifies that all types of strings -// that could be obtained from the configuration file, are correctly parsed -// into a slice of string elements. -func TestParseDetectDeadlockConfigParameter(t *testing.T) { - for _, tc := range []struct { - name string - detectDeadlockConfigParameter string - expectedResult []string - }{ - { - name: "empty-string", - }, - { - name: "single-value", - detectDeadlockConfigParameter: "bar", - expectedResult: []string{"bar"}, - }, - { - name: "single-value-mixed-case", - detectDeadlockConfigParameter: "BaR", - expectedResult: []string{"bar"}, - }, - { - name: "multiple-values", - detectDeadlockConfigParameter: "bar,BAZ,fIZ", - expectedResult: []string{"bar", "baz", "fiz"}, - }, - { - name: "non-canonical-string-list", - detectDeadlockConfigParameter: "bar , baz, ", - expectedResult: []string{"bar", "baz", ""}, - }, - } { - t.Run(tc.name, func(t *testing.T) { - result := ParseDetectDeadlockConfigParameter(tc.detectDeadlockConfigParameter) - assert.ElementsMatch(t, tc.expectedResult, result) - }) - } -} - -// TestCreateConfigurableRWMutex verifies the correct behaviour in determining -// whether a deadlock detecting RWMutex should be returned or not based on the -// input arguments for the CreateConfigurableRWMutex function. -func TestCreateConfigurableRWMutex(t *testing.T) { - mutexTypes := map[bool]string{ - false: "locking.SyncRWMutex", - true: "locking.DeadlockRWMutex", - } - - for _, tc := range []struct { - name string - detectDeadlocks []string - lock string - expectDeadlockLock bool - }{ - { - name: "no-lock-types-specified", - lock: "foo", - }, - { - name: "single-lock-specified-no-match", - detectDeadlocks: []string{"bar"}, - lock: "foo", - }, - { - name: "single-lock-specified-match", - detectDeadlocks: []string{"foo"}, - lock: "foo", - expectDeadlockLock: true, - }, - { - name: "multiple-locks-specified-no-match", - detectDeadlocks: []string{"bar", "baz", "fiz"}, - lock: "foo", - }, - { - name: "multiple-locks-specified-match", - detectDeadlocks: []string{"bar", "foo", "baz"}, - lock: "foo", - expectDeadlockLock: true, - }, - } { - t.Run(tc.name, func(t *testing.T) { - m := CreateConfigurableRWMutex(tc.detectDeadlocks, tc.lock) - - _, ok := m.(*DeadlockRWMutex) - if tc.expectDeadlockLock != ok { - t.Fatalf("unexpected RWMutex type returned, expected: %s got %s", mutexTypes[tc.expectDeadlockLock], mutexTypes[ok]) - } - }) - } -} diff --git a/helper/testhelpers/corehelpers/corehelpers.go b/helper/testhelpers/corehelpers/corehelpers.go index 1c7da787d7b6..abd5cb8cba68 100644 --- a/helper/testhelpers/corehelpers/corehelpers.go +++ b/helper/testhelpers/corehelpers/corehelpers.go @@ -11,7 +11,6 @@ import ( "os" "path/filepath" "strings" - "testing" "time" "github.com/hashicorp/go-hclog" @@ -20,13 +19,14 @@ import ( "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/helper/consts" "github.com/hashicorp/vault/sdk/logical" + "github.com/mitchellh/go-testing-interface" ) var externalPlugins = []string{"transform", "kmip", "keymgmt"} // RetryUntil runs f until it returns a nil result or the timeout is reached. // If a nil result hasn't been obtained by timeout, calls t.Fatal. -func RetryUntil(t testing.TB, timeout time.Duration, f func() error) { +func RetryUntil(t testing.T, timeout time.Duration, f func() error) { t.Helper() deadline := time.Now().Add(timeout) var err error @@ -41,7 +41,7 @@ func RetryUntil(t testing.TB, timeout time.Duration, f func() error) { // MakeTestPluginDir creates a temporary directory suitable for holding plugins. // This helper also resolves symlinks to make tests happy on OS X. -func MakeTestPluginDir(t testing.TB) string { +func MakeTestPluginDir(t testing.T) string { t.Helper() dir, err := os.MkdirTemp("", "") @@ -210,11 +210,11 @@ type TestLogger struct { sink hclog.SinkAdapter } -func NewTestLogger(t testing.TB) *TestLogger { +func NewTestLogger(t testing.T) *TestLogger { return NewTestLoggerWithSuffix(t, "") } -func NewTestLoggerWithSuffix(t testing.TB, logFileSuffix string) *TestLogger { +func NewTestLoggerWithSuffix(t testing.T, logFileSuffix string) *TestLogger { var logFile *os.File var logPath string output := os.Stderr diff --git a/helper/testhelpers/minimal/minimal.go b/helper/testhelpers/minimal/minimal.go index 5af4d6d6031c..caf440d26fbb 100644 --- a/helper/testhelpers/minimal/minimal.go +++ b/helper/testhelpers/minimal/minimal.go @@ -4,8 +4,6 @@ package minimal import ( - "testing" - logicalKv "github.com/hashicorp/vault-plugin-secrets-kv" "github.com/hashicorp/vault/audit" logicalDb "github.com/hashicorp/vault/builtin/logical/database" @@ -17,6 +15,7 @@ import ( "github.com/hashicorp/vault/sdk/physical/inmem" "github.com/hashicorp/vault/vault" "github.com/mitchellh/copystructure" + "github.com/mitchellh/go-testing-interface" ) // NewTestSoloCluster is a simpler version of NewTestCluster that only creates @@ -24,7 +23,7 @@ import ( // from vault.TestClusterOptions, use NewTestCluster instead. It should work fine // with a nil config argument. There is no need to call Start or Cleanup or // TestWaitActive on the resulting cluster. -func NewTestSoloCluster(t testing.TB, config *vault.CoreConfig) *vault.TestCluster { +func NewTestSoloCluster(t testing.T, config *vault.CoreConfig) *vault.TestCluster { logger := corehelpers.NewTestLogger(t) mycfg := &vault.CoreConfig{} diff --git a/helper/testhelpers/pluginhelpers/pluginhelpers.go b/helper/testhelpers/pluginhelpers/pluginhelpers.go index 2d9c2355399d..40035fc59f38 100644 --- a/helper/testhelpers/pluginhelpers/pluginhelpers.go +++ b/helper/testhelpers/pluginhelpers/pluginhelpers.go @@ -14,9 +14,9 @@ import ( "path/filepath" "strings" "sync" - "testing" "github.com/hashicorp/vault/sdk/helper/consts" + "github.com/mitchellh/go-testing-interface" ) var ( @@ -34,7 +34,7 @@ type TestPlugin struct { ImageSha256 string } -func GetPlugin(t testing.TB, typ consts.PluginType) (string, string, string, string) { +func GetPlugin(t testing.T, typ consts.PluginType) (string, string, string, string) { t.Helper() var pluginName string var pluginType string @@ -65,7 +65,7 @@ func GetPlugin(t testing.TB, typ consts.PluginType) (string, string, string, str // to mount a plugin, we need a working binary plugin, so we compile one here. // pluginVersion is used to override the plugin's self-reported version -func CompilePlugin(t testing.TB, typ consts.PluginType, pluginVersion string, pluginDir string) TestPlugin { +func CompilePlugin(t testing.T, typ consts.PluginType, pluginVersion string, pluginDir string) TestPlugin { t.Helper() pluginName, pluginType, pluginMain, pluginVersionLocation := GetPlugin(t, typ) @@ -76,17 +76,15 @@ func CompilePlugin(t testing.TB, typ consts.PluginType, pluginVersion string, pl var pluginBytes []byte dir := "" + var err error pluginRootDir := "builtin" if typ == consts.PluginTypeDatabase { pluginRootDir = "plugins" } for { - // So that we can assign to dir without overshadowing the other - // err variables. - var getWdErr error - dir, getWdErr = os.Getwd() - if getWdErr != nil { - t.Fatal(getWdErr) + dir, err = os.Getwd() + if err != nil { + t.Fatal(err) } // detect if we are in a subdirectory or the root directory and compensate if _, err := os.Stat(pluginRootDir); os.IsNotExist(err) { @@ -130,20 +128,15 @@ func CompilePlugin(t testing.TB, typ consts.PluginType, pluginVersion string, pl } // write the cached plugin if necessary - _, statErr := os.Stat(pluginPath) - if os.IsNotExist(statErr) { - err := os.WriteFile(pluginPath, pluginBytes, 0o755) - if err != nil { - t.Fatal(err) - } - } else { - if statErr != nil { - t.Fatal(statErr) - } + if _, err := os.Stat(pluginPath); os.IsNotExist(err) { + err = os.WriteFile(pluginPath, pluginBytes, 0o755) + } + if err != nil { + t.Fatal(err) } sha := sha256.New() - _, err := sha.Write(pluginBytes) + _, err = sha.Write(pluginBytes) if err != nil { t.Fatal(err) } @@ -156,7 +149,7 @@ func CompilePlugin(t testing.TB, typ consts.PluginType, pluginVersion string, pl } } -func BuildPluginContainerImage(t testing.TB, plugin TestPlugin, pluginDir string) (image string, sha256 string) { +func BuildPluginContainerImage(t testing.T, plugin TestPlugin, pluginDir string) (image string, sha256 string) { t.Helper() ref := plugin.Name if plugin.Version != "" { diff --git a/helper/testhelpers/postgresql/postgresqlhelper.go b/helper/testhelpers/postgresql/postgresqlhelper.go index c6ced3190b25..7e5f25c626af 100644 --- a/helper/testhelpers/postgresql/postgresqlhelper.go +++ b/helper/testhelpers/postgresql/postgresqlhelper.go @@ -9,53 +9,18 @@ import ( "fmt" "net/url" "os" - "strconv" "testing" - "time" - "github.com/hashicorp/vault/helper/testhelpers/certhelpers" "github.com/hashicorp/vault/sdk/helper/docker" - "github.com/hashicorp/vault/sdk/helper/pluginutil" ) -const ( - defaultPGImage = "docker.mirror.hashicorp.services/postgres" - defaultPGVersion = "13.4-buster" - defaultPGPass = "secret" -) - -func defaultRunOpts(t *testing.T) docker.RunOptions { - return docker.RunOptions{ - ContainerName: "postgres", - ImageRepo: defaultPGImage, - ImageTag: defaultPGVersion, - Env: []string{ - "POSTGRES_PASSWORD=" + defaultPGPass, - "POSTGRES_DB=database", - }, - Ports: []string{"5432/tcp"}, - DoNotAutoRemove: false, - OmitLogTimestamps: true, - LogConsumer: func(s string) { - if t.Failed() { - t.Logf("container logs: %s", s) - } - }, +func PrepareTestContainer(t *testing.T, version string) (func(), string) { + env := []string{ + "POSTGRES_PASSWORD=secret", + "POSTGRES_DB=database", } -} - -func PrepareTestContainer(t *testing.T) (func(), string) { - _, cleanup, url, _ := prepareTestContainer(t, defaultRunOpts(t), defaultPGPass, true, false, false) - - return cleanup, url -} - -func PrepareTestContainerSelfManaged(t *testing.T) (func(), *url.URL) { - return prepareTestContainerSelfManaged(t, defaultRunOpts(t), defaultPGPass, true, false, false) -} -func PrepareTestContainerMultiHost(t *testing.T) (func(), string) { - _, cleanup, url, _ := prepareTestContainer(t, defaultRunOpts(t), defaultPGPass, true, false, true) + _, cleanup, url, _ := prepareTestContainer(t, "postgres", "docker.mirror.hashicorp.services/postgres", version, "secret", true, false, false, env) return cleanup, url } @@ -63,149 +28,65 @@ func PrepareTestContainerMultiHost(t *testing.T) (func(), string) { // PrepareTestContainerWithVaultUser will setup a test container with a Vault // admin user configured so that we can safely call rotate-root without // rotating the root DB credentials -func PrepareTestContainerWithVaultUser(t *testing.T, ctx context.Context) (func(), string) { - runner, cleanup, url, id := prepareTestContainer(t, defaultRunOpts(t), defaultPGPass, true, false, false) - - cmd := []string{"psql", "-U", "postgres", "-c", "CREATE USER vaultadmin WITH LOGIN PASSWORD 'vaultpass' SUPERUSER"} - mustRunCommand(t, ctx, runner, id, cmd) - - return cleanup, url -} - -// PrepareTestContainerWithSSL will setup a test container with SSL enabled so -// that we can test client certificate authentication. -func PrepareTestContainerWithSSL( - t *testing.T, - sslMode string, - caCert certhelpers.Certificate, - clientCert certhelpers.Certificate, - useFallback bool, -) (func(), string) { - runOpts := defaultRunOpts(t) - runner, err := docker.NewServiceRunner(runOpts) - if err != nil { - t.Fatalf("Could not provision docker service runner: %s", err) - } - - // first we connect with username/password because ssl is not enabled yet - svc, id, err := runner.StartNewService(context.Background(), true, false, connectPostgres(defaultPGPass, runOpts.ImageRepo, false)) - if err != nil { - t.Fatalf("Could not start docker Postgres: %s", err) - } - - // Create certificates for postgres authentication - serverCert := certhelpers.NewCert(t, - certhelpers.CommonName("server"), - certhelpers.DNS("localhost"), - certhelpers.Parent(caCert), - ) - - bCtx := docker.NewBuildContext() - bCtx["ca.crt"] = docker.PathContentsFromBytes(caCert.CombinedPEM()) - bCtx["server.crt"] = docker.PathContentsFromBytes(serverCert.CombinedPEM()) - bCtx["server.key"] = &docker.FileContents{ - Data: serverCert.PrivateKeyPEM(), - Mode: 0o600, - // postgres uid - UID: 999, +func PrepareTestContainerWithVaultUser(t *testing.T, ctx context.Context, version string) (func(), string) { + env := []string{ + "POSTGRES_PASSWORD=secret", + "POSTGRES_DB=database", } - // https://www.postgresql.org/docs/current/auth-pg-hba-conf.html - clientAuthConfig := "echo 'hostssl all all all cert clientcert=verify-ca' > /var/lib/postgresql/data/pg_hba.conf" - bCtx["ssl-conf.sh"] = docker.PathContentsFromString(clientAuthConfig) - pgConfig := ` -cat << EOF > /var/lib/postgresql/data/postgresql.conf -# PostgreSQL configuration file -listen_addresses = '*' -max_connections = 100 -shared_buffers = 128MB -dynamic_shared_memory_type = posix -max_wal_size = 1GB -min_wal_size = 80MB -ssl = on -ssl_ca_file = '/var/lib/postgresql/ca.crt' -ssl_cert_file = '/var/lib/postgresql/server.crt' -ssl_key_file= '/var/lib/postgresql/server.key' -EOF -` - bCtx["pg-conf.sh"] = docker.PathContentsFromString(pgConfig) + runner, cleanup, url, id := prepareTestContainer(t, "postgres", "docker.mirror.hashicorp.services/postgres", version, "secret", true, false, false, env) - err = runner.CopyTo(id, "/var/lib/postgresql/", bCtx) + cmd := []string{"psql", "-U", "postgres", "-c", "CREATE USER vaultadmin WITH LOGIN PASSWORD 'vaultpass' SUPERUSER"} + _, err := runner.RunCmdInBackground(ctx, id, cmd) if err != nil { - t.Fatalf("failed to copy to container: %v", err) - } - - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - - // overwrite the postgresql.conf config file with our ssl settings - mustRunCommand(t, ctx, runner, id, - []string{"bash", "/var/lib/postgresql/pg-conf.sh"}) - - // overwrite the pg_hba.conf file and set it to require SSL for each connection - mustRunCommand(t, ctx, runner, id, - []string{"bash", "/var/lib/postgresql/ssl-conf.sh"}) - - // reload so the config changes take effect and ssl is enabled - mustRunCommand(t, ctx, runner, id, - []string{"psql", "-U", "postgres", "-c", "SELECT pg_reload_conf()"}) - - if sslMode == "disable" { - // return non-tls connection url - return svc.Cleanup, svc.Config.URL().String() + t.Fatalf("Could not run command (%v) in container: %v", cmd, err) } - sslConfig := getPostgresSSLConfig( - t, - svc.Config.URL().Host, - sslMode, - string(caCert.CombinedPEM()), - string(clientCert.CombinedPEM()), - string(clientCert.PrivateKeyPEM()), - useFallback, - ) - if err != nil { - svc.Cleanup() - t.Fatalf("failed to connect to postgres container via SSL: %v", err) - } - return svc.Cleanup, sslConfig.URL().String() + return cleanup, url } -func PrepareTestContainerWithPassword(t *testing.T, password string) (func(), string) { - runOpts := defaultRunOpts(t) - runOpts.Env = []string{ +func PrepareTestContainerWithPassword(t *testing.T, version, password string) (func(), string) { + env := []string{ "POSTGRES_PASSWORD=" + password, "POSTGRES_DB=database", } - _, cleanup, url, _ := prepareTestContainer(t, runOpts, password, true, false, false) + _, cleanup, url, _ := prepareTestContainer(t, "postgres", "docker.mirror.hashicorp.services/postgres", version, password, true, false, false, env) return cleanup, url } -func prepareTestContainer(t *testing.T, runOpts docker.RunOptions, password string, addSuffix, forceLocalAddr, useFallback bool, +func PrepareTestContainerRepmgr(t *testing.T, name, version string, envVars []string) (*docker.Runner, func(), string, string) { + env := append(envVars, + "REPMGR_PARTNER_NODES=psql-repl-node-0,psql-repl-node-1", + "REPMGR_PRIMARY_HOST=psql-repl-node-0", + "REPMGR_PASSWORD=repmgrpass", + "POSTGRESQL_PASSWORD=secret") + + return prepareTestContainer(t, name, "docker.mirror.hashicorp.services/bitnami/postgresql-repmgr", version, "secret", false, true, true, env) +} + +func prepareTestContainer(t *testing.T, name, repo, version, password string, + addSuffix, forceLocalAddr, doNotAutoRemove bool, envVars []string, ) (*docker.Runner, func(), string, string) { if os.Getenv("PG_URL") != "" { return nil, func() {}, "", os.Getenv("PG_URL") } - runner, err := docker.NewServiceRunner(runOpts) - if err != nil { - t.Fatalf("Could not start docker Postgres: %s", err) + if version == "" { + version = "11" } - svc, containerID, err := runner.StartNewService(context.Background(), addSuffix, forceLocalAddr, connectPostgres(password, runOpts.ImageRepo, useFallback)) - if err != nil { - t.Fatalf("Could not start docker Postgres: %s", err) + runOpts := docker.RunOptions{ + ContainerName: name, + ImageRepo: repo, + ImageTag: version, + Env: envVars, + Ports: []string{"5432/tcp"}, + DoNotAutoRemove: doNotAutoRemove, } - - return runner, svc.Cleanup, svc.Config.URL().String(), containerID -} - -func prepareTestContainerSelfManaged(t *testing.T, runOpts docker.RunOptions, password string, addSuffix, forceLocalAddr, useFallback bool, -) (func(), *url.URL) { - if os.Getenv("PG_URL") != "" { - return func() {}, nil + if repo == "bitnami/postgresql-repmgr" { + runOpts.NetworkID = os.Getenv("POSTGRES_MULTIHOST_NET") } runner, err := docker.NewServiceRunner(runOpts) @@ -213,61 +94,20 @@ func prepareTestContainerSelfManaged(t *testing.T, runOpts docker.RunOptions, pa t.Fatalf("Could not start docker Postgres: %s", err) } - svc, _, err := runner.StartNewService(context.Background(), addSuffix, forceLocalAddr, connectPostgres(password, runOpts.ImageRepo, useFallback)) + svc, containerID, err := runner.StartNewService(context.Background(), addSuffix, forceLocalAddr, connectPostgres(password, repo)) if err != nil { t.Fatalf("Could not start docker Postgres: %s", err) } - return svc.Cleanup, svc.Config.URL() -} - -func getPostgresSSLConfig(t *testing.T, host, sslMode, caCert, clientCert, clientKey string, useFallback bool) docker.ServiceConfig { - if useFallback { - // set the first host to a bad address so we can test the fallback logic - host = "localhost:55," + host - } - - u := url.URL{} - - if ok, _ := strconv.ParseBool(os.Getenv(pluginutil.PluginUsePostgresSSLInline)); ok { - // TODO: remove this when we remove the underlying feature in a future SDK version - u = url.URL{ - Scheme: "postgres", - User: url.User("postgres"), - Host: host, - Path: "postgres", - RawQuery: url.Values{ - "sslmode": {sslMode}, - "sslinline": {"true"}, - "sslrootcert": {caCert}, - "sslcert": {clientCert}, - "sslkey": {clientKey}, - }.Encode(), - } - } else { - u = url.URL{ - Scheme: "postgres", - User: url.User("postgres"), - Host: host, - Path: "postgres", - RawQuery: url.Values{"sslmode": {sslMode}}.Encode(), - } - } - - return docker.NewServiceURL(u) + return runner, svc.Cleanup, svc.Config.URL().String(), containerID } -func connectPostgres(password, repo string, useFallback bool) docker.ServiceAdapter { +func connectPostgres(password, repo string) docker.ServiceAdapter { return func(ctx context.Context, host string, port int) (docker.ServiceConfig, error) { - hostAddr := fmt.Sprintf("%s:%d", host, port) - if useFallback { - // set the first host to a bad address so we can test the fallback logic - hostAddr = "localhost:55," + hostAddr - } u := url.URL{ Scheme: "postgres", User: url.UserPassword("postgres", password), - Host: hostAddr, + Host: fmt.Sprintf("%s:%d", host, port), Path: "postgres", RawQuery: "sslmode=disable", } @@ -296,14 +136,3 @@ func RestartContainer(t *testing.T, ctx context.Context, runner *docker.Runner, t.Fatalf("Could not restart docker Postgres: %s", err) } } - -func mustRunCommand(t *testing.T, ctx context.Context, runner *docker.Runner, containerID string, cmd []string) { - t.Helper() - _, stderr, retcode, err := runner.RunCmdWithOutput(ctx, containerID, cmd) - if err != nil { - t.Fatalf("Could not run command (%v) in container: %v", cmd, err) - } - if retcode != 0 || len(stderr) != 0 { - t.Fatalf("exit code: %v, stderr: %v", retcode, string(stderr)) - } -} diff --git a/helper/testhelpers/seal/sealhelper.go b/helper/testhelpers/seal/sealhelper.go index 474367faa4ec..580f42e9e081 100644 --- a/helper/testhelpers/seal/sealhelper.go +++ b/helper/testhelpers/seal/sealhelper.go @@ -6,7 +6,6 @@ package sealhelper import ( "path" "strconv" - "testing" "github.com/hashicorp/vault/api" "github.com/hashicorp/vault/builtin/logical/transit" @@ -17,13 +16,14 @@ import ( "github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/vault" "github.com/hashicorp/vault/vault/seal" + "github.com/mitchellh/go-testing-interface" ) type TransitSealServer struct { *vault.TestCluster } -func NewTransitSealServer(t testing.TB, idx int) *TransitSealServer { +func NewTransitSealServer(t testing.T, idx int) *TransitSealServer { conf := &vault.CoreConfig{ LogicalBackends: map[string]logical.Factory{ "transit": transit.Factory, @@ -47,7 +47,7 @@ func NewTransitSealServer(t testing.TB, idx int) *TransitSealServer { return &TransitSealServer{cluster} } -func (tss *TransitSealServer) MakeKey(t testing.TB, key string) { +func (tss *TransitSealServer) MakeKey(t testing.T, key string) { client := tss.Cores[0].Client if _, err := client.Logical().Write(path.Join("transit", "keys", key), nil); err != nil { t.Fatal(err) @@ -59,7 +59,7 @@ func (tss *TransitSealServer) MakeKey(t testing.TB, key string) { } } -func (tss *TransitSealServer) MakeSeal(t testing.TB, key string) (vault.Seal, error) { +func (tss *TransitSealServer) MakeSeal(t testing.T, key string) (vault.Seal, error) { client := tss.Cores[0].Client wrapperConfig := map[string]string{ "address": client.Address(), diff --git a/helper/testhelpers/testhelpers.go b/helper/testhelpers/testhelpers.go index e7f8ed30a068..b087e1fcaca0 100644 --- a/helper/testhelpers/testhelpers.go +++ b/helper/testhelpers/testhelpers.go @@ -9,11 +9,10 @@ import ( "encoding/json" "errors" "fmt" - "io" + "io/ioutil" "math/rand" "os" "strings" - "testing" "time" "github.com/armon/go-metrics" @@ -24,6 +23,7 @@ import ( "github.com/hashicorp/vault/physical/raft" "github.com/hashicorp/vault/sdk/helper/xor" "github.com/hashicorp/vault/vault" + "github.com/mitchellh/go-testing-interface" ) //go:generate enumer -type=GenerateRootKind -trimprefix=GenerateRoot @@ -36,7 +36,7 @@ const ( ) // GenerateRoot generates a root token on the target cluster. -func GenerateRoot(t testing.TB, cluster *vault.TestCluster, kind GenerateRootKind) string { +func GenerateRoot(t testing.T, cluster *vault.TestCluster, kind GenerateRootKind) string { t.Helper() token, err := GenerateRootWithError(t, cluster, kind) if err != nil { @@ -45,7 +45,7 @@ func GenerateRoot(t testing.TB, cluster *vault.TestCluster, kind GenerateRootKin return token } -func GenerateRootWithError(t testing.TB, cluster *vault.TestCluster, kind GenerateRootKind) (string, error) { +func GenerateRootWithError(t testing.T, cluster *vault.TestCluster, kind GenerateRootKind) (string, error) { t.Helper() // If recovery keys supported, use those to perform root token generation instead var keys [][]byte @@ -118,14 +118,14 @@ func RandomWithPrefix(name string) string { return fmt.Sprintf("%s-%d", name, rand.New(rand.NewSource(time.Now().UnixNano())).Int()) } -func EnsureCoresSealed(t testing.TB, c *vault.TestCluster) { +func EnsureCoresSealed(t testing.T, c *vault.TestCluster) { t.Helper() for _, core := range c.Cores { EnsureCoreSealed(t, core) } } -func EnsureCoreSealed(t testing.TB, core *vault.TestClusterCore) { +func EnsureCoreSealed(t testing.T, core *vault.TestClusterCore) { t.Helper() core.Seal(t) timeout := time.Now().Add(60 * time.Second) @@ -140,7 +140,7 @@ func EnsureCoreSealed(t testing.TB, core *vault.TestClusterCore) { } } -func EnsureCoresUnsealed(t testing.TB, c *vault.TestCluster) { +func EnsureCoresUnsealed(t testing.T, c *vault.TestCluster) { t.Helper() for i, core := range c.Cores { err := AttemptUnsealCore(c, core) @@ -150,7 +150,7 @@ func EnsureCoresUnsealed(t testing.TB, c *vault.TestCluster) { } } -func EnsureCoreUnsealed(t testing.TB, c *vault.TestCluster, core *vault.TestClusterCore) { +func EnsureCoreUnsealed(t testing.T, c *vault.TestCluster, core *vault.TestClusterCore) { t.Helper() err := AttemptUnsealCore(c, core) if err != nil { @@ -208,17 +208,17 @@ func AttemptUnsealCore(c *vault.TestCluster, core *vault.TestClusterCore) error return nil } -func EnsureStableActiveNode(t testing.TB, cluster *vault.TestCluster) { +func EnsureStableActiveNode(t testing.T, cluster *vault.TestCluster) { t.Helper() deriveStableActiveCore(t, cluster) } -func DeriveStableActiveCore(t testing.TB, cluster *vault.TestCluster) *vault.TestClusterCore { +func DeriveStableActiveCore(t testing.T, cluster *vault.TestCluster) *vault.TestClusterCore { t.Helper() return deriveStableActiveCore(t, cluster) } -func deriveStableActiveCore(t testing.TB, cluster *vault.TestCluster) *vault.TestClusterCore { +func deriveStableActiveCore(t testing.T, cluster *vault.TestCluster) *vault.TestClusterCore { t.Helper() activeCore := DeriveActiveCore(t, cluster) minDuration := time.NewTimer(3 * time.Second) @@ -247,7 +247,7 @@ func deriveStableActiveCore(t testing.TB, cluster *vault.TestCluster) *vault.Tes return activeCore } -func DeriveActiveCore(t testing.TB, cluster *vault.TestCluster) *vault.TestClusterCore { +func DeriveActiveCore(t testing.T, cluster *vault.TestCluster) *vault.TestClusterCore { t.Helper() for i := 0; i < 60; i++ { for _, core := range cluster.Cores { @@ -268,7 +268,7 @@ func DeriveActiveCore(t testing.TB, cluster *vault.TestCluster) *vault.TestClust return nil } -func DeriveStandbyCores(t testing.TB, cluster *vault.TestCluster) []*vault.TestClusterCore { +func DeriveStandbyCores(t testing.T, cluster *vault.TestCluster) []*vault.TestClusterCore { t.Helper() cores := make([]*vault.TestClusterCore, 0, 2) for _, core := range cluster.Cores { @@ -287,7 +287,7 @@ func DeriveStandbyCores(t testing.TB, cluster *vault.TestCluster) []*vault.TestC return cores } -func WaitForNCoresUnsealed(t testing.TB, cluster *vault.TestCluster, n int) { +func WaitForNCoresUnsealed(t testing.T, cluster *vault.TestCluster, n int) { t.Helper() for i := 0; i < 30; i++ { unsealed := 0 @@ -306,7 +306,7 @@ func WaitForNCoresUnsealed(t testing.TB, cluster *vault.TestCluster, n int) { t.Fatalf("%d cores were not unsealed", n) } -func SealCores(t testing.TB, cluster *vault.TestCluster) { +func SealCores(t testing.T, cluster *vault.TestCluster) { t.Helper() for _, core := range cluster.Cores { if err := core.Shutdown(); err != nil { @@ -325,7 +325,7 @@ func SealCores(t testing.TB, cluster *vault.TestCluster) { } } -func WaitForNCoresSealed(t testing.TB, cluster *vault.TestCluster, n int) { +func WaitForNCoresSealed(t testing.T, cluster *vault.TestCluster, n int) { t.Helper() for i := 0; i < 60; i++ { sealed := 0 @@ -344,7 +344,7 @@ func WaitForNCoresSealed(t testing.TB, cluster *vault.TestCluster, n int) { t.Fatalf("%d cores were not sealed", n) } -func WaitForActiveNode(t testing.TB, cluster *vault.TestCluster) *vault.TestClusterCore { +func WaitForActiveNode(t testing.T, cluster *vault.TestCluster) *vault.TestClusterCore { t.Helper() for i := 0; i < 60; i++ { for _, core := range cluster.Cores { @@ -360,7 +360,7 @@ func WaitForActiveNode(t testing.TB, cluster *vault.TestCluster) *vault.TestClus return nil } -func WaitForStandbyNode(t testing.TB, core *vault.TestClusterCore) { +func WaitForStandbyNode(t testing.T, core *vault.TestClusterCore) { t.Helper() for i := 0; i < 30; i++ { if isLeader, _, clusterAddr, _ := core.Core.Leader(); isLeader != true && clusterAddr != "" { @@ -376,7 +376,7 @@ func WaitForStandbyNode(t testing.TB, core *vault.TestClusterCore) { t.Fatalf("node did not become standby") } -func RekeyCluster(t testing.TB, cluster *vault.TestCluster, recovery bool) [][]byte { +func RekeyCluster(t testing.T, cluster *vault.TestCluster, recovery bool) [][]byte { t.Helper() cluster.Logger.Info("rekeying cluster", "recovery", recovery) client := cluster.Cores[0].Client @@ -505,7 +505,7 @@ func RaftAppliedIndex(core *vault.TestClusterCore) uint64 { return core.UnderlyingRawStorage.(*raft.RaftBackend).AppliedIndex() } -func WaitForRaftApply(t testing.TB, core *vault.TestClusterCore, index uint64) { +func WaitForRaftApply(t testing.T, core *vault.TestClusterCore, index uint64) { t.Helper() backend := core.UnderlyingRawStorage.(*raft.RaftBackend) @@ -521,7 +521,7 @@ func WaitForRaftApply(t testing.TB, core *vault.TestClusterCore, index uint64) { } // AwaitLeader waits for one of the cluster's nodes to become leader. -func AwaitLeader(t testing.TB, cluster *vault.TestCluster) (int, error) { +func AwaitLeader(t testing.T, cluster *vault.TestCluster) (int, error) { timeout := time.Now().Add(60 * time.Second) for { if time.Now().After(timeout) { @@ -545,7 +545,7 @@ func AwaitLeader(t testing.TB, cluster *vault.TestCluster) (int, error) { return 0, fmt.Errorf("timeout waiting leader") } -func GenerateDebugLogs(t testing.TB, client *api.Client) chan struct{} { +func GenerateDebugLogs(t testing.T, client *api.Client) chan struct{} { t.Helper() stopCh := make(chan struct{}) @@ -584,7 +584,7 @@ func GenerateDebugLogs(t testing.TB, client *api.Client) chan struct{} { // from the map by removing entries whose keys are in the raft configuration. // Remaining entries result in an error return so that the caller can poll for // an expected configuration. -func VerifyRaftPeers(t testing.TB, client *api.Client, expected map[string]bool) error { +func VerifyRaftPeers(t testing.T, client *api.Client, expected map[string]bool) error { t.Helper() resp, err := client.Logical().Read("sys/storage/raft/configuration") @@ -641,7 +641,7 @@ func SysMetricsReq(client *api.Client, cluster *vault.TestCluster, unauth bool) if err != nil { return nil, err } - bodyBytes, err := io.ReadAll(resp.Response.Body) + bodyBytes, err := ioutil.ReadAll(resp.Response.Body) if err != nil { return nil, err } @@ -720,7 +720,7 @@ func SetNonRootToken(client *api.Client) error { // RetryUntilAtCadence runs f until it returns a nil result or the timeout is reached. // If a nil result hasn't been obtained by timeout, calls t.Fatal. -func RetryUntilAtCadence(t testing.TB, timeout, sleepTime time.Duration, f func() error) { +func RetryUntilAtCadence(t testing.T, timeout, sleepTime time.Duration, f func() error) { t.Helper() fail := func(err error) { t.Fatalf("did not complete before deadline, err: %v", err) @@ -730,7 +730,7 @@ func RetryUntilAtCadence(t testing.TB, timeout, sleepTime time.Duration, f func( // RetryUntilAtCadenceWithHandler runs f until it returns a nil result or the timeout is reached. // If a nil result hasn't been obtained by timeout, onFailure is called. -func RetryUntilAtCadenceWithHandler(t testing.TB, timeout, sleepTime time.Duration, onFailure func(error), f func() error) { +func RetryUntilAtCadenceWithHandler(t testing.T, timeout, sleepTime time.Duration, onFailure func(error), f func() error) { t.Helper() deadline := time.Now().Add(timeout) var err error @@ -748,20 +748,20 @@ func RetryUntilAtCadenceWithHandler(t testing.TB, timeout, sleepTime time.Durati // If a nil result hasn't been obtained by timeout, calls t.Fatal. // NOTE: See RetryUntilAtCadence if you want to specify a different wait/sleep // duration between calls. -func RetryUntil(t testing.TB, timeout time.Duration, f func() error) { +func RetryUntil(t testing.T, timeout time.Duration, f func() error) { t.Helper() RetryUntilAtCadence(t, timeout, 100*time.Millisecond, f) } // CreateEntityAndAlias clones an existing client and creates an entity/alias, uses userpass mount path // It returns the cloned client, entityID, and aliasID. -func CreateEntityAndAlias(t testing.TB, client *api.Client, mountAccessor, entityName, aliasName string) (*api.Client, string, string) { +func CreateEntityAndAlias(t testing.T, client *api.Client, mountAccessor, entityName, aliasName string) (*api.Client, string, string) { return CreateEntityAndAliasWithinMount(t, client, mountAccessor, "userpass", entityName, aliasName) } // CreateEntityAndAliasWithinMount clones an existing client and creates an entity/alias, within the specified mountPath // It returns the cloned client, entityID, and aliasID. -func CreateEntityAndAliasWithinMount(t testing.TB, client *api.Client, mountAccessor, mountPath, entityName, aliasName string) (*api.Client, string, string) { +func CreateEntityAndAliasWithinMount(t testing.T, client *api.Client, mountAccessor, mountPath, entityName, aliasName string) (*api.Client, string, string) { t.Helper() userClient, err := client.Clone() if err != nil { @@ -802,7 +802,7 @@ func CreateEntityAndAliasWithinMount(t testing.TB, client *api.Client, mountAcce // SetupTOTPMount enables the totp secrets engine by mounting it. This requires // that the test cluster has a totp backend available. -func SetupTOTPMount(t testing.TB, client *api.Client) { +func SetupTOTPMount(t testing.T, client *api.Client) { t.Helper() // Mount the TOTP backend mountInfo := &api.MountInput{ @@ -814,7 +814,7 @@ func SetupTOTPMount(t testing.TB, client *api.Client) { } // SetupTOTPMethod configures the TOTP secrets engine with a provided config map. -func SetupTOTPMethod(t testing.TB, client *api.Client, config map[string]interface{}) string { +func SetupTOTPMethod(t testing.T, client *api.Client, config map[string]interface{}) string { t.Helper() resp1, err := client.Logical().Write("identity/mfa/method/totp", config) @@ -833,7 +833,7 @@ func SetupTOTPMethod(t testing.TB, client *api.Client, config map[string]interfa // SetupMFALoginEnforcement configures a single enforcement method using the // provided config map. "name" field is required in the config map. -func SetupMFALoginEnforcement(t testing.TB, client *api.Client, config map[string]interface{}) { +func SetupMFALoginEnforcement(t testing.T, client *api.Client, config map[string]interface{}) { t.Helper() enfName, ok := config["name"] if !ok { @@ -848,7 +848,7 @@ func SetupMFALoginEnforcement(t testing.TB, client *api.Client, config map[strin // SetupUserpassMountAccessor sets up userpass auth and returns its mount // accessor. This requires that the test cluster has a "userpass" auth method // available. -func SetupUserpassMountAccessor(t testing.TB, client *api.Client) string { +func SetupUserpassMountAccessor(t testing.T, client *api.Client) string { t.Helper() // Enable Userpass authentication err := client.Sys().EnableAuthWithOptions("userpass", &api.EnableAuthOptions{ @@ -871,7 +871,7 @@ func SetupUserpassMountAccessor(t testing.TB, client *api.Client) string { // RegisterEntityInTOTPEngine registers an entity with a methodID and returns // the generated name. -func RegisterEntityInTOTPEngine(t testing.TB, client *api.Client, entityID, methodID string) string { +func RegisterEntityInTOTPEngine(t testing.T, client *api.Client, entityID, methodID string) string { t.Helper() totpGenName := fmt.Sprintf("%s-%s", entityID, methodID) secret, err := client.Logical().WriteWithContext(context.Background(), "identity/mfa/method/totp/admin-generate", map[string]interface{}{ @@ -905,7 +905,7 @@ func RegisterEntityInTOTPEngine(t testing.TB, client *api.Client, entityID, meth } // GetTOTPCodeFromEngine requests a TOTP code from the specified enginePath. -func GetTOTPCodeFromEngine(t testing.TB, client *api.Client, enginePath string) string { +func GetTOTPCodeFromEngine(t testing.T, client *api.Client, enginePath string) string { t.Helper() totpPath := fmt.Sprintf("totp/code/%s", enginePath) secret, err := client.Logical().ReadWithContext(context.Background(), totpPath) @@ -920,7 +920,7 @@ func GetTOTPCodeFromEngine(t testing.TB, client *api.Client, enginePath string) // SetupLoginMFATOTP setups up a TOTP MFA using some basic configuration and // returns all relevant information to the client. -func SetupLoginMFATOTP(t testing.TB, client *api.Client, methodName string, waitPeriod int) (*api.Client, string, string) { +func SetupLoginMFATOTP(t testing.T, client *api.Client, methodName string, waitPeriod int) (*api.Client, string, string) { t.Helper() // Mount the totp secrets engine SetupTOTPMount(t, client) @@ -956,7 +956,7 @@ func SetupLoginMFATOTP(t testing.TB, client *api.Client, methodName string, wait return entityClient, entityID, methodID } -func SkipUnlessEnvVarsSet(t testing.TB, envVars []string) { +func SkipUnlessEnvVarsSet(t testing.T, envVars []string) { t.Helper() for _, i := range envVars { @@ -974,7 +974,7 @@ func SkipUnlessEnvVarsSet(t testing.TB, envVars []string) { // The intention/use case for this function is to allow a cluster to start and become active with one // or more nodes not joined, so that we can test scenarios where a node joins later. // e.g. 4 nodes in the cluster, only 3 nodes in cluster 'active', 1 node can be joined later in tests. -func WaitForNodesExcludingSelectedStandbys(t testing.TB, cluster *vault.TestCluster, indexesToSkip ...int) { +func WaitForNodesExcludingSelectedStandbys(t testing.T, cluster *vault.TestCluster, indexesToSkip ...int) { WaitForActiveNode(t, cluster) contains := func(elems []int, e int) bool { diff --git a/helper/testhelpers/testhelpers_oss.go b/helper/testhelpers/testhelpers_oss.go index e7e6ff8ebafd..8965ed9169a3 100644 --- a/helper/testhelpers/testhelpers_oss.go +++ b/helper/testhelpers/testhelpers_oss.go @@ -6,14 +6,13 @@ package testhelpers import ( - "testing" - "github.com/hashicorp/vault/vault" + "github.com/mitchellh/go-testing-interface" ) // WaitForActiveNodeAndStandbys does nothing more than wait for the active node // on OSS. On enterprise it waits for perf standbys to be healthy too. -func WaitForActiveNodeAndStandbys(t testing.TB, cluster *vault.TestCluster) { +func WaitForActiveNodeAndStandbys(t testing.T, cluster *vault.TestCluster) { WaitForActiveNode(t, cluster) for _, core := range cluster.Cores { if standby, _ := core.Core.Standby(); standby { diff --git a/helper/testhelpers/teststorage/consul/consul.go b/helper/testhelpers/teststorage/consul/consul.go index cb5cec92d561..26a2175dac2e 100644 --- a/helper/testhelpers/teststorage/consul/consul.go +++ b/helper/testhelpers/teststorage/consul/consul.go @@ -5,16 +5,16 @@ package consul import ( "sync" - "testing" realtesting "testing" "github.com/hashicorp/go-hclog" "github.com/hashicorp/vault/helper/testhelpers/consul" physConsul "github.com/hashicorp/vault/physical/consul" "github.com/hashicorp/vault/vault" + "github.com/mitchellh/go-testing-interface" ) -func MakeConsulBackend(t testing.TB, logger hclog.Logger) *vault.PhysicalBackendBundle { +func MakeConsulBackend(t testing.T, logger hclog.Logger) *vault.PhysicalBackendBundle { cleanup, config := consul.PrepareTestContainer(t.(*realtesting.T), "", false, true) consulConf := map[string]string{ @@ -56,7 +56,7 @@ type consulContainerManager struct { current *consulContainerBackendFactory } -func (m *consulContainerManager) Backend(t testing.TB, coreIdx int, +func (m *consulContainerManager) Backend(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}, ) *vault.PhysicalBackendBundle { m.mu.Lock() @@ -77,7 +77,7 @@ type consulContainerBackendFactory struct { config map[string]string } -func (f *consulContainerBackendFactory) Backend(t testing.TB, coreIdx int, +func (f *consulContainerBackendFactory) Backend(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}, ) *vault.PhysicalBackendBundle { f.mu.Lock() @@ -100,7 +100,7 @@ func (f *consulContainerBackendFactory) Backend(t testing.TB, coreIdx int, } } -func (f *consulContainerBackendFactory) startContainerLocked(t testing.TB) { +func (f *consulContainerBackendFactory) startContainerLocked(t testing.T) { cleanup, config := consul.PrepareTestContainer(t.(*realtesting.T), "", false, true) f.config = map[string]string{ "address": config.Address(), diff --git a/helper/testhelpers/teststorage/teststorage.go b/helper/testhelpers/teststorage/teststorage.go index 4a39e8f98eb6..96a3a1bd0f72 100644 --- a/helper/testhelpers/teststorage/teststorage.go +++ b/helper/testhelpers/teststorage/teststorage.go @@ -9,7 +9,6 @@ import ( "io/ioutil" "math/rand" "os" - "testing" "time" "github.com/hashicorp/go-hclog" @@ -26,9 +25,10 @@ import ( physFile "github.com/hashicorp/vault/sdk/physical/file" "github.com/hashicorp/vault/sdk/physical/inmem" "github.com/hashicorp/vault/vault" + "github.com/mitchellh/go-testing-interface" ) -func MakeInmemBackend(t testing.TB, logger hclog.Logger) *vault.PhysicalBackendBundle { +func MakeInmemBackend(t testing.T, logger hclog.Logger) *vault.PhysicalBackendBundle { inm, err := inmem.NewTransactionalInmem(nil, logger) if err != nil { t.Fatal(err) @@ -44,7 +44,7 @@ func MakeInmemBackend(t testing.TB, logger hclog.Logger) *vault.PhysicalBackendB } } -func MakeLatentInmemBackend(t testing.TB, logger hclog.Logger) *vault.PhysicalBackendBundle { +func MakeLatentInmemBackend(t testing.T, logger hclog.Logger) *vault.PhysicalBackendBundle { r := rand.New(rand.NewSource(time.Now().UnixNano())) jitter := r.Intn(20) latency := time.Duration(r.Intn(15)) * time.Millisecond @@ -55,7 +55,7 @@ func MakeLatentInmemBackend(t testing.TB, logger hclog.Logger) *vault.PhysicalBa return pbb } -func MakeInmemNonTransactionalBackend(t testing.TB, logger hclog.Logger) *vault.PhysicalBackendBundle { +func MakeInmemNonTransactionalBackend(t testing.T, logger hclog.Logger) *vault.PhysicalBackendBundle { inm, err := inmem.NewInmem(nil, logger) if err != nil { t.Fatal(err) @@ -71,7 +71,7 @@ func MakeInmemNonTransactionalBackend(t testing.TB, logger hclog.Logger) *vault. } } -func MakeFileBackend(t testing.TB, logger hclog.Logger) *vault.PhysicalBackendBundle { +func MakeFileBackend(t testing.T, logger hclog.Logger) *vault.PhysicalBackendBundle { path, err := ioutil.TempDir("", "vault-integ-file-") if err != nil { t.Fatal(err) @@ -101,7 +101,7 @@ func MakeFileBackend(t testing.TB, logger hclog.Logger) *vault.PhysicalBackendBu } } -func MakeRaftBackend(t testing.TB, coreIdx int, logger hclog.Logger, extraConf map[string]interface{}, bridge *raft.ClusterAddrBridge) *vault.PhysicalBackendBundle { +func MakeRaftBackend(t testing.T, coreIdx int, logger hclog.Logger, extraConf map[string]interface{}, bridge *raft.ClusterAddrBridge) *vault.PhysicalBackendBundle { nodeID := fmt.Sprintf("core-%d", coreIdx) raftDir, err := ioutil.TempDir("", "vault-raft-") if err != nil { @@ -155,8 +155,8 @@ func makeRaftBackend(logger hclog.Logger, nodeID, raftDir string, extraConf map[ // RaftHAFactory returns a PhysicalBackendBundle with raft set as the HABackend // and the physical.Backend provided in PhysicalBackendBundler as the storage // backend. -func RaftHAFactory(f PhysicalBackendBundler) func(t testing.TB, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle { - return func(t testing.TB, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle { +func RaftHAFactory(f PhysicalBackendBundler) func(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle { + return func(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle { // Call the factory func to create the storage backend physFactory := SharedPhysicalFactory(f) bundle := physFactory(t, coreIdx, logger, nil) @@ -201,10 +201,10 @@ func RaftHAFactory(f PhysicalBackendBundler) func(t testing.TB, coreIdx int, log } } -type PhysicalBackendBundler func(t testing.TB, logger hclog.Logger) *vault.PhysicalBackendBundle +type PhysicalBackendBundler func(t testing.T, logger hclog.Logger) *vault.PhysicalBackendBundle -func SharedPhysicalFactory(f PhysicalBackendBundler) func(t testing.TB, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle { - return func(t testing.TB, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle { +func SharedPhysicalFactory(f PhysicalBackendBundler) func(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle { + return func(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle { if coreIdx == 0 { return f(t, logger) } @@ -230,7 +230,7 @@ func FileBackendSetup(conf *vault.CoreConfig, opts *vault.TestClusterOptions) { opts.PhysicalFactory = SharedPhysicalFactory(MakeFileBackend) } -func RaftClusterJoinNodes(t testing.TB, cluster *vault.TestCluster) { +func RaftClusterJoinNodes(t testing.T, cluster *vault.TestCluster) { leader := cluster.Cores[0] leaderInfos := []*raft.LeaderJoinInfo{ @@ -255,7 +255,7 @@ func RaftClusterJoinNodes(t testing.TB, cluster *vault.TestCluster) { func RaftBackendSetup(conf *vault.CoreConfig, opts *vault.TestClusterOptions) { opts.KeepStandbysSealed = true var bridge *raft.ClusterAddrBridge - opts.PhysicalFactory = func(t testing.TB, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle { + opts.PhysicalFactory = func(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle { // The same PhysicalFactory can be shared across multiple clusters. // The coreIdx == 0 check ensures that each time a new cluster is setup, // when setting up its first node we create a new ClusterAddrBridge. @@ -269,7 +269,7 @@ func RaftBackendSetup(conf *vault.CoreConfig, opts *vault.TestClusterOptions) { } return bundle } - opts.SetupFunc = func(t testing.TB, c *vault.TestCluster) { + opts.SetupFunc = func(t testing.T, c *vault.TestCluster) { if opts.NumCores != 1 { RaftClusterJoinNodes(t, c) time.Sleep(15 * time.Second) diff --git a/helper/testhelpers/teststorage/teststorage_reusable.go b/helper/testhelpers/teststorage/teststorage_reusable.go index db18dfb8c293..89642cf61fd7 100644 --- a/helper/testhelpers/teststorage/teststorage_reusable.go +++ b/helper/testhelpers/teststorage/teststorage_reusable.go @@ -7,12 +7,12 @@ import ( "fmt" "io/ioutil" "os" - "testing" hclog "github.com/hashicorp/go-hclog" "github.com/hashicorp/vault/physical/raft" "github.com/hashicorp/vault/sdk/physical" "github.com/hashicorp/vault/vault" + "github.com/mitchellh/go-testing-interface" ) // ReusableStorage is a physical backend that can be re-used across @@ -29,7 +29,7 @@ type ReusableStorage struct { // Cleanup should be called after a TestCluster is no longer // needed -- generally in a defer, just before the call to // cluster.Cleanup(). - Cleanup func(t testing.TB, cluster *vault.TestCluster) + Cleanup func(t testing.T, cluster *vault.TestCluster) } // StorageCleanup is a function that should be called once -- at the very end @@ -39,12 +39,12 @@ type StorageCleanup func() // MakeReusableStorage makes a physical backend that can be re-used across // multiple test clusters in sequence. -func MakeReusableStorage(t testing.TB, logger hclog.Logger, bundle *vault.PhysicalBackendBundle) (ReusableStorage, StorageCleanup) { +func MakeReusableStorage(t testing.T, logger hclog.Logger, bundle *vault.PhysicalBackendBundle) (ReusableStorage, StorageCleanup) { storage := ReusableStorage{ IsRaft: false, Setup: func(conf *vault.CoreConfig, opts *vault.TestClusterOptions) { - opts.PhysicalFactory = func(t testing.TB, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle { + opts.PhysicalFactory = func(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle { if coreIdx == 0 { // We intentionally do not clone the backend's Cleanup func, // because we don't want it to be run until the entire test has @@ -59,7 +59,7 @@ func MakeReusableStorage(t testing.TB, logger hclog.Logger, bundle *vault.Physic }, // No-op - Cleanup: func(t testing.TB, cluster *vault.TestCluster) {}, + Cleanup: func(t testing.T, cluster *vault.TestCluster) {}, } cleanup := func() { @@ -73,7 +73,7 @@ func MakeReusableStorage(t testing.TB, logger hclog.Logger, bundle *vault.Physic // MakeReusableRaftStorage makes a physical raft backend that can be re-used // across multiple test clusters in sequence. -func MakeReusableRaftStorage(t testing.TB, logger hclog.Logger, numCores int) (ReusableStorage, StorageCleanup) { +func MakeReusableRaftStorage(t testing.T, logger hclog.Logger, numCores int) (ReusableStorage, StorageCleanup) { raftDirs := make([]string, numCores) for i := 0; i < numCores; i++ { raftDirs[i] = makeRaftDir(t) @@ -85,13 +85,13 @@ func MakeReusableRaftStorage(t testing.TB, logger hclog.Logger, numCores int) (R Setup: func(conf *vault.CoreConfig, opts *vault.TestClusterOptions) { conf.DisablePerformanceStandby = true opts.KeepStandbysSealed = true - opts.PhysicalFactory = func(t testing.TB, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle { + opts.PhysicalFactory = func(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle { return makeReusableRaftBackend(t, coreIdx, logger, raftDirs[coreIdx], false) } }, // Close open files being used by raft. - Cleanup: func(t testing.TB, cluster *vault.TestCluster) { + Cleanup: func(t testing.T, cluster *vault.TestCluster) { for i := 0; i < len(cluster.Cores); i++ { CloseRaftStorage(t, cluster, i) } @@ -108,14 +108,14 @@ func MakeReusableRaftStorage(t testing.TB, logger hclog.Logger, numCores int) (R } // CloseRaftStorage closes open files being used by raft. -func CloseRaftStorage(t testing.TB, cluster *vault.TestCluster, idx int) { +func CloseRaftStorage(t testing.T, cluster *vault.TestCluster, idx int) { raftStorage := cluster.Cores[idx].UnderlyingRawStorage.(*raft.RaftBackend) if err := raftStorage.Close(); err != nil { t.Fatal(err) } } -func MakeReusableRaftHAStorage(t testing.TB, logger hclog.Logger, numCores int, bundle *vault.PhysicalBackendBundle) (ReusableStorage, StorageCleanup) { +func MakeReusableRaftHAStorage(t testing.T, logger hclog.Logger, numCores int, bundle *vault.PhysicalBackendBundle) (ReusableStorage, StorageCleanup) { raftDirs := make([]string, numCores) for i := 0; i < numCores; i++ { raftDirs[i] = makeRaftDir(t) @@ -125,7 +125,7 @@ func MakeReusableRaftHAStorage(t testing.TB, logger hclog.Logger, numCores int, Setup: func(conf *vault.CoreConfig, opts *vault.TestClusterOptions) { opts.InmemClusterLayers = true opts.KeepStandbysSealed = true - opts.PhysicalFactory = func(t testing.TB, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle { + opts.PhysicalFactory = func(t testing.T, coreIdx int, logger hclog.Logger, conf map[string]interface{}) *vault.PhysicalBackendBundle { haBundle := makeReusableRaftBackend(t, coreIdx, logger, raftDirs[coreIdx], true) return &vault.PhysicalBackendBundle{ @@ -136,7 +136,7 @@ func MakeReusableRaftHAStorage(t testing.TB, logger hclog.Logger, numCores int, }, // Close open files being used by raft. - Cleanup: func(t testing.TB, cluster *vault.TestCluster) { + Cleanup: func(t testing.T, cluster *vault.TestCluster) { for _, core := range cluster.Cores { raftStorage := core.UnderlyingHAStorage.(*raft.RaftBackend) if err := raftStorage.Close(); err != nil { @@ -159,7 +159,7 @@ func MakeReusableRaftHAStorage(t testing.TB, logger hclog.Logger, numCores int, return storage, cleanup } -func makeRaftDir(t testing.TB) string { +func makeRaftDir(t testing.T) string { raftDir, err := ioutil.TempDir("", "vault-raft-") if err != nil { t.Fatal(err) @@ -168,7 +168,7 @@ func makeRaftDir(t testing.TB) string { return raftDir } -func makeReusableRaftBackend(t testing.TB, coreIdx int, logger hclog.Logger, raftDir string, ha bool) *vault.PhysicalBackendBundle { +func makeReusableRaftBackend(t testing.T, coreIdx int, logger hclog.Logger, raftDir string, ha bool) *vault.PhysicalBackendBundle { nodeID := fmt.Sprintf("core-%d", coreIdx) backend, err := makeRaftBackend(logger, nodeID, raftDir, nil, nil) if err != nil { diff --git a/http/forwarding_bench_test.go b/http/forwarding_bench_test.go index 311dc0bc66e8..287a6c9ff49a 100644 --- a/http/forwarding_bench_test.go +++ b/http/forwarding_bench_test.go @@ -14,6 +14,7 @@ import ( log "github.com/hashicorp/go-hclog" "github.com/hashicorp/vault/builtin/logical/transit" + "github.com/hashicorp/vault/helper/benchhelpers" "github.com/hashicorp/vault/helper/forwarding" "github.com/hashicorp/vault/sdk/helper/consts" "github.com/hashicorp/vault/sdk/helper/logging" @@ -31,7 +32,7 @@ func BenchmarkHTTP_Forwarding_Stress(b *testing.B) { }, } - cluster := vault.NewTestCluster(b, coreConfig, &vault.TestClusterOptions{ + cluster := vault.NewTestCluster(benchhelpers.TBtoT(b), coreConfig, &vault.TestClusterOptions{ HandlerFunc: Handler, Logger: logging.NewVaultLoggerWithWriter(ioutil.Discard, log.Error), }) @@ -41,7 +42,7 @@ func BenchmarkHTTP_Forwarding_Stress(b *testing.B) { // make it easy to get access to the active core := cores[0].Core - vault.TestWaitActive(b, core) + vault.TestWaitActive(benchhelpers.TBtoT(b), core) handler := cores[0].Handler host := fmt.Sprintf("https://127.0.0.1:%d/v1/transit/", cores[0].Listeners[0].Address.Port) diff --git a/http/handler.go b/http/handler.go index ceaaf34b457f..f5f5cb5479bc 100644 --- a/http/handler.go +++ b/http/handler.go @@ -14,6 +14,7 @@ import ( "fmt" "io" "io/fs" + "io/ioutil" "mime" "net" "net/http" @@ -312,7 +313,7 @@ func (w *copyResponseWriter) WriteHeader(code int) { func handleAuditNonLogical(core *vault.Core, h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { origBody := new(bytes.Buffer) - reader := io.NopCloser(io.TeeReader(r.Body, origBody)) + reader := ioutil.NopCloser(io.TeeReader(r.Body, origBody)) r.Body = reader req, _, status, err := buildLogicalRequestNoAuth(core.PerfStandby(), core.RouterAccess(), w, r) if err != nil || status != 0 { @@ -816,14 +817,14 @@ func parseJSONRequest(perfStandby bool, r *http.Request, w http.ResponseWriter, // Since we're checking PerfStandby here we key on origBody being nil // or not later, so we need to always allocate so it's non-nil origBody = new(bytes.Buffer) - reader = io.NopCloser(io.TeeReader(reader, origBody)) + reader = ioutil.NopCloser(io.TeeReader(reader, origBody)) } err := jsonutil.DecodeJSONFromReader(reader, out) if err != nil && err != io.EOF { return nil, fmt.Errorf("failed to parse JSON input: %w", err) } if origBody != nil { - return io.NopCloser(origBody), err + return ioutil.NopCloser(origBody), err } return nil, err } @@ -866,7 +867,6 @@ func forwardBasedOnHeaders(core *vault.Core, r *http.Request) (bool, error) { return false, fmt.Errorf("forwarding via header %s disabled in configuration", VaultForwardHeaderName) } if rawForward == "active-node" { - core.Logger().Trace("request will be routed based on the 'active-node' header") return true, nil } return false, nil @@ -989,7 +989,7 @@ func forwardRequest(core *vault.Core, w http.ResponseWriter, r *http.Request) { statusCode, header, retBytes, err := core.ForwardRequest(r) if err != nil { if err == vault.ErrCannotForward { - core.Logger().Trace("cannot forward request (possibly disabled on active node), falling back to redirection to standby") + core.Logger().Debug("cannot forward request (possibly disabled on active node), falling back") } else { core.Logger().Error("forward request error", "error", err) } @@ -999,8 +999,6 @@ func forwardRequest(core *vault.Core, w http.ResponseWriter, r *http.Request) { return } - core.Logger().Trace("request forwarded", "statusCode", statusCode) - for k, v := range header { w.Header()[k] = v } diff --git a/http/handler_test.go b/http/handler_test.go index dde4acd3a8df..ebfee0401644 100644 --- a/http/handler_test.go +++ b/http/handler_test.go @@ -9,7 +9,7 @@ import ( "crypto/tls" "encoding/json" "errors" - "io" + "io/ioutil" "net/http" "net/http/httptest" "net/textproto" @@ -885,7 +885,7 @@ func TestHandler_Parse_Form(t *testing.T) { if err != nil { t.Fatal(err) } - req.Body = io.NopCloser(strings.NewReader(values.Encode())) + req.Body = ioutil.NopCloser(strings.NewReader(values.Encode())) req.Header.Set("x-vault-token", cluster.RootToken) req.Header.Set("content-type", "application/x-www-form-urlencoded") resp, err := c.Do(req) diff --git a/http/plugin_test.go b/http/plugin_test.go index 8a1b35d98dbf..b215a6b1c6bc 100644 --- a/http/plugin_test.go +++ b/http/plugin_test.go @@ -6,7 +6,7 @@ package http import ( "encoding/json" "fmt" - "io" + "io/ioutil" "os" "reflect" "sync" @@ -15,6 +15,7 @@ import ( log "github.com/hashicorp/go-hclog" "github.com/hashicorp/vault/api" bplugin "github.com/hashicorp/vault/builtin/plugin" + "github.com/hashicorp/vault/helper/benchhelpers" "github.com/hashicorp/vault/helper/testhelpers/corehelpers" "github.com/hashicorp/vault/sdk/helper/consts" "github.com/hashicorp/vault/sdk/helper/pluginutil" @@ -47,7 +48,7 @@ func getPluginClusterAndCore(t *testing.T, logger log.Logger) (*vault.TestCluste PluginDirectory: pluginDir, } - cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{ + cluster := vault.NewTestCluster(benchhelpers.TBtoT(t), coreConfig, &vault.TestClusterOptions{ HandlerFunc: Handler, }) cluster.Start() @@ -55,8 +56,8 @@ func getPluginClusterAndCore(t *testing.T, logger log.Logger) (*vault.TestCluste cores := cluster.Cores core := cores[0] - vault.TestWaitActive(t, core.Core) - vault.TestAddTestPlugin(t, core.Core, "mock-plugin", consts.PluginTypeSecrets, "", "TestPlugin_PluginMain", + vault.TestWaitActive(benchhelpers.TBtoT(t), core.Core) + vault.TestAddTestPlugin(benchhelpers.TBtoT(t), core.Core, "mock-plugin", consts.PluginTypeSecrets, "", "TestPlugin_PluginMain", []string{fmt.Sprintf("%s=%s", pluginutil.PluginCACertPEMEnv, cluster.CACertPEMFile)}) // Mount the mock plugin @@ -147,7 +148,7 @@ func TestPlugin_MockRawResponse(t *testing.T) { t.Fatal(err) } defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) + body, err := ioutil.ReadAll(resp.Body) if err != nil { t.Fatal(err) } diff --git a/http/sys_health_test.go b/http/sys_health_test.go index dcc3473b0636..bd64ea853232 100644 --- a/http/sys_health_test.go +++ b/http/sys_health_test.go @@ -4,7 +4,7 @@ package http import ( - "io" + "io/ioutil" "net/http" "net/url" "testing" @@ -206,7 +206,7 @@ func TestSysHealth_head(t *testing.T) { t.Fatalf("HEAD %v expected code %d, got %d.", queryurl, tt.code, resp.StatusCode) } - data, err := io.ReadAll(resp.Body) + data, err := ioutil.ReadAll(resp.Body) if err != nil { t.Fatalf("err on %v: %s", queryurl, err) } diff --git a/internalshared/configutil/listener.go b/internalshared/configutil/listener.go index b9ed168abf7e..1e959b5c86ad 100644 --- a/internalshared/configutil/listener.go +++ b/internalshared/configutil/listener.go @@ -638,7 +638,7 @@ func (l *Listener) parseProfilingSettings() error { return nil } -// parseInFlightRequestSettings attempts to parse the raw listener in-flight request logging settings. +// parseProfilingSettings attempts to parse the raw listener in-flight request logging settings. // The state of the listener will be modified, raw data will be cleared upon // successful parsing. func (l *Listener) parseInFlightRequestSettings() error { diff --git a/internalshared/configutil/telemetry.go b/internalshared/configutil/telemetry.go index 7c49fce00917..d00b922b75a9 100644 --- a/internalshared/configutil/telemetry.go +++ b/internalshared/configutil/telemetry.go @@ -22,7 +22,6 @@ import ( "github.com/hashicorp/hcl" "github.com/hashicorp/hcl/hcl/ast" "github.com/hashicorp/vault/helper/metricsutil" - "github.com/hashicorp/vault/sdk/helper/metricregistry" "google.golang.org/api/option" ) @@ -290,10 +289,6 @@ func SetupTelemetry(opts *SetupTelemetryOpts) (*metrics.InmemSink, *metricsutil. Expiration: opts.Config.PrometheusRetentionTime, } - // Merge in explicit metric definitions so Prometheus always reports those - // metrics. - metricregistry.MergeDefinitions(&prometheusOpts) - sink, err := prometheus.NewPrometheusSinkFrom(prometheusOpts) if err != nil { return nil, nil, false, err diff --git a/physical/azure/azure.go b/physical/azure/azure.go index e941af1611b8..70995c8c8f69 100644 --- a/physical/azure/azure.go +++ b/physical/azure/azure.go @@ -7,7 +7,7 @@ import ( "context" "errors" "fmt" - "io" + "io/ioutil" "net/url" "os" "regexp" @@ -271,7 +271,7 @@ func (a *AzureBackend) Get(ctx context.Context, key string) (*physical.Entry, er reader := res.Body(azblob.RetryReaderOptions{}) defer reader.Close() - data, err := io.ReadAll(reader) + data, err := ioutil.ReadAll(reader) ent := &physical.Entry{ Key: key, @@ -344,7 +344,7 @@ func (a *AzureBackend) List(ctx context.Context, prefix string) ([]string, error // getAuthTokenFromIMDS uses the Azure Instance Metadata Service to retrieve a short-lived credential using OAuth // more info on this https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview func getAuthTokenFromIMDS(resource string) (*adal.ServicePrincipalToken, error) { - msiEndpoint, err := adal.GetMSIEndpoint() + msiEndpoint, err := adal.GetMSIVMEndpoint() if err != nil { return nil, err } diff --git a/physical/cassandra/cassandra.go b/physical/cassandra/cassandra.go index 9e650f5ff830..a7f22c468dc7 100644 --- a/physical/cassandra/cassandra.go +++ b/physical/cassandra/cassandra.go @@ -150,14 +150,6 @@ func NewCassandraBackend(conf map[string]string, logger log.Logger) (physical.Ba cluster.Timeout = time.Duration(connectionTimeout) * time.Second } - if disableInitialHostLookupStr, ok := conf["disable_host_initial_lookup"]; ok { - disableInitialHostLookup, err := strconv.ParseBool(disableInitialHostLookupStr) - if err != nil { - return nil, fmt.Errorf("'disable_host_initial_lookup' must be a bool") - } - cluster.DisableInitialHostLookup = disableInitialHostLookup - } - if err := setupCassandraTLS(conf, cluster); err != nil { return nil, err } diff --git a/physical/couchdb/couchdb.go b/physical/couchdb/couchdb.go index cbb32e56096f..0a1c379c6ee9 100644 --- a/physical/couchdb/couchdb.go +++ b/physical/couchdb/couchdb.go @@ -8,7 +8,7 @@ import ( "context" "encoding/json" "fmt" - "io" + "io/ioutil" "net/http" "net/url" "os" @@ -114,7 +114,7 @@ func (m *couchDBClient) get(key string) (*physical.Entry, error) { } else if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("GET returned %q", resp.Status) } - bs, err := io.ReadAll(resp.Body) + bs, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } @@ -143,7 +143,7 @@ func (m *couchDBClient) list(prefix string) ([]couchDBListItem, error) { } defer resp.Body.Close() - data, err := io.ReadAll(resp.Body) + data, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } diff --git a/physical/couchdb/couchdb_test.go b/physical/couchdb/couchdb_test.go index 0428d52d250f..bc8f6b41dffa 100644 --- a/physical/couchdb/couchdb_test.go +++ b/physical/couchdb/couchdb_test.go @@ -6,7 +6,7 @@ package couchdb import ( "context" "fmt" - "io" + "io/ioutil" "net/http" "net/url" "os" @@ -145,7 +145,7 @@ func setupCouchDB(ctx context.Context, host string, port int) (docker.ServiceCon } defer resp.Body.Close() if resp.StatusCode != http.StatusCreated { - bs, _ := io.ReadAll(resp.Body) + bs, _ := ioutil.ReadAll(resp.Body) return nil, fmt.Errorf("failed to create database: %s %s\n", resp.Status, string(bs)) } } @@ -164,7 +164,7 @@ func setupCouchDB(ctx context.Context, host string, port int) (docker.ServiceCon } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - bs, _ := io.ReadAll(resp.Body) + bs, _ := ioutil.ReadAll(resp.Body) return nil, fmt.Errorf("Failed to create admin user: %s %s\n", resp.Status, string(bs)) } } diff --git a/physical/dynamodb/dynamodb.go b/physical/dynamodb/dynamodb.go index bc27def0c987..7b6413f143a0 100644 --- a/physical/dynamodb/dynamodb.go +++ b/physical/dynamodb/dynamodb.go @@ -294,7 +294,7 @@ func (d *DynamoDBBackend) Put(ctx context.Context, entry *physical.Entry) error }) } - return d.batchWriteRequests(ctx, requests) + return d.batchWriteRequests(requests) } // Get is used to fetch an entry @@ -304,7 +304,7 @@ func (d *DynamoDBBackend) Get(ctx context.Context, key string) (*physical.Entry, d.permitPool.Acquire() defer d.permitPool.Release() - resp, err := d.client.GetItemWithContext(ctx, &dynamodb.GetItemInput{ + resp, err := d.client.GetItem(&dynamodb.GetItemInput{ TableName: aws.String(d.table), ConsistentRead: aws.Bool(true), Key: map[string]*dynamodb.AttributeValue{ @@ -363,7 +363,7 @@ func (d *DynamoDBBackend) Delete(ctx context.Context, key string) error { excluded = append(excluded, recordKeyForVaultKey(prefixes[index-1])) } - hasChildren, err := d.hasChildren(ctx, prefix, excluded) + hasChildren, err := d.hasChildren(prefix, excluded) if err != nil { return err } @@ -387,7 +387,7 @@ func (d *DynamoDBBackend) Delete(ctx context.Context, key string) error { } } - return d.batchWriteRequests(ctx, requests) + return d.batchWriteRequests(requests) } // List is used to list all the keys under a given @@ -410,17 +410,12 @@ func (d *DynamoDBBackend) List(ctx context.Context, prefix string) ([]string, er }}, }, }, - ProjectionExpression: aws.String("#key, #path"), - ExpressionAttributeNames: map[string]*string{ - "#key": aws.String("Key"), - "#path": aws.String("Path"), - }, } d.permitPool.Acquire() defer d.permitPool.Release() - err := d.client.QueryPagesWithContext(ctx, queryInput, func(out *dynamodb.QueryOutput, lastPage bool) bool { + err := d.client.QueryPages(queryInput, func(out *dynamodb.QueryOutput, lastPage bool) bool { var record DynamoDBRecord for _, item := range out.Items { dynamodbattribute.UnmarshalMap(item, &record) @@ -443,7 +438,7 @@ func (d *DynamoDBBackend) List(ctx context.Context, prefix string) ([]string, er // before any deletes take place. To account for that hasChildren accepts a slice of // strings representing values we expect to find that should NOT be counted as children // because they are going to be deleted. -func (d *DynamoDBBackend) hasChildren(ctx context.Context, prefix string, exclude []string) (bool, error) { +func (d *DynamoDBBackend) hasChildren(prefix string, exclude []string) (bool, error) { prefix = strings.TrimSuffix(prefix, "/") prefix = escapeEmptyPath(prefix) @@ -458,11 +453,6 @@ func (d *DynamoDBBackend) hasChildren(ctx context.Context, prefix string, exclud }}, }, }, - ProjectionExpression: aws.String("#key, #path"), - ExpressionAttributeNames: map[string]*string{ - "#key": aws.String("Key"), - "#path": aws.String("Path"), - }, // Avoid fetching too many items from DynamoDB for performance reasons. // We want to know if there are any children we don't expect to see. // Answering that question requires fetching a minimum of one more item @@ -473,7 +463,7 @@ func (d *DynamoDBBackend) hasChildren(ctx context.Context, prefix string, exclud d.permitPool.Acquire() defer d.permitPool.Release() - out, err := d.client.QueryWithContext(ctx, queryInput) + out, err := d.client.Query(queryInput) if err != nil { return false, err } @@ -519,7 +509,7 @@ func (d *DynamoDBBackend) HAEnabled() bool { // batchWriteRequests takes a list of write requests and executes them in badges // with a maximum size of 25 (which is the limit of BatchWriteItem requests). -func (d *DynamoDBBackend) batchWriteRequests(ctx context.Context, requests []*dynamodb.WriteRequest) error { +func (d *DynamoDBBackend) batchWriteRequests(requests []*dynamodb.WriteRequest) error { for len(requests) > 0 { batchSize := int(math.Min(float64(len(requests)), 25)) batch := map[string][]*dynamodb.WriteRequest{d.table: requests[:batchSize]} @@ -534,7 +524,7 @@ func (d *DynamoDBBackend) batchWriteRequests(ctx context.Context, requests []*dy for len(batch) > 0 { var output *dynamodb.BatchWriteItemOutput - output, err = d.client.BatchWriteItemWithContext(ctx, &dynamodb.BatchWriteItemInput{ + output, err = d.client.BatchWriteItem(&dynamodb.BatchWriteItemInput{ RequestItems: batch, }) if err != nil { diff --git a/physical/gcs/gcs.go b/physical/gcs/gcs.go index 51b1f926ff44..eea7a515ac8d 100644 --- a/physical/gcs/gcs.go +++ b/physical/gcs/gcs.go @@ -8,7 +8,7 @@ import ( "crypto/md5" "errors" "fmt" - "io" + "io/ioutil" "os" "sort" "strconv" @@ -230,7 +230,7 @@ func (b *Backend) Get(ctx context.Context, key string) (retEntry *physical.Entry } }() - value, err := io.ReadAll(r) + value, err := ioutil.ReadAll(r) if err != nil { return nil, fmt.Errorf("failed to read value into a string: %w", err) } diff --git a/physical/oci/oci.go b/physical/oci/oci.go index 628f31049182..3665813d0479 100644 --- a/physical/oci/oci.go +++ b/physical/oci/oci.go @@ -5,7 +5,7 @@ import ( "bytes" "errors" "fmt" - "io" + "io/ioutil" "net/http" "sort" "strconv" @@ -172,7 +172,7 @@ func (o *Backend) Put(ctx context.Context, entry *physical.Entry) error { BucketName: &o.bucketName, ObjectName: &entry.Key, ContentLength: &size, - PutObjectBody: io.NopCloser(bytes.NewReader(entry.Value)), + PutObjectBody: ioutil.NopCloser(bytes.NewReader(entry.Value)), OpcMeta: nil, OpcClientRequestId: &opcClientRequestId, } @@ -230,7 +230,7 @@ func (o *Backend) Get(ctx context.Context, key string) (*physical.Entry, error) return nil, fmt.Errorf("failed to read Value: %w", err) } - body, err := io.ReadAll(resp.Content) + body, err := ioutil.ReadAll(resp.Content) if err != nil { metrics.IncrCounter(metricGetFailed, 1) return nil, fmt.Errorf("failed to decode Value into bytes: %w", err) diff --git a/physical/oci/oci_ha.go b/physical/oci/oci_ha.go index cc0e0edc62a5..a4c6ad52ea6b 100644 --- a/physical/oci/oci_ha.go +++ b/physical/oci/oci_ha.go @@ -7,7 +7,7 @@ import ( "encoding/json" "errors" "fmt" - "io" + "io/ioutil" "net/http" "sync" "sync/atomic" @@ -398,7 +398,7 @@ func (l *Lock) get(ctx context.Context) (*LockRecord, string, error) { defer response.RawResponse.Body.Close() - body, err := io.ReadAll(response.Content) + body, err := ioutil.ReadAll(response.Content) if err != nil { metrics.IncrCounter(metricGetFailed, 1) l.backend.logger.Error("Error reading content", "err", err) @@ -487,7 +487,7 @@ func (l *Lock) writeLock() (bool, error) { BucketName: &l.backend.lockBucketName, ObjectName: &l.key, ContentLength: &size, - PutObjectBody: io.NopCloser(bytes.NewReader(newLockRecordJson)), + PutObjectBody: ioutil.NopCloser(bytes.NewReader(newLockRecordJson)), OpcMeta: nil, OpcClientRequestId: &opcClientRequestId, } diff --git a/physical/postgresql/postgresql_test.go b/physical/postgresql/postgresql_test.go index 0dc0ce948602..301fc15ec263 100644 --- a/physical/postgresql/postgresql_test.go +++ b/physical/postgresql/postgresql_test.go @@ -22,7 +22,7 @@ func TestPostgreSQLBackend(t *testing.T) { // Use docker as pg backend if no url is provided via environment variables connURL := os.Getenv("PGURL") if connURL == "" { - cleanup, u := postgresql.PrepareTestContainer(t) + cleanup, u := postgresql.PrepareTestContainer(t, "11.1") defer cleanup() connURL = u } diff --git a/physical/raft/raft.go b/physical/raft/raft.go index a79ee3507dd9..d07dedea4042 100644 --- a/physical/raft/raft.go +++ b/physical/raft/raft.go @@ -690,12 +690,6 @@ func (b *RaftBackend) UpgradeVersion() string { return b.effectiveSDKVersion } -func (b *RaftBackend) SDKVersion() string { - b.l.RLock() - defer b.l.RUnlock() - return b.effectiveSDKVersion -} - func (b *RaftBackend) verificationInterval() time.Duration { b.l.RLock() defer b.l.RUnlock() diff --git a/physical/raft/raft_autopilot.go b/physical/raft/raft_autopilot.go index fb17283e663e..6a5edf970305 100644 --- a/physical/raft/raft_autopilot.go +++ b/physical/raft/raft_autopilot.go @@ -211,86 +211,6 @@ type FollowerState struct { RedundancyZone string } -// partialCopy returns a partial copy of the follower state. -// This copy uses the same pointer to the IsDead -// atomic field. We need to do this to ensure that -// an update of the IsDead boolean will still be -// accessible in a copied state. -func (f *FollowerState) partialCopy() *FollowerState { - return &FollowerState{ - AppliedIndex: f.AppliedIndex, - LastHeartbeat: f.LastHeartbeat, - LastTerm: f.LastTerm, - IsDead: f.IsDead, - DesiredSuffrage: f.DesiredSuffrage, - Version: f.Version, - UpgradeVersion: f.UpgradeVersion, - RedundancyZone: f.RedundancyZone, - } -} - -// PersistedFollowerState holds the information that gets persisted to storage -type PersistedFollowerState struct { - Version string `json:"version"` - UpgradeVersion string `json:"upgrade_version"` -} - -type PersistedFollowerStates struct { - l sync.RWMutex - States map[string]PersistedFollowerState -} - -// shouldUpdate checks if the persisted state contains the same servers as the -// current autopilot state. If grabLock is true, a read lock is acquired before -// accessing the map -func (p *PersistedFollowerStates) shouldUpdate(state *autopilot.State, grabLock bool) bool { - if grabLock { - p.l.RLock() - defer p.l.RUnlock() - } - if len(state.Servers) != len(p.States) { - return true - } - for id, server := range state.Servers { - persistedServer, found := p.States[string(id)] - if !found { - return true - } - if server.Server.Version != persistedServer.Version || - server.Server.Meta[AutopilotUpgradeVersionTag] != persistedServer.UpgradeVersion { - return true - } - } - return false -} - -// updatePersistedState checks if the persisted state matches the current -// autopilot state. If not, the state is replaced and persisted -func (d *Delegate) updatePersistedState(state *autopilot.State) error { - if !d.persistedState.shouldUpdate(state, true) { - return nil - } - newStates := make(map[string]PersistedFollowerState) - for id, server := range state.Servers { - newStates[string(id)] = PersistedFollowerState{ - Version: server.Server.Version, - UpgradeVersion: server.Server.Meta[AutopilotUpgradeVersionTag], - } - } - d.persistedState.l.Lock() - defer d.persistedState.l.Unlock() - if !d.persistedState.shouldUpdate(state, false) { - return nil - } - d.logger.Debug("updating autopilot persisted state") - err := d.saveStateFn(newStates) - if err != nil { - return err - } - d.persistedState.States = newStates - return nil -} - // EchoRequestUpdate is here to avoid 1) the list of arguments to Update() getting huge 2) an import cycle on the vault package type EchoRequestUpdate struct { NodeID string @@ -395,17 +315,13 @@ type Delegate struct { dl sync.RWMutex inflightRemovals map[raft.ServerID]bool emptyVersionLogs map[raft.ServerID]struct{} - persistedState *PersistedFollowerStates - saveStateFn func(p map[string]PersistedFollowerState) error } -func NewDelegate(b *RaftBackend, persistedStates map[string]PersistedFollowerState, savePersistedStates func(p map[string]PersistedFollowerState) error) *Delegate { +func NewDelegate(b *RaftBackend) *Delegate { return &Delegate{ RaftBackend: b, inflightRemovals: make(map[raft.ServerID]bool), emptyVersionLogs: make(map[raft.ServerID]struct{}), - persistedState: &PersistedFollowerStates{States: persistedStates}, - saveStateFn: savePersistedStates, } } @@ -449,13 +365,6 @@ func (d *Delegate) NotifyState(state *autopilot.State) { metrics.SetGaugeWithLabels([]string{"autopilot", "node", "healthy"}, 0, labels) } } - - // if there is a change in versions or membership, we should update - // our persisted state - err := d.updatePersistedState(state) - if err != nil { - d.logger.Error("failed to persist autopilot state", "error", err) - } } } @@ -511,9 +420,6 @@ func (d *Delegate) KnownServers() map[raft.ServerID]*autopilot.Server { d.followerStates.l.RLock() defer d.followerStates.l.RUnlock() - d.persistedState.l.RLock() - defer d.persistedState.l.RUnlock() - ret := make(map[raft.ServerID]*autopilot.Server) for id, state := range d.followerStates.followers { // If the server is not in raft configuration, even if we received a follower @@ -522,14 +428,26 @@ func (d *Delegate) KnownServers() map[raft.ServerID]*autopilot.Server { continue } + // If version isn't found in the state, fake it using the version from the leader so that autopilot + // doesn't demote the node to a non-voter, just because of a missed heartbeat. Note that this should + // be the SDK version, not the upgrade version. currentServerID := raft.ServerID(id) - followerVersion, upgradeVersion := d.determineFollowerVersions(id, state) - if state.UpgradeVersion != upgradeVersion { - // we only have a read lock on state, so we can't modify it - // safely. Instead, copy it to override the upgrade version - state = state.partialCopy() - state.UpgradeVersion = upgradeVersion + followerVersion := state.Version + leaderVersion := d.effectiveSDKVersion + d.dl.Lock() + if followerVersion == "" { + if _, ok := d.emptyVersionLogs[currentServerID]; !ok { + d.logger.Trace("received empty Vault version in heartbeat state. faking it with the leader version for now", "id", id, "leader version", leaderVersion) + d.emptyVersionLogs[currentServerID] = struct{}{} + } + followerVersion = leaderVersion + } else { + if _, ok := d.emptyVersionLogs[currentServerID]; ok { + d.logger.Trace("received non-empty version in heartbeat state. no longer need to fake it", "id", id, "update_version", followerVersion) + delete(d.emptyVersionLogs, currentServerID) + } } + d.dl.Unlock() server := &autopilot.Server{ ID: currentServerID, @@ -583,54 +501,6 @@ func (d *Delegate) KnownServers() map[raft.ServerID]*autopilot.Server { return ret } -// determineFollowerVersions uses the following logic: -// - if the version and upgrade version are present in the follower state, -// return those. -// - if the persisted states map is empty, it means that persisted states -// don't exist. This happens on an upgrade to 1.18. Use the leader node's -// versions. -// - use the versions in the persisted states map -// -// This function must be called with a lock on d.followerStates -// and d.persistedStates. -func (d *Delegate) determineFollowerVersions(id string, state *FollowerState) (version string, upgradeVersion string) { - // if we have both versions in follower states, use those - if state.Version != "" && state.UpgradeVersion != "" { - return state.Version, state.UpgradeVersion - } - - version = state.Version - upgradeVersion = state.UpgradeVersion - - // the persistedState map should only be empty on upgrades - // to 1.18.x. This is the only case where we'll stub with - // the leader's versions - if len(d.persistedState.States) == 0 { - if version == "" { - version = d.effectiveSDKVersion - d.logger.Debug("no persisted state, using leader version", "id", id, "version", version) - } - if upgradeVersion == "" { - upgradeVersion = d.upgradeVersion - d.logger.Debug("no persisted state, using leader upgrade version version", "id", id, "upgrade_version", upgradeVersion) - } - return version, upgradeVersion - } - - // Use the persistedStates map to fill in the sdk - // and upgrade versions - pState := d.persistedState.States[id] - if version == "" { - version = pState.Version - d.logger.Debug("using follower version from persisted states", "id", id, "version", version) - } - if upgradeVersion == "" { - upgradeVersion = pState.UpgradeVersion - d.logger.Debug("using upgrade version from persisted states", "id", id, "upgrade_version", upgradeVersion) - } - return version, upgradeVersion -} - // RemoveFailedServer is called by the autopilot library when it desires a node // to be removed from the raft configuration. This function removes the node // from the raft cluster and stops tracking its information in follower states. @@ -964,19 +834,11 @@ func (b *RaftBackend) DisableAutopilot() { b.l.Unlock() } -type AutopilotSetupOptions struct { - StorageConfig *AutopilotConfig - FollowerStates *FollowerStates - Disable bool - PersistedStates map[string]PersistedFollowerState - SavePersistedStates func(p map[string]PersistedFollowerState) error -} - // SetupAutopilot gathers information required to configure autopilot and starts // it. If autopilot is disabled, this function does nothing. -func (b *RaftBackend) SetupAutopilot(ctx context.Context, opts *AutopilotSetupOptions) { +func (b *RaftBackend) SetupAutopilot(ctx context.Context, storageConfig *AutopilotConfig, followerStates *FollowerStates, disable bool) { b.l.Lock() - if opts.Disable || os.Getenv("VAULT_RAFT_AUTOPILOT_DISABLE") != "" { + if disable || os.Getenv("VAULT_RAFT_AUTOPILOT_DISABLE") != "" { b.disableAutopilot = true } @@ -990,7 +852,7 @@ func (b *RaftBackend) SetupAutopilot(ctx context.Context, opts *AutopilotSetupOp b.autopilotConfig = b.defaultAutopilotConfig() // Merge the setting provided over the API - b.autopilotConfig.Merge(opts.StorageConfig) + b.autopilotConfig.Merge(storageConfig) infoArgs := []interface{}{"config", b.autopilotConfig} @@ -1007,9 +869,8 @@ func (b *RaftBackend) SetupAutopilot(ctx context.Context, opts *AutopilotSetupOp options = append(options, autopilot.WithUpdateInterval(b.autopilotUpdateInterval)) infoArgs = append(infoArgs, []interface{}{"update_interval", b.autopilotUpdateInterval}...) } - delegate := NewDelegate(b, opts.PersistedStates, opts.SavePersistedStates) - b.autopilot = autopilot.New(b.raft, delegate, options...) - b.followerStates = opts.FollowerStates + b.autopilot = autopilot.New(b.raft, NewDelegate(b), options...) + b.followerStates = followerStates b.followerHeartbeatTicker = time.NewTicker(1 * time.Second) b.l.Unlock() diff --git a/physical/raft/snapshot.go b/physical/raft/snapshot.go index e44769bf6d2a..8a016f2b1288 100644 --- a/physical/raft/snapshot.go +++ b/physical/raft/snapshot.go @@ -267,7 +267,7 @@ func (f *BoltSnapshotStore) openFromFile(id string) (*raft.SnapshotMeta, io.Read filename := filepath.Join(f.path, id, databaseFilename) installer := &boltSnapshotInstaller{ meta: meta, - ReadCloser: io.NopCloser(strings.NewReader(filename)), + ReadCloser: ioutil.NopCloser(strings.NewReader(filename)), filename: filename, } diff --git a/physical/raft/snapshot_test.go b/physical/raft/snapshot_test.go index fe7fafd3fc01..d85af4da5f73 100644 --- a/physical/raft/snapshot_test.go +++ b/physical/raft/snapshot_test.go @@ -495,7 +495,7 @@ func TestRaft_Snapshot_Take_Restore(t *testing.T) { } } - snapFile, cleanup, metadata, err := raft1.WriteSnapshotToTemp(io.NopCloser(recorder.Body), nil) + snapFile, cleanup, metadata, err := raft1.WriteSnapshotToTemp(ioutil.NopCloser(recorder.Body), nil) if err != nil { t.Fatal(err) } diff --git a/physical/s3/s3.go b/physical/s3/s3.go index b1687a91622e..da82acccd3ca 100644 --- a/physical/s3/s3.go +++ b/physical/s3/s3.go @@ -183,7 +183,7 @@ func (s *S3Backend) Put(ctx context.Context, entry *physical.Entry) error { putObjectInput.SSEKMSKeyId = aws.String(s.kmsKeyId) } - _, err := s.client.PutObjectWithContext(ctx, putObjectInput) + _, err := s.client.PutObject(putObjectInput) if err != nil { return err } @@ -201,7 +201,7 @@ func (s *S3Backend) Get(ctx context.Context, key string) (*physical.Entry, error // Setup key key = path.Join(s.path, key) - resp, err := s.client.GetObjectWithContext(ctx, &s3.GetObjectInput{ + resp, err := s.client.GetObject(&s3.GetObjectInput{ Bucket: aws.String(s.bucket), Key: aws.String(key), }) @@ -254,7 +254,7 @@ func (s *S3Backend) Delete(ctx context.Context, key string) error { // Setup key key = path.Join(s.path, key) - _, err := s.client.DeleteObjectWithContext(ctx, &s3.DeleteObjectInput{ + _, err := s.client.DeleteObject(&s3.DeleteObjectInput{ Bucket: aws.String(s.bucket), Key: aws.String(key), }) @@ -289,7 +289,7 @@ func (s *S3Backend) List(ctx context.Context, prefix string) ([]string, error) { keys := []string{} - err := s.client.ListObjectsV2PagesWithContext(ctx, params, + err := s.client.ListObjectsV2Pages(params, func(page *s3.ListObjectsV2Output, lastPage bool) bool { if page != nil { // Add truncated 'folder' paths diff --git a/plugins/database/mssql/mssql.go b/plugins/database/mssql/mssql.go index 488d7f39226d..833202b8d406 100644 --- a/plugins/database/mssql/mssql.go +++ b/plugins/database/mssql/mssql.go @@ -285,7 +285,7 @@ func (m *MSSQL) revokeUserDefault(ctx context.Context, username string) error { rows, err := stmt.QueryContext(ctx, username) if err != nil { - return fmt.Errorf("failed to query users: %w", err) + return err } defer rows.Close() diff --git a/plugins/database/mssql/mssql_test.go b/plugins/database/mssql/mssql_test.go index d549d52cd178..6e866fea9505 100644 --- a/plugins/database/mssql/mssql_test.go +++ b/plugins/database/mssql/mssql_test.go @@ -294,7 +294,7 @@ func TestUpdateUser_password(t *testing.T) { Username: dbUser, } - ctx, cancel = context.WithTimeout(context.Background(), 20*time.Second) + ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) defer cancel() deleteResp, err := db.DeleteUser(ctx, deleteReq) if err != nil { @@ -342,7 +342,7 @@ func TestDeleteUser(t *testing.T) { Username: dbUser, } - ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() deleteResp, err := db.DeleteUser(ctx, deleteReq) if err != nil { diff --git a/plugins/database/mysql/connection_producer.go b/plugins/database/mysql/connection_producer.go index f35bfaf522fb..0fb027bb29d1 100644 --- a/plugins/database/mysql/connection_producer.go +++ b/plugins/database/mysql/connection_producer.go @@ -123,8 +123,11 @@ func (c *mySQLConnectionProducer) Init(ctx context.Context, conf map[string]inte } // validate auth_type if provided - if ok := connutil.ValidateAuthType(c.AuthType); !ok { - return nil, fmt.Errorf("invalid auth_type: %s", c.AuthType) + authType := c.AuthType + if authType != "" { + if ok := connutil.ValidateAuthType(authType); !ok { + return nil, fmt.Errorf("invalid auth_type %s provided", authType) + } } if c.AuthType == connutil.AuthTypeGCPIAM { @@ -319,7 +322,7 @@ func (c *mySQLConnectionProducer) rewriteProtocolForGCP(inDSN string) (string, e } func registerDriverMySQL(driverName, credentials string) (cleanup func() error, err error) { - opts, err := connutil.GetCloudSQLAuthOptions(credentials, false) + opts, err := connutil.GetCloudSQLAuthOptions(credentials) if err != nil { return nil, err } diff --git a/plugins/database/postgresql/postgresql.go b/plugins/database/postgresql/postgresql.go index ffe460f45c53..0bdd91641240 100644 --- a/plugins/database/postgresql/postgresql.go +++ b/plugins/database/postgresql/postgresql.go @@ -5,11 +5,7 @@ package postgresql import ( "context" - "crypto/tls" - "crypto/x509" "database/sql" - "encoding/pem" - "errors" "fmt" "regexp" "strings" @@ -83,65 +79,11 @@ func new() *PostgreSQL { type PostgreSQL struct { *connutil.SQLConnectionProducer - TLSCertificateData []byte `json:"tls_certificate" structs:"-" mapstructure:"tls_certificate"` - TLSPrivateKey []byte `json:"private_key" structs:"-" mapstructure:"private_key"` - TLSCAData []byte `json:"tls_ca" structs:"-" mapstructure:"tls_ca"` - usernameProducer template.StringTemplate passwordAuthentication passwordAuthentication } func (p *PostgreSQL) Initialize(ctx context.Context, req dbplugin.InitializeRequest) (dbplugin.InitializeResponse, error) { - sslcert, err := strutil.GetString(req.Config, "tls_certificate") - if err != nil { - return dbplugin.InitializeResponse{}, fmt.Errorf("failed to retrieve tls_certificate: %w", err) - } - - sslkey, err := strutil.GetString(req.Config, "private_key") - if err != nil { - return dbplugin.InitializeResponse{}, fmt.Errorf("failed to retrieve private_key: %w", err) - } - - sslrootcert, err := strutil.GetString(req.Config, "tls_ca") - if err != nil { - return dbplugin.InitializeResponse{}, fmt.Errorf("failed to retrieve tls_ca: %w", err) - } - - useTLS := false - tlsConfig := &tls.Config{} - if sslrootcert != "" { - caCertPool := x509.NewCertPool() - if !caCertPool.AppendCertsFromPEM([]byte(sslrootcert)) { - return dbplugin.InitializeResponse{}, errors.New("unable to add CA to cert pool") - } - - tlsConfig.RootCAs = caCertPool - tlsConfig.ClientCAs = caCertPool - p.TLSConfig = tlsConfig - useTLS = true - } - - if (sslcert != "" && sslkey == "") || (sslcert == "" && sslkey != "") { - return dbplugin.InitializeResponse{}, errors.New(`both "sslcert" and "sslkey" are required`) - } - - if sslcert != "" && sslkey != "" { - block, _ := pem.Decode([]byte(sslkey)) - - cert, err := tls.X509KeyPair([]byte(sslcert), pem.EncodeToMemory(block)) - if err != nil { - return dbplugin.InitializeResponse{}, fmt.Errorf("unable to load cert: %w", err) - } - tlsConfig.Certificates = []tls.Certificate{cert} - p.TLSConfig = tlsConfig - useTLS = true - } - - if !useTLS { - // set to nil to flag that this connection does not use a custom TLS config - p.TLSConfig = nil - } - newConf, err := p.SQLConnectionProducer.Init(ctx, req.Config, req.VerifyConnection) if err != nil { return dbplugin.InitializeResponse{}, err @@ -199,15 +141,6 @@ func (p *PostgreSQL) getConnection(ctx context.Context) (*sql.DB, error) { return db.(*sql.DB), nil } -func (p *PostgreSQL) getStaticConnection(ctx context.Context, username, password string) (*sql.DB, error) { - db, err := p.StaticConnection(ctx, username, password) - if err != nil { - return nil, err - } - - return db, nil -} - func (p *PostgreSQL) UpdateUser(ctx context.Context, req dbplugin.UpdateUserRequest) (dbplugin.UpdateUserResponse, error) { if req.Username == "" { return dbplugin.UpdateUserResponse{}, fmt.Errorf("missing username") @@ -218,17 +151,17 @@ func (p *PostgreSQL) UpdateUser(ctx context.Context, req dbplugin.UpdateUserRequ merr := &multierror.Error{} if req.Password != nil { - err := p.changeUserPassword(ctx, req.Username, req.Password, req.SelfManagedPassword) + err := p.changeUserPassword(ctx, req.Username, req.Password) merr = multierror.Append(merr, err) } if req.Expiration != nil { - err := p.changeUserExpiration(ctx, req.Username, req.Expiration, req.SelfManagedPassword) + err := p.changeUserExpiration(ctx, req.Username, req.Expiration) merr = multierror.Append(merr, err) } return dbplugin.UpdateUserResponse{}, merr.ErrorOrNil() } -func (p *PostgreSQL) changeUserPassword(ctx context.Context, username string, changePass *dbplugin.ChangePassword, selfManagedPass string) error { +func (p *PostgreSQL) changeUserPassword(ctx context.Context, username string, changePass *dbplugin.ChangePassword) error { stmts := changePass.Statements.Commands if len(stmts) == 0 { stmts = []string{defaultChangePasswordStatement} @@ -242,18 +175,9 @@ func (p *PostgreSQL) changeUserPassword(ctx context.Context, username string, ch p.Lock() defer p.Unlock() - var db *sql.DB - var err error - if selfManagedPass == "" { - db, err = p.getConnection(ctx) - if err != nil { - return fmt.Errorf("unable to get connection: %w", err) - } - } else { - db, err = p.getStaticConnection(ctx, username, selfManagedPass) - if err != nil { - return fmt.Errorf("unable to get static connection from cache: %w", err) - } + db, err := p.getConnection(ctx) + if err != nil { + return fmt.Errorf("unable to get connection: %w", err) } // Check if the role exists @@ -303,7 +227,7 @@ func (p *PostgreSQL) changeUserPassword(ctx context.Context, username string, ch return nil } -func (p *PostgreSQL) changeUserExpiration(ctx context.Context, username string, changeExp *dbplugin.ChangeExpiration, selfManagedPass string) error { +func (p *PostgreSQL) changeUserExpiration(ctx context.Context, username string, changeExp *dbplugin.ChangeExpiration) error { p.Lock() defer p.Unlock() @@ -312,18 +236,9 @@ func (p *PostgreSQL) changeUserExpiration(ctx context.Context, username string, renewStmts = []string{defaultExpirationStatement} } - var db *sql.DB - var err error - if selfManagedPass == "" { - db, err = p.getConnection(ctx) - if err != nil { - return fmt.Errorf("unable to get connection: %w", err) - } - } else { - db, err = p.getStaticConnection(ctx, username, selfManagedPass) - if err != nil { - return fmt.Errorf("unable to get static connection from cache: %w", err) - } + db, err := p.getConnection(ctx) + if err != nil { + return err } tx, err := db.BeginTx(ctx, nil) @@ -529,7 +444,7 @@ func (p *PostgreSQL) defaultDeleteUser(ctx context.Context, username string) err } revocationStmts = append(revocationStmts, fmt.Sprintf( `REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA %s FROM %s;`, - dbutil.QuoteIdentifier(schema), + (schema), dbutil.QuoteIdentifier(username))) revocationStmts = append(revocationStmts, fmt.Sprintf( diff --git a/plugins/database/postgresql/postgresql_test.go b/plugins/database/postgresql/postgresql_test.go index 281c42990e18..90184e10a3eb 100644 --- a/plugins/database/postgresql/postgresql_test.go +++ b/plugins/database/postgresql/postgresql_test.go @@ -12,21 +12,19 @@ import ( "testing" "time" - "github.com/hashicorp/vault/helper/constants" - "github.com/hashicorp/vault/helper/testhelpers/certhelpers" "github.com/hashicorp/vault/helper/testhelpers/postgresql" "github.com/hashicorp/vault/sdk/database/dbplugin/v5" dbtesting "github.com/hashicorp/vault/sdk/database/dbplugin/v5/testing" "github.com/hashicorp/vault/sdk/database/helper/connutil" "github.com/hashicorp/vault/sdk/database/helper/dbutil" - "github.com/hashicorp/vault/sdk/helper/pluginutil" + "github.com/hashicorp/vault/sdk/helper/docker" "github.com/hashicorp/vault/sdk/helper/template" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func getPostgreSQL(t *testing.T, options map[string]interface{}) (*PostgreSQL, func()) { - cleanup, connURL := postgresql.PrepareTestContainer(t) + cleanup, connURL := postgresql.PrepareTestContainer(t, "13.4-buster") connectionDetails := map[string]interface{}{ "connection_url": connURL, @@ -60,463 +58,6 @@ func TestPostgreSQL_Initialize(t *testing.T) { } } -// TestPostgreSQL_InitializeMultiHost tests the functionality of Postgres's -// multi-host connection strings. -func TestPostgreSQL_InitializeMultiHost(t *testing.T) { - cleanup, connURL := postgresql.PrepareTestContainerMultiHost(t) - defer cleanup() - - connectionDetails := map[string]interface{}{ - "connection_url": connURL, - "max_open_connections": 5, - } - - req := dbplugin.InitializeRequest{ - Config: connectionDetails, - VerifyConnection: true, - } - - db := new() - dbtesting.AssertInitialize(t, db, req) - - if !db.Initialized { - t.Fatal("Database should be initialized") - } - - if err := db.Close(); err != nil { - t.Fatalf("err: %s", err) - } -} - -// TestPostgreSQL_InitializeSSLInlineFeatureFlag tests that the VAULT_PLUGIN_USE_POSTGRES_SSLINLINE -// flag guards against unwanted usage of the deprecated SSL client authentication path. -// TODO: remove this when we remove the underlying feature in a future SDK version -func TestPostgreSQL_InitializeSSLInlineFeatureFlag(t *testing.T) { - // set the flag to true so we can call PrepareTestContainerWithSSL - // which does a validation check on the connection - t.Setenv(pluginutil.PluginUsePostgresSSLInline, "true") - - // Create certificates for postgres authentication - caCert := certhelpers.NewCert(t, certhelpers.CommonName("ca"), certhelpers.IsCA(true), certhelpers.SelfSign()) - clientCert := certhelpers.NewCert(t, certhelpers.CommonName("postgres"), certhelpers.DNS("localhost"), certhelpers.Parent(caCert)) - cleanup, connURL := postgresql.PrepareTestContainerWithSSL(t, "verify-ca", caCert, clientCert, false) - t.Cleanup(cleanup) - - type testCase struct { - env string - wantErr bool - expectedError string - } - - tests := map[string]testCase{ - "feature flag is true": { - env: "true", - wantErr: false, - expectedError: "", - }, - "feature flag is unset or empty": { - env: "", - wantErr: true, - // this error is expected because the env var unset means we are - // using pgx's native connection string parsing which does not - // support inlining of the certificate material in the sslrootcert, - // sslcert, and sslkey fields - expectedError: "error verifying connection", - }, - "feature flag is false": { - env: "false", - wantErr: true, - expectedError: "failed to open postgres connection with deprecated funtion", - }, - "feature flag is invalid": { - env: "foo", - wantErr: true, - expectedError: "failed to open postgres connection with deprecated funtion", - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - // update the env var with the value we are testing - t.Setenv(pluginutil.PluginUsePostgresSSLInline, test.env) - - connectionDetails := map[string]interface{}{ - "connection_url": connURL, - "max_open_connections": 5, - } - - req := dbplugin.InitializeRequest{ - Config: connectionDetails, - VerifyConnection: true, - } - - db := new() - _, err := dbtesting.VerifyInitialize(t, db, req) - if test.wantErr && err == nil { - t.Fatal("expected error, got nil") - } else if test.wantErr && !strings.Contains(err.Error(), test.expectedError) { - t.Fatalf("got: %s, want: %s", err.Error(), test.expectedError) - } - - if !test.wantErr && !db.Initialized { - t.Fatal("Database should be initialized") - } - - if err := db.Close(); err != nil { - t.Fatalf("err: %s", err) - } - // unset for the next test case - os.Unsetenv(pluginutil.PluginUsePostgresSSLInline) - }) - } -} - -// TestPostgreSQL_InitializeSSLInline tests that we can successfully authenticate -// with a postgres server via ssl with a URL connection string or DSN (key/value) -// for each ssl mode. -// TODO: remove this when we remove the underlying feature in a future SDK version -func TestPostgreSQL_InitializeSSLInline(t *testing.T) { - // required to enable the sslinline custom parsing - t.Setenv(pluginutil.PluginUsePostgresSSLInline, "true") - - type testCase struct { - sslMode string - useDSN bool - useFallback bool - wantErr bool - expectedError string - } - - tests := map[string]testCase{ - "disable sslmode": { - sslMode: "disable", - wantErr: true, - expectedError: "error verifying connection", - }, - "allow sslmode": { - sslMode: "allow", - wantErr: false, - }, - "prefer sslmode": { - sslMode: "prefer", - wantErr: false, - }, - "require sslmode": { - sslMode: "require", - wantErr: false, - }, - "verify-ca sslmode": { - sslMode: "verify-ca", - wantErr: false, - }, - "disable sslmode with DSN": { - sslMode: "disable", - useDSN: true, - wantErr: true, - expectedError: "error verifying connection", - }, - "allow sslmode with DSN": { - sslMode: "allow", - useDSN: true, - wantErr: false, - }, - "prefer sslmode with DSN": { - sslMode: "prefer", - useDSN: true, - wantErr: false, - }, - "require sslmode with DSN": { - sslMode: "require", - useDSN: true, - wantErr: false, - }, - "verify-ca sslmode with DSN": { - sslMode: "verify-ca", - useDSN: true, - wantErr: false, - }, - "disable sslmode with fallback": { - sslMode: "disable", - useFallback: true, - wantErr: true, - expectedError: "error verifying connection", - }, - "allow sslmode with fallback": { - sslMode: "allow", - useFallback: true, - }, - "prefer sslmode with fallback": { - sslMode: "prefer", - useFallback: true, - }, - "require sslmode with fallback": { - sslMode: "require", - useFallback: true, - }, - "verify-ca sslmode with fallback": { - sslMode: "verify-ca", - useFallback: true, - }, - "disable sslmode with DSN with fallback": { - sslMode: "disable", - useDSN: true, - useFallback: true, - wantErr: true, - expectedError: "error verifying connection", - }, - "allow sslmode with DSN with fallback": { - sslMode: "allow", - useDSN: true, - useFallback: true, - wantErr: false, - }, - "prefer sslmode with DSN with fallback": { - sslMode: "prefer", - useDSN: true, - useFallback: true, - wantErr: false, - }, - "require sslmode with DSN with fallback": { - sslMode: "require", - useDSN: true, - useFallback: true, - wantErr: false, - }, - "verify-ca sslmode with DSN with fallback": { - sslMode: "verify-ca", - useDSN: true, - useFallback: true, - wantErr: false, - }, - } - for name, test := range tests { - t.Run(name, func(t *testing.T) { - t.Parallel() - - // Create certificates for postgres authentication - caCert := certhelpers.NewCert(t, certhelpers.CommonName("ca"), certhelpers.IsCA(true), certhelpers.SelfSign()) - clientCert := certhelpers.NewCert(t, certhelpers.CommonName("postgres"), certhelpers.DNS("localhost"), certhelpers.Parent(caCert)) - cleanup, connURL := postgresql.PrepareTestContainerWithSSL(t, test.sslMode, caCert, clientCert, test.useFallback) - t.Cleanup(cleanup) - - if test.useDSN { - var err error - connURL, err = dbutil.ParseURL(connURL) - if err != nil { - t.Fatal(err) - } - } - connectionDetails := map[string]interface{}{ - "connection_url": connURL, - "max_open_connections": 5, - } - - req := dbplugin.InitializeRequest{ - Config: connectionDetails, - VerifyConnection: true, - } - - db := new() - _, err := dbtesting.VerifyInitialize(t, db, req) - if test.wantErr && err == nil { - t.Fatal("expected error, got nil") - } else if test.wantErr && !strings.Contains(err.Error(), test.expectedError) { - t.Fatalf("got: %s, want: %s", err.Error(), test.expectedError) - } - - if !test.wantErr && !db.Initialized { - t.Fatal("Database should be initialized") - } - - if err := db.Close(); err != nil { - t.Fatalf("err: %s", err) - } - }) - } -} - -// TestPostgreSQL_InitializeSSL tests that we can successfully authenticate -// with a postgres server via ssl with a URL connection string or DSN (key/value) -// for each ssl mode. -func TestPostgreSQL_InitializeSSL(t *testing.T) { - type testCase struct { - sslMode string - useDSN bool - useFallback bool - wantErr bool - expectedError string - } - - tests := map[string]testCase{ - "disable sslmode": { - sslMode: "disable", - wantErr: true, - expectedError: "error verifying connection", - }, - "allow sslmode": { - sslMode: "allow", - wantErr: false, - }, - "prefer sslmode": { - sslMode: "prefer", - wantErr: false, - }, - "require sslmode": { - sslMode: "require", - wantErr: false, - }, - "verify-ca sslmode": { - sslMode: "verify-ca", - wantErr: false, - }, - "verify-full sslmode": { - sslMode: "verify-full", - wantErr: false, - }, - "disable sslmode with DSN": { - sslMode: "disable", - useDSN: true, - wantErr: true, - expectedError: "error verifying connection", - }, - "allow sslmode with DSN": { - sslMode: "allow", - useDSN: true, - wantErr: false, - }, - "prefer sslmode with DSN": { - sslMode: "prefer", - useDSN: true, - wantErr: false, - }, - "require sslmode with DSN": { - sslMode: "require", - useDSN: true, - wantErr: false, - }, - "verify-ca sslmode with DSN": { - sslMode: "verify-ca", - useDSN: true, - wantErr: false, - }, - "verify-full sslmode with DSN": { - sslMode: "verify-full", - useDSN: true, - wantErr: false, - }, - "disable sslmode with fallback": { - sslMode: "disable", - useFallback: true, - wantErr: true, - expectedError: "error verifying connection", - }, - "allow sslmode with fallback": { - sslMode: "allow", - useFallback: true, - }, - "prefer sslmode with fallback": { - sslMode: "prefer", - useFallback: true, - }, - "require sslmode with fallback": { - sslMode: "require", - useFallback: true, - }, - "verify-ca sslmode with fallback": { - sslMode: "verify-ca", - useFallback: true, - }, - "verify-full sslmode with fallback": { - sslMode: "verify-full", - useFallback: true, - }, - "disable sslmode with DSN with fallback": { - sslMode: "disable", - useDSN: true, - useFallback: true, - wantErr: true, - expectedError: "error verifying connection", - }, - "allow sslmode with DSN with fallback": { - sslMode: "allow", - useDSN: true, - useFallback: true, - wantErr: false, - }, - "prefer sslmode with DSN with fallback": { - sslMode: "prefer", - useDSN: true, - useFallback: true, - wantErr: false, - }, - "require sslmode with DSN with fallback": { - sslMode: "require", - useDSN: true, - useFallback: true, - wantErr: false, - }, - "verify-ca sslmode with DSN with fallback": { - sslMode: "verify-ca", - useDSN: true, - useFallback: true, - wantErr: false, - }, - "verify-full sslmode with DSN with fallback": { - sslMode: "verify-full", - useDSN: true, - useFallback: true, - wantErr: false, - }, - } - for name, test := range tests { - t.Run(name, func(t *testing.T) { - t.Parallel() - - // Create certificates for postgres authentication - caCert := certhelpers.NewCert(t, certhelpers.CommonName("ca"), certhelpers.IsCA(true), certhelpers.SelfSign()) - clientCert := certhelpers.NewCert(t, certhelpers.CommonName("postgres"), certhelpers.DNS("localhost"), certhelpers.Parent(caCert)) - cleanup, connURL := postgresql.PrepareTestContainerWithSSL(t, test.sslMode, caCert, clientCert, test.useFallback) - t.Cleanup(cleanup) - - if test.useDSN { - var err error - connURL, err = dbutil.ParseURL(connURL) - if err != nil { - t.Fatal(err) - } - } - connectionDetails := map[string]interface{}{ - "connection_url": connURL, - "max_open_connections": 5, - "tls_certificate": string(clientCert.CombinedPEM()), - "private_key": string(clientCert.PrivateKeyPEM()), - "tls_ca": string(caCert.CombinedPEM()), - } - - req := dbplugin.InitializeRequest{ - Config: connectionDetails, - VerifyConnection: true, - } - - db := new() - _, err := dbtesting.VerifyInitialize(t, db, req) - if test.wantErr && err == nil { - t.Fatal("expected error, got nil") - } else if test.wantErr && !strings.Contains(err.Error(), test.expectedError) { - t.Fatalf("got: %s, want: %s", err.Error(), test.expectedError) - } - - if !test.wantErr && !db.Initialized { - t.Fatal("Database should be initialized") - } - - if err := db.Close(); err != nil { - t.Fatalf("err: %s", err) - } - }) - } -} - func TestPostgreSQL_InitializeWithStringVals(t *testing.T) { db, cleanup := getPostgreSQL(t, map[string]interface{}{ "max_open_connections": "5", @@ -529,7 +70,7 @@ func TestPostgreSQL_InitializeWithStringVals(t *testing.T) { } func TestPostgreSQL_Initialize_ConnURLWithDSNFormat(t *testing.T) { - cleanup, connURL := postgresql.PrepareTestContainer(t) + cleanup, connURL := postgresql.PrepareTestContainer(t, "13.4-buster") defer cleanup() dsnConnURL, err := dbutil.ParseURL(connURL) @@ -641,102 +182,10 @@ func TestPostgreSQL_Initialize_CloudGCP(t *testing.T) { } } -// TestPostgreSQL_Initialize_SelfManaged_OSS tests the initialization of -// the self-managed flow and ensures an error is returned on OSS. -func TestPostgreSQL_Initialize_SelfManaged_OSS(t *testing.T) { - if constants.IsEnterprise { - t.Skip("this test is only valid on OSS") - } - - cleanup, url := postgresql.PrepareTestContainerSelfManaged(t) - defer cleanup() - - connURL := fmt.Sprintf("postgresql://{{username}}:{{password}}@%s/postgres?sslmode=disable", url.Host) - - testCases := []struct { - name string - connectionDetails map[string]interface{} - wantErr bool - errContains string - }{ - { - name: "no parameters set", - connectionDetails: map[string]interface{}{ - "connection_url": connURL, - "self_managed": false, - "username": "", - "password": "", - }, - wantErr: true, - errContains: "must either provide username/password or set self-managed to 'true'", - }, - { - name: "both sets of parameters set", - connectionDetails: map[string]interface{}{ - "connection_url": connURL, - "self_managed": true, - "username": "test", - "password": "test", - }, - wantErr: true, - errContains: "cannot use both self-managed and vault-managed workflows", - }, - { - name: "either username/password with self-managed", - connectionDetails: map[string]interface{}{ - "connection_url": connURL, - "self_managed": true, - "username": "test", - "password": "", - }, - wantErr: true, - errContains: "cannot use both self-managed and vault-managed workflows", - }, - { - name: "cache not implemented", - connectionDetails: map[string]interface{}{ - "connection_url": connURL, - "self_managed": true, - "username": "", - "password": "", - }, - wantErr: true, - errContains: "self-managed static roles only available in Vault Enterprise", - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - req := dbplugin.InitializeRequest{ - Config: tc.connectionDetails, - VerifyConnection: true, - } - - db := new() - _, err := dbtesting.VerifyInitialize(t, db, req) - if err == nil && tc.wantErr { - t.Fatalf("got: %s, wantErr: %t", err, tc.wantErr) - } - - if err != nil && !strings.Contains(err.Error(), tc.errContains) { - t.Fatalf("expected error: %s, received error: %s", tc.errContains, err) - } - - if !tc.wantErr && !db.Initialized { - t.Fatal("Database should be initialized") - } - - if err := db.Close(); err != nil { - t.Fatalf("err closing DB: %s", err) - } - }) - } -} - // TestPostgreSQL_PasswordAuthentication tests that the default "password_authentication" is "none", and that // an error is returned if an invalid "password_authentication" is provided. func TestPostgreSQL_PasswordAuthentication(t *testing.T) { - cleanup, connURL := postgresql.PrepareTestContainer(t) + cleanup, connURL := postgresql.PrepareTestContainer(t, "13.4-buster") defer cleanup() dsnConnURL, err := dbutil.ParseURL(connURL) @@ -778,7 +227,7 @@ func TestPostgreSQL_PasswordAuthentication(t *testing.T) { // TestPostgreSQL_PasswordAuthentication_SCRAMSHA256 tests that password_authentication works when set to scram-sha-256. // When sending an encrypted password, the raw password should still successfully authenticate the user. func TestPostgreSQL_PasswordAuthentication_SCRAMSHA256(t *testing.T) { - cleanup, connURL := postgresql.PrepareTestContainer(t) + cleanup, connURL := postgresql.PrepareTestContainer(t, "13.4-buster") defer cleanup() dsnConnURL, err := dbutil.ParseURL(connURL) @@ -1138,41 +587,6 @@ func TestUpdateUser_Password(t *testing.T) { }) } -// TestUpdateUser_SelfManaged_OSS checks basic validation -// for self-managed fields and confirms an error is returned on OSS -func TestUpdateUser_SelfManaged_OSS(t *testing.T) { - if constants.IsEnterprise { - t.Skip("this test is only valid on OSS") - } - - // Shared test container for speed - there should not be any overlap between the tests - db, cleanup := getPostgreSQL(t, nil) - defer cleanup() - - updateReq := dbplugin.UpdateUserRequest{ - Username: "static", - Password: &dbplugin.ChangePassword{ - NewPassword: "somenewpassword", - Statements: dbplugin.Statements{ - Commands: nil, - }, - }, - SelfManagedPassword: "test", - } - - expectedErr := "self-managed static roles only available in Vault Enterprise" - - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - _, err := db.UpdateUser(ctx, updateReq) - if err == nil { - t.Fatalf("err expected, got nil") - } - if !strings.Contains(err.Error(), expectedErr) { - t.Fatalf("err expected: %s, got: %s", expectedErr, err) - } -} - func TestUpdateUser_Expiration(t *testing.T) { type testCase struct { initialExpiration time.Time @@ -1678,7 +1092,7 @@ func TestUsernameGeneration(t *testing.T) { } func TestNewUser_CustomUsername(t *testing.T) { - cleanup, connURL := postgresql.PrepareTestContainer(t) + cleanup, connURL := postgresql.PrepareTestContainer(t, "13.4-buster") defer cleanup() type testCase struct { @@ -1854,6 +1268,139 @@ func TestNewUser_CloudGCP(t *testing.T) { } } +// This is a long-running integration test which tests the functionality of Postgres's multi-host +// connection strings. It uses two Postgres containers preconfigured with Replication Manager +// provided by Bitnami. This test currently does not run in CI and must be run manually. This is +// due to the test length, as it requires multiple sleep calls to ensure cluster setup and +// primary node failover occurs before the test steps continue. +// +// To run the test, set the environment variable POSTGRES_MULTIHOST_NET to the value of +// a docker network you've preconfigured, e.g. +// 'docker network create -d bridge postgres-repmgr' +// 'export POSTGRES_MULTIHOST_NET=postgres-repmgr' +func TestPostgreSQL_Repmgr(t *testing.T) { + _, exists := os.LookupEnv("POSTGRES_MULTIHOST_NET") + if !exists { + t.Skipf("POSTGRES_MULTIHOST_NET not set, skipping test") + } + + // Run two postgres-repmgr containers in a replication cluster + db0, runner0, url0, container0 := testPostgreSQL_Repmgr_Container(t, "psql-repl-node-0") + _, _, url1, _ := testPostgreSQL_Repmgr_Container(t, "psql-repl-node-1") + + ctx, cancel := context.WithTimeout(context.Background(), 300*time.Second) + defer cancel() + + time.Sleep(10 * time.Second) + + // Write a read role to the cluster + _, err := db0.NewUser(ctx, dbplugin.NewUserRequest{ + Statements: dbplugin.Statements{ + Commands: []string{ + `CREATE ROLE "ro" NOINHERIT; + GRANT SELECT ON ALL TABLES IN SCHEMA public TO "ro";`, + }, + }, + }) + if err != nil { + t.Fatalf("no error expected, got: %s", err) + } + + // Open a connection to both databases using the multihost connection string + connectionDetails := map[string]interface{}{ + "connection_url": fmt.Sprintf("postgresql://{{username}}:{{password}}@%s,%s/postgres?target_session_attrs=read-write", getHost(url0), getHost(url1)), + "username": "postgres", + "password": "secret", + } + req := dbplugin.InitializeRequest{ + Config: connectionDetails, + VerifyConnection: true, + } + + db := new() + dbtesting.AssertInitialize(t, db, req) + if !db.Initialized { + t.Fatal("Database should be initialized") + } + defer db.Close() + + // Add a user to the cluster, then stop the primary container + if err = testPostgreSQL_Repmgr_AddUser(ctx, db); err != nil { + t.Fatalf("no error expected, got: %s", err) + } + postgresql.StopContainer(t, ctx, runner0, container0) + + // Try adding a new user immediately - expect failure as the database + // cluster is still switching primaries + err = testPostgreSQL_Repmgr_AddUser(ctx, db) + if !strings.HasSuffix(err.Error(), "ValidateConnect failed (read only connection)") { + t.Fatalf("expected error was not received, got: %s", err) + } + + time.Sleep(20 * time.Second) + + // Try adding a new user again which should succeed after the sleep + // as the primary failover should have finished. Then, restart + // the first container which should become a secondary DB. + if err = testPostgreSQL_Repmgr_AddUser(ctx, db); err != nil { + t.Fatalf("no error expected, got: %s", err) + } + postgresql.RestartContainer(t, ctx, runner0, container0) + + time.Sleep(10 * time.Second) + + // A final new user to add, which should succeed after the secondary joins. + if err = testPostgreSQL_Repmgr_AddUser(ctx, db); err != nil { + t.Fatalf("no error expected, got: %s", err) + } + + if err := db.Close(); err != nil { + t.Fatalf("err: %s", err) + } +} + +func testPostgreSQL_Repmgr_Container(t *testing.T, name string) (*PostgreSQL, *docker.Runner, string, string) { + envVars := []string{ + "REPMGR_NODE_NAME=" + name, + "REPMGR_NODE_NETWORK_NAME=" + name, + } + + runner, cleanup, connURL, containerID := postgresql.PrepareTestContainerRepmgr(t, name, "13.4.0", envVars) + t.Cleanup(cleanup) + + connectionDetails := map[string]interface{}{ + "connection_url": connURL, + } + req := dbplugin.InitializeRequest{ + Config: connectionDetails, + VerifyConnection: true, + } + db := new() + dbtesting.AssertInitialize(t, db, req) + if !db.Initialized { + t.Fatal("Database should be initialized") + } + + if err := db.Close(); err != nil { + t.Fatalf("err: %s", err) + } + + return db, runner, connURL, containerID +} + +func testPostgreSQL_Repmgr_AddUser(ctx context.Context, db *PostgreSQL) error { + _, err := db.NewUser(ctx, dbplugin.NewUserRequest{ + Statements: dbplugin.Statements{ + Commands: []string{ + `CREATE ROLE "{{name}}" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}' INHERIT; + GRANT ro TO "{{name}}";`, + }, + }, + }) + + return err +} + func getHost(url string) string { splitCreds := strings.Split(url, "@")[1] diff --git a/sdk/database/dbplugin/v5/conversions_test.go b/sdk/database/dbplugin/v5/conversions_test.go index c6b805bb9ff7..5e65c3467068 100644 --- a/sdk/database/dbplugin/v5/conversions_test.go +++ b/sdk/database/dbplugin/v5/conversions_test.go @@ -116,7 +116,6 @@ func TestConversionsHaveAllFields(t *testing.T) { }, }, }, - SelfManagedPassword: "test-password", } protoReq, err := updateUserReqToProto(req) @@ -195,7 +194,6 @@ func TestConversionsHaveAllFields(t *testing.T) { }, }, }, - SelfManagedPassword: "test-password", } protoReq, err := getUpdateUserRequest(req) diff --git a/sdk/database/dbplugin/v5/database.go b/sdk/database/dbplugin/v5/database.go index 2943451b7212..ddbcb6c81bbc 100644 --- a/sdk/database/dbplugin/v5/database.go +++ b/sdk/database/dbplugin/v5/database.go @@ -181,13 +181,6 @@ type UpdateUserRequest struct { // Expiration indicates the new expiration date to change to. // If nil, no change is requested. Expiration *ChangeExpiration - - // SelfManagedPassword is the password for an externally managed user in the DB. - // If this field is supplied, a DB connection is retrieved from the static - // account cache for the particular DB plugin and used to update the password of - // the self-managed static role. - // *ENTERPRISE-ONLY* - SelfManagedPassword string } // ChangePublicKey of a given user diff --git a/sdk/database/dbplugin/v5/grpc_client.go b/sdk/database/dbplugin/v5/grpc_client.go index 4e1ef57492a9..9b0b984f42af 100644 --- a/sdk/database/dbplugin/v5/grpc_client.go +++ b/sdk/database/dbplugin/v5/grpc_client.go @@ -199,12 +199,11 @@ func updateUserReqToProto(req UpdateUserRequest) (*proto.UpdateUserRequest, erro } rpcReq := &proto.UpdateUserRequest{ - Username: req.Username, - CredentialType: int32(req.CredentialType), - Password: password, - PublicKey: publicKey, - Expiration: expiration, - SelfManagedPassword: req.SelfManagedPassword, + Username: req.Username, + CredentialType: int32(req.CredentialType), + Password: password, + PublicKey: publicKey, + Expiration: expiration, } return rpcReq, nil } diff --git a/sdk/database/dbplugin/v5/grpc_server.go b/sdk/database/dbplugin/v5/grpc_server.go index 691de2d0a89e..7e1bc3fa1fc7 100644 --- a/sdk/database/dbplugin/v5/grpc_server.go +++ b/sdk/database/dbplugin/v5/grpc_server.go @@ -222,12 +222,11 @@ func getUpdateUserRequest(req *proto.UpdateUserRequest) (UpdateUserRequest, erro } dbReq := UpdateUserRequest{ - Username: req.GetUsername(), - CredentialType: CredentialType(req.GetCredentialType()), - Password: password, - PublicKey: publicKey, - Expiration: expiration, - SelfManagedPassword: req.SelfManagedPassword, + Username: req.GetUsername(), + CredentialType: CredentialType(req.GetCredentialType()), + Password: password, + PublicKey: publicKey, + Expiration: expiration, } if !hasChange(dbReq) { diff --git a/sdk/database/dbplugin/v5/proto/database.pb.go b/sdk/database/dbplugin/v5/proto/database.pb.go index 376315758927..745bd853342d 100644 --- a/sdk/database/dbplugin/v5/proto/database.pb.go +++ b/sdk/database/dbplugin/v5/proto/database.pb.go @@ -343,12 +343,11 @@ type UpdateUserRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` - Password *ChangePassword `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` - Expiration *ChangeExpiration `protobuf:"bytes,3,opt,name=expiration,proto3" json:"expiration,omitempty"` - PublicKey *ChangePublicKey `protobuf:"bytes,4,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` - CredentialType int32 `protobuf:"varint,5,opt,name=credential_type,json=credentialType,proto3" json:"credential_type,omitempty"` - SelfManagedPassword string `protobuf:"bytes,6,opt,name=self_managed_password,json=selfManagedPassword,proto3" json:"self_managed_password,omitempty"` + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` + Password *ChangePassword `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` + Expiration *ChangeExpiration `protobuf:"bytes,3,opt,name=expiration,proto3" json:"expiration,omitempty"` + PublicKey *ChangePublicKey `protobuf:"bytes,4,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` + CredentialType int32 `protobuf:"varint,5,opt,name=credential_type,json=credentialType,proto3" json:"credential_type,omitempty"` } func (x *UpdateUserRequest) Reset() { @@ -418,13 +417,6 @@ func (x *UpdateUserRequest) GetCredentialType() int32 { return 0 } -func (x *UpdateUserRequest) GetSelfManagedPassword() string { - if x != nil { - return x.SelfManagedPassword - } - return "" -} - type ChangePassword struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -918,7 +910,7 @@ var file_sdk_database_dbplugin_v5_proto_database_proto_rawDesc = []byte{ 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x2d, 0x0a, 0x0f, 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xc1, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x8d, 0x02, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, @@ -935,79 +927,76 @@ var file_sdk_database_dbplugin_v5_proto_database_proto_rawDesc = []byte{ 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, - 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x32, - 0x0a, 0x15, 0x73, 0x65, 0x6c, 0x66, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x64, 0x5f, 0x70, - 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, - 0x65, 0x6c, 0x66, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x64, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, - 0x72, 0x64, 0x22, 0x6c, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x65, 0x77, 0x50, - 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x37, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x64, 0x62, - 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x22, 0x70, 0x0a, 0x0f, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x4b, 0x65, 0x79, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6e, 0x65, 0x77, - 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x37, 0x0a, 0x0a, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x10, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x45, 0x78, 0x70, - 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0e, 0x6e, 0x65, 0x77, 0x5f, 0x65, - 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x6e, 0x65, 0x77, - 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x0a, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, - 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x22, 0x14, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x68, 0x0a, 0x11, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, - 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, - 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x22, 0x14, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x0a, 0x0c, 0x54, 0x79, 0x70, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x22, 0x28, 0x0a, - 0x0a, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x43, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x43, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x32, 0xa5, 0x03, 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x4d, 0x0a, - 0x0a, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x12, 0x1e, 0x2e, 0x64, 0x62, - 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, - 0x6c, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x64, 0x62, - 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, - 0x6c, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x07, - 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, - 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, - 0x76, 0x35, 0x2e, 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, - 0x12, 0x1e, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1f, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x4d, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, - 0x1e, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1f, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x35, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, - 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x64, - 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x05, 0x43, 0x6c, 0x6f, 0x73, 0x65, - 0x12, 0x12, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, - 0x76, 0x35, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, - 0x61, 0x73, 0x65, 0x2f, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x76, 0x35, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x22, 0x6c, + 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x65, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, + 0x6f, 0x72, 0x64, 0x12, 0x37, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x70, 0x0a, 0x0f, + 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, + 0x24, 0x0a, 0x0e, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6e, 0x65, 0x77, 0x50, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x37, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x64, 0x62, 0x70, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x8e, + 0x01, 0x0a, 0x10, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0e, 0x6e, 0x65, 0x77, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x6e, 0x65, 0x77, 0x45, 0x78, 0x70, 0x69, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x64, 0x62, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, + 0x14, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x68, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, + 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, + 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, + 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x64, 0x62, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, + 0x14, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x0a, 0x0c, 0x54, 0x79, 0x70, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x22, 0x28, 0x0a, 0x0a, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x43, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x73, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x32, 0xa5, 0x03, 0x0a, + 0x08, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0a, 0x49, 0x6e, 0x69, + 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x12, 0x1e, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x07, 0x4e, 0x65, 0x77, 0x55, + 0x73, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, + 0x35, 0x2e, 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1c, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x4e, + 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, + 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x64, + 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x64, + 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, + 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x64, 0x62, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x64, 0x62, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, + 0x76, 0x35, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, + 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x05, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x12, 0x12, 0x2e, 0x64, + 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x1a, 0x12, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x76, 0x61, 0x75, + 0x6c, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2f, + 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/sdk/database/dbplugin/v5/proto/database.proto b/sdk/database/dbplugin/v5/proto/database.proto index c30984ef758b..2b0ebde48574 100644 --- a/sdk/database/dbplugin/v5/proto/database.proto +++ b/sdk/database/dbplugin/v5/proto/database.proto @@ -53,7 +53,6 @@ message UpdateUserRequest { ChangeExpiration expiration = 3; ChangePublicKey public_key = 4; int32 credential_type = 5; - string self_managed_password = 6; } message ChangePassword { diff --git a/sdk/database/helper/cacheutil/cache_stubs_oss.go b/sdk/database/helper/cacheutil/cache_stubs_oss.go deleted file mode 100644 index 18e141832fcc..000000000000 --- a/sdk/database/helper/cacheutil/cache_stubs_oss.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -//go:build !enterprise - -package cacheutil - -import "errors" - -type EvictionFunc func(key interface{}, value interface{}) - -type Cache struct{} - -func NewCache(_ int, _ EvictionFunc) (*Cache, error) { - return nil, errors.New("self-managed static roles only available in Vault Enterprise") -} diff --git a/sdk/database/helper/connutil/cloudsql.go b/sdk/database/helper/connutil/cloudsql.go index f6cbba1d2407..5330c1cc22a7 100644 --- a/sdk/database/helper/connutil/cloudsql.go +++ b/sdk/database/helper/connutil/cloudsql.go @@ -10,6 +10,10 @@ import ( "cloud.google.com/go/cloudsqlconn/postgres/pgxv4" ) +var configurableAuthTypes = []string{ + AuthTypeGCPIAM, +} + func (c *SQLConnectionProducer) getCloudSQLDriverType() (string, error) { var driverType string // using switch case for future extensibility @@ -23,13 +27,13 @@ func (c *SQLConnectionProducer) getCloudSQLDriverType() (string, error) { return driverType, nil } -func (c *SQLConnectionProducer) registerDrivers(driverName string, credentials string, usePrivateIP bool) (func() error, error) { +func (c *SQLConnectionProducer) registerDrivers(driverName string, credentials string) (func() error, error) { typ, err := c.getCloudSQLDriverType() if err != nil { return nil, err } - opts, err := GetCloudSQLAuthOptions(credentials, usePrivateIP) + opts, err := GetCloudSQLAuthOptions(credentials) if err != nil { return nil, err } @@ -45,16 +49,24 @@ func (c *SQLConnectionProducer) registerDrivers(driverName string, credentials s // GetCloudSQLAuthOptions takes a credentials JSON and returns // a set of GCP CloudSQL options - always WithIAMAUthN, and then the appropriate file/JSON option. -func GetCloudSQLAuthOptions(credentials string, usePrivateIP bool) ([]cloudsqlconn.Option, error) { +func GetCloudSQLAuthOptions(credentials string) ([]cloudsqlconn.Option, error) { opts := []cloudsqlconn.Option{cloudsqlconn.WithIAMAuthN()} if credentials != "" { opts = append(opts, cloudsqlconn.WithCredentialsJSON([]byte(credentials))) } - if usePrivateIP { - opts = append(opts, cloudsqlconn.WithDefaultDialOptions(cloudsqlconn.WithPrivateIP())) + return opts, nil +} + +func ValidateAuthType(authType string) bool { + var valid bool + for _, typ := range configurableAuthTypes { + if authType == typ { + valid = true + break + } } - return opts, nil + return valid } diff --git a/sdk/database/helper/connutil/postgres.go b/sdk/database/helper/connutil/postgres.go deleted file mode 100644 index f8ad876c5a58..000000000000 --- a/sdk/database/helper/connutil/postgres.go +++ /dev/null @@ -1,466 +0,0 @@ -// Copyright (c) 2019-2021 Jack Christensen - -// MIT License - -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: - -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -// Copied from https://github.com/jackc/pgconn/blob/1860f4e57204614f40d05a5c76a43e8d80fde9da/config.go - -package connutil - -import ( - "context" - "crypto/tls" - "crypto/x509" - "database/sql" - "encoding/pem" - "errors" - "fmt" - "math" - "net" - "net/url" - "os" - "strconv" - "strings" - - "github.com/hashicorp/vault/sdk/helper/pluginutil" - "github.com/jackc/pgconn" - "github.com/jackc/pgx/v4" - "github.com/jackc/pgx/v4/stdlib" -) - -// openPostgres parses the connection string and opens a connection to the database. -// -// If sslinline is set, strips the connection string of all ssl settings and -// creates a TLS config based on the settings provided, then uses the -// RegisterConnConfig function to create a new connection. This is necessary -// because the pgx driver does not support the sslinline parameter and instead -// expects to source ssl material from the file system. -// -// Deprecated: openPostgres will be removed in a future version of the Vault SDK. -func openPostgres(driverName, connString string) (*sql.DB, error) { - if ok, _ := strconv.ParseBool(os.Getenv(pluginutil.PluginUsePostgresSSLInline)); !ok { - return nil, fmt.Errorf("failed to open postgres connection with deprecated funtion, set feature flag to enable") - } - - var options pgconn.ParseConfigOptions - - settings := make(map[string]string) - if connString != "" { - var err error - // connString may be a database URL or a DSN - if strings.HasPrefix(connString, "postgres://") || strings.HasPrefix(connString, "postgresql://") { - settings, err = parsePostgresURLSettings(connString) - if err != nil { - return nil, fmt.Errorf("failed to parse as URL: %w", err) - } - } else { - settings, err = parsePostgresDSNSettings(connString) - if err != nil { - return nil, fmt.Errorf("failed to parse as DSN: %w", err) - } - } - } - - // get the inline flag - sslInline := settings["sslinline"] == "true" - - // if sslinline is not set, open a regular connection - if !sslInline { - return sql.Open(driverName, connString) - } - - // generate a new DSN without the ssl settings - newConnStr := []string{"sslmode=disable"} - for k, v := range settings { - switch k { - case "sslinline", "sslcert", "sslkey", "sslrootcert", "sslmode": - continue - } - - newConnStr = append(newConnStr, fmt.Sprintf("%s='%s'", k, v)) - } - - // parse the updated config - config, err := pgx.ParseConfig(strings.Join(newConnStr, " ")) - if err != nil { - return nil, err - } - - // create a TLS config - fallbacks := []*pgconn.FallbackConfig{} - - hosts := strings.Split(settings["host"], ",") - ports := strings.Split(settings["port"], ",") - - for i, host := range hosts { - var portStr string - if i < len(ports) { - portStr = ports[i] - } else { - portStr = ports[0] - } - - port, err := parsePort(portStr) - if err != nil { - return nil, fmt.Errorf("invalid port: %w", err) - } - - var tlsConfigs []*tls.Config - - // Ignore TLS settings if Unix domain socket like libpq - if network, _ := pgconn.NetworkAddress(host, port); network == "unix" { - tlsConfigs = append(tlsConfigs, nil) - } else { - var err error - tlsConfigs, err = configPostgresTLS(settings, host, options) - if err != nil { - return nil, fmt.Errorf("failed to configure TLS: %w", err) - } - } - - for _, tlsConfig := range tlsConfigs { - fallbacks = append(fallbacks, &pgconn.FallbackConfig{ - Host: host, - Port: port, - TLSConfig: tlsConfig, - }) - } - } - - config.Host = fallbacks[0].Host - config.Port = fallbacks[0].Port - config.TLSConfig = fallbacks[0].TLSConfig - config.Fallbacks = fallbacks[1:] - - return sql.Open(driverName, stdlib.RegisterConnConfig(config)) -} - -// configPostgresTLS uses libpq's TLS parameters to construct []*tls.Config. It is -// necessary to allow returning multiple TLS configs as sslmode "allow" and -// "prefer" allow fallback. -// -// Copied from https://github.com/jackc/pgconn/blob/1860f4e57204614f40d05a5c76a43e8d80fde9da/config.go -// and modified to read ssl material by value instead of file location. -func configPostgresTLS(settings map[string]string, thisHost string, parseConfigOptions pgconn.ParseConfigOptions) ([]*tls.Config, error) { - host := thisHost - sslmode := settings["sslmode"] - sslrootcert := settings["sslrootcert"] - sslcert := settings["sslcert"] - sslkey := settings["sslkey"] - sslpassword := settings["sslpassword"] - sslsni := settings["sslsni"] - - // Match libpq default behavior - if sslmode == "" { - sslmode = "prefer" - } - if sslsni == "" { - sslsni = "1" - } - - tlsConfig := &tls.Config{} - - switch sslmode { - case "disable": - return []*tls.Config{nil}, nil - case "allow", "prefer": - tlsConfig.InsecureSkipVerify = true - case "require": - // According to PostgreSQL documentation, if a root CA file exists, - // the behavior of sslmode=require should be the same as that of verify-ca - // - // See https://www.postgresql.org/docs/12/libpq-ssl.html - if sslrootcert != "" { - goto nextCase - } - tlsConfig.InsecureSkipVerify = true - break - nextCase: - fallthrough - case "verify-ca": - // Don't perform the default certificate verification because it - // will verify the hostname. Instead, verify the server's - // certificate chain ourselves in VerifyPeerCertificate and - // ignore the server name. This emulates libpq's verify-ca - // behavior. - // - // See https://github.com/golang/go/issues/21971#issuecomment-332693931 - // and https://pkg.go.dev/crypto/tls?tab=doc#example-Config-VerifyPeerCertificate - // for more info. - tlsConfig.InsecureSkipVerify = true - tlsConfig.VerifyPeerCertificate = func(certificates [][]byte, _ [][]*x509.Certificate) error { - certs := make([]*x509.Certificate, len(certificates)) - for i, asn1Data := range certificates { - cert, err := x509.ParseCertificate(asn1Data) - if err != nil { - return errors.New("failed to parse certificate from server: " + err.Error()) - } - certs[i] = cert - } - - // Leave DNSName empty to skip hostname verification. - opts := x509.VerifyOptions{ - Roots: tlsConfig.RootCAs, - Intermediates: x509.NewCertPool(), - } - // Skip the first cert because it's the leaf. All others - // are intermediates. - for _, cert := range certs[1:] { - opts.Intermediates.AddCert(cert) - } - _, err := certs[0].Verify(opts) - return err - } - case "verify-full": - tlsConfig.ServerName = host - default: - return nil, errors.New("sslmode is invalid") - } - - if sslrootcert != "" { - caCertPool := x509.NewCertPool() - if !caCertPool.AppendCertsFromPEM([]byte(sslrootcert)) { - return nil, errors.New("unable to add CA to cert pool") - } - - tlsConfig.RootCAs = caCertPool - tlsConfig.ClientCAs = caCertPool - } - - if (sslcert != "" && sslkey == "") || (sslcert == "" && sslkey != "") { - return nil, errors.New(`both "sslcert" and "sslkey" are required`) - } - - if sslcert != "" && sslkey != "" { - block, _ := pem.Decode([]byte(sslkey)) - var pemKey []byte - var decryptedKey []byte - var decryptedError error - // If PEM is encrypted, attempt to decrypt using pass phrase - if x509.IsEncryptedPEMBlock(block) { - // Attempt decryption with pass phrase - // NOTE: only supports RSA (PKCS#1) - if sslpassword != "" { - decryptedKey, decryptedError = x509.DecryptPEMBlock(block, []byte(sslpassword)) - } - // if sslpassword not provided or has decryption error when use it - // try to find sslpassword with callback function - if sslpassword == "" || decryptedError != nil { - if parseConfigOptions.GetSSLPassword != nil { - sslpassword = parseConfigOptions.GetSSLPassword(context.Background()) - } - if sslpassword == "" { - return nil, fmt.Errorf("unable to find sslpassword") - } - } - decryptedKey, decryptedError = x509.DecryptPEMBlock(block, []byte(sslpassword)) - // Should we also provide warning for PKCS#1 needed? - if decryptedError != nil { - return nil, fmt.Errorf("unable to decrypt key: %w", decryptedError) - } - - pemBytes := pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: decryptedKey, - } - pemKey = pem.EncodeToMemory(&pemBytes) - } else { - pemKey = pem.EncodeToMemory(block) - } - - cert, err := tls.X509KeyPair([]byte(sslcert), pemKey) - if err != nil { - return nil, fmt.Errorf("unable to load cert: %w", err) - } - tlsConfig.Certificates = []tls.Certificate{cert} - } - - // Set Server Name Indication (SNI), if enabled by connection parameters. - // Per RFC 6066, do not set it if the host is a literal IP address (IPv4 - // or IPv6). - if sslsni == "1" && net.ParseIP(host) == nil { - tlsConfig.ServerName = host - } - - switch sslmode { - case "allow": - return []*tls.Config{nil, tlsConfig}, nil - case "prefer": - return []*tls.Config{tlsConfig, nil}, nil - case "require", "verify-ca", "verify-full": - return []*tls.Config{tlsConfig}, nil - default: - panic("BUG: bad sslmode should already have been caught") - } -} - -func parsePort(s string) (uint16, error) { - port, err := strconv.ParseUint(s, 10, 16) - if err != nil { - return 0, err - } - if port < 1 || port > math.MaxUint16 { - return 0, errors.New("outside range") - } - return uint16(port), nil -} - -var asciiSpace = [256]uint8{'\t': 1, '\n': 1, '\v': 1, '\f': 1, '\r': 1, ' ': 1} - -func parsePostgresURLSettings(connString string) (map[string]string, error) { - settings := make(map[string]string) - - url, err := url.Parse(connString) - if err != nil { - return nil, err - } - - if url.User != nil { - settings["user"] = url.User.Username() - if password, present := url.User.Password(); present { - settings["password"] = password - } - } - - // Handle multiple host:port's in url.Host by splitting them into host,host,host and port,port,port. - var hosts []string - var ports []string - for _, host := range strings.Split(url.Host, ",") { - if host == "" { - continue - } - if isIPOnly(host) { - hosts = append(hosts, strings.Trim(host, "[]")) - continue - } - h, p, err := net.SplitHostPort(host) - if err != nil { - return nil, fmt.Errorf("failed to split host:port in '%s', err: %w", host, err) - } - if h != "" { - hosts = append(hosts, h) - } - if p != "" { - ports = append(ports, p) - } - } - if len(hosts) > 0 { - settings["host"] = strings.Join(hosts, ",") - } - if len(ports) > 0 { - settings["port"] = strings.Join(ports, ",") - } - - database := strings.TrimLeft(url.Path, "/") - if database != "" { - settings["database"] = database - } - - nameMap := map[string]string{ - "dbname": "database", - } - - for k, v := range url.Query() { - if k2, present := nameMap[k]; present { - k = k2 - } - - settings[k] = v[0] - } - - return settings, nil -} - -func parsePostgresDSNSettings(s string) (map[string]string, error) { - settings := make(map[string]string) - - nameMap := map[string]string{ - "dbname": "database", - } - - for len(s) > 0 { - var key, val string - eqIdx := strings.IndexRune(s, '=') - if eqIdx < 0 { - return nil, errors.New("invalid dsn") - } - - key = strings.Trim(s[:eqIdx], " \t\n\r\v\f") - s = strings.TrimLeft(s[eqIdx+1:], " \t\n\r\v\f") - if len(s) == 0 { - } else if s[0] != '\'' { - end := 0 - for ; end < len(s); end++ { - if asciiSpace[s[end]] == 1 { - break - } - if s[end] == '\\' { - end++ - if end == len(s) { - return nil, errors.New("invalid backslash") - } - } - } - val = strings.Replace(strings.Replace(s[:end], "\\\\", "\\", -1), "\\'", "'", -1) - if end == len(s) { - s = "" - } else { - s = s[end+1:] - } - } else { // quoted string - s = s[1:] - end := 0 - for ; end < len(s); end++ { - if s[end] == '\'' { - break - } - if s[end] == '\\' { - end++ - } - } - if end == len(s) { - return nil, errors.New("unterminated quoted string in connection info string") - } - val = strings.Replace(strings.Replace(s[:end], "\\\\", "\\", -1), "\\'", "'", -1) - if end == len(s) { - s = "" - } else { - s = s[end+1:] - } - } - - if k, ok := nameMap[key]; ok { - key = k - } - - if key == "" { - return nil, errors.New("invalid dsn") - } - - settings[key] = val - } - - return settings, nil -} - -func isIPOnly(host string) bool { - return net.ParseIP(strings.Trim(host, "[]")) != nil || !strings.Contains(host, ":") -} diff --git a/sdk/database/helper/connutil/sql.go b/sdk/database/helper/connutil/sql.go index 489becf0c113..ca3cd489aa7d 100644 --- a/sdk/database/helper/connutil/sql.go +++ b/sdk/database/helper/connutil/sql.go @@ -5,43 +5,26 @@ package connutil import ( "context" - "crypto/tls" "database/sql" "fmt" "net/url" - "os" "strings" "sync" "time" "github.com/hashicorp/errwrap" - log "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-secure-stdlib/parseutil" "github.com/hashicorp/go-uuid" "github.com/hashicorp/vault/sdk/database/dbplugin" - "github.com/hashicorp/vault/sdk/database/helper/cacheutil" "github.com/hashicorp/vault/sdk/database/helper/dbutil" - "github.com/hashicorp/vault/sdk/helper/pluginutil" - "github.com/jackc/pgx/v4" - "github.com/jackc/pgx/v4/stdlib" "github.com/mitchellh/mapstructure" ) const ( - AuthTypeGCPIAM = "gcp_iam" - AuthTypeCert = "cert" - AuthTypeUsernamePassword = "" -) + AuthTypeGCPIAM = "gcp_iam" -const ( dbTypePostgres = "pgx" cloudSQLPostgres = "cloudsql-postgres" - - // controls the size of the static account cache - // as part of the self-managed workflow - defaultStaticCacheSize = 4 - defaultSelfManagedUsername = "self-managed-user" - defaultSelfManagedPassword = "self-managed-password" ) var _ ConnectionProducer = &SQLConnectionProducer{} @@ -52,20 +35,13 @@ type SQLConnectionProducer struct { MaxOpenConnections int `json:"max_open_connections" mapstructure:"max_open_connections" structs:"max_open_connections"` MaxIdleConnections int `json:"max_idle_connections" mapstructure:"max_idle_connections" structs:"max_idle_connections"` MaxConnectionLifetimeRaw interface{} `json:"max_connection_lifetime" mapstructure:"max_connection_lifetime" structs:"max_connection_lifetime"` + Username string `json:"username" mapstructure:"username" structs:"username"` + Password string `json:"password" mapstructure:"password" structs:"password"` + AuthType string `json:"auth_type" mapstructure:"auth_type" structs:"auth_type"` + ServiceAccountJSON string `json:"service_account_json" mapstructure:"service_account_json" structs:"service_account_json"` DisableEscaping bool `json:"disable_escaping" mapstructure:"disable_escaping" structs:"disable_escaping"` - usePrivateIP bool `json:"use_private_ip" mapstructure:"use_private_ip" structs:"use_private_ip"` - SelfManaged bool `json:"self_managed" mapstructure:"self_managed" structs:"self_managed"` - - // Username/Password is the default auth type when AuthType is not set - Username string `json:"username" mapstructure:"username" structs:"username"` - Password string `json:"password" mapstructure:"password" structs:"password"` - // AuthType defines the type of client authenticate used for this connection - AuthType string `json:"auth_type" mapstructure:"auth_type" structs:"auth_type"` - ServiceAccountJSON string `json:"service_account_json" mapstructure:"service_account_json" structs:"service_account_json"` - TLSConfig *tls.Config - - // cloudDriverName is globally unique, but only needs to be retained for the lifetime + // cloud options here - cloudDriverName is globally unique, but only needs to be retained for the lifetime // of driver registration, not across plugin restarts. cloudDriverName string cloudDialerCleanup func() error @@ -75,7 +51,6 @@ type SQLConnectionProducer struct { maxConnectionLifetime time.Duration Initialized bool db *sql.DB - staticAccountsCache *cacheutil.Cache sync.Mutex } @@ -99,11 +74,6 @@ func (c *SQLConnectionProducer) Init(ctx context.Context, conf map[string]interf return nil, fmt.Errorf("connection_url cannot be empty") } - isTemplatedURL := true - if !strings.Contains(c.ConnectionURL, "{{username}}") || !strings.Contains(c.ConnectionURL, "{{password}}") { - isTemplatedURL = false - } - // Do not allow the username or password template pattern to be used as // part of the user-supplied username or password if strings.Contains(c.Username, "{{username}}") || @@ -114,40 +84,16 @@ func (c *SQLConnectionProducer) Init(ctx context.Context, conf map[string]interf return nil, fmt.Errorf("username and/or password cannot contain the template variables") } - // validate that at least one of username/password / self_managed is set - if !c.SelfManaged && (c.Username == "" && c.Password == "") && isTemplatedURL { - return nil, fmt.Errorf("must either provide username/password or set self-managed to 'true'") + // Don't escape special characters for MySQL password + // Also don't escape special characters for the username and password if + // the disable_escaping parameter is set to true + username := c.Username + password := c.Password + if !c.DisableEscaping { + username = url.PathEscape(c.Username) } - - // validate that self-managed and username/password are mutually exclusive - if c.SelfManaged { - if (c.Username != "" || c.Password != "") || !isTemplatedURL { - return nil, fmt.Errorf("cannot use both self-managed and vault-managed workflows") - } - } - - var username string - var password string - if !c.SelfManaged { - // Default behavior - username = c.Username - password = c.Password - - // Don't escape special characters for MySQL password - // Also don't escape special characters for the username and password if - // the disable_escaping parameter is set to true - if !c.DisableEscaping { - username = url.PathEscape(c.Username) - } - if (c.Type != "mysql") && !c.DisableEscaping { - password = url.PathEscape(c.Password) - } - - } else { - // this is added to make middleware happy - // these placeholders are replaced when we make the actual static connection - username = defaultSelfManagedUsername - password = defaultSelfManagedPassword + if (c.Type != "mysql") && !c.DisableEscaping { + password = url.PathEscape(c.Password) } // QueryHelper doesn't do any SQL escaping, but if it starts to do so @@ -176,11 +122,15 @@ func (c *SQLConnectionProducer) Init(ctx context.Context, conf map[string]interf return nil, errwrap.Wrapf("invalid max_connection_lifetime: {{err}}", err) } - if ok := ValidateAuthType(c.AuthType); !ok { - return nil, fmt.Errorf("invalid auth_type: %s", c.AuthType) + // validate auth_type if provided + authType := c.AuthType + if authType != "" { + if ok := ValidateAuthType(authType); !ok { + return nil, fmt.Errorf("invalid auth_type %s provided", authType) + } } - if c.AuthType == AuthTypeGCPIAM { + if authType == AuthTypeGCPIAM { c.cloudDriverName, err = uuid.GenerateUUID() if err != nil { return nil, fmt.Errorf("unable to generate UUID for IAM configuration: %w", err) @@ -190,7 +140,7 @@ func (c *SQLConnectionProducer) Init(ctx context.Context, conf map[string]interf // however, the driver might store a credentials file, in which case the state stored by the driver is in // fact critical to the proper function of the connection. So it needs to be registered here inside the // ConnectionProducer init. - dialerCleanup, err := c.registerDrivers(c.cloudDriverName, c.ServiceAccountJSON, c.usePrivateIP) + dialerCleanup, err := c.registerDrivers(c.cloudDriverName, c.ServiceAccountJSON) if err != nil { return nil, err } @@ -198,41 +148,17 @@ func (c *SQLConnectionProducer) Init(ctx context.Context, conf map[string]interf c.cloudDialerCleanup = dialerCleanup } - if c.SelfManaged && c.staticAccountsCache == nil { - logger := log.New(&log.LoggerOptions{ - Level: log.Trace, - }) - - closer := func(key interface{}, value interface{}) { - logger.Trace(fmt.Sprintf("Evicting key %s from static LRU cache", key)) - conn, ok := value.(*sql.DB) - if !ok { - logger.Error(fmt.Sprintf("error retrieving connection %s from static LRU cache, err=%s", key, err)) - } - - if err := conn.Close(); err != nil { - logger.Error(fmt.Sprintf("error closing connection for %s, err=%s", key, err)) - } - logger.Trace(fmt.Sprintf("closed DB connection for %s", key)) - } - c.staticAccountsCache, err = cacheutil.NewCache(defaultStaticCacheSize, closer) - if err != nil { - return nil, fmt.Errorf("error initializing static account cache: %s", err) - } - } - // Set initialized to true at this point since all fields are set, // and the connection can be established at a later time. c.Initialized = true - // only verify if not self-managed - if verifyConnection && !c.SelfManaged { + if verifyConnection { if _, err := c.Connection(ctx); err != nil { return nil, errwrap.Wrapf("error verifying connection: {{err}}", err) } if err := c.db.PingContext(ctx); err != nil { - return nil, errwrap.Wrapf("error verifying connection: ping failed: {{err}}", err) + return nil, errwrap.Wrapf("error verifying connection: {{err}}", err) } } @@ -273,45 +199,27 @@ func (c *SQLConnectionProducer) Connection(ctx context.Context) (interface{}, er } // Otherwise, attempt to make connection - // Apply PostgreSQL specific settings if needed - conn := applyPostgresSettings(c.ConnectionURL) + conn := c.ConnectionURL - if driverName == dbTypePostgres && c.TLSConfig != nil { - config, err := pgx.ParseConfig(conn) - if err != nil { - return nil, fmt.Errorf("failed to parse config: %w", err) - } - if config.TLSConfig == nil { - // handle sslmode=disable - config.TLSConfig = &tls.Config{} + // PostgreSQL specific settings + if strings.HasPrefix(conn, "postgres://") || strings.HasPrefix(conn, "postgresql://") { + // Ensure timezone is set to UTC for all the connections + if strings.Contains(conn, "?") { + conn += "&timezone=UTC" + } else { + conn += "?timezone=UTC" } - config.TLSConfig.RootCAs = c.TLSConfig.RootCAs - config.TLSConfig.ClientCAs = c.TLSConfig.ClientCAs - config.TLSConfig.Certificates = c.TLSConfig.Certificates - - // Ensure there are no stale fallbacks when manually setting TLSConfig - for _, fallback := range config.Fallbacks { - fallback.TLSConfig = config.TLSConfig + // Ensure a reasonable application_name is set + if !strings.Contains(conn, "application_name") { + conn += "&application_name=vault" } + } - c.db = stdlib.OpenDB(*config) - if err != nil { - return nil, fmt.Errorf("failed to open connection: %w", err) - } - } else if driverName == dbTypePostgres && os.Getenv(pluginutil.PluginUsePostgresSSLInline) != "" { - var err error - // TODO: remove this deprecated function call in a future SDK version - c.db, err = openPostgres(driverName, conn) - if err != nil { - return nil, fmt.Errorf("failed to open connection: %w", err) - } - } else { - var err error - c.db, err = sql.Open(driverName, conn) - if err != nil { - return nil, fmt.Errorf("failed to open connection: %w", err) - } + var err error + c.db, err = sql.Open(driverName, conn) + if err != nil { + return nil, err } // Set some connection pool settings. We don't need much of this, @@ -360,32 +268,3 @@ func (c *SQLConnectionProducer) Close() error { func (c *SQLConnectionProducer) SetCredentials(ctx context.Context, statements dbplugin.Statements, staticUser dbplugin.StaticUserConfig) (username, password string, err error) { return "", "", dbutil.Unimplemented() } - -func applyPostgresSettings(connURL string) string { - res := connURL - if strings.HasPrefix(res, "postgres://") || strings.HasPrefix(res, "postgresql://") { - // Ensure timezone is set to UTC for all the connections - if strings.Contains(res, "?") { - res += "&timezone=UTC" - } else { - res += "?timezone=UTC" - } - - // Ensure a reasonable application_name is set - if !strings.Contains(res, "application_name") { - res += "&application_name=vault" - } - } - - return res -} - -var configurableAuthTypes = map[string]bool{ - AuthTypeUsernamePassword: true, - AuthTypeCert: true, - AuthTypeGCPIAM: true, -} - -func ValidateAuthType(authType string) bool { - return configurableAuthTypes[authType] -} diff --git a/sdk/database/helper/connutil/sql_stubs_oss.go b/sdk/database/helper/connutil/sql_stubs_oss.go deleted file mode 100644 index b8ab85bec412..000000000000 --- a/sdk/database/helper/connutil/sql_stubs_oss.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -//go:build !enterprise - -package connutil - -import ( - "context" - "database/sql" - "errors" -) - -func (c *SQLConnectionProducer) StaticConnection(_ context.Context, _, _ string) (*sql.DB, error) { - return nil, errors.New("self-managed static roles only available in Vault Enterprise") -} diff --git a/sdk/go.mod b/sdk/go.mod index 55c541e50bb2..ba8f53b6f612 100644 --- a/sdk/go.mod +++ b/sdk/go.mod @@ -1,13 +1,13 @@ module github.com/hashicorp/vault/sdk -go 1.22 +go 1.21 require ( cloud.google.com/go/cloudsqlconn v1.4.3 github.com/armon/go-metrics v0.4.1 github.com/armon/go-radix v1.0.0 github.com/cenkalti/backoff/v3 v3.2.2 - github.com/docker/docker v26.1.5+incompatible + github.com/docker/docker v25.0.6+incompatible github.com/docker/go-connections v0.4.0 github.com/evanphx/json-patch/v5 v5.6.0 github.com/fatih/structs v1.1.0 @@ -23,13 +23,13 @@ require ( github.com/hashicorp/go-kms-wrapping/entropy/v2 v2.0.0 github.com/hashicorp/go-kms-wrapping/v2 v2.0.8 github.com/hashicorp/go-multierror v1.1.1 - github.com/hashicorp/go-plugin v1.6.1 + github.com/hashicorp/go-plugin v1.6.0 github.com/hashicorp/go-retryablehttp v0.7.7 github.com/hashicorp/go-secure-stdlib/base62 v0.1.2 github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8 github.com/hashicorp/go-secure-stdlib/password v0.1.1 - github.com/hashicorp/go-secure-stdlib/plugincontainer v0.4.0 + github.com/hashicorp/go-secure-stdlib/plugincontainer v0.3.0 github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.3 github.com/hashicorp/go-sockaddr v1.0.6 @@ -39,6 +39,7 @@ require ( github.com/hashicorp/hcl v1.0.1-vault-5 github.com/hashicorp/vault/api v1.14.0 github.com/mitchellh/copystructure v1.2.0 + github.com/mitchellh/go-testing-interface v1.14.1 github.com/mitchellh/mapstructure v1.5.0 github.com/pierrec/lz4 v2.6.1+incompatible github.com/ryanuber/go-glob v1.0.0 @@ -53,15 +54,8 @@ require ( ) require ( - github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/go-jose/go-jose/v4 v4.0.1 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/prometheus/client_golang v1.14.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.37.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect + go.opentelemetry.io/otel/sdk v1.22.0 // indirect golang.org/x/sync v0.8.0 // indirect ) @@ -79,7 +73,7 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/frankban/quicktest v1.14.0 // indirect github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -90,19 +84,18 @@ require ( github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect - github.com/jackc/pgconn v1.14.3 + github.com/jackc/pgconn v1.14.3 // indirect github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgproto3/v2 v2.3.3 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgtype v1.14.0 // indirect - github.com/jackc/pgx/v4 v4.18.3 + github.com/jackc/pgx/v4 v4.18.3 // indirect github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531 // indirect github.com/klauspost/compress v1.16.5 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/patternmatcher v0.5.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect @@ -119,10 +112,10 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/stretchr/objx v0.5.2 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 // indirect - go.opentelemetry.io/otel v1.28.0 // indirect - go.opentelemetry.io/otel/metric v1.28.0 // indirect - go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect golang.org/x/mod v0.17.0 // indirect golang.org/x/oauth2 v0.20.0 // indirect golang.org/x/sys v0.24.0 // indirect @@ -130,7 +123,7 @@ require ( golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/api v0.169.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/sdk/go.sum b/sdk/go.sum index a15693362241..6335ccbd9ef5 100644 --- a/sdk/go.sum +++ b/sdk/go.sum @@ -1,40 +1,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/cloudsqlconn v1.4.3 h1:/WYFbB1NtMtoMxCbqpzzTFPDkxxlLTPme390KEGaEPc= cloud.google.com/go/cloudsqlconn v1.4.3/go.mod h1:QL3tuStVOO70txb3rs4G8j5uMfo5ztZii8K3oGD3VYA= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= @@ -42,7 +10,6 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg6 github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= @@ -54,7 +21,6 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA= github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= @@ -63,7 +29,6 @@ github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= @@ -75,12 +40,6 @@ github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqy github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -101,8 +60,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v26.1.5+incompatible h1:NEAxTwEjxV6VbBMBoGG3zPqbiJosIApZjxlbrG9q3/g= -github.com/docker/docker v26.1.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v25.0.6+incompatible h1:5cPwbwriIcsua2REJe8HqQV+6WlWc1byg2QSXzBxBGg= +github.com/docker/docker v25.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -124,24 +83,19 @@ github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzP github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA= github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U= github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-ldap/ldap/v3 v3.4.6 h1:ert95MdbiG7aWo/oPYp9btL3KJlMPKnP58r09rI8T+A= github.com/go-ldap/ldap/v3 v3.4.6/go.mod h1:IGMQANNtxpsOzj7uUAMjpGBaOVTC4DYyIy8VsTdxmtc= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= @@ -159,63 +113,34 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2V github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= @@ -225,8 +150,6 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA= github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= @@ -250,8 +173,8 @@ github.com/hashicorp/go-kms-wrapping/v2 v2.0.8 h1:9Q2lu1YbbmiAgvYZ7Pr31RdlVonUpX github.com/hashicorp/go-kms-wrapping/v2 v2.0.8/go.mod h1:qTCjxGig/kjuj3hk1z8pOUrzbse/GxB1tGfbrq8tGJg= 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-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI= -github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= +github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= +github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= @@ -265,8 +188,8 @@ github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8 h1:iBt4Ew4XEGLfh6/bPk4rSY github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8/go.mod h1:aiJI+PIApBRQG7FZTEBx5GiiX+HbOHilUdNxUZi4eV0= github.com/hashicorp/go-secure-stdlib/password v0.1.1 h1:6JzmBqXprakgFEHwBgdchsjaA9x3GyjdI568bXKxa60= github.com/hashicorp/go-secure-stdlib/password v0.1.1/go.mod h1:9hH302QllNwu1o2TGYtSk8I8kTAN0ca1EHpwhm5Mmzo= -github.com/hashicorp/go-secure-stdlib/plugincontainer v0.4.0 h1:7Yran48kl6X7jfUg3sfYDrFot1gD3LvzdC3oPu5l/qo= -github.com/hashicorp/go-secure-stdlib/plugincontainer v0.4.0/go.mod h1:9WJFu7L3d+Z4ViZmwUf+6/73/Uy7YMY1NXrB9wdElYE= +github.com/hashicorp/go-secure-stdlib/plugincontainer v0.3.0 h1:KMWpBsC65ZBXDpoxJ0n2/zVfZaZIW73k2d8cy5Dv/Kk= +github.com/hashicorp/go-secure-stdlib/plugincontainer v0.3.0/go.mod h1:qKYwSZ2EOpppko5ud+Sh9TrUgiTAZSaQCr8XWIYXsbM= 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.3 h1:xbrxd0U9XQW8qL1BAz2XrAjAF/P2vcqUTAues9c24B8= @@ -280,7 +203,6 @@ github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= @@ -289,7 +211,6 @@ github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -346,23 +267,15 @@ github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531 h1:hgVxRoDDPtQE68PT4 github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531/go.mod h1:fqTUQpVYBvhCNIsMXGl2GE9q6z94DIP6NtFKXCSTVbg= github.com/joshlf/testutil v0.0.0-20170608050642-b5d8aa79d93d h1:J8tJzRyiddAFF65YVgxli+TyWBi0f79Sld6rJP6CBcY= github.com/joshlf/testutil v0.0.0-20170608050642-b5d8aa79d93d/go.mod h1:b+Q3v8Yrg5o15d71PSUraUzYb+jWl6wQMSBXSGS/hv0= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= @@ -391,8 +304,6 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/microsoft/go-mssqldb v1.5.0 h1:CgENxkwtOBNj3Jg6T1X209y2blCfTTcwuOlznd2k9fk= github.com/microsoft/go-mssqldb v1.5.0/go.mod h1:lmWsjHD8XX/Txr0f8ZqgbEZSC+BZjmEQy/Ms+rLrvho= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= @@ -405,8 +316,6 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= -github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo= github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= @@ -419,11 +328,9 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ 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 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= @@ -449,32 +356,15 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= @@ -493,7 +383,6 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -517,33 +406,26 @@ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8 github.com/tink-crypto/tink-go/v2 v2.2.0 h1:L2Da0F2Udh2agtKztdr69mV/KpnY3/lGTkMgLTVIXlA= github.com/tink-crypto/tink-go/v2 v2.2.0/go.mod h1:JJ6PomeNPF3cJpfWC0lgyTES6zpJILkAX0cJNwlS3xU= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 h1:Xs2Ncz0gNihqu9iosIZ5SkBbWo5T8JhhLJFMQL1qmLI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0/go.mod h1:vy+2G/6NvVMpwGX/NyLqcC41fxepnuKHk16E6IZUcJc= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= -go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= -go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -563,7 +445,6 @@ 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-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -575,35 +456,14 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 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-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -613,62 +473,30 @@ golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= @@ -678,48 +506,20 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/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-20210616094352-59db8d763f22/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-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -739,9 +539,7 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -752,57 +550,21 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= @@ -814,76 +576,22 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY= google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 h1:g/4bk7P6TPMkAUbUhquq98xey1slwvuVJPosdBqYJlU= google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988 h1:V71AcdLZr2p8dC9dbOIMCpqi4EmRl8wUwnJzXXLmbmc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= @@ -895,10 +603,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -913,20 +618,11 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/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.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 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= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/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.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/sdk/helper/certutil/certutil_test.go b/sdk/helper/certutil/certutil_test.go index 4ebab01827d2..8b550946121d 100644 --- a/sdk/helper/certutil/certutil_test.go +++ b/sdk/helper/certutil/certutil_test.go @@ -1006,101 +1006,6 @@ func TestBasicConstraintExtension(t *testing.T) { }) } -// TestIgnoreCSRSigning Make sure we validate the CSR by default and that we can override -// the behavior disabling CSR signature checks -func TestIgnoreCSRSigning(t *testing.T) { - t.Parallel() - - caKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - t.Fatalf("failed generating ca key: %v", err) - } - subjKeyID, err := GetSubjKeyID(caKey) - if err != nil { - t.Fatalf("failed generating ca subject key id: %v", err) - } - caCertTemplate := &x509.Certificate{ - Subject: pkix.Name{ - CommonName: "root.localhost", - }, - SubjectKeyId: subjKeyID, - DNSNames: []string{"root.localhost"}, - KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, - SerialNumber: big.NewInt(mathrand.Int63()), - NotBefore: time.Now().Add(-30 * time.Second), - NotAfter: time.Now().Add(262980 * time.Hour), - BasicConstraintsValid: true, - IsCA: true, - } - caBytes, err := x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, caKey.Public(), caKey) - if err != nil { - t.Fatalf("failed creating ca certificate: %v", err) - } - caCert, err := x509.ParseCertificate(caBytes) - if err != nil { - t.Fatalf("failed parsing ca certificate: %v", err) - } - - signingBundle := &CAInfoBundle{ - ParsedCertBundle: ParsedCertBundle{ - PrivateKeyType: ECPrivateKey, - PrivateKey: caKey, - CertificateBytes: caBytes, - Certificate: caCert, - CAChain: nil, - }, - URLs: &URLEntries{}, - } - - key := genEdDSA(t) - csr := &x509.CertificateRequest{ - PublicKeyAlgorithm: x509.ECDSA, - PublicKey: key.Public(), - Subject: pkix.Name{ - CommonName: "test.dadgarcorp.com", - }, - } - t.Run(fmt.Sprintf("ignore-csr-disabled"), func(t *testing.T) { - params := &CreationParameters{ - URLs: &URLEntries{}, - } - data := &CreationBundle{ - Params: params, - SigningBundle: signingBundle, - CSR: csr, - } - - _, err := SignCertificate(data) - if err == nil { - t.Fatalf("should have failed signing csr with ignore csr signature disabled") - } - if !strings.Contains(err.Error(), "request signature invalid") { - t.Fatalf("expected error to contain 'request signature invalid': got: %v", err) - } - }) - - t.Run(fmt.Sprintf("ignore-csr-enabled"), func(t *testing.T) { - params := &CreationParameters{ - IgnoreCSRSignature: true, - URLs: &URLEntries{}, - } - data := &CreationBundle{ - Params: params, - SigningBundle: signingBundle, - CSR: csr, - } - - cert, err := SignCertificate(data) - if err != nil { - t.Fatalf("failed to sign certificate: %v", err) - } - - if err := cert.Verify(); err != nil { - t.Fatalf("signature verification failed: %v", err) - } - }) -} - func genRsaKey(t *testing.T) *rsa.PrivateKey { key, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { diff --git a/sdk/helper/certutil/helpers.go b/sdk/helper/certutil/helpers.go index 1c673b058acd..b7fc22db0262 100644 --- a/sdk/helper/certutil/helpers.go +++ b/sdk/helper/certutil/helpers.go @@ -17,11 +17,13 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/asn1" + "encoding/binary" "encoding/hex" "encoding/pem" "errors" "fmt" "io" + "io/ioutil" "math/big" "net" "net/url" @@ -1102,7 +1104,6 @@ func createCSR(data *CreationBundle, addBasicConstraints bool, randReader io.Rea } // Like many root CAs, other information is ignored - csrTemplate := &x509.CertificateRequest{ Subject: data.Params.Subject, DNSNames: data.Params.DNSNames, @@ -1111,14 +1112,6 @@ func createCSR(data *CreationBundle, addBasicConstraints bool, randReader io.Rea URIs: data.Params.URIs, } - if data.Params.KeyUsage != 0 { - keyUsageExt, err := marshalKeyUsage(data.Params.KeyUsage) - if err != nil { - return nil, fmt.Errorf("failed marshalling existing key usage: %w", err) - } - csrTemplate.ExtraExtensions = []pkix.Extension{keyUsageExt} - } - if err := HandleOtherCSRSANs(csrTemplate, data.Params.OtherSANs); err != nil { return nil, errutil.InternalError{Err: errwrap.Wrapf("error marshaling other SANs: {{err}}", err).Error()} } @@ -1168,56 +1161,6 @@ func createCSR(data *CreationBundle, addBasicConstraints bool, randReader io.Rea return result, nil } -// Marshal Key Usage taken from: https://cs.opensource.google/go/go/+/master:src/crypto/x509/x509.go;drc=370a6959e3edd9d901446661ee9fef3f72d150d4;l=1339 -// It requires the two following functions (reverseBitsInAByte and asn1BitLength) below, taken from the same code base -// It's used for that code only for certificates; but we need to marshal key usage on CSR (createCSR above) as well -func marshalKeyUsage(ku x509.KeyUsage) (pkix.Extension, error) { - ext := pkix.Extension{Id: KeyUsageOID, Critical: true} - - var a [2]byte - a[0] = reverseBitsInAByte(byte(ku)) - a[1] = reverseBitsInAByte(byte(ku >> 8)) - - l := 1 - if a[1] != 0 { - l = 2 - } - - bitString := a[:l] - var err error - ext.Value, err = asn1.Marshal(asn1.BitString{Bytes: bitString, BitLength: asn1BitLength(bitString)}) - return ext, err -} - -// reverseBitsInAByte Taken from: https://cs.opensource.google/go/go/+/master:src/crypto/x509/x509.go;drc=370a6959e3edd9d901446661ee9fef3f72d150d4;l=1011 -// needed for marshalKeyUsage called above -func reverseBitsInAByte(in byte) byte { - b1 := in>>4 | in<<4 - b2 := b1>>2&0x33 | b1<<2&0xcc - b3 := b2>>1&0x55 | b2<<1&0xaa - return b3 -} - -// asn1BitLength returns the bit-length of bitString by considering the -// most-significant bit in a byte to be the "first" bit. This convention -// matches ASN.1, but differs from almost everything else. -func asn1BitLength(bitString []byte) int { - bitLen := len(bitString) * 8 - - for i := range bitString { - b := bitString[len(bitString)-i-1] - - for bit := uint(0); bit < 8; bit++ { - if (b>>bit)&1 == 1 { - return bitLen - } - bitLen-- - } - } - - return 0 -} - // SignCertificate performs the heavy lifting // of generating a certificate from a CSR. // Returns a ParsedCertBundle sans private keys. @@ -1244,10 +1187,9 @@ func signCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertBun return nil, errutil.UserError{Err: "nil csr given to signCertificate"} } - if !data.Params.IgnoreCSRSignature { - if err := data.CSR.CheckSignature(); err != nil { - return nil, errutil.UserError{Err: "request signature invalid"} - } + err := data.CSR.CheckSignature() + if err != nil { + return nil, errutil.UserError{Err: "request signature invalid"} } result := &ParsedCertBundle{} @@ -1373,7 +1315,7 @@ func signCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertBun } func NewCertPool(reader io.Reader) (*x509.CertPool, error) { - pemBlock, err := io.ReadAll(reader) + pemBlock, err := ioutil.ReadAll(reader) if err != nil { return nil, err } @@ -1695,28 +1637,19 @@ func getKeyUsage(exts []pkix.Extension) (x509.KeyUsage, error) { keyUsage := x509.KeyUsage(0) for _, ext := range exts { if ext.Id.Equal(KeyUsageOID) { - return parseKeyUsageExtension(ext.Value) + // ASN1 is Big Endian + // another example of equivalent code: https://cs.opensource.google/go/go/+/master:src/crypto/x509/parser.go;drc=dd84bb682482390bb8465482cb7b13d2e3b17297;l=319 + buf := bytes.NewReader(ext.Value) + err := binary.Read(buf, binary.BigEndian, &keyUsage) + if err != nil { + return keyUsage, err + } + return keyUsage, nil } } return keyUsage, nil } -// Taken from: https://cs.opensource.google/go/go/+/master:src/crypto/x509/parser.go;drc=dd84bb682482390bb8465482cb7b13d2e3b17297;l=319 -func parseKeyUsageExtension(der cryptobyte.String) (x509.KeyUsage, error) { - var usageBits asn1.BitString - if !der.ReadASN1BitString(&usageBits) { - return 0, errors.New("x509: invalid key usage") - } - - var usage int - for i := 0; i < 9; i++ { - if usageBits.At(i) != 0 { - usage |= 1 << uint(i) - } - } - return x509.KeyUsage(usage), nil -} - func getExtKeyUsageOids(exts []pkix.Extension) ([]string, error) { keyUsageOidStrings := make([]string, 0) keyUsageOids := make([]asn1.ObjectIdentifier, 0) diff --git a/sdk/helper/certutil/types.go b/sdk/helper/certutil/types.go index cdfc912e9289..bfdc153c4852 100644 --- a/sdk/helper/certutil/types.go +++ b/sdk/helper/certutil/types.go @@ -819,11 +819,6 @@ type CreationParameters struct { // The explicit SKID to use; especially useful for cross-signing. SKID []byte - - // Ignore validating the CSR's signature. This should only be enabled if the - // sender of the CSR has proven proof of possession of the associated - // private key by some other means, otherwise keep this set to false. - IgnoreCSRSignature bool } type CreationBundle struct { diff --git a/sdk/helper/docker/testhelpers.go b/sdk/helper/docker/testhelpers.go index af1f3f72a666..f1fefd65cd70 100644 --- a/sdk/helper/docker/testhelpers.go +++ b/sdk/helper/docker/testhelpers.go @@ -12,6 +12,7 @@ import ( "encoding/json" "fmt" "io" + "io/ioutil" "net/url" "os" "strconv" @@ -414,7 +415,7 @@ func (d *Runner) Start(ctx context.Context, addSuffix, forceLocalAddr bool) (*St } resp, _ := d.DockerAPI.ImageCreate(ctx, cfg.Image, opts) if resp != nil { - _, _ = io.ReadAll(resp) + _, _ = ioutil.ReadAll(resp) } for vol, mtpt := range d.RunOptions.VolumeNameToMountPoint { diff --git a/sdk/helper/metricregistry/metricregistry.go b/sdk/helper/metricregistry/metricregistry.go deleted file mode 100644 index 30e8d44cb19b..000000000000 --- a/sdk/helper/metricregistry/metricregistry.go +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Package metricregistry is a helper that allows Vault code or plugins that are -// compiled into Vault to pre-define any metrics they will emit to go-metrics at -// init time. Metrics registered this way will always be reported by the -// go-metrics PrometheusSink if it is used so infrequently updated metrics are -// always present. It is not required to pre-register metrics to use go-metrics -// with Prometheus, but it's preferable as it makes them behave more like the -// Prometheus ecosystem expects, being always present and with a helpful -// description in the output which some systems use to help operators explore -// metrics. -// -// Note that this will not work for external Vault plugins since they are in a -// separate process and only started after Vault's metrics sink is already -// configured. -package metricregistry - -import promsink "github.com/armon/go-metrics/prometheus" - -var Registry definitionRegistry - -// Re-export these types so that we don't have the whole of Vault depending -// directly on go-metrics prometheus sink and can buffer changes if needed -type ( - // GaugeDefinition provides the name and help text of a gauge metric that will - // be exported via go-metrics' Prometheus sink if enabled. - GaugeDefinition promsink.GaugeDefinition - - // CounterDefinition provides the name and help text of a counter metric that - // will be exported via go-metrics' Prometheus sink if enabled. - CounterDefinition promsink.CounterDefinition - - // SummaryDefinition provides the name and help text of a summary metric that - // will be exported via go-metrics' Prometheus sink if enabled. - SummaryDefinition promsink.SummaryDefinition -) - -// definitionRegistry is a central place for packages to register their metrics -// definitions during init so that we can correctly report metrics to Prometheus -// even before they are observed. Typically there is one global instance. -type definitionRegistry struct { - gauges []GaugeDefinition - counters []CounterDefinition - summaries []SummaryDefinition -} - -// RegisterGauges is intended to be called during init. It accesses global state -// without synchronization. Statically defined definitions should be registered -// during `init` of a package read to be configured if the prometheus sink is -// enabled in configuration. Registering metrics is not mandatory but it is -// strongly preferred as it ensures they are always output even before the are -// observed which makes dashboards much easier to work with, provides helpful -// descriptions and matches Prometheus eco system expectations. It also prevents -// the metrics ever being expired which means users don't need to work around -// that quirk of go-metrics by setting long prometheus retention times. All -// registered metrics will report 0 until an actual observation is made. -func RegisterGauges(defs []GaugeDefinition) { - Registry.gauges = append(Registry.gauges, defs...) -} - -// RegisterCounters is intended to be called during init. It accesses global -// state without synchronization. Statically defined definitions should be -// registered during `init` of a package read to be configured if the prometheus -// sink is enabled in configuration. Registering metrics is not mandatory but it -// is strongly preferred as it ensures they are always output even before the -// are observed which makes dashboards much easier to work with, provides -// helpful descriptions and matches Prometheus eco system expectations. It also -// prevents the metrics ever being expired which means users don't need to work -// around that quirk of go-metrics by setting long prometheus retention times. -// All registered metrics will report 0 until an actual observation is made. -func RegisterCounters(defs []CounterDefinition) { - Registry.counters = append(Registry.counters, defs...) -} - -// RegisterSummaries is intended to be called during init. It accesses global -// state without synchronization. Statically defined definitions should be -// registered during `init` of a package read to be configured if the prometheus -// sink is enabled in configuration. Registering metrics is not mandatory but it -// is strongly preferred as it ensures they are always output even before the -// are observed which makes dashboards much easier to work with, provides -// helpful descriptions and matches Prometheus eco system expectations. It also -// prevents the metrics ever being expired which means users don't need to work -// around that quirk of go-metrics by setting long prometheus retention times. -// All registered metrics will report 0 until an actual observation is made. -func RegisterSummaries(defs []SummaryDefinition) { - Registry.summaries = append(Registry.summaries, defs...) -} - -// MergeDefinitions adds all registered metrics to any already present in `cfg` -// ready to be passed to the go-metrics prometheus sink. Note it is not safe to -// call this concurrently with registrations or other calls, it's intended this -// is called once only after all registrations (which should be in init -// functions) just before the PrometheusSink is created. Calling more than once -// could result in duplicate metrics definitions being passed unless the cfg is -// different each time for different Prometheus sinks. -func MergeDefinitions(cfg *promsink.PrometheusOpts) { - for _, g := range Registry.gauges { - cfg.GaugeDefinitions = append(cfg.GaugeDefinitions, promsink.GaugeDefinition(g)) - } - for _, c := range Registry.counters { - cfg.CounterDefinitions = append(cfg.CounterDefinitions, promsink.CounterDefinition(c)) - } - for _, s := range Registry.summaries { - cfg.SummaryDefinitions = append(cfg.SummaryDefinitions, promsink.SummaryDefinition(s)) - } -} diff --git a/sdk/helper/metricregistry/metricregistry_test.go b/sdk/helper/metricregistry/metricregistry_test.go deleted file mode 100644 index c94e8c821dcc..000000000000 --- a/sdk/helper/metricregistry/metricregistry_test.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package metricregistry - -import ( - "testing" - - promsink "github.com/armon/go-metrics/prometheus" - "github.com/stretchr/testify/require" -) - -var testGauges = []GaugeDefinition{ - { - Name: []string{"test_gauge"}, - Help: "A test gauge", - }, - { - Name: []string{"test_gauge2"}, - Help: "Another test gauge", - }, -} - -var testCounters = []CounterDefinition{ - { - Name: []string{"test_counter"}, - Help: "A test counter", - }, - { - Name: []string{"test_counter2"}, - Help: "Another test counter", - }, -} - -var testSummaries = []SummaryDefinition{ - { - Name: []string{"test_summary"}, - Help: "A test summary", - }, - { - Name: []string{"test_summary2"}, - Help: "Another test summary", - }, -} - -func TestMetricRegistry(t *testing.T) { - // Register some metrics - RegisterGauges(testGauges) - RegisterCounters(testCounters) - RegisterSummaries(testSummaries) - - var opts promsink.PrometheusOpts - - // Add some pre-existing metrics to ensure merge is really a merge - opts.GaugeDefinitions = []promsink.GaugeDefinition{ - { - Name: []string{"preexisting_gauge"}, - Help: "A pre-existing gauge", - }, - } - opts.CounterDefinitions = []promsink.CounterDefinition{ - { - Name: []string{"preexisting_counter"}, - Help: "A pre-existing counter", - }, - } - opts.SummaryDefinitions = []promsink.SummaryDefinition{ - { - Name: []string{"preexisting_summary"}, - Help: "A pre-existing summary", - }, - } - - MergeDefinitions(&opts) - - require.Len(t, opts.GaugeDefinitions, 3) - require.Len(t, opts.CounterDefinitions, 3) - require.Len(t, opts.SummaryDefinitions, 3) - - wantGauges := []string{"test_gauge", "test_gauge2", "preexisting_gauge"} - wantGaugeHelp := []string{"A test gauge", "Another test gauge", "A pre-existing gauge"} - gotGauges := reduce(opts.GaugeDefinitions, nil, func(r []string, d promsink.GaugeDefinition) []string { - return append(r, d.Name[0]) - }) - gotGaugeHelp := reduce(opts.GaugeDefinitions, nil, func(r []string, d promsink.GaugeDefinition) []string { - return append(r, d.Help) - }) - - require.ElementsMatch(t, wantGauges, gotGauges) - require.ElementsMatch(t, wantGaugeHelp, gotGaugeHelp) - - wantCounters := []string{"test_counter", "test_counter2", "preexisting_counter"} - wantCounterHelp := []string{"A test counter", "Another test counter", "A pre-existing counter"} - gotCounters := reduce(opts.CounterDefinitions, nil, func(r []string, d promsink.CounterDefinition) []string { - return append(r, d.Name[0]) - }) - gotCounterHelp := reduce(opts.CounterDefinitions, nil, func(r []string, d promsink.CounterDefinition) []string { - return append(r, d.Help) - }) - - require.ElementsMatch(t, wantCounters, gotCounters) - require.ElementsMatch(t, wantCounterHelp, gotCounterHelp) - - wantSummaries := []string{"test_summary", "test_summary2", "preexisting_summary"} - wantSummaryHelp := []string{"A test summary", "Another test summary", "A pre-existing summary"} - gotSummaries := reduce(opts.SummaryDefinitions, nil, func(r []string, d promsink.SummaryDefinition) []string { - return append(r, d.Name[0]) - }) - gotSummaryHelp := reduce(opts.SummaryDefinitions, nil, func(r []string, d promsink.SummaryDefinition) []string { - return append(r, d.Help) - }) - - require.ElementsMatch(t, wantSummaries, gotSummaries) - require.ElementsMatch(t, wantSummaryHelp, gotSummaryHelp) -} - -func reduce[T, R any](s []T, r R, f func(R, T) R) R { - for _, v := range s { - r = f(r, v) - } - return r -} diff --git a/sdk/helper/ocsp/ocsp_test.go b/sdk/helper/ocsp/ocsp_test.go index fcd868e2d613..b05e57f82672 100644 --- a/sdk/helper/ocsp/ocsp_test.go +++ b/sdk/helper/ocsp/ocsp_test.go @@ -15,6 +15,7 @@ import ( "errors" "fmt" "io" + "io/ioutil" "math/big" "net" "net/http" @@ -64,7 +65,7 @@ func TestOCSP(t *testing.T) { t.Fatalf("failed to GET contents. err: %v", err) } defer res.Body.Close() - _, err = io.ReadAll(res.Body) + _, err = ioutil.ReadAll(res.Body) if err != nil { t.Fatalf("failed to read content body for %v", tgt) } @@ -113,7 +114,7 @@ func TestMultiOCSP(t *testing.T) { t.Fatalf("failed to GET contents. err: %v", err) } defer res.Body.Close() - _, err = io.ReadAll(res.Body) + _, err = ioutil.ReadAll(res.Body) if err != nil { t.Fatalf("failed to read content body for %v", tgt) } diff --git a/sdk/helper/pluginutil/env.go b/sdk/helper/pluginutil/env.go index ea05e8462c70..515baa1f7619 100644 --- a/sdk/helper/pluginutil/env.go +++ b/sdk/helper/pluginutil/env.go @@ -44,11 +44,6 @@ const ( // colliding plugin-specific environment variables. Otherwise, plugin-specific // environment variables take precedence over Vault process environment variables. PluginUseLegacyEnvLayering = "VAULT_PLUGIN_USE_LEGACY_ENV_LAYERING" - - // PluginUsePostgresSSLInline enables the usage of a custom sslinline - // configuration as a shim to the pgx posgtres library. - // Deprecated: VAULT_PLUGIN_USE_POSTGRES_SSLINLINE will be removed in a future version of the Vault SDK. - PluginUsePostgresSSLInline = "VAULT_PLUGIN_USE_POSTGRES_SSLINLINE" ) // OptionallyEnableMlock determines if mlock should be called, and if so enables diff --git a/sdk/helper/policyutil/policyutil.go b/sdk/helper/policyutil/policyutil.go index a8e6214ab0b6..a5a8082e13c2 100644 --- a/sdk/helper/policyutil/policyutil.go +++ b/sdk/helper/policyutil/policyutil.go @@ -79,25 +79,33 @@ func SanitizePolicies(policies []string, addDefault bool) []string { // EquivalentPolicies checks whether the given policy sets are equivalent, as in, // they contain the same values. The benefit of this method is that it leaves // the "default" policy out of its comparisons as it may be added later by core -// after a set of policies has been saved by a backend and performs policy name -// normalization. +// after a set of policies has been saved by a backend. func EquivalentPolicies(a, b []string) bool { + switch { + case a == nil && b == nil: + return true + case a == nil && len(b) == 1 && b[0] == "default": + return true + case b == nil && len(a) == 1 && a[0] == "default": + return true + case a == nil || b == nil: + return false + } + // First we'll build maps to ensure unique values and filter default - mapA := map[string]struct{}{} - mapB := map[string]struct{}{} + mapA := map[string]bool{} + mapB := map[string]bool{} for _, keyA := range a { - keyA := strings.ToLower(keyA) if keyA == "default" { continue } - mapA[keyA] = struct{}{} + mapA[keyA] = true } for _, keyB := range b { - keyB := strings.ToLower(keyB) if keyB == "default" { continue } - mapB[keyB] = struct{}{} + mapB[keyB] = true } // Now we'll build our checking slices diff --git a/sdk/helper/policyutil/policyutil_test.go b/sdk/helper/policyutil/policyutil_test.go index 04aedfae727e..2280ba93eed8 100644 --- a/sdk/helper/policyutil/policyutil_test.go +++ b/sdk/helper/policyutil/policyutil_test.go @@ -56,48 +56,24 @@ func TestParsePolicies(t *testing.T) { } func TestEquivalentPolicies(t *testing.T) { - testCases := map[string]struct { - A []string - B []string - Expected bool - }{ - "nil": { - A: nil, - B: nil, - Expected: true, - }, - "empty": { - A: []string{"foo", "bar"}, - B: []string{}, - Expected: false, - }, - "missing": { - A: []string{"foo", "bar"}, - B: []string{"foo"}, - Expected: false, - }, - "equal": { - A: []string{"bar", "foo"}, - B: []string{"bar", "foo"}, - Expected: true, - }, - "default": { - A: []string{"bar", "foo"}, - B: []string{"foo", "default", "bar"}, - Expected: true, - }, - "case-insensitive": { - A: []string{"test"}, - B: []string{"Test"}, - Expected: true, - }, + a := []string{"foo", "bar"} + var b []string + if EquivalentPolicies(a, b) { + t.Fatal("bad") } - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - if EquivalentPolicies(tc.A, tc.B) != tc.Expected { - t.Fatal("bad") - } - }) + b = []string{"foo"} + if EquivalentPolicies(a, b) { + t.Fatal("bad") + } + + b = []string{"bar", "foo"} + if !EquivalentPolicies(a, b) { + t.Fatal("bad") + } + + b = []string{"foo", "default", "bar"} + if !EquivalentPolicies(a, b) { + t.Fatal("bad") } } diff --git a/sdk/helper/testcluster/docker/environment.go b/sdk/helper/testcluster/docker/environment.go index 8dd40904f7d9..fd1c11ffee9b 100644 --- a/sdk/helper/testcluster/docker/environment.go +++ b/sdk/helper/testcluster/docker/environment.go @@ -805,23 +805,20 @@ func (n *DockerClusterNode) Start(ctx context.Context, opts *DockerClusterOption } } - envs := []string{ - // For now we're using disable_mlock, because this is for testing - // anyway, and because it prevents us using external plugins. - "SKIP_SETCAP=true", - "VAULT_LOG_FORMAT=json", - "VAULT_LICENSE=" + opts.VaultLicense, - } - envs = append(envs, opts.Envs...) - r, err := dockhelper.NewServiceRunner(dockhelper.RunOptions{ ImageRepo: n.ImageRepo, ImageTag: n.ImageTag, // We don't need to run update-ca-certificates in the container, because // we're providing the CA in the raft join call, and otherwise Vault // servers don't talk to one another on the API port. - Cmd: append([]string{"server"}, opts.Args...), - Env: envs, + Cmd: append([]string{"server"}, opts.Args...), + Env: []string{ + // For now we're using disable_mlock, because this is for testing + // anyway, and because it prevents us using external plugins. + "SKIP_SETCAP=true", + "VAULT_LOG_FORMAT=json", + "VAULT_LICENSE=" + opts.VaultLicense, + }, Ports: ports, ContainerName: n.Name(), NetworkName: opts.NetworkName, @@ -1092,7 +1089,6 @@ type DockerClusterOptions struct { CA *testcluster.CA VaultBinary string Args []string - Envs []string StartProbe func(*api.Client) error Storage testcluster.ClusterStorage DisableTLS bool diff --git a/sdk/helper/testcluster/docker/environment_test.go b/sdk/helper/testcluster/docker/environment_test.go deleted file mode 100644 index bb2376405281..000000000000 --- a/sdk/helper/testcluster/docker/environment_test.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package docker - -import ( - "testing" -) - -func TestSettingEnvsToContainer(t *testing.T) { - expectedEnv := "TEST_ENV=value1" - expectedEnv2 := "TEST_ENV2=value2" - opts := &DockerClusterOptions{ - ImageRepo: "hashicorp/vault", - ImageTag: "latest", - Envs: []string{expectedEnv, expectedEnv2}, - } - cluster := NewTestDockerCluster(t, opts) - defer cluster.Cleanup() - - envs := cluster.GetActiveClusterNode().Container.Config.Env - - if !findEnv(envs, expectedEnv) { - t.Errorf("Missing ENV variable: %s", expectedEnv) - } - if !findEnv(envs, expectedEnv2) { - t.Errorf("Missing ENV variable: %s", expectedEnv2) - } -} - -func findEnv(envs []string, env string) bool { - for _, e := range envs { - if e == env { - return true - } - } - return false -} diff --git a/sdk/helper/testcluster/exec.go b/sdk/helper/testcluster/exec.go index f871e0dabb8a..d91a3de034ac 100644 --- a/sdk/helper/testcluster/exec.go +++ b/sdk/helper/testcluster/exec.go @@ -53,7 +53,7 @@ type ExecDevClusterOptions struct { BaseListenAddress string } -func NewTestExecDevServer(t *testing.T, opts *ExecDevClusterOptions) *ExecDevCluster { +func NewTestExecDevCluster(t *testing.T, opts *ExecDevClusterOptions) *ExecDevCluster { if opts == nil { opts = &ExecDevClusterOptions{} } @@ -141,10 +141,12 @@ func (dc *ExecDevCluster) setupExecDevCluster(ctx context.Context, opts *ExecDev clusterJsonPath := filepath.Join(dc.tmpDir, "cluster.json") args := []string{"server", "-dev", "-dev-cluster-json", clusterJsonPath} switch { + case opts.NumCores == 3: + args = append(args, "-dev-three-node") case opts.NumCores == 1: args = append(args, "-dev-tls") default: - return fmt.Errorf("NumCores=1 is the only supported option right now") + return fmt.Errorf("NumCores=1 and NumCores=3 are the only supported options right now") } if opts.BaseListenAddress != "" { args = append(args, "-dev-listen-address", opts.BaseListenAddress) @@ -221,7 +223,6 @@ func (dc *ExecDevCluster) setupExecDevCluster(ctx context.Context, opts *ExecDev } time.Sleep(500 * time.Millisecond) } - return ctx.Err() } diff --git a/sdk/helper/testhelpers/output.go b/sdk/helper/testhelpers/output.go index 9fde77f0d6c6..c18b1bb6deb1 100644 --- a/sdk/helper/testhelpers/output.go +++ b/sdk/helper/testhelpers/output.go @@ -7,8 +7,8 @@ import ( "crypto/sha256" "fmt" "reflect" - "testing" + "github.com/mitchellh/go-testing-interface" "github.com/mitchellh/mapstructure" ) @@ -74,7 +74,7 @@ func ToString(in any) string { // StringOrDie renders its input using ToMap, and returns a string containing the // result. If rendering yields an error, calls t.Fatal. -func StringOrDie(t testing.TB, in any) string { +func StringOrDie(t testing.T, in any) string { t.Helper() m, err := ToMap(in) if err != nil { diff --git a/sdk/logical/testing.go b/sdk/logical/testing.go index c507b1c3e35e..d37956193099 100644 --- a/sdk/logical/testing.go +++ b/sdk/logical/testing.go @@ -6,15 +6,15 @@ package logical import ( "context" "reflect" - "testing" "time" log "github.com/hashicorp/go-hclog" "github.com/hashicorp/vault/sdk/helper/logging" + testing "github.com/mitchellh/go-testing-interface" ) // TestRequest is a helper to create a purely in-memory Request struct. -func TestRequest(t testing.TB, op Operation, path string) *Request { +func TestRequest(t testing.T, op Operation, path string) *Request { return &Request{ Operation: op, Path: path, @@ -26,7 +26,7 @@ func TestRequest(t testing.TB, op Operation, path string) *Request { // TestStorage is a helper that can be used from unit tests to verify // the behavior of a Storage impl. -func TestStorage(t testing.TB, s Storage) { +func TestStorage(t testing.T, s Storage) { keys, err := s.List(context.Background(), "") if err != nil { t.Fatalf("list error: %s", err) diff --git a/serviceregistration/consul/consul_service_registration.go b/serviceregistration/consul/consul_service_registration.go index f3830121aebd..c59ed775cc99 100644 --- a/serviceregistration/consul/consul_service_registration.go +++ b/serviceregistration/consul/consul_service_registration.go @@ -5,7 +5,6 @@ package consul import ( "context" - "encoding/json" "errors" "fmt" "math/rand" @@ -74,7 +73,6 @@ type serviceRegistration struct { redirectPort int64 serviceName string serviceTags []string - serviceMeta map[string]string serviceAddress *string disableRegistration bool checkTimeout time.Duration @@ -231,18 +229,6 @@ func (c *serviceRegistration) merge(conf map[string]string) error { c.logger.Debug("config service_tags set", "service_tags", tags) } - // Get user-defined meta tags to attach to the registered service name - metaTags := map[string]string{} - if metaTagsJSON, ok := conf["service_meta"]; ok { - if err := json.Unmarshal([]byte(metaTagsJSON), &metaTags); err != nil { - return errors.New("service tags must be a dictionary of string keys and values") - } - } - metaTags["external-source"] = metaExternalSource - if c.logger.IsDebug() { - c.logger.Debug("config service_meta set", "service_meta", metaTags) - } - // Get the service-specific address to override the use of the HA redirect address var serviceAddr *string serviceAddrStr, ok := conf["service_address"] @@ -308,7 +294,6 @@ func (c *serviceRegistration) merge(conf map[string]string) error { c.config = consulConf c.serviceName = service c.serviceTags = strutil.ParseDedupAndSortStrings(tags, ",") - c.serviceMeta = metaTags c.serviceAddress = serviceAddr c.checkTimeout = checkTimeout c.disableRegistration = disableRegistration @@ -601,10 +586,12 @@ func (c *serviceRegistration) reconcileConsul() (serviceID string, err error) { ID: serviceID, Name: c.serviceName, Tags: tags, - Meta: c.serviceMeta, Port: int(c.redirectPort), Address: serviceAddress, EnableTagOverride: false, + Meta: map[string]string{ + "external-source": metaExternalSource, + }, } checkStatus := api.HealthCritical diff --git a/serviceregistration/consul/consul_service_registration_test.go b/serviceregistration/consul/consul_service_registration_test.go index c728e721c1c0..8dcc3d66952b 100644 --- a/serviceregistration/consul/consul_service_registration_test.go +++ b/serviceregistration/consul/consul_service_registration_test.go @@ -492,66 +492,6 @@ func TestConsul_serviceTags(t *testing.T) { } } -// TestConsul_ServiceMeta tests whether consul service meta registration works -func TestConsul_ServiceMeta(t *testing.T) { - tests := []struct { - conf map[string]string - pass bool - expect map[string]string - }{ - { - conf: map[string]string{}, - pass: true, - expect: map[string]string{"external-source": "vault"}, - }, - { - conf: map[string]string{"service_meta": "true"}, - pass: false, - expect: map[string]string{"external-source": "vault"}, - }, - { - conf: map[string]string{"service_meta": "{\"key\":\"value\"}"}, - pass: true, - expect: map[string]string{"key": "value", "external-source": "vault"}, - }, - { - conf: map[string]string{"service_meta": "{\"external-source\":\"something-else\"}"}, - pass: true, - expect: map[string]string{"external-source": "vault"}, - }, - } - - for _, test := range tests { - logger := logging.NewVaultLogger(log.Debug) - - shutdownCh := make(chan struct{}) - defer func() { - close(shutdownCh) - }() - sr, err := NewServiceRegistration(test.conf, logger, sr.State{}) - if !test.pass { - if err == nil { - t.Fatal("Expected Consul to fail with error") - } - continue - } - - if err != nil && test.pass { - t.Fatalf("Expected Consul to initialize: %v", err) - } - - c, ok := sr.(*serviceRegistration) - if !ok { - t.Fatalf("Expected serviceRegistration") - } - - if !reflect.DeepEqual(c.serviceMeta, test.expect) { - t.Fatalf("Did not produce expected meta: wanted: %v, got %v", test.expect, c.serviceMeta) - } - - } -} - func TestConsul_setRedirectAddr(t *testing.T) { tests := []struct { addr string diff --git a/tools/semgrep/ci/no-nil-check.yml b/tools/semgrep/ci/no-nil-check.yml index a470f35c87fb..00c64c3641bb 100644 --- a/tools/semgrep/ci/no-nil-check.yml +++ b/tools/semgrep/ci/no-nil-check.yml @@ -99,13 +99,6 @@ rules: ... } ... - - pattern-not: | - $VAR, $ERR = NamespaceByID(...) - ... - if !a.includeInResponse(..., $VAR) { - ... - } - ... message: missed nil check languages: - go diff --git a/ui/.gitignore b/ui/.gitignore index 639f011c1dcb..99318284a7e4 100644 --- a/ui/.gitignore +++ b/ui/.gitignore @@ -15,7 +15,6 @@ /testem.log /yarn-error.log package-lock.json -/docs/components/* # ember-try /.node_modules.ember-try/ diff --git a/ui/.yarnrc b/ui/.yarnrc new file mode 100644 index 000000000000..65dab0366d67 --- /dev/null +++ b/ui/.yarnrc @@ -0,0 +1,6 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +lastUpdateCheck 1664829239911 +yarn-path ".yarn/releases/yarn-1.22.19.js" diff --git a/ui/app/adapters/aws/lease-config.js b/ui/app/adapters/aws/lease-config.js deleted file mode 100644 index 0b44c3272b62..000000000000 --- a/ui/app/adapters/aws/lease-config.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import ApplicationAdapter from '../application'; -import { encodePath } from 'vault/utils/path-encoding-helpers'; - -export default class AwsLeaseConfig extends ApplicationAdapter { - namespace = 'v1'; - - queryRecord(store, type, query) { - const { backend } = query; - return this.ajax(`${this.buildURL()}/${encodePath(backend)}/config/lease`, 'GET').then((resp) => { - return { - ...resp, - id: backend, - backend, - }; - }); - } - - createOrUpdate(store, type, snapshot) { - const serializer = store.serializerFor(type.modelName); - const data = serializer.serialize(snapshot); - const backend = snapshot.record.backend; - return this.ajax(`${this.buildURL()}/${backend}/config/lease`, 'POST', { data }).then((resp) => { - // ember data requires an id on the response - return { - ...resp, - id: backend, - }; - }); - } - - createRecord() { - return this.createOrUpdate(...arguments); - } - - updateRecord() { - return this.createOrUpdate(...arguments); - } -} diff --git a/ui/app/adapters/aws/root-config.js b/ui/app/adapters/aws/root-config.js deleted file mode 100644 index 9d64dd1b2a23..000000000000 --- a/ui/app/adapters/aws/root-config.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import ApplicationAdapter from '../application'; -import { encodePath } from 'vault/utils/path-encoding-helpers'; - -export default class AwsRootConfig extends ApplicationAdapter { - namespace = 'v1'; - - queryRecord(store, type, query) { - const { backend } = query; - return this.ajax(`${this.buildURL()}/${encodePath(backend)}/config/root`, 'GET').then((resp) => { - return { - ...resp, - id: backend, - backend, - }; - }); - } - - createOrUpdate(store, type, snapshot) { - const serializer = store.serializerFor(type.modelName); - const data = serializer.serialize(snapshot); - const backend = snapshot.record.backend; - return this.ajax(`${this.buildURL()}/${backend}/config/root`, 'POST', { data }).then((resp) => { - // ember data requires an id on the response - return { - ...resp, - id: backend, - }; - }); - } - - createRecord() { - return this.createOrUpdate(...arguments); - } - - updateRecord() { - return this.createOrUpdate(...arguments); - } -} diff --git a/ui/app/adapters/capabilities.js b/ui/app/adapters/capabilities.js index ba18bcd133e5..2d8a7c2e478a 100644 --- a/ui/app/adapters/capabilities.js +++ b/ui/app/adapters/capabilities.js @@ -6,31 +6,24 @@ import AdapterError from '@ember-data/adapter/error'; import { set } from '@ember/object'; import ApplicationAdapter from './application'; -import { sanitizePath, sanitizeStart } from 'core/utils/sanitize-path'; +import { sanitizePath } from 'core/utils/sanitize-path'; -export default class CapabilitiesAdapter extends ApplicationAdapter { +export default ApplicationAdapter.extend({ pathForType() { return 'capabilities-self'; - } + }, - /* - users don't always have access to the capabilities-self endpoint in the current namespace, - this can happen when logging in to a namespace and then navigating to a child namespace. - adding "relativeNamespace" to the path and/or "this.namespaceService.userRootNamespace" - to the request header ensures we are querying capabilities-self in the user's root namespace, - which is where they are most likely to have their policy/permissions. - */ - _formatPath(path) { + formatPaths(path) { const { relativeNamespace } = this.namespaceService; if (!relativeNamespace) { - return path; + return [path]; } // ensure original path doesn't have leading slash - return `${relativeNamespace}/${sanitizeStart(path)}`; - } + return [`${relativeNamespace}/${path.replace(/^\//, '')}`]; + }, async findRecord(store, type, id) { - const paths = [this._formatPath(id)]; + const paths = this.formatPaths(id); return this.ajax(this.buildURL(type), 'POST', { data: { paths }, namespace: sanitizePath(this.namespaceService.userRootNamespace), @@ -40,7 +33,7 @@ export default class CapabilitiesAdapter extends ApplicationAdapter { } throw e; }); - } + }, queryRecord(store, type, query) { const { id } = query; @@ -51,33 +44,5 @@ export default class CapabilitiesAdapter extends ApplicationAdapter { resp.path = id; return resp; }); - } - - query(store, type, query) { - const pathMap = query?.paths.reduce((mapping, path) => { - const withNs = this._formatPath(path); - if (withNs) { - mapping[withNs] = path; - } - return mapping; - }, {}); - - return this.ajax(this.buildURL(type), 'POST', { - data: { paths: Object.keys(pathMap) }, - namespace: sanitizePath(this.namespaceService.userRootNamespace), - }) - .then((queryResult) => { - if (queryResult) { - // send the pathMap with the response so the serializer can normalize the paths to be relative to the namespace - queryResult.pathMap = pathMap; - } - return queryResult; - }) - .catch((e) => { - if (e instanceof AdapterError) { - set(e, 'policyPath', 'sys/capabilities-self'); - } - throw e; - }); - } -} + }, +}); diff --git a/ui/app/adapters/clients/activity.js b/ui/app/adapters/clients/activity.js index 317444c13795..c5d8d4cc8ae2 100644 --- a/ui/app/adapters/clients/activity.js +++ b/ui/app/adapters/clients/activity.js @@ -3,78 +3,35 @@ * SPDX-License-Identifier: BUSL-1.1 */ -import queryParamString from 'vault/utils/query-param-string'; import ApplicationAdapter from '../application'; import { formatDateObject } from 'core/utils/client-count-utils'; import { debug } from '@ember/debug'; export default class ActivityAdapter extends ApplicationAdapter { - formatTimeParam(dateObj, isEnd = false) { - let formatted; - if (dateObj) { - try { - const iso = dateObj.timestamp || formatDateObject(dateObj, isEnd); - formatted = iso; - } catch (e) { - // carry on - } - } - return formatted; - } // javascript localizes new Date() objects but all activity log data is stored in UTC // create date object from user's input using Date.UTC() then send to backend as unix // time params from the backend are formatted as a zulu timestamp formatQueryParams(queryParams) { - const query = {}; - const start = this.formatTimeParam(queryParams?.start_time); - const end = this.formatTimeParam(queryParams?.end_time, true); - if (start) { - query.start_time = start; - } - if (end) { - query.end_time = end; + if (queryParams?.current_billing_period) { + // { current_billing_period: true } automatically queries the activity log + // from the builtin license start timestamp to the current month + return queryParams; } - return query; + let { start_time, end_time } = queryParams; + start_time = start_time.timestamp || formatDateObject(start_time); + end_time = end_time.timestamp || formatDateObject(end_time, true); + return { start_time, end_time }; } queryRecord(store, type, query) { const url = `${this.buildURL()}/internal/counters/activity`; - const options = { - data: this.formatQueryParams(query), - }; - - if (query?.namespace) { - options.namespace = query.namespace; - } - - return this.ajax(url, 'GET', options).then((resp) => { - const response = resp || {}; - response.id = response.request_id || 'no-data'; - return response; - }); - } - - async exportData(query) { - const url = `${this.buildURL()}/internal/counters/activity/export${queryParamString({ - format: query?.format || 'csv', - start_time: query?.start_time ?? undefined, - end_time: query?.end_time ?? undefined, - })}`; - let errorMsg; - try { - const options = query?.namespace ? { namespace: query.namespace } : {}; - const resp = await this.rawRequest(url, 'GET', options); - if (resp.status === 200) { - return resp.blob(); - } - // If it's an empty response (eg 204), there's no data so return an error - errorMsg = 'no data to export in provided time range.'; - } catch (e) { - const { errors } = await e.json(); - errorMsg = errors?.join('. '); - } - if (errorMsg) { - throw new Error(errorMsg); + const queryParams = this.formatQueryParams(query); + if (queryParams) { + return this.ajax(url, 'GET', { data: queryParams }).then((resp) => { + const response = resp || {}; + response.id = response.request_id || 'no-data'; + return response; + }); } } diff --git a/ui/app/adapters/generated-item-list.js b/ui/app/adapters/generated-item-list.js index 2d2efd8a9ea7..5c5d3f2e9145 100644 --- a/ui/app/adapters/generated-item-list.js +++ b/ui/app/adapters/generated-item-list.js @@ -4,112 +4,44 @@ */ import ApplicationAdapter from './application'; +import { task } from 'ember-concurrency'; import { service } from '@ember/service'; -import { sanitizePath } from 'core/utils/sanitize-path'; -import { encodePath } from 'vault/utils/path-encoding-helpers'; -import { tracked } from '@glimmer/tracking'; -export default class GeneratedItemListAdapter extends ApplicationAdapter { - @service store; - namespace = 'v1'; +export default ApplicationAdapter.extend({ + store: service(), + namespace: 'v1', + urlForItem() {}, + dynamicApiPath: '', - // these items are set by calling getNewAdapter in the path-help service. - @tracked apiPath = ''; - paths = {}; + getDynamicApiPath: task(function* (id) { + // TODO: remove yield at some point. + const result = yield this.store.peekRecord('auth-method', id); + this.dynamicApiPath = result.apiPath; + return; + }), - // These are the paths used for the adapter actions - get getPath() { - return this.paths.getPath || ''; - } - get createPath() { - return this.paths.createPath || ''; - } - get deletePath() { - return this.paths.deletePath || ''; - } - - getDynamicApiPath(id) { - const result = this.store.peekRecord('auth-method', id); - this.apiPath = result.apiPath; - return result.apiPath; - } - - async fetchByQuery(store, query, isList) { + fetchByQuery: task(function* (store, query, isList) { const { id } = query; - const payload = {}; + const data = {}; if (isList) { - payload.list = true; + data.list = true; + yield this.getDynamicApiPath.perform(id); } - const path = isList ? this.getDynamicApiPath(id) : ''; - const resp = await this.ajax(this.urlForItem(id, isList, path), 'GET', { data: payload }); - const data = { - id, - method: id, - }; - return { ...resp, ...data }; - } + return this.ajax(this.urlForItem(id, isList, this.dynamicApiPath), 'GET', { data }).then((resp) => { + const data = { + id, + method: id, + }; + return { ...resp, ...data }; + }); + }), query(store, type, query) { - return this.fetchByQuery(store, query, true); - } + return this.fetchByQuery.perform(store, query, true); + }, queryRecord(store, type, query) { - return this.fetchByQuery(store, query); - } - - urlForItem(id, isList, dynamicApiPath) { - const itemType = sanitizePath(this.getPath); - let url; - id = encodePath(id); - // the apiPath changes when you switch between routes but the apiPath variable does not unless the model is reloaded - // overwrite apiPath if dynamicApiPath exist. - // dynamicApiPath comes from the model->adapter - let apiPath = this.apiPath; - if (dynamicApiPath) { - apiPath = dynamicApiPath; - } - // isList indicates whether we are viewing the list page - // of a top-level item such as userpass - if (isList) { - url = `${this.buildURL()}/${apiPath}${itemType}/`; - } else { - // build the URL for the show page of a nested item - // such as a userpass group - url = `${this.buildURL()}/${apiPath}${itemType}/${id}`; - } - - return url; - } - - urlForQueryRecord(id, modelName) { - return this.urlForItem(id, modelName); - } - - urlForUpdateRecord(id) { - const itemType = this.createPath.slice(1, this.createPath.indexOf('{') - 1); - return `${this.buildURL()}/${this.apiPath}${itemType}/${id}`; - } - - urlForCreateRecord(modelType, snapshot) { - const id = snapshot.record.mutableId; // computed property that returns either id or private settable _id value - const path = this.createPath.slice(1, this.createPath.indexOf('{') - 1); - return `${this.buildURL()}/${this.apiPath}${path}/${id}`; - } - - urlForDeleteRecord(id) { - const path = this.deletePath.slice(1, this.deletePath.indexOf('{') - 1); - return `${this.buildURL()}/${this.apiPath}${path}/${id}`; - } - - createRecord(store, type, snapshot) { - return super.createRecord(...arguments).then((response) => { - // if the server does not return an id and one has not been set on the model we need to set it manually from the mutableId value - if (!response?.id && !snapshot.record.id) { - snapshot.record.id = snapshot.record.mutableId; - snapshot.id = snapshot.record.id; - } - return response; - }); - } -} + return this.fetchByQuery.perform(store, query); + }, +}); diff --git a/ui/app/adapters/identity/oidc/config.js b/ui/app/adapters/identity/oidc/config.js deleted file mode 100644 index f18b0917f223..000000000000 --- a/ui/app/adapters/identity/oidc/config.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import ApplicationAdapter from '../../application'; - -export default class IdentityOidcConfig extends ApplicationAdapter { - namespace = 'v1'; - - queryRecord() { - return this.ajax(`${this.buildURL()}/identity/oidc/config`, 'GET').then((resp) => { - return { - ...resp, - id: 'identity-oidc-config', // id required for ember data. only one record is expected so static id is fine - }; - }); - } - - createOrUpdate(store, type, snapshot) { - const serializer = store.serializerFor(type.modelName); - const data = serializer.serialize(snapshot); - return this.ajax(`${this.buildURL()}/identity/oidc/config`, 'POST', { data }).then((resp) => { - // id is returned from API so we do not need to explicitly set it here - return { - ...resp, - }; - }); - } - - createRecord() { - return this.createOrUpdate(...arguments); - } - - updateRecord() { - return this.createOrUpdate(...arguments); - } -} diff --git a/ui/app/adapters/kmip/role.js b/ui/app/adapters/kmip/role.js index 4023ed0f7627..9779ad67a564 100644 --- a/ui/app/adapters/kmip/role.js +++ b/ui/app/adapters/kmip/role.js @@ -6,11 +6,10 @@ import BaseAdapter from './base'; import { decamelize } from '@ember/string'; import { getProperties } from '@ember/object'; -import { nonOperationFields } from 'vault/utils/model-helpers/kmip-role-fields'; export default BaseAdapter.extend({ createRecord(store, type, snapshot) { - const name = snapshot.id || snapshot.record.role; + const name = snapshot.id || snapshot.attr('name'); const url = this._url( type.modelName, { @@ -19,11 +18,10 @@ export default BaseAdapter.extend({ }, name ); - const data = this.serialize(snapshot); - return this.ajax(url, 'POST', { data }).then(() => { + return this.ajax(url, 'POST', { data: this.serialize(snapshot) }).then(() => { return { id: name, - role: name, + name, backend: snapshot.record.backend, scope: snapshot.record.scope, }; @@ -31,8 +29,7 @@ export default BaseAdapter.extend({ }, deleteRecord(store, type, snapshot) { - // records must always have IDs - const name = snapshot.id; + const name = snapshot.id || snapshot.attr('name'); const url = this._url( type.modelName, { @@ -44,35 +41,35 @@ export default BaseAdapter.extend({ return this.ajax(url, 'DELETE'); }, - updateRecord() { - return this.createRecord(...arguments); - }, - serialize(snapshot) { // the endpoint here won't allow sending `operation_all` and `operation_none` at the same time or with // other operation_ values, so we manually check for them and send an abbreviated object const json = snapshot.serialize(); - const keys = nonOperationFields(snapshot.record.editableFields).map(decamelize); - const nonOp = getProperties(json, keys); - for (const field in nonOp) { - if (nonOp[field] == null) { - delete nonOp[field]; + const keys = snapshot.record.nonOperationFields.map(decamelize); + const nonOperationFields = getProperties(json, keys); + for (const field in nonOperationFields) { + if (nonOperationFields[field] == null) { + delete nonOperationFields[field]; } } if (json.operation_all) { return { operation_all: true, - ...nonOp, + ...nonOperationFields, }; } if (json.operation_none) { return { operation_none: true, - ...nonOp, + ...nonOperationFields, }; } delete json.operation_none; delete json.operation_all; return json; }, + + updateRecord() { + return this.createRecord(...arguments); + }, }); diff --git a/ui/app/adapters/kv/data.js b/ui/app/adapters/kv/data.js index 9ed2039a528f..2b68acd5a782 100644 --- a/ui/app/adapters/kv/data.js +++ b/ui/app/adapters/kv/data.js @@ -4,7 +4,7 @@ */ import ApplicationAdapter from '../application'; -import { kvDataPath, kvDeletePath, kvDestroyPath, kvSubkeysPath, kvUndeletePath } from 'vault/utils/kv-path'; +import { kvDataPath, kvDeletePath, kvDestroyPath, kvMetadataPath, kvUndeletePath } from 'vault/utils/kv-path'; import { assert } from '@ember/debug'; import ControlGroupError from 'vault/lib/control-group-error'; @@ -31,36 +31,12 @@ export default class KvDataAdapter extends ApplicationAdapter { }); } - fetchSubkeys(backend, path, query) { - const url = this._url(kvSubkeysPath(backend, path, query)); - return ( - this.ajax(url, 'GET') - .then((resp) => resp.data) - // deleted/destroyed secret versions throw an error - // but still have metadata that we want to return - .catch((errorOrResponse) => { - return this.parseErrorOrResponse(errorOrResponse, { backend, path }, true); - }) - ); - } - fetchWrapInfo(query) { const { backend, path, version, wrapTTL } = query; const id = kvDataPath(backend, path, version); return this.ajax(this._url(id), 'GET', { wrapTTL }).then((resp) => resp.wrap_info); } - // patching a secret happens without retrieving the ember data model - // so we use a custom method instead of updateRecord - patchSecret(backend, path, patchData, version) { - const url = this._url(kvDataPath(backend, path)); - const data = { - options: { cas: version }, - data: patchData, - }; - return this.ajax(url, 'PATCH', { data }); - } - queryRecord(store, type, query) { const { backend, path, version } = query; // ID is the full path for the data (including version) @@ -84,7 +60,39 @@ export default class KvDataAdapter extends ApplicationAdapter { }; }) .catch((errorOrResponse) => { - return this.parseErrorOrResponse(errorOrResponse, { id, backend, path, version }); + const baseResponse = { id, backend, path, version }; + const errorCode = errorOrResponse.httpStatus; + // if it's a legitimate error - throw it! + if (errorOrResponse instanceof ControlGroupError) { + throw errorOrResponse; + } + + if (errorCode === 403) { + return { + data: { + ...baseResponse, + fail_read_error_code: errorCode, + }, + }; + } + + if (errorOrResponse.data) { + // in the case of a deleted/destroyed secret the API returns a 404 because { data: null } + // however, there could be a metadata block with important information like deletion_time + // handleResponse below checks 404 status codes for metadata and updates the code to 200 if it exists. + // we still end up in the good ol' catch() block, but instead of a 404 adapter error we've "caught" + // the metadata that sneakily tried to hide from us + return { + ...errorOrResponse, + data: { + ...baseResponse, + ...errorOrResponse.data, // includes the { metadata } key we want + }, + }; + } + + // If we get here, it's probably a 404 because it doesn't exist + throw errorOrResponse; }); } @@ -112,8 +120,12 @@ export default class KvDataAdapter extends ApplicationAdapter { return this.ajax(this._url(kvUndeletePath(backend, path)), 'POST', { data: { versions: deleteVersions }, }); + case 'destroy-all-versions': + return this.ajax(this._url(kvMetadataPath(backend, path)), 'DELETE'); default: - assert('deleteType must be one of delete-latest-version, delete-version, destroy, or undelete.'); + assert( + 'deleteType must be one of delete-latest-version, delete-version, destroy, undelete, or destroy-all-versions.' + ); } } @@ -125,42 +137,4 @@ export default class KvDataAdapter extends ApplicationAdapter { } return super.handleResponse(...arguments); } - - parseErrorOrResponse(errorOrResponse, secretDataBaseResponse, isSubkeys = false) { - // if it's a legitimate error - throw it! - if (errorOrResponse instanceof ControlGroupError) { - throw errorOrResponse; - } - - const errorCode = errorOrResponse.httpStatus; - if (errorCode === 403) { - return { - data: { - ...secretDataBaseResponse, - fail_read_error_code: errorCode, - }, - }; - } - - // in the case of a deleted/destroyed secret the API returns a 404 because { data: null } - // however, there could be a metadata block with important information like deletion_time - // handleResponse below checks 404 status codes for metadata and updates the code to 200 if it exists. - // we still end up in the good ol' catch() block, but instead of a 404 adapter error we've "caught" - // the metadata that sneakily tried to hide from us - if (errorOrResponse.data) { - // subkeys response doesn't correspond to a model, no need to include base response - if (isSubkeys) return errorOrResponse.data; - - return { - ...errorOrResponse, - data: { - ...secretDataBaseResponse, - ...errorOrResponse.data, // includes the { metadata } key we want - }, - }; - } - - // If we get here, it's probably a 404 because it doesn't exist - throw errorOrResponse; - } } diff --git a/ui/app/adapters/kv/metadata.js b/ui/app/adapters/kv/metadata.js index f87d34160043..ac61daf0163c 100644 --- a/ui/app/adapters/kv/metadata.js +++ b/ui/app/adapters/kv/metadata.js @@ -68,17 +68,11 @@ export default class KvMetadataAdapter extends ApplicationAdapter { }); } - // This method is called when deleting from the list or metadata details view. - // Otherwise, delete happens in kv/data adapter + // This method is only called when deleting from the LIST view. Otherwise, delete on kv/data deleteRecord(store, type, snapshot) { const { backend, path, fullSecretPath } = snapshot.record; // fullSecretPath is used when deleting from the LIST view and is defined via the serializer // path is used when deleting from the metadata details view. return this.ajax(this._url(kvMetadataPath(backend, fullSecretPath || path)), 'DELETE'); } - - // custom method used if users do not have "read" permissions to fetch record - deleteMetadata(backend, path) { - return this.ajax(this._url(kvMetadataPath(backend, path)), 'DELETE'); - } } diff --git a/ui/app/adapters/named-path.js b/ui/app/adapters/named-path.js index 6b8fb7297483..535cf33e3d9a 100644 --- a/ui/app/adapters/named-path.js +++ b/ui/app/adapters/named-path.js @@ -30,7 +30,7 @@ export default class NamedPathAdapter extends ApplicationAdapter { const [store, { modelName }, snapshot] = arguments; const name = snapshot.attr('name'); // throw error if user attempts to create a record with same name, otherwise POST request silently overrides (updates) the existing model - if (store.peekRecord({ type: modelName, id: name }) !== null) { + if (store.hasRecordForId(modelName, name)) { throw new Error(`A record already exists with the name: ${name}`); } else { return this._saveRecord(...arguments); diff --git a/ui/app/adapters/secret-engine.js b/ui/app/adapters/secret-engine.js index 16a9cfd7a778..c19b68b3fb17 100644 --- a/ui/app/adapters/secret-engine.js +++ b/ui/app/adapters/secret-engine.js @@ -87,6 +87,23 @@ export default ApplicationAdapter.extend({ } }, + findRecord(store, type, path, snapshot) { + if (snapshot.attr('type') === 'ssh') { + return this.ajax(`/v1/${encodePath(path)}/config/ca`, 'GET'); + } + return { data: {} }; + }, + + queryRecord(store, type, query) { + if (query.type === 'aws') { + return this.ajax(`/v1/${encodePath(query.backend)}/config/lease`, 'GET').then((resp) => { + resp.path = query.backend + '/'; + return resp; + }); + } + return; + }, + updateRecord(store, type, snapshot) { const { apiPath, options, adapterMethod } = snapshot.adapterOptions; if (adapterMethod) { @@ -100,6 +117,18 @@ export default ApplicationAdapter.extend({ } }, + saveAWSRoot(store, type, snapshot) { + const { data } = snapshot.adapterOptions; + const path = encodePath(snapshot.id); + return this.ajax(`/v1/${path}/config/root`, 'POST', { data }); + }, + + saveAWSLease(store, type, snapshot) { + const { data } = snapshot.adapterOptions; + const path = encodePath(snapshot.id); + return this.ajax(`/v1/${path}/config/lease`, 'POST', { data }); + }, + saveZeroAddressConfig(store, type, snapshot) { const path = encodePath(snapshot.id); const roles = store diff --git a/ui/app/adapters/ssh/ca-config.js b/ui/app/adapters/ssh/ca-config.js deleted file mode 100644 index 6f745a70a931..000000000000 --- a/ui/app/adapters/ssh/ca-config.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import ApplicationAdapter from '../application'; -import { encodePath } from 'vault/utils/path-encoding-helpers'; - -export default class SshCaConfig extends ApplicationAdapter { - namespace = 'v1'; - - queryRecord(store, type, query) { - const { backend } = query; - return this.ajax(`${this.buildURL()}/${encodePath(backend)}/config/ca`, 'GET').then((resp) => { - resp.id = backend; - resp.backend = backend; - return resp; - }); - } - - createOrUpdate(store, type, snapshot) { - const serializer = store.serializerFor(type.modelName); - const data = serializer.serialize(snapshot); - const backend = snapshot.record.backend; - return this.ajax(`${this.buildURL()}/${backend}/config/ca`, 'POST', { data }).then((resp) => { - // ember data requires an id on the response - return { - ...resp, - id: backend, - }; - }); - } - - createRecord() { - return this.createOrUpdate(...arguments); - } - - updateRecord() { - return this.createOrUpdate(...arguments); - } - - deleteRecord(store, type, snapshot) { - const backend = snapshot.record.backend; - return this.ajax(`${this.buildURL()}/${backend}/config/ca`, 'DELETE'); - } -} diff --git a/ui/app/app.js b/ui/app/app.js index 5de9c28a3a33..779ba59370cc 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -8,7 +8,6 @@ import Resolver from 'ember-resolver'; import loadInitializers from 'ember-load-initializers'; import config from 'vault/config/environment'; -// TODO: DEPRECATION https://ember-engines.com/docs/deprecations#-use-alias-for-inject-router-service-from-host-application export default class App extends Application { modulePrefix = config.modulePrefix; podModulePrefix = config.podModulePrefix; @@ -28,7 +27,6 @@ export default class App extends Application { dependencies: { services: [ 'auth', - 'capabilities', 'flash-messages', 'namespace', 'replication-mode', @@ -80,15 +78,13 @@ export default class App extends Application { kv: { dependencies: { services: [ - 'capabilities', - 'control-group', 'download', - 'flash-messages', 'namespace', 'router', - 'secret-mount-path', 'store', - 'version', + 'secret-mount-path', + 'flash-messages', + 'control-group', ], externalRoutes: { secrets: 'vault.cluster.secrets.backends', @@ -120,7 +116,7 @@ export default class App extends Application { dependencies: { services: ['flash-messages', 'flags', 'router', 'store', 'version'], externalRoutes: { - kvSecretOverview: 'vault.cluster.secrets.backend.kv.secret.index', + kvSecretDetails: 'vault.cluster.secrets.backend.kv.secret.details', clientCountOverview: 'vault.cluster.clients', }, }, diff --git a/ui/app/components/app-footer.hbs b/ui/app/components/app-footer.hbs index 00bbee18486a..477807626a91 100644 --- a/ui/app/components/app-footer.hbs +++ b/ui/app/components/app-footer.hbs @@ -28,16 +28,4 @@ Documentation - - {{#if this.isDevelopment}} - - {{/if}} - \ No newline at end of file diff --git a/ui/app/components/auth-form.js b/ui/app/components/auth-form.js index d87161b29048..cf7e93102c95 100644 --- a/ui/app/components/auth-form.js +++ b/ui/app/components/auth-form.js @@ -3,6 +3,7 @@ * SPDX-License-Identifier: BUSL-1.1 */ +import Ember from 'ember'; import { next } from '@ember/runloop'; import { service } from '@ember/service'; import { match, or } from '@ember/object/computed'; @@ -10,25 +11,27 @@ import { dasherize } from '@ember/string'; import Component from '@ember/component'; import { computed } from '@ember/object'; import { allSupportedAuthBackends, supportedAuthBackends } from 'vault/helpers/supported-auth-backends'; -import { task } from 'ember-concurrency'; +import { task, timeout } from 'ember-concurrency'; import { waitFor } from '@ember/test-waiters'; import { v4 as uuidv4 } from 'uuid'; /** * @module AuthForm - * The AuthForm displays the form used to sign users into Vault and passes input data to the Auth::Page component which handles authentication + * The `AuthForm` is used to sign users into Vault. * - * @example - * + * @example ```js + * // All properties are passed in via query params. + * ``` * - * @param {string} wrappedToken - Token that can be used to login if added directly to the URL via the "wrapped_token" query param - * @param {object} cluster - The cluster model which contains information such as cluster id, name and boolean for if the cluster is in standby + * @param {string} wrappedToken - The auth method that is currently selected in the dropdown. + * @param {object} cluster - The auth method that is currently selected in the dropdown. This corresponds to an Ember Model. * @param {string} namespace- The currently active namespace. * @param {string} selectedAuth - The auth method that is currently selected in the dropdown. - * @param {function} performAuth - Callback that triggers authenticate task in the parent, backend type (i.e. 'okta') and relevant auth data are passed as args - * @param {string} error - Error returned by the parent authenticate task, message is generated by the auth service handleError method - * @param {boolean} authIsRunning - Boolean that relays whether or not the authenticate task is running - * @param {boolean} delayIsIdle - Boolean that relays whether or not the delayAuthMessageReminder parent task is idle + * @param {function} onSuccess - Fired on auth success. + * @param {function} [setOktaNumberChallenge] - Sets whether we are waiting for okta number challenge to be used to sign in. + * @param {boolean} [waitingForOktaNumberChallenge=false] - Determines if we are waiting for the Okta Number Challenge to sign in. + * @param {function} [setCancellingAuth] - Sets whether we are cancelling or not the login authentication for Okta Number Challenge. + * @param {boolean} [cancelAuthForOktaNumberChallenge=false] - Determines if we are cancelling the login authentication for the Okta Number Challenge. */ const DEFAULTS = { @@ -46,7 +49,7 @@ export default Component.extend(DEFAULTS, { csp: service('csp-event'), version: service(), - // set by query params, passed from parent Auth::Page component + // passed in via a query param selectedAuth: null, methods: null, cluster: null, @@ -55,6 +58,9 @@ export default Component.extend(DEFAULTS, { // internal oldNamespace: null, + // number answer for okta number challenge if applicable + oktaNumberChallengeAnswer: null, + authMethods: computed('version.isEnterprise', function () { return this.version.isEnterprise ? allSupportedAuthBackends() : supportedAuthBackends(); }), @@ -68,13 +74,18 @@ export default Component.extend(DEFAULTS, { namespace: ns, selectedAuth: newMethod, oldSelectedAuth: oldMethod, + cancelAuthForOktaNumberChallenge: cancelAuth, } = this; + // if we are cancelling the login then we reset the number challenge answer and cancel the current authenticate and polling tasks + if (cancelAuth) { + this.set('oktaNumberChallengeAnswer', null); + this.authenticate.cancelAll(); + this.pollForOktaNumberChallenge.cancelAll(); + } next(() => { if (!token && (oldNS === null || oldNS !== ns)) { this.fetchMethods.perform(); } - // don't set any variables if the component is being torn down - if (this.isDestroyed || this.isDestroying) return; this.set('oldNamespace', ns); // we only want to trigger this once if (token && !oldToken) { @@ -224,7 +235,65 @@ export default Component.extend(DEFAULTS, { }) ), - showLoading: or('isLoading', 'authIsRunning', 'fetchMethods.isRunning', 'unwrapToken.isRunning'), + showLoading: or('isLoading', 'authenticate.isRunning', 'fetchMethods.isRunning', 'unwrapToken.isRunning'), + + authenticate: task( + waitFor(function* (backendType, data) { + const { + selectedAuth, + cluster: { id: clusterId }, + } = this; + try { + if (backendType === 'okta') { + this.pollForOktaNumberChallenge.perform(data.nonce, data.path); + } else { + this.delayAuthMessageReminder.perform(); + } + const authResponse = yield this.auth.authenticate({ + clusterId, + backend: backendType, + data, + selectedAuth, + }); + this.onSuccess(authResponse, backendType, data); + } catch (e) { + this.set('isLoading', false); + if (!this.auth.mfaError) { + this.set('error', `Authentication failed: ${this.auth.handleError(e)}`); + } + } + }) + ), + + pollForOktaNumberChallenge: task(function* (nonce, mount) { + // yield for 1s to wait to see if there is a login error before polling + yield timeout(1000); + if (this.error) { + return; + } + let response = null; + this.setOktaNumberChallenge(true); + this.setCancellingAuth(false); + // keep polling /auth/okta/verify/:nonce API every 1s until a response is given with the correct number for the Okta Number Challenge + while (response === null) { + // when testing, the polling loop causes promises to be rejected making acceptance tests fail + // so disable the poll in tests + if (Ember.testing) { + return; + } + yield timeout(1000); + response = yield this.auth.getOktaNumberChallengeAnswer(nonce, mount); + } + this.set('oktaNumberChallengeAnswer', response); + }), + + delayAuthMessageReminder: task(function* () { + if (Ember.testing) { + yield timeout(0); + } else { + yield timeout(5000); + } + }), actions: { doSubmit(passedData, event, token) { @@ -257,7 +326,7 @@ export default Component.extend(DEFAULTS, { data.path = 'okta'; } } - return this.performAuth(backend.type, data); + return this.authenticate.unlinked().perform(backend.type, data); }, handleError(e) { this.setProperties({ @@ -265,5 +334,9 @@ export default Component.extend(DEFAULTS, { error: e ? this.auth.handleError(e) : null, }); }, + returnToLoginFromOktaNumberChallenge() { + this.setOktaNumberChallenge(false); + this.set('oktaNumberChallengeAnswer', null); + }, }, }); diff --git a/ui/app/components/auth/login-form.hbs b/ui/app/components/auth/login-form.hbs deleted file mode 100644 index e8b4d0c2e2e7..000000000000 --- a/ui/app/components/auth/login-form.hbs +++ /dev/null @@ -1,23 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -~}} - -{{#if this.waitingForOktaNumberChallenge}} - -{{else}} - -{{/if}} \ No newline at end of file diff --git a/ui/app/components/auth/login-form.js b/ui/app/components/auth/login-form.js deleted file mode 100644 index e3551ce68dc0..000000000000 --- a/ui/app/components/auth/login-form.js +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Component from '@glimmer/component'; -import Ember from 'ember'; -import { service } from '@ember/service'; -import { task, timeout } from 'ember-concurrency'; -import { waitFor } from '@ember/test-waiters'; -import { tracked } from '@glimmer/tracking'; -import { action } from '@ember/object'; - -/** - * @module AuthLoginForm - * The Auth::LoginForm wraps OktaNumberChallenge and AuthForm to manage the login flow and is responsible for calling the authenticate method - * - * @example - * - * - * @param {string} wrappedToken - Query param value of a wrapped token that can be used to login when added directly to the URL via the "wrapped_token" query param - * @param {object} cluster - The route model which is the ember data cluster model. contains information such as cluster id, name and boolean for if the cluster is in standby - * @param {string} namespace- Namespace query param, passed to AuthForm and set by typing in namespace input or URL - * @param {string} selectedAuth - The auth method selected in the dropdown, passed to auth service's authenticate method - * @param {function} onSuccess - Callback that fires the "onAuthResponse" action in the auth controller and handles transitioning after success - */ - -export default class AuthLoginFormComponent extends Component { - @service auth; - - @tracked authError = null; - @tracked oktaNumberChallengeAnswer = ''; - @tracked waitingForOktaNumberChallenge = false; - - @action - performAuth(backendType, data) { - this.authenticate.unlinked().perform(backendType, data); - } - - @task - @waitFor - *delayAuthMessageReminder() { - if (Ember.testing) { - yield timeout(0); - } else { - yield timeout(5000); - } - } - - @task - @waitFor - *authenticate(backendType, data) { - const { - selectedAuth, - cluster: { id: clusterId }, - } = this.args; - try { - if (backendType === 'okta') { - this.pollForOktaNumberChallenge.perform(data.nonce, data.path); - } else { - this.delayAuthMessageReminder.perform(); - } - const authResponse = yield this.auth.authenticate({ - clusterId, - backend: backendType, - data, - selectedAuth, - }); - - this.args.onSuccess(authResponse, backendType, data); - } catch (e) { - if (!this.auth.mfaError) { - this.authError = `Authentication failed: ${this.auth.handleError(e)}`; - } - } - } - - @task - @waitFor - *pollForOktaNumberChallenge(nonce, mount) { - // yield for 1s to wait to see if there is a login error before polling - yield timeout(1000); - if (this.authError) return; - - this.waitingForOktaNumberChallenge = true; - // keep polling /auth/okta/verify/:nonce API every 1s until response returns with correct_number - let response = null; - while (response === null) { - // disable polling for tests otherwise promises reject and acceptance tests fail - if (Ember.testing) return; - - yield timeout(1000); - response = yield this.auth.getOktaNumberChallengeAnswer(nonce, mount); - } - // display correct number so user can select on personal MFA device - this.oktaNumberChallengeAnswer = response; - } - - @action - onCancel() { - // reset variables and stop polling tasks if canceling login - this.authError = null; - this.oktaNumberChallengeAnswer = null; - this.waitingForOktaNumberChallenge = false; - this.authenticate.cancelAll(); - this.pollForOktaNumberChallenge.cancelAll(); - } -} diff --git a/ui/app/components/auth/page.hbs b/ui/app/components/auth/page.hbs deleted file mode 100644 index 046a9655d903..000000000000 --- a/ui/app/components/auth/page.hbs +++ /dev/null @@ -1,119 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -~}} - -{{#if this.mfaErrors}} -
- - - -
-{{else}} - - <:header> - {{#if @oidcProviderQueryParam}} -
- -
- {{else}} -
-
- -
-
-
- {{#if this.mfaAuthData}} - - {{/if}} -

- {{if this.mfaAuthData "Authenticate" "Sign in to Vault"}} -

-
- {{/if}} - - - <:subHeader> - {{#if (has-feature "Namespaces")}} - {{#unless this.mfaAuthData}} - -
-
- -
- {{#if this.flags.hvdManagedNamespaceRoot}} -
- /{{this.flags.hvdManagedNamespaceRoot}} -
- {{/if}} -
-
-
- -
-
-
-
-
- {{/unless}} - {{/if}} - - - <:content> - {{#if this.mfaAuthData}} - - {{else}} - - {{/if}} - - - <:footer> -
-

- {{#if @oidcProviderQueryParam}} - Once you log in, you will be redirected back to your application. If you require login credentials, contact your - administrator. - {{else}} - Contact your administrator for login credentials. - {{/if}} -

-
- -
-{{/if}} \ No newline at end of file diff --git a/ui/app/components/auth/page.js b/ui/app/components/auth/page.js deleted file mode 100644 index 85dc29c20708..000000000000 --- a/ui/app/components/auth/page.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Component from '@glimmer/component'; -import { service } from '@ember/service'; -import { tracked } from '@glimmer/tracking'; -import { action } from '@ember/object'; - -/** - * @module AuthPage - * The Auth::Page wraps OktaNumberChallenge and AuthForm to manage the login flow and is responsible for calling the authenticate method - * - * @example - * - * - * @param {string} authMethodQueryParam - auth method type to login with, updated by selecting an auth method from the dropdown - * @param {string} namespaceQueryParam - namespace to login with, updated by typing in to the namespace input - * @param {string} oidcProviderQueryParam - oidc provider query param, set in url as "?o=someprovider" - * @param {function} onAuthSuccess - callback task in controller that receives the auth response (after MFA, if enabled) when login is successful - * @param {function} onNamespaceUpdate - callback task that passes user input to the controller to update the login namespace in the url query params - * @param {string} wrappedToken - passed down to the AuthForm component and can be used to login if added directly to the URL via the "wrapped_token" query param - * */ - -export default class AuthPage extends Component { - @service flags; - - @tracked mfaErrors; - @tracked mfaAuthData; - - get namespaceInput() { - const namespaceQP = this.args.namespaceQueryParam; - if (this.flags.hvdManagedNamespaceRoot) { - // When managed, the user isn't allowed to edit the prefix `admin/` for their nested namespace - const split = namespaceQP.split('/'); - if (split.length > 1) { - split.shift(); - return `/${split.join('/')}`; - } - return ''; - } - return namespaceQP; - } - - @action - handleNamespaceUpdate(event) { - this.args.onNamespaceUpdate(event.target.value); - } - - @action - onAuthResponse(authResponse, backend, data) { - const { mfa_requirement } = authResponse; - // if an mfa requirement exists further action is required - if (mfa_requirement) { - this.mfaAuthData = { mfa_requirement, backend, data }; - } else { - this.args.onAuthSuccess(authResponse); - } - } - - @action - onMfaSuccess(authResponse) { - this.args.onAuthSuccess(authResponse); - } - - @action - onMfaErrorDismiss() { - this.mfaAuthData = null; - this.mfaErrors = null; - } -} diff --git a/ui/app/components/calendar-widget.js b/ui/app/components/calendar-widget.js new file mode 100644 index 000000000000..804c9af1963a --- /dev/null +++ b/ui/app/components/calendar-widget.js @@ -0,0 +1,103 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { tracked } from '@glimmer/tracking'; +import { ARRAY_OF_MONTHS, parseAPITimestamp } from 'core/utils/date-formatters'; +import { addYears, isSameYear, subYears } from 'date-fns'; +import timestamp from 'core/utils/timestamp'; +/** + * @module CalendarWidget + * CalendarWidget component is used in the client counts dashboard to select a month/year to query the /activity endpoint. + * The component returns an object with selected date info, example: { dateType: 'endDate', monthIdx: 0, monthName: 'January', year: 2022 } + * + * @example + * ```js + * + * + * @param {string} startTimestamp - ISO timestamp string of the calendar widget's start time, displays in dropdown trigger + * @param {string} endTimestamp - ISO timestamp string for the calendar widget's end time, displays in dropdown trigger + * @param {function} selectMonth - callback function from parent - fires when selecting a month or clicking "Current billing period" + * /> + * ``` + */ +export default class CalendarWidget extends Component { + currentDate = timestamp.now(); + @tracked calendarDisplayDate = this.currentDate; // init to current date, updates when user clicks on calendar chevrons + @tracked showCalendar = false; + + // both date getters return a date object + get startDate() { + return parseAPITimestamp(this.args.startTimestamp); + } + get endDate() { + return parseAPITimestamp(this.args.endTimestamp); + } + get displayYear() { + return this.calendarDisplayDate.getFullYear(); + } + get disableFutureYear() { + return isSameYear(this.calendarDisplayDate, this.currentDate); + } + get disablePastYear() { + // calendar widget should only go as far back as the passed in start time + return isSameYear(this.calendarDisplayDate, this.startDate); + } + get widgetMonths() { + const startYear = this.startDate.getFullYear(); + const startMonthIdx = this.startDate.getMonth(); + return ARRAY_OF_MONTHS.map((month, index) => { + let readonly = false; + + // if widget is showing same year as @startTimestamp year, disable if month is before start month + if (startYear === this.displayYear && index < startMonthIdx) { + readonly = true; + } + + // if widget showing current year, disable if month is later than current month + if (this.displayYear === this.currentDate.getFullYear() && index > this.currentDate.getMonth()) { + readonly = true; + } + return { + index, + year: this.displayYear, + name: month, + readonly, + }; + }); + } + + @action + addYear() { + this.calendarDisplayDate = addYears(this.calendarDisplayDate, 1); + } + + @action + subYear() { + this.calendarDisplayDate = subYears(this.calendarDisplayDate, 1); + } + + @action + toggleShowCalendar() { + this.showCalendar = !this.showCalendar; + this.calendarDisplayDate = this.endDate; + } + + @action + handleDateShortcut(dropdown, { target }) { + this.args.selectMonth({ dateType: target.name }); // send clicked shortcut to parent callback + this.showCalendar = false; + dropdown.close(); + } + + @action + selectMonth(month, dropdown) { + const { index, year, name } = month; + this.toggleShowCalendar(); + this.args.selectMonth({ monthIdx: index, monthName: name, year, dateType: 'endDate' }); + dropdown.close(); + } +} diff --git a/ui/app/components/clients/activity.ts b/ui/app/components/clients/activity.ts index b64ff76f6c92..f22134b94a43 100644 --- a/ui/app/components/clients/activity.ts +++ b/ui/app/components/clients/activity.ts @@ -7,16 +7,10 @@ // contains getters that filter and extract data from activity model for use in charts import Component from '@glimmer/component'; -import { isSameMonth } from 'date-fns'; +import { isSameMonth, fromUnixTime } from 'date-fns'; import { parseAPITimestamp } from 'core/utils/date-formatters'; import { calculateAverage } from 'vault/utils/chart-helpers'; -import { - filterByMonthDataForMount, - filteredTotalForMount, - filterVersionHistory, -} from 'core/utils/client-count-utils'; -import { service } from '@ember/service'; -import { sanitizePath } from 'core/utils/sanitize-path'; +import { filterVersionHistory, hasMountsKey, hasNamespacesKey } from 'core/utils/client-count-utils'; import type ClientsActivityModel from 'vault/models/clients/activity'; import type ClientsVersionHistoryModel from 'vault/models/clients/version-history'; @@ -25,22 +19,18 @@ import type { MountNewClients, NamespaceByKey, NamespaceNewClients, - TotalClients, } from 'core/utils/client-count-utils'; -import type NamespaceService from 'vault/services/namespace'; interface Args { activity: ClientsActivityModel; versionHistory: ClientsVersionHistoryModel[]; - startTimestamp: string; - endTimestamp: string; + startTimestamp: number; + endTimestamp: number; namespace: string; mountPath: string; } export default class ClientsActivityComponent extends Component { - @service declare readonly namespace: NamespaceService; - average = ( data: | (ByMonthNewClients | NamespaceNewClients | MountNewClients | undefined)[] @@ -50,27 +40,56 @@ export default class ClientsActivityComponent extends Component { return calculateAverage(data, key); }; - // path of the filtered namespace OR current one, for filtering relevant data - get namespacePathForFilter() { - const { namespace } = this.args; - const currentNs = this.namespace.currentNamespace; - return sanitizePath(namespace || currentNs || 'root'); + get startTimeISO() { + return fromUnixTime(this.args.startTimestamp).toISOString(); + } + + get endTimeISO() { + return fromUnixTime(this.args.endTimestamp).toISOString(); } get byMonthActivityData() { - const { activity, mountPath } = this.args; - const nsPath = this.namespacePathForFilter; - if (mountPath) { - // only do client-side filtering if we have a mountPath filter set - return filterByMonthDataForMount(activity.byMonth, nsPath, mountPath); - } - return activity.byMonth; + const { activity, namespace } = this.args; + return namespace ? this.filteredActivityByMonth : activity.byMonth; } get byMonthNewClients() { return this.byMonthActivityData ? this.byMonthActivityData?.map((m) => m?.new_clients) : []; } + get filteredActivityByMonth() { + const { namespace, mountPath, activity } = this.args; + if (!namespace && !mountPath) { + return activity.byMonth; + } + const namespaceData = activity.byMonth + ?.map((m) => m.namespaces_by_key[namespace]) + .filter((d) => d !== undefined); + + if (!mountPath) { + return namespaceData || []; + } + + const mountData = namespaceData + ?.map((namespace) => namespace?.mounts_by_key[mountPath]) + .filter((d) => d !== undefined); + + return mountData || []; + } + + get filteredActivityByNamespace() { + const { namespace, activity } = this.args; + return activity.byNamespace.find((ns) => ns.label === namespace); + } + + get filteredActivityByAuthMount() { + return this.filteredActivityByNamespace?.mounts?.find((mount) => mount.label === this.args.mountPath); + } + + get filteredActivity() { + return this.args.mountPath ? this.filteredActivityByAuthMount : this.filteredActivityByNamespace; + } + get isCurrentMonth() { const { activity } = this.args; const current = parseAPITimestamp(activity.responseTimestamp) as Date; @@ -88,18 +107,62 @@ export default class ClientsActivityComponent extends Component { } // (object) top level TOTAL client counts for given date range - get totalUsageCounts(): TotalClients { - const { namespace, activity, mountPath } = this.args; - // only do this if we have a mountPath filter. - // namespace is filtered on API layer - if (activity?.byNamespace && namespace && mountPath) { - return filteredTotalForMount(activity.byNamespace, namespace, mountPath); - } - return activity?.total; + get totalUsageCounts() { + const { namespace, activity } = this.args; + return namespace ? this.filteredActivity : activity.total; } get upgradesDuringActivity() { const { versionHistory, activity } = this.args; return filterVersionHistory(versionHistory, activity.startTime, activity.endTime); } + + // (object) single month new client data with total counts and array of + // either namespaces or mounts + get newClientCounts() { + if (this.isDateRange || this.byMonthActivityData.length === 0) { + return null; + } + + return this.byMonthActivityData[0]?.new_clients; + } + + // total client data for horizontal bar chart in attribution component + get totalClientAttribution() { + const { namespace, activity } = this.args; + if (namespace) { + return this.filteredActivityByNamespace?.mounts || null; + } else { + return activity.byNamespace || null; + } + } + + // new client data for horizontal bar chart + get newClientAttribution() { + // new client attribution only available in a single, historical month (not a date range or current month) + if (this.isDateRange || this.isCurrentMonth || !this.newClientCounts) return null; + + const newCounts = this.newClientCounts; + if (this.args.namespace && hasMountsKey(newCounts)) return newCounts?.mounts; + + if (hasNamespacesKey(newCounts)) return newCounts?.namespaces; + + return null; + } + + get hasAttributionData() { + const { mountPath, namespace } = this.args; + if (!mountPath) { + if (namespace) { + const mounts = this.filteredActivityByNamespace?.mounts?.map((mount) => ({ + id: mount.label, + name: mount.label, + })); + return mounts && mounts.length > 0; + } + return !!this.totalClientAttribution && this.totalUsageCounts && this.totalUsageCounts.clients !== 0; + } + + return false; + } } diff --git a/ui/app/components/clients/attribution.hbs b/ui/app/components/clients/attribution.hbs index 385f0334614e..b28def480395 100644 --- a/ui/app/components/clients/attribution.hbs +++ b/ui/app/components/clients/attribution.hbs @@ -3,29 +3,66 @@ SPDX-License-Identifier: BUSL-1.1 ~}} -
-
-

{{capitalize this.noun}} attribution

-

{{this.chartText.description}}

-
- {{#if @attribution}} -
- +{{! only show side-by-side horizontal bar charts if data is from a single, historical month }} +
+ \ No newline at end of file +
+ +{{! MODAL FOR CSV DOWNLOAD }} +{{#if this.showCSVDownloadModal}} + + + Export attribution data + + +

+ {{this.modalExportText}} +

+

+ The + mount_path + for entity/non-entity clients is the corresponding authentication method path + {{if @isSecretsSyncActivated "and for secrets sync clients is the KV v2 engine path"}}. +

+

SELECTED DATE {{if this.formattedEndDate " RANGE"}}

+

+ {{this.formattedStartDate}} + {{if this.formattedEndDate "-"}} + {{this.formattedEndDate}}

+
+ + + + + + {{#if @upgradesDuringActivity}} + + + Data contains {{pluralize @upgradesDuringActivity.length "upgrade"}}: + + +
    + {{#each @upgradesDuringActivity as |upgrade|}} +
  • + {{upgrade.version}} + {{this.parseAPITimestamp upgrade.timestampInstalled "(MMM d, yyyy)"}} +
  • + {{/each}} +
+
+ + Visit our + + Client count FAQ + + for more information. + +
+ {{/if}} +
+
+{{/if}} \ No newline at end of file diff --git a/ui/app/components/clients/attribution.js b/ui/app/components/clients/attribution.js index 06d83d633b73..ed8bde49f30d 100644 --- a/ui/app/components/clients/attribution.js +++ b/ui/app/components/clients/attribution.js @@ -4,30 +4,47 @@ */ import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { tracked } from '@glimmer/tracking'; +import { service } from '@ember/service'; +import { parseAPITimestamp } from 'core/utils/date-formatters'; +import { format, isSameMonth } from 'date-fns'; /** * @module Attribution - * Attribution components display the top 10 total client counts for namespaces or mounts during a billing period. - * A horizontal bar chart shows on the right, with the top namespace/mount and respective client totals on the left. + * Attribution components display the top 10 total client counts for namespaces or auth methods (mounts) during a billing period. + * A horizontal bar chart shows on the right, with the top namespace/auth method and respective client totals on the left. * * @example * * - * @param {string} noun - noun which reflects the type of data and used in title. Should be "namespace" (default) or "mount" - * @param {array} attribution - array of objects containing a label and breakdown of client counts for total clients + * @param {object} totalUsageCounts - object with total client counts for chart tooltip text + * @param {object} newUsageCounts - object with new client counts for chart tooltip text + * @param {array} totalClientAttribution - array of objects containing a label and breakdown of client counts for total clients + * @param {array} newClientAttribution - array of objects containing a label and breakdown of client counts for new clients + * @param {string} selectedNamespace - namespace selected from filter bar + * @param {string} startTimestamp - timestamp string from activity response to render start date for CSV modal and whether copy reads 'month' or 'date range' + * @param {string} endTimestamp - timestamp string from activity response to render end date for CSV modal and whether copy reads 'month' or 'date range' * @param {string} responseTimestamp - ISO timestamp created in serializer to timestamp the response, renders in bottom left corner below attribution chart - * @param {boolean} isSecretsSyncActivated - boolean reflecting if secrets sync is activated. Determines the labels and data shown + * @param {boolean} isHistoricalMonth - when true data is from a single, historical month so side-by-side charts should display for attribution data + * @param {array} upgradesDuringActivity - array of objects containing version history upgrade data + * @param {boolean} isSecretsSyncActivated - boolean to determine if secrets sync is activated */ export default class Attribution extends Component { - get noun() { - return this.args.noun || 'namespace'; - } + @service download; + @tracked showCSVDownloadModal = false; get attributionLegend() { const attributionLegend = [ @@ -42,38 +59,191 @@ export default class Attribution extends Component { return attributionLegend; } - get sortedAttribution() { - if (this.args.attribution) { - // shallow copy so it doesn't mutate the data during tests - return this.args.attribution?.slice().sort((a, b) => b.clients - a.clients); - } - return []; + get formattedStartDate() { + if (!this.args.startTimestamp) return null; + return parseAPITimestamp(this.args.startTimestamp, 'MMMM yyyy'); + } + + get formattedEndDate() { + if (!this.args.startTimestamp && !this.args.endTimestamp) return null; + // displays on CSV export modal, no need to display duplicate months and years + const startDateObject = parseAPITimestamp(this.args.startTimestamp); + const endDateObject = parseAPITimestamp(this.args.endTimestamp); + return isSameMonth(startDateObject, endDateObject) ? null : format(endDateObject, 'MMMM yyyy'); + } + + get hasCsvData() { + return this.args.totalClientAttribution ? this.args.totalClientAttribution.length > 0 : false; + } + + get isSingleNamespace() { + // if a namespace is selected, then we're viewing top 10 auth methods (mounts) + return !!this.args.selectedNamespace; } // truncate data before sending to chart component - get topTenAttribution() { - return this.sortedAttribution.slice(0, 10); + get barChartTotalClients() { + return this.args.totalClientAttribution?.slice(0, 10); + } + + get barChartNewClients() { + return this.args.newClientAttribution?.slice(0, 10); } - get topAttribution() { - // get top namespace or mount - return this.sortedAttribution[0] ?? null; + get topClientCounts() { + // get top namespace or auth method + return this.args.totalClientAttribution ? this.args.totalClientAttribution[0] : null; + } + + get attributionBreakdown() { + // display text for hbs + return this.isSingleNamespace ? 'auth method' : 'namespace'; } get chartText() { - if (this.noun === 'namespace') { - return { - subtext: 'This data shows the top ten namespaces by total clients for the date range selected.', - description: - 'This data shows the top ten namespaces by total clients and can be used to understand where clients are originating. Namespaces are identified by path.', - }; - } else { - return { - subtext: - 'The total clients used by the mounts for this date range. This number is useful for identifying overall usage volume.', - description: - 'This data shows the top ten mounts by client count within this namespace, and can be used to understand where clients are originating. Mounts are organized by path.', - }; + if (!this.args.totalClientAttribution) { + return { description: 'There is a problem gathering data' }; + } + const dateText = this.formattedEndDate ? 'date range' : 'month'; + switch (this.isSingleNamespace) { + case true: + return { + description: + 'This data shows the top ten authentication methods by client count within this namespace, and can be used to understand where clients are originating. Authentication methods are organized by path.', + newCopy: `The new clients used by the auth method for this ${dateText}. This aids in understanding which auth methods create and use new clients${ + dateText === 'date range' ? ' over time.' : '.' + }`, + totalCopy: `The total clients used by the auth method for this ${dateText}. This number is useful for identifying overall usage volume. `, + }; + case false: + return { + description: + 'This data shows the top ten namespaces by client count and can be used to understand where clients are originating. Namespaces are identified by path. To see all namespaces, export this data.', + newCopy: `The new clients in the namespace for this ${dateText}. + This aids in understanding which namespaces create and use new clients${ + dateText === 'date range' ? ' over time.' : '.' + }`, + totalCopy: `The total clients in the namespace for this ${dateText}. This number is useful for identifying overall usage volume.`, + }; + default: + return ''; } } + + destructureCountsToArray(object) { + // destructure the namespace object {label: 'some-namespace', entity_clients: 171, non_entity_clients: 20, acme_clients: 6, secret_syncs: 10, clients: 207} + // to get integers for CSV file + const { clients, entity_clients, non_entity_clients, acme_clients, secret_syncs } = object; + const { isSecretsSyncActivated } = this.args; + + return [ + clients, + entity_clients, + non_entity_clients, + acme_clients, + ...(isSecretsSyncActivated ? [secret_syncs] : []), + ]; + } + + constructCsvRow(namespaceColumn, mountColumn = null, totalColumns, newColumns = null) { + // if namespaceColumn is a string, then we're at mount level attribution, otherwise it is an object + // if constructing a namespace row, mountColumn=null so the column is blank, otherwise it is an object + const otherColumns = newColumns ? [...totalColumns, ...newColumns] : [...totalColumns]; + return [ + `${typeof namespaceColumn === 'string' ? namespaceColumn : namespaceColumn.label}`, + `${mountColumn ? mountColumn.label : '*'}`, + ...otherColumns, + ]; + } + + generateCsvData() { + const totalAttribution = this.args.totalClientAttribution; + const newAttribution = this.barChartNewClients ? this.args.newClientAttribution : null; + const { isSecretsSyncActivated } = this.args; + const csvData = []; + // added to clarify that the row of namespace totals without an auth method (blank) are not additional clients + // but indicate the total clients for that ns, including its auth methods + const upgrade = this.args.upgradesDuringActivity?.length + ? `\n **data contains an upgrade (mount summation may not equal namespace totals)` + : ''; + const descriptionOfBlanks = this.isSingleNamespace + ? '' + : `\n *namespace totals, inclusive of mount clients${upgrade}`; + // client type order here should match array order returned by destructureCountsToArray + let csvHeader = [ + 'Namespace path', + `"Mount path${descriptionOfBlanks}"`, // double quotes necessary so description stays inside this cell + 'Total clients', + 'Entity clients', + 'Non-entity clients', + 'ACME clients', + ...(isSecretsSyncActivated ? ['Secrets sync clients'] : []), + ]; + + if (newAttribution) { + csvHeader = [ + ...csvHeader, + 'Total new clients', + 'New entity clients', + 'New non-entity clients', + 'New ACME clients', + ...(isSecretsSyncActivated ? 'New secrets sync clients' : []), + ]; + } + + totalAttribution.forEach((totalClientsObject) => { + const namespace = this.isSingleNamespace ? this.args.selectedNamespace : totalClientsObject; + const mount = this.isSingleNamespace ? totalClientsObject : null; + + // find new client data for namespace/mount object we're iterating over + const newClientsObject = newAttribution + ? newAttribution.find((d) => d.label === totalClientsObject.label) + : null; + + const totalClients = this.destructureCountsToArray(totalClientsObject); + const newClients = newClientsObject ? this.destructureCountsToArray(newClientsObject) : null; + + csvData.push(this.constructCsvRow(namespace, mount, totalClients, newClients)); + // constructCsvRow returns an array that corresponds to a row in the csv file: + // ['ns label', 'mount label', total client #, entity #, non-entity #, acme #, secrets sync #, ...new client #'s] + + // only iterate through mounts if NOT viewing a single namespace + if (!this.isSingleNamespace && namespace.mounts) { + namespace.mounts.forEach((mount) => { + const newMountData = newAttribution + ? newClientsObject?.mounts.find((m) => m.label === mount.label) + : null; + const mountTotalClients = this.destructureCountsToArray(mount); + const mountNewClients = newMountData ? this.destructureCountsToArray(newMountData) : null; + csvData.push(this.constructCsvRow(namespace, mount, mountTotalClients, mountNewClients)); + }); + } + }); + + csvData.unshift(csvHeader); + // make each nested array a comma separated string, join each array "row" in csvData with line break (\n) + return csvData.map((d) => d.join()).join('\n'); + } + + get formattedCsvFileName() { + const endRange = this.formattedEndDate ? `-${this.formattedEndDate}` : ''; + const csvDateRange = this.formattedStartDate ? `_${this.formattedStartDate + endRange}` : ''; + return this.isSingleNamespace + ? `clients_by_mount_path${csvDateRange}` + : `clients_by_namespace${csvDateRange}`; + } + + get modalExportText() { + const { isSecretsSyncActivated } = this.args; + return `This export will include the namespace path, mount path and associated total entity, non-entity${ + isSecretsSyncActivated ? ', ACME and secrets sync clients' : ' and ACME clients' + } for the ${this.formattedEndDate ? 'date range' : 'month'} below.`; + } + + @action + exportChartData(filename) { + const contents = this.generateCsvData(); + this.download.csv(filename, contents); + this.showCSVDownloadModal = false; + } } diff --git a/ui/app/components/clients/chart-container.hbs b/ui/app/components/clients/chart-container.hbs index 9508b4024a56..b8b994d8fef5 100644 --- a/ui/app/components/clients/chart-container.hbs +++ b/ui/app/components/clients/chart-container.hbs @@ -30,11 +30,7 @@
{{/if}} - {{#if (has-block "legend")}} -
- {{yield to="legend"}} -
- {{else if @legend}} + {{#if @legend}}
{{#each @legend as |legend idx|}} diff --git a/ui/app/components/clients/charts/line.hbs b/ui/app/components/clients/charts/line.hbs new file mode 100644 index 000000000000..2af7dc7c5b95 --- /dev/null +++ b/ui/app/components/clients/charts/line.hbs @@ -0,0 +1,129 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +~}} +
+ {{#if this.data}} +
+ + {{#let + (scale-point domain=this.xDomain range=(array 0 width) padding=0.2) + (scale-linear domain=this.yDomain range=(array this.chartHeight 0) nice=true) + (scale-linear range=(array 0 this.chartHeight)) + as |xScale yScale tooltipScale| + }} + + {{@chartTitle}} + + {{#if (and xScale.isValid yScale.isValid)}} + + + {{#each this.upgradedMonths as |d|}} + + {{/each}} + {{/if}} + + {{! this is here to qualify the scales }} + + {{#if (and xScale.isValid yScale.isValid)}} + {{#each this.data as |d|}} + {{#if (this.hasValue d.y)}} + + + {{/if}} + {{/each}} + {{/if}} + + + {{#if this.activeDatum}} +
+ +

{{date-format this.activeDatum.x "MMMM yyyy"}}

+

{{format-number this.activeDatum.y}} total clients

+

{{format-number (or this.activeDatum.new)}} new clients

+ {{#if this.activeDatum.tooltipUpgrade}} +
+

{{this.activeDatum.tooltipUpgrade}}

+ {{/if}} +
+
+ {{/if}} + {{/let}} +
+
+ {{else}} + + {{/if}} +
\ No newline at end of file diff --git a/ui/app/components/clients/charts/line.ts b/ui/app/components/clients/charts/line.ts new file mode 100644 index 000000000000..47c19a6684ed --- /dev/null +++ b/ui/app/components/clients/charts/line.ts @@ -0,0 +1,146 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; +import { SVG_DIMENSIONS, numericalAxisLabel } from 'vault/utils/chart-helpers'; +import { parseAPITimestamp } from 'core/utils/date-formatters'; +import { format, isValid } from 'date-fns'; +import { debug } from '@ember/debug'; + +import type ClientsVersionHistoryModel from 'vault/models/clients/version-history'; +import type { MonthlyChartData, Timestamp } from 'vault/vault/charts/client-counts'; +import type { TotalClients } from 'core/utils/client-count-utils'; + +interface Args { + dataset: MonthlyChartData[]; + upgradeData: ClientsVersionHistoryModel[]; + xKey?: string; + yKey?: string; + chartHeight?: number; +} + +interface ChartData { + x: Date; + y: number | null; + new: number; + tooltipUpgrade: string | null; + month: string; // used for test selectors and to match key on upgradeData +} + +interface UpgradeByMonth { + [key: string]: ClientsVersionHistoryModel; +} + +/** + * @module LineChart + * LineChart components are used to display time-based data in a line plot with accompanying tooltip + * + * @example + * ```js + * + * ``` + * @param {array} dataset - array of objects containing data to be plotted + * @param {string} [xKey=clients] - string denoting key for x-axis data of dataset. Should reference a timestamp string. + * @param {string} [yKey=timestamp] - string denoting key for y-axis data of dataset. Should reference a number or null. + * @param {array} [upgradeData=null] - array of objects containing version history from the /version-history endpoint + * @param {number} [chartHeight=190] - height of chart in pixels + */ +export default class LineChart extends Component { + // Chart settings + get yKey() { + return this.args.yKey || 'clients'; + } + get xKey() { + return this.args.xKey || 'timestamp'; + } + get chartHeight() { + return this.args.chartHeight || SVG_DIMENSIONS.height; + } + // Plot points + get data(): ChartData[] { + try { + return this.args.dataset?.map((datum) => { + const timestamp = parseAPITimestamp(datum[this.xKey as keyof Timestamp]) as Date; + if (isValid(timestamp) === false) + throw new Error(`Unable to parse value "${datum[this.xKey as keyof Timestamp]}" as date`); + const upgradeMessage = this.getUpgradeMessage(datum); + return { + x: timestamp, + y: (datum[this.yKey as keyof TotalClients] as number) ?? null, + new: this.getNewClients(datum), + tooltipUpgrade: upgradeMessage, + month: datum.month, + }; + }); + } catch (e) { + debug(e as string); + return []; + } + } + get upgradedMonths() { + // only render upgrade month circle if datum has client count data (the y value) + return this.data.filter((datum) => datum.tooltipUpgrade && datum.y); + } + // Domains + get yDomain() { + const counts: number[] = this.data + .map((d) => d.y) + .flatMap((num) => (typeof num === 'number' ? [num] : [])); + const max = Math.max(...counts); + // if max is <=4, hardcode 4 which is the y-axis tickCount so y-axes are not decimals + return [0, max <= 4 ? 4 : max]; + } + + get xDomain() { + // these values are date objects but are already in chronological order so we use scale-point (instead of scale-time) + // which calculates the x-scale based on the number of data points + return this.data.map((d) => d.x); + } + + get upgradeByMonthYear(): UpgradeByMonth { + const empty: UpgradeByMonth = {}; + if (!Array.isArray(this.args.upgradeData)) return empty; + return ( + this.args.upgradeData?.reduce((acc, upgrade) => { + if (upgrade.timestampInstalled) { + const key = parseAPITimestamp(upgrade.timestampInstalled, 'M/yy'); + acc[key as string] = upgrade; + } + return acc; + }, empty) || empty + ); + } + + getUpgradeMessage(datum: MonthlyChartData) { + const upgradeInfo = this.upgradeByMonthYear[datum.month as string]; + if (upgradeInfo) { + const { version, previousVersion } = upgradeInfo; + return `Vault was upgraded + ${previousVersion ? 'from ' + previousVersion : ''} to ${version}`; + } + return null; + } + getNewClients(datum: MonthlyChartData) { + if (!datum?.new_clients) return 0; + return (datum?.new_clients[this.yKey as keyof TotalClients] as number) || 0; + } + + // TEMPLATE HELPERS + hasValue = (count: number | null) => { + return typeof count === 'number' ? true : false; + }; + formatCount = (num: number): string => { + return numericalAxisLabel(num) || num.toString(); + }; + formatMonth = (date: Date) => { + return format(date, 'M/yy'); + }; + tooltipX = (original: number) => { + return original.toString(); + }; + tooltipY = (original: number) => { + return `${this.chartHeight - original + 15}`; + }; +} diff --git a/ui/app/components/clients/charts/vertical-bar-grouped.hbs b/ui/app/components/clients/charts/vertical-bar-grouped.hbs deleted file mode 100644 index 85986e3640d0..000000000000 --- a/ui/app/components/clients/charts/vertical-bar-grouped.hbs +++ /dev/null @@ -1,133 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -~}} - -{{#if (and @data @legend)}} -
- - {{#let - (scale-band domain=this.xBounds range=(array 0 width) padding=0.1) - (scale-linear range=(array this.chartHeight 0) domain=this.yBounds) - (scale-linear range=(array 0 this.chartHeight) domain=this.yBounds) - as |xScale yScale hScale| - }} - - {{@chartTitle}} - - {{#if (and xScale.isValid yScale.isValid)}} - - - {{/if}} - - {{#each @legend as |l idx|}} - - {{/each}} - - {{! TOOLTIP target rectangles }} - {{#if (and xScale.isValid yScale.isValid)}} - {{#each this.aggregatedData as |d|}} - - {{/each}} - {{/if}} - - - {{#if this.activeDatum}} -
-
-

{{this.activeDatum.legendX}}

- {{#each this.activeDatum.legendY as |stat|}} -

{{stat}}

- {{/each}} - {{#if this.activeDatum.tooltipUpgrade}} -
-

{{this.activeDatum.tooltipUpgrade}}

- {{/if}} -
-
-
- {{/if}} - {{/let}} -
-
- - {{#if @showTable}} -
- {{@chartTitle}} data - - <:head as |H|> - - Timestamp - {{#each this.dataKeys as |key|}} - {{humanize key}} - {{/each}} - - - <:body as |B|> - {{#each @data as |row|}} - - {{row.timestamp}} - {{#each this.dataKeys as |key|}} - {{or (get row key) "-"}} - {{/each}} - - {{/each}} - - -
- {{/if}} -{{else}} - -{{/if}} \ No newline at end of file diff --git a/ui/app/components/clients/charts/vertical-bar-grouped.ts b/ui/app/components/clients/charts/vertical-bar-grouped.ts deleted file mode 100644 index 0c3022652b5a..000000000000 --- a/ui/app/components/clients/charts/vertical-bar-grouped.ts +++ /dev/null @@ -1,179 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Component from '@glimmer/component'; -import { tracked } from '@glimmer/tracking'; -import { BAR_WIDTH, numericalAxisLabel } from 'vault/utils/chart-helpers'; -import { formatNumber } from 'core/helpers/format-number'; -import { parseAPITimestamp } from 'core/utils/date-formatters'; -import { flatGroup } from 'd3-array'; -import type { MonthlyChartData } from 'vault/vault/charts/client-counts'; -import type { ClientTypes } from 'core/utils/client-count-utils'; -import ClientsVersionHistoryModel from 'vault/vault/models/clients/version-history'; - -interface Args { - legend: Legend[]; - data: MonthlyChartData[]; - upgradeData?: ClientsVersionHistoryModel[]; - chartTitle?: string; - chartHeight?: number; -} - -interface Legend { - key: ClientTypes; - label: string; -} -interface AggregatedDatum { - x: string; - y: number; - legendX: string; - legendY: string[]; -} - -type ChartDatum = { - timestamp: string; - clientType: string; -} & { - [key in ClientTypes]?: number | undefined; -}; - -interface UpgradeByMonth { - [key: string]: ClientsVersionHistoryModel; -} - -/** - * @module VerticalBarGrouped - * Renders a grouped bar chart of counts for different client types over time. Which client types render - * is mapped from the "key" values of the @legend arg. - * - * @example - * - */ -export default class VerticalBarGrouped extends Component { - barWidth = BAR_WIDTH; - @tracked activeDatum: AggregatedDatum | null = null; - - get chartHeight() { - return this.args.chartHeight || 190; - } - - get dataKeys(): ClientTypes[] { - return this.args.legend.map((l: Legend) => l.key); - } - - label(legendKey: string) { - return this.args.legend.find((l: Legend) => l.key === legendKey)?.label; - } - - get chartData() { - let dataset: [string, number | undefined, string, ChartDatum[]][] = []; - // each datum needs to be its own object - for (const key of this.dataKeys) { - const chartData: ChartDatum[] = this.args.data.map((d: MonthlyChartData) => ({ - timestamp: d.timestamp, - clientType: key, - [key]: d[key], - })); - - const group = flatGroup( - chartData, - // order here must match destructure order in return below - (d) => d.timestamp, - (d) => d[key], - (d) => d.clientType - ); - dataset = [...dataset, ...group]; - } - - return dataset.map(([timestamp, counts, clientType]) => ({ - timestamp, // x value - counts, // y value - clientType, // corresponds to chart's @color arg - })); - } - - // for yBounds scale, tooltip target area and tooltip text data - get aggregatedData(): AggregatedDatum[] { - return this.args.data.map((datum: MonthlyChartData) => { - const values = this.dataKeys - .map((k: string) => datum[k as ClientTypes]) - .filter((count) => Number.isInteger(count)); - const maximum = values.length - ? values.reduce((prev, currentValue) => (prev > currentValue ? prev : currentValue), 0) - : null; - const xValue = datum.timestamp; - const legend = { - x: xValue, - y: maximum ?? 0, // y-axis point where tooltip renders - legendX: parseAPITimestamp(xValue, 'MMMM yyyy') as string, - legendY: - maximum === null - ? ['No data'] - : this.dataKeys.map((k) => `${formatNumber([datum[k]])} ${this.label(k)}`), - tooltipUpgrade: this.upgradeMessage(datum), - }; - return legend; - }); - } - - get yBounds() { - const counts: number[] = this.aggregatedData - .map((d) => d.y) - .flatMap((num) => (typeof num === 'number' ? [num] : [])); - const max = Math.max(...counts); - // if max is <=4, hardcode 4 which is the y-axis tickCount so y-axes are not decimals - return [0, max <= 4 ? 4 : max]; - } - - get xBounds() { - const domain = this.args.data.map((d) => d.timestamp); - return new Set(domain); - } - - // UPGRADE STUFF - get upgradeByMonthYear(): UpgradeByMonth { - const empty: UpgradeByMonth = {}; - if (!Array.isArray(this.args.upgradeData)) return empty; - return ( - this.args.upgradeData?.reduce((acc, upgrade) => { - if (upgrade.timestampInstalled) { - const key = parseAPITimestamp(upgrade.timestampInstalled, 'M/yy'); - acc[key as string] = upgrade; - } - return acc; - }, empty) || empty - ); - } - - upgradeMessage(datum: MonthlyChartData) { - const upgradeInfo = this.upgradeByMonthYear[datum.month as string]; - if (upgradeInfo) { - const { version, previousVersion } = upgradeInfo; - return `Vault was upgraded - ${previousVersion ? 'from ' + previousVersion : ''} to ${version}`; - } - return null; - } - - // TEMPLATE HELPERS - barOffset = (bandwidth: number, idx = 0) => { - const withPadding = this.barWidth + 4; - const moved = (bandwidth - withPadding * this.args.legend.length) / 2; - return moved + idx * withPadding; - }; - - tooltipX = (original: number, bandwidth: number) => (original + bandwidth / 2).toString(); - - tooltipY = (original: number) => (!original ? '0' : `${original}`); - - formatTicksX = (timestamp: string): string => parseAPITimestamp(timestamp, 'M/yy') as string; - - formatTicksY = (num: number): string => numericalAxisLabel(num) || num.toString(); -} diff --git a/ui/app/components/clients/date-range.hbs b/ui/app/components/clients/date-range.hbs deleted file mode 100644 index ddea1545e19a..000000000000 --- a/ui/app/components/clients/date-range.hbs +++ /dev/null @@ -1,109 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -~}} - -
- - Client counting period - - - The dashboard displays client count activity during the specified date range below. Click edit to update the date range. - - -
- {{#if (and @startTime @endTime)}} -

{{this.formattedDate @startTime}}

-

-

{{this.formattedDate @endTime}}

- - {{else}} - - {{/if}} -
- - {{#if this.showEditModal}} - - - Edit date range - - -

- The start date will be used as the client counting start time and all clients in that month will be considered new. - {{#if this.version.isEnterprise}} - We recommend setting this date as your license or billing start date to get the most accurate new and total - client count estimations. These dates are only for querying data in storage. Editing the date range does not - change any license or billing configurations. - {{/if}} -

-
-
- - Start - -
-
- - End - -
- {{#if this.version.isEnterprise}} - - {{/if}} -
- {{#if this.validationError}} - {{this.validationError}} - {{/if}} - {{#if (and this.version.isEnterprise this.useDefaultDates)}} - - Dashboard will use the default date range from the API. - - {{/if}} -
- - - - -
- {{/if}} -
\ No newline at end of file diff --git a/ui/app/components/clients/date-range.ts b/ui/app/components/clients/date-range.ts deleted file mode 100644 index 9e87e413cf8b..000000000000 --- a/ui/app/components/clients/date-range.ts +++ /dev/null @@ -1,125 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import { action } from '@ember/object'; -import { service } from '@ember/service'; -import Component from '@glimmer/component'; -import { tracked } from '@glimmer/tracking'; -import { formatDateObject } from 'core/utils/client-count-utils'; -import { parseAPITimestamp } from 'core/utils/date-formatters'; -import timestamp from 'core/utils/timestamp'; -import { format } from 'date-fns'; -import type VersionService from 'vault/services/version'; -import type { HTMLElementEvent } from 'forms'; - -interface OnChangeParams { - start_time: number | undefined; - end_time: number | undefined; -} -interface Args { - onChange: (callback: OnChangeParams) => void; - startTime: string; - endTime: string; -} -/** - * @module ClientsDateRange - * ClientsDateRange components are used to display the current date range and provide a modal interface for editing the date range. - * - * @example - * - * - * - * @param {function} onChange - callback when a new range is saved. - * @param {string} [startTime] - ISO string timestamp of the current start date - * @param {string} [endTime] - ISO string timestamp of the current end date - */ - -export default class ClientsDateRangeComponent extends Component { - @service declare readonly version: VersionService; - - @tracked showEditModal = false; - @tracked startDate = ''; // format yyyy-MM - @tracked endDate = ''; // format yyyy-MM - currentMonth = format(timestamp.now(), 'yyyy-MM'); - - constructor(owner: unknown, args: Args) { - super(owner, args); - this.setTrackedFromArgs(); - } - - setTrackedFromArgs() { - if (this.args.startTime) { - this.startDate = parseAPITimestamp(this.args.startTime, 'yyyy-MM') as string; - } - if (this.args.endTime) { - this.endDate = parseAPITimestamp(this.args.endTime, 'yyyy-MM') as string; - } - } - - formattedDate = (isoTimestamp: string) => { - return parseAPITimestamp(isoTimestamp, 'MMMM yyyy'); - }; - - get useDefaultDates() { - return !this.startDate && !this.endDate; - } - - get validationError() { - if (this.useDefaultDates && this.version.isEnterprise) { - // this means we want to reset, which is fine for ent only - return null; - } - if (!this.startDate || !this.endDate) { - return 'You must supply both start and end dates.'; - } - if (this.startDate > this.endDate) { - return 'Start date must be before end date.'; - } - return null; - } - - @action onClose() { - // since the component never gets torn down, we have to manually re-set this on close - this.setTrackedFromArgs(); - this.showEditModal = false; - } - - @action resetDates() { - this.startDate = ''; - this.endDate = ''; - } - - @action updateDate(evt: HTMLElementEvent) { - const { name, value } = evt.target; - if (name === 'end') { - this.endDate = value; - } else { - this.startDate = value; - } - } - - @action handleSave() { - if (this.validationError) return; - const params: OnChangeParams = { - start_time: undefined, - end_time: undefined, - }; - if (this.startDate) { - const [year, month] = this.startDate.split('-'); - if (year && month) { - params.start_time = formatDateObject({ monthIdx: parseInt(month) - 1, year: parseInt(year) }, false); - } - } - if (this.endDate) { - const [year, month] = this.endDate.split('-'); - if (year && month) { - params.end_time = formatDateObject({ monthIdx: parseInt(month) - 1, year: parseInt(year) }, true); - } - } - - this.args.onChange(params); - this.onClose(); - } -} diff --git a/ui/app/components/clients/page-header.hbs b/ui/app/components/clients/page-header.hbs deleted file mode 100644 index cb2f983ea6ab..000000000000 --- a/ui/app/components/clients/page-header.hbs +++ /dev/null @@ -1,112 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -~}} - - - Vault Usage Metrics - - This dashboard surfaces Vault client usage over time. - Documentation is available here. - Date queries are sent in UTC. - - - {{#if this.showExportButton}} - - {{/if}} - - - -{{#if this.showExportModal}} - - - Export activity data - - - {{#if this.exportChartData.isRunning}} -

- Your export request is being processed. This may take some time; please do not navigate away from this page. -

-

- -

- {{else}} -

- This file will include an export of the clients that had activity within the date range below. See the - activity export documentation - for more details. -

-

SELECTED DATE {{if this.formattedEndDate " RANGE"}}

-

- {{this.formattedStartDate}} - {{if this.formattedEndDate "-"}} - {{this.formattedEndDate}}

- - - Export format - - - - - - {{/if}} - - {{#if this.downloadError}} - - CSV export failed - {{this.downloadError}} - - {{/if}} -
- - - - - - {{#if @upgradesDuringActivity}} - - - Data contains {{pluralize @upgradesDuringActivity.length "upgrade"}}: - - -
    - {{#each @upgradesDuringActivity as |upgrade|}} -
  • - {{upgrade.version}} - {{this.parseAPITimestamp upgrade.timestampInstalled "(MMM d, yyyy)"}} -
  • - {{/each}} -
-
- - Visit our - - Client count FAQ - - for more information. - -
- {{/if}} -
-
-{{/if}} \ No newline at end of file diff --git a/ui/app/components/clients/page-header.js b/ui/app/components/clients/page-header.js deleted file mode 100644 index 9915ceeb069b..000000000000 --- a/ui/app/components/clients/page-header.js +++ /dev/null @@ -1,126 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import { action } from '@ember/object'; -import { service } from '@ember/service'; -import { waitFor } from '@ember/test-waiters'; -import Component from '@glimmer/component'; -import { tracked } from '@glimmer/tracking'; -import { parseAPITimestamp } from 'core/utils/date-formatters'; -import { sanitizePath } from 'core/utils/sanitize-path'; -import { format, isSameMonth } from 'date-fns'; -import { task } from 'ember-concurrency'; - -/** - * @module ClientsPageHeader - * ClientsPageHeader components are used to render a header and check for export capabilities before rendering an export button. - * - * @example - * ```js - * - * ``` - * @param {string} [startTimestamp] - ISO timestamp of start time, to be passed to export request - * @param {string} [endTimestamp] - ISO timestamp of end time, to be passed to export request - * @param {string} [namespace] - namespace filter. Will be appended to the current namespace in the export request. - * @param {string} [upgradesDuringActivity] - array of objects containing version history upgrade data - * @param {boolean} [noData = false] - when true, export button will hide regardless of capabilities - */ -export default class ClientsPageHeaderComponent extends Component { - @service download; - @service namespace; - @service store; - - @tracked canDownload = false; - @tracked showExportModal = false; - @tracked exportFormat = 'csv'; - @tracked downloadError = ''; - - constructor() { - super(...arguments); - this.getExportCapabilities(this.args.namespace); - } - - get showExportButton() { - if (this.args.noData === true) return false; - return this.canDownload; - } - - @waitFor - async getExportCapabilities(ns = '') { - try { - // selected namespace usually ends in / - const url = ns - ? `${sanitizePath(ns)}/sys/internal/counters/activity/export` - : 'sys/internal/counters/activity/export'; - const cap = await this.store.findRecord('capabilities', url); - this.canDownload = cap.canSudo; - } catch (e) { - // if we can't read capabilities, default to show - this.canDownload = true; - } - } - - get formattedStartDate() { - if (!this.args.startTimestamp) return null; - return parseAPITimestamp(this.args.startTimestamp, 'MMMM yyyy'); - } - - get formattedEndDate() { - if (!this.args.startTimestamp && !this.args.endTimestamp) return null; - // displays on CSV export modal, no need to display duplicate months and years - const startDateObject = parseAPITimestamp(this.args.startTimestamp); - const endDateObject = parseAPITimestamp(this.args.endTimestamp); - return isSameMonth(startDateObject, endDateObject) ? null : format(endDateObject, 'MMMM yyyy'); - } - - get formattedCsvFileName() { - const endRange = this.formattedEndDate ? `-${this.formattedEndDate}` : ''; - const csvDateRange = this.formattedStartDate ? `_${this.formattedStartDate + endRange}` : ''; - const ns = this.namespaceFilter ? `_${this.namespaceFilter}` : ''; - return `clients_export${ns}${csvDateRange}`; - } - - get namespaceFilter() { - const currentNs = this.namespace.path; - const { namespace } = this.args; - return namespace ? sanitizePath(`${currentNs}/${namespace}`) : sanitizePath(currentNs); - } - - async getExportData() { - const adapter = this.store.adapterFor('clients/activity'); - const { startTimestamp, endTimestamp } = this.args; - return adapter.exportData({ - // the API only accepts json or csv - format: this.exportFormat === 'jsonl' ? 'json' : 'csv', - start_time: startTimestamp, - end_time: endTimestamp, - namespace: this.namespaceFilter, - }); - } - - parseAPITimestamp = (timestamp, format) => { - return parseAPITimestamp(timestamp, format); - }; - - exportChartData = task({ drop: true }, async (filename) => { - try { - const contents = await this.getExportData(); - this.download.download(filename, contents, this.exportFormat); - this.showExportModal = false; - } catch (e) { - this.downloadError = e.message; - } - }); - - @action setExportFormat(evt) { - const { value } = evt.target; - this.exportFormat = value; - } - - @action resetModal() { - this.showExportModal = false; - this.downloadError = ''; - } -} diff --git a/ui/app/components/clients/page/acme.hbs b/ui/app/components/clients/page/acme.hbs index 75baeef643f9..b7489361554e 100644 --- a/ui/app/components/clients/page/acme.hbs +++ b/ui/app/components/clients/page/acme.hbs @@ -32,6 +32,20 @@ /> + <:stats> + {{#let (this.average this.byMonthActivityData "acme_clients") as |avg|}} + {{! 0 is falsy, intentionally hide 0 averages }} + {{#if avg}} + + {{/if}} + {{/let}} + + <:chart> + + +

+ Vault Usage Metrics +

+
+
-
- +
+

+ This dashboard surfaces Vault client usage over time. + Documentation is available here. + Date queries are sent in UTC. +

+ + + {{this.versionText.label}} + + +
+ {{#if this.formattedStartDate}} +

{{this.formattedStartDate}}

+ + {{else}} + + {{/if}} +
+ + + {{this.versionText.description}} + {{#if (eq @activity.id "no-data")}} @@ -36,7 +65,7 @@ {{/if}} - {{#if (or @namespace this.namespaces @mountPath this.mountPaths)}} + {{#if @startTimestamp}} Filters @@ -47,6 +76,11 @@ + {{#if (or @namespace this.namespaces)}} -
{{/if}} {{#if (or @mountPath this.mountPaths)}} @@ -81,7 +114,7 @@
{{/if}} - {{#if this.totalUsageCounts}} + {{#if this.filteredActivity}} {{#if this.upgradeExplanations}} @@ -123,12 +156,9 @@ {{! CLIENT COUNT PAGE COMPONENTS RENDER HERE }} {{yield}} - {{else if (and this.version.isCommunity (not @startTimestamp))}} - {{! Empty state for community without start query param }} - + {{else if (and (not @config.billingStartTimestamp) (not @startTimestamp))}} + {{! Empty state for no billing/license start date }} + {{else}} {{/if}} {{/if}} -
\ No newline at end of file +
+ +{{#if this.showBillingStartModal}} + + + Edit start month + + +

+ {{this.versionText.description}} +

+

{{this.versionText.label}}

+ +
+ + + +
+{{/if}} \ No newline at end of file diff --git a/ui/app/components/clients/page/counts.ts b/ui/app/components/clients/page/counts.ts index 8d1b6c56cf3b..265c90da17db 100644 --- a/ui/app/components/clients/page/counts.ts +++ b/ui/app/components/clients/page/counts.ts @@ -6,10 +6,10 @@ import Component from '@glimmer/component'; import { service } from '@ember/service'; import { action } from '@ember/object'; -import { isSameMonth, isAfter } from 'date-fns'; +import { fromUnixTime, getUnixTime, isSameMonth, isAfter } from 'date-fns'; import { parseAPITimestamp } from 'core/utils/date-formatters'; -import { filteredTotalForMount, filterVersionHistory, TotalClients } from 'core/utils/client-count-utils'; -import { sanitizePath } from 'core/utils/sanitize-path'; +import { filterVersionHistory, formatDateObject } from 'core/utils/client-count-utils'; +import timestamp from 'core/utils/timestamp'; import type AdapterError from '@ember-data/adapter'; import type FlagsService from 'vault/services/flags'; @@ -18,53 +18,55 @@ import type VersionService from 'vault/services/version'; import type ClientsActivityModel from 'vault/models/clients/activity'; import type ClientsConfigModel from 'vault/models/clients/config'; import type ClientsVersionHistoryModel from 'vault/models/clients/version-history'; -import type NamespaceService from 'vault/services/namespace'; interface Args { activity: ClientsActivityModel; activityError?: AdapterError; config: ClientsConfigModel; - endTimestamp: string; // ISO format + endTimestamp: number; mountPath: string; namespace: string; onFilterChange: CallableFunction; - startTimestamp: string; // ISO format + startTimestamp: number; versionHistory: ClientsVersionHistoryModel[]; } export default class ClientsCountsPageComponent extends Component { @service declare readonly flags: FlagsService; @service declare readonly version: VersionService; - @service declare readonly namespace: NamespaceService; @service declare readonly store: StoreService; + get startTimestampISO() { + return this.args.startTimestamp ? fromUnixTime(this.args.startTimestamp).toISOString() : null; + } + + get endTimestampISO() { + return this.args.endTimestamp ? fromUnixTime(this.args.endTimestamp).toISOString() : null; + } + get formattedStartDate() { - return this.args.startTimestamp ? parseAPITimestamp(this.args.startTimestamp, 'MMMM yyyy') : null; + return this.startTimestampISO ? parseAPITimestamp(this.startTimestampISO, 'MMMM yyyy') : null; } // returns text for empty state message if noActivityData get dateRangeMessage() { - if (this.args.startTimestamp && this.args.endTimestamp) { + if (this.startTimestampISO && this.endTimestampISO) { const endMonth = isSameMonth( - parseAPITimestamp(this.args.startTimestamp) as Date, - parseAPITimestamp(this.args.endTimestamp) as Date + parseAPITimestamp(this.startTimestampISO) as Date, + parseAPITimestamp(this.endTimestampISO) as Date ) ? '' - : `to ${parseAPITimestamp(this.args.endTimestamp, 'MMMM yyyy')}`; + : `to ${parseAPITimestamp(this.endTimestampISO, 'MMMM yyyy')}`; // completes the message 'No data received from { dateRangeMessage }' - return `from ${parseAPITimestamp(this.args.startTimestamp, 'MMMM yyyy')} ${endMonth}`; + return `from ${parseAPITimestamp(this.startTimestampISO, 'MMMM yyyy')} ${endMonth}`; } return null; } - // passed into page-header for the export modal alert - get upgradesDuringActivity() { - const { versionHistory, activity } = this.args; - return filterVersionHistory(versionHistory, activity.startTime, activity.endTime); - } - get upgradeExplanations() { - if (this.upgradesDuringActivity.length) { - return this.upgradesDuringActivity.map((upgrade: ClientsVersionHistoryModel) => { + const { versionHistory, activity } = this.args; + const upgradesDuringActivity = filterVersionHistory(versionHistory, activity.startTime, activity.endTime); + if (upgradesDuringActivity.length) { + return upgradesDuringActivity.map((upgrade: ClientsVersionHistoryModel) => { let explanation; const date = parseAPITimestamp(upgrade.timestampInstalled, 'MMM d, yyyy'); const version = upgrade.version || ''; @@ -92,72 +94,49 @@ export default class ClientsCountsPageComponent extends Component { get versionText() { return this.version.isEnterprise ? { + label: 'Billing start month', + description: + 'This date comes from your license, and defines when client counting starts. Without this starting point, the data shown is not reliable.', title: 'No billing start date found', message: 'In order to get the most from this data, please enter your billing period start month. This will ensure that the resulting data is accurate.', } : { + label: 'Client counting start date', + description: + 'This date is when client counting starts. Without this starting point, the data shown is not reliable.', title: 'No start date found', message: 'In order to get the most from this data, please enter a start month above. Vault will calculate new clients starting from that month.', }; } - // path of the filtered namespace OR current one, for filtering relevant data - get namespacePathForFilter() { - const { namespace } = this.args; - const currentNs = this.namespace.currentNamespace; - return sanitizePath(namespace || currentNs || 'root'); - } - - // activityForNamespace gets the byNamespace data for the selected or current namespace so we can get the list of mounts from that namespace for attribution - get activityForNamespace() { - const { activity } = this.args; - const nsPath = this.namespacePathForFilter; - // we always return activity for namespace, either the selected filter or the current - return activity?.byNamespace?.find((ns) => sanitizePath(ns.label) === nsPath); - } - - // duplicate of the method found in the activity component, so that we render the child only when there is activity to view - get totalUsageCounts(): TotalClients { - const { namespace, mountPath, activity } = this.args; - if (mountPath) { - // only do this if we have a mountPath filter. - // namespace is filtered on API layer - return filteredTotalForMount(activity.byNamespace, namespace, mountPath); - } - return activity?.total; - } - - // namespace list for the search-select filter get namespaces() { - return this.args.activity?.byNamespace - ? this.args.activity.byNamespace - .map((namespace) => ({ - name: namespace.label, - id: namespace.label, - })) - .filter((ns) => sanitizePath(ns.name) !== this.namespacePathForFilter) + return this.args.activity.byNamespace + ? this.args.activity.byNamespace.map((namespace) => ({ + name: namespace.label, + id: namespace.label, + })) : []; } - // mounts within the current/filtered namespace for the sesarch-select filter get mountPaths() { - return ( - this.activityForNamespace?.mounts.map((mount) => ({ + if (this.namespaces.length) { + return this.activityForNamespace?.mounts.map((mount) => ({ id: mount.label, name: mount.label, - })) || [] - ); + })); + } + return []; } - // banner contents shown if startTime returned from activity API (which matches the first month with data) is after the queried startTime get startTimeDiscrepancy() { + // show banner if startTime returned from activity log (response) is after the queried startTime const { activity, config } = this.args; const activityStartDateObject = parseAPITimestamp(activity.startTime) as Date; - const queryStartDateObject = parseAPITimestamp(this.args.startTimestamp) as Date; + const queryStartDateObject = parseAPITimestamp(this.startTimestampISO) as Date; const isEnterprise = - this.args.startTimestamp === config.billingStartTimestamp?.toISOString() && this.version.isEnterprise; + this.startTimestampISO === config.billingStartTimestamp?.toISOString() && this.version.isEnterprise; const message = isEnterprise ? 'Your license start date is' : 'You requested data from'; if ( @@ -172,25 +151,56 @@ export default class ClientsCountsPageComponent extends Component { } } - // the dashboard should show sync tab if the flag is on or there's data + get activityForNamespace() { + const { activity, namespace } = this.args; + return namespace ? activity.byNamespace.find((ns) => ns.label === namespace) : null; + } + + get filteredActivity() { + // return activity counts based on selected namespace and auth mount values + const { namespace, mountPath, activity } = this.args; + if (namespace) { + return mountPath + ? this.activityForNamespace?.mounts.find((mount) => mount.label === mountPath) + : this.activityForNamespace; + } + return activity?.total; + } + get hasSecretsSyncClients(): boolean { - return this.args.activity?.total?.secret_syncs > 0; + const { activity } = this.args; + // if there is any sync client data, show it + return activity && activity?.total?.secret_syncs > 0; } @action - onDateChange(params: { start_time: number | undefined; end_time: number | undefined }) { - this.args.onFilterChange(params); + onDateChange(dateObject: { dateType: string; monthIdx: number; year: number }) { + const { dateType, monthIdx, year } = dateObject; + const { config } = this.args; + const currentTimestamp = getUnixTime(timestamp.now()); + + // converts the selectedDate to unix timestamp for activity query + const selectedDate = formatDateObject({ monthIdx, year }, dateType === 'endDate'); + + if (dateType !== 'cancel') { + const start_time = { + reset: getUnixTime(config?.billingStartTimestamp) || null, // clicked 'Current billing period' in calendar widget -> resets to billing start date + currentMonth: currentTimestamp, // clicked 'Current month' from calendar widget -> defaults to currentTimestamp + startDate: selectedDate, // from "Edit billing start" modal + }[dateType]; + // endDate type is selection from calendar widget + const end_time = dateType === 'endDate' ? selectedDate : currentTimestamp; // defaults to currentTimestamp + const params = start_time !== undefined ? { start_time, end_time } : { end_time }; + this.args.onFilterChange(params); + } } @action setFilterValue(type: 'ns' | 'mountPath', [value]: [string | undefined]) { const params = { [type]: value }; + // unset mountPath value when namespace is cleared if (type === 'ns' && !value) { - // unset mountPath value when namespace is cleared params['mountPath'] = undefined; - } else if (type === 'mountPath' && !this.args.namespace) { - // set namespace when mountPath set without namespace already set - params['ns'] = this.namespacePathForFilter; } this.args.onFilterChange(params); } diff --git a/ui/app/components/clients/page/overview.hbs b/ui/app/components/clients/page/overview.hbs index 7486ab37681f..f069423df279 100644 --- a/ui/app/components/clients/page/overview.hbs +++ b/ui/app/components/clients/page/overview.hbs @@ -13,20 +13,18 @@ @responseTimestamp={{@activity.responseTimestamp}} @mountPath={{@mountPath}} /> - {{#if this.hasAttributionData}} - {{#if this.namespaceMountAttribution}} - - {{/if}} {{/if}} \ No newline at end of file diff --git a/ui/app/components/clients/page/overview.ts b/ui/app/components/clients/page/overview.ts index e4292161e30e..acdcfd6fc2b4 100644 --- a/ui/app/components/clients/page/overview.ts +++ b/ui/app/components/clients/page/overview.ts @@ -5,23 +5,8 @@ import ActivityComponent from '../activity'; import { service } from '@ember/service'; -import { sanitizePath } from 'core/utils/sanitize-path'; import type FlagsService from 'vault/services/flags'; export default class ClientsOverviewPageComponent extends ActivityComponent { @service declare readonly flags: FlagsService; - - get hasAttributionData() { - // we hide attribution data when mountPath filter present - // or if there's no data - if (this.args.mountPath || !this.totalUsageCounts.clients) return false; - return true; - } - - // mounts attribution - get namespaceMountAttribution() { - const { activity } = this.args; - const nsLabel = this.namespacePathForFilter; - return activity?.byNamespace?.find((ns) => sanitizePath(ns.label) === nsLabel)?.mounts || []; - } } diff --git a/ui/app/components/clients/page/sync.hbs b/ui/app/components/clients/page/sync.hbs index 2c0eac688b67..01d25fbd3571 100644 --- a/ui/app/components/clients/page/sync.hbs +++ b/ui/app/components/clients/page/sync.hbs @@ -30,6 +30,20 @@ /> + <:stats> + {{#let (this.average this.byMonthActivityData "secret_syncs") as |avg|}} + {{! intentionally hides a 0 average (0 is falsy) }} + {{#if avg}} + + {{/if}} + {{/let}} + + <:chart> + <:stats> + + + <:chart> <:stats> m.entity_clients || m.non_entity_clients); + get averageTotalClients() { + return this.calculateClientAverages(this.byMonthActivityData); + } + + get averageNewClients() { + return this.calculateClientAverages(this.byMonthNewClients); } get tokenStats() { diff --git a/ui/app/components/clients/running-total.hbs b/ui/app/components/clients/running-total.hbs index 0de347fca940..991046753654 100644 --- a/ui/app/components/clients/running-total.hbs +++ b/ui/app/components/clients/running-total.hbs @@ -25,6 +25,7 @@
+
@@ -36,20 +37,13 @@ <:chart> - - - <:legend> - {{#each this.chartLegend as |l|}} - {{capitalize l.label}} - {{/each}} - {{else}} {{#let (get @byMonthActivityData "0") as |singleMonthData|}} diff --git a/ui/app/components/clients/running-total.ts b/ui/app/components/clients/running-total.ts index dd09da32e611..04044b7d0ba4 100644 --- a/ui/app/components/clients/running-total.ts +++ b/ui/app/components/clients/running-total.ts @@ -4,18 +4,9 @@ */ import Component from '@glimmer/component'; -import type { ByMonthClients, TotalClients } from 'core/utils/client-count-utils'; -import ClientsVersionHistoryModel from 'vault/vault/models/clients/version-history'; interface Args { isSecretsSyncActivated: boolean; - byMonthActivityData: ByMonthClients[]; - isHistoricalMonth: boolean; - isCurrentMonth: boolean; - runningTotals: TotalClients; - upgradesDuringActivity: ClientsVersionHistoryModel[]; - responseTimestamp: string; - mountPath: string; } export default class RunningTotal extends Component { @@ -25,18 +16,4 @@ export default class RunningTotal extends Component { isSecretsSyncActivated ? ', ACME and secrets sync clients' : ' and ACME clients' }. The total client count number is an important consideration for Vault billing.`; } - - get runningTotalData() { - return this.args.byMonthActivityData.map((monthly) => ({ - ...monthly, - new_clients: monthly.new_clients?.clients, - })); - } - - get chartLegend() { - return [ - { key: 'clients', label: 'total clients' }, - { key: 'new_clients', label: 'new clients' }, - ]; - } } diff --git a/ui/app/components/configure-aws-secret.js b/ui/app/components/configure-aws-secret.js new file mode 100644 index 000000000000..c5639a0d4f42 --- /dev/null +++ b/ui/app/components/configure-aws-secret.js @@ -0,0 +1,56 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; + +/** + * @module ConfigureAwsSecretComponent + * + * @example + * ```js + * + * ``` + * + * @param {object} model - aws secret engine model + * @param {string} tab - current tab selection + * @param {string} accessKey - AWS access key + * @param {string} secretKey - AWS secret key + * @param {string} region - AWS region + * @param {string} iamEndpoint - IAM endpoint + * @param {string} stsEndpoint - Sts endpoint + * @param {Function} saveAWSRoot - parent action which saves AWS root credentials + * @param {Function} saveAWSLease - parent action which updates AWS lease information + * + */ +export default class ConfigureAwsSecretComponent extends Component { + @action + saveRootCreds(data, event) { + event.preventDefault(); + this.args.saveAWSRoot(data); + } + + @action + saveLease(data, event) { + event.preventDefault(); + this.args.saveAWSLease(data); + } + + @action + handleTtlChange(name, ttlObj) { + // lease values cannot be undefined, set to 0 to use default + const valueToSet = ttlObj.enabled ? ttlObj.goSafeTimeString : 0; + this.args.model.set(name, valueToSet); + } +} diff --git a/ui/app/components/configure-ssh-secret.js b/ui/app/components/configure-ssh-secret.js new file mode 100644 index 000000000000..a6ea08c6f801 --- /dev/null +++ b/ui/app/components/configure-ssh-secret.js @@ -0,0 +1,38 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; + +/** + * @module ConfigureSshSecretComponent + * + * @example + * ```js + * + * ``` + * + * @param {string} model - ssh secret engine model + * @param {Function} saveConfig - parent action which updates the configuration + * @param {boolean} loading - property in parent that updates depending on status of parent's action + * + */ +export default class ConfigureSshSecretComponent extends Component { + @action + delete() { + this.args.saveConfig({ delete: true }); + } + + @action + saveConfig(event) { + event.preventDefault(); + this.args.saveConfig({ delete: false }); + } +} diff --git a/ui/app/components/console/ui-panel.js b/ui/app/components/console/ui-panel.js index 525dfb227070..a001b051f5df 100644 --- a/ui/app/components/console/ui-panel.js +++ b/ui/app/components/console/ui-panel.js @@ -6,7 +6,7 @@ import { service } from '@ember/service'; import { alias, or } from '@ember/object/computed'; import Component from '@ember/component'; -import { getOwner } from '@ember/owner'; +import { getOwner } from '@ember/application'; import { schedule } from '@ember/runloop'; import { camelize } from '@ember/string'; import { task } from 'ember-concurrency'; diff --git a/ui/app/components/dashboard/quick-actions-card.js b/ui/app/components/dashboard/quick-actions-card.js index eccc519ab36f..6c2b8bca05d7 100644 --- a/ui/app/components/dashboard/quick-actions-card.js +++ b/ui/app/components/dashboard/quick-actions-card.js @@ -49,7 +49,7 @@ export default class DashboardQuickActionsCard extends Component { subText: 'Path of the secret you want to read.', buttonText: 'Read secrets', model: 'kv/metadata', - route: 'vault.cluster.secrets.backend.kv.secret.index', + route: 'vault.cluster.secrets.backend.kv.secret.details', nameKey: 'path', queryObject: { pathToSecret: '', backend: this.selectedEngine.id }, objectKeys: ['path', 'id'], @@ -149,7 +149,7 @@ export default class DashboardQuickActionsCard extends Component { const path = this.paramValue.path || this.paramValue; route = pathIsDirectory(path) ? 'vault.cluster.secrets.backend.kv.list-directory' - : 'vault.cluster.secrets.backend.kv.secret.index'; + : 'vault.cluster.secrets.backend.kv.secret.details'; param = path; } diff --git a/ui/app/components/database-connection.js b/ui/app/components/database-connection.js index 8c291be71784..84c7380952f5 100644 --- a/ui/app/components/database-connection.js +++ b/ui/app/components/database-connection.js @@ -8,7 +8,6 @@ import { service } from '@ember/service'; import { tracked } from '@glimmer/tracking'; import { action } from '@ember/object'; import { waitFor } from '@ember/test-waiters'; -import { task } from 'ember-concurrency'; const LIST_ROOT_ROUTE = 'vault.cluster.secrets.backend.list-root'; const SHOW_ROUTE = 'vault.cluster.secrets.backend.show'; @@ -57,43 +56,42 @@ export default class DatabaseConnectionEdit extends Component { this.args.model[attr] = value; } - handleCreateConnection = task( - waitFor(async (evt) => { - evt.preventDefault(); - try { - const secret = this.args.model; - await secret.save(); + @action + async handleCreateConnection(evt) { + evt.preventDefault(); + const secret = this.args.model; + secret + .save() + .then(() => { this.showSaveModal = true; - } catch (e) { + }) + .catch((e) => { const errorMessage = getErrorMessage(e.errors); this.flashMessages.danger(errorMessage); - } - }) - ); + }); + } @action continueWithoutRotate() { - if (this.continueWithRotate.isRunning) return; this.showSaveModal = false; const { name } = this.args.model; this.transitionToRoute(SHOW_ROUTE, name); } - continueWithRotate = task( - waitFor(async () => { - const { backend, name } = this.args.model; - try { - await this.rotateCredentials(backend, name); - this.flashMessages.success(`Successfully rotated root credentials for connection "${name}"`); - this.transitionToRoute(SHOW_ROUTE, name); - } catch (e) { - this.flashMessages.danger(`Error rotating root credentials: ${e.errors}`); - this.transitionToRoute(SHOW_ROUTE, name); - } finally { - this.showSaveModal = false; - } - }) - ); + @action + @waitFor + async continueWithRotate() { + this.showSaveModal = false; + const { backend, name } = this.args.model; + try { + await this.rotateCredentials(backend, name); + this.flashMessages.success(`Successfully rotated root credentials for connection "${name}"`); + this.transitionToRoute(SHOW_ROUTE, name); + } catch (e) { + this.flashMessages.danger(`Error rotating root credentials: ${e.errors}`); + this.transitionToRoute(SHOW_ROUTE, name); + } + } @action handleUpdateConnection(evt) { diff --git a/ui/app/components/database-role-setting-form.js b/ui/app/components/database-role-setting-form.js index 4bad5e0921f5..de49188ff45b 100644 --- a/ui/app/components/database-role-setting-form.js +++ b/ui/app/components/database-role-setting-form.js @@ -4,7 +4,7 @@ */ import Component from '@glimmer/component'; -import { getStatementFields, getRoleFields } from '../utils/model-helpers/database-helpers'; +import { getStatementFields, getRoleFields } from '../utils/database-helpers'; /** * @module DatabaseRoleSettingForm diff --git a/ui/app/components/date-dropdown.js b/ui/app/components/date-dropdown.js new file mode 100644 index 000000000000..7fee2b45510f --- /dev/null +++ b/ui/app/components/date-dropdown.js @@ -0,0 +1,78 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { tracked } from '@glimmer/tracking'; +import { ARRAY_OF_MONTHS } from 'core/utils/date-formatters'; +import timestamp from 'core/utils/timestamp'; +/** + * @module DateDropdown + * DateDropdown components are used to display a dropdown of months and years to handle date selection. Future dates are disabled (current month and year are selectable). + * The component returns an object with selected date info, example: { dateType: 'start', monthIdx: 0, monthName: 'January', year: 2022 } + * + * @example + * ```js + * + * ``` + * @param {function} handleSubmit - callback function from parent that the date picker triggers on submit + * @param {string} [dateType] - optional argument to give the selected month/year a type + * @param {string} [submitText] - optional argument to change submit button text + * @param {function} [validateDate] - parent function to validate date selection, receives date object and returns an error message that's passed to the inline alert + */ +export default class DateDropdown extends Component { + currentDate = timestamp.now(); + currentYear = this.currentDate.getFullYear(); // integer of year + currentMonthIdx = this.currentDate.getMonth(); // integer of month, 0 indexed + dropdownMonths = ARRAY_OF_MONTHS.map((m, i) => ({ name: m, index: i })); + dropdownYears = Array.from({ length: 5 }, (item, i) => this.currentYear - i); + + @tracked maxMonthIdx = 11; // disables months with index greater than this number, initially all months are selectable + @tracked disabledYear = null; // year as integer if current year should be disabled + @tracked selectedMonth = null; + @tracked selectedYear = null; + @tracked invalidDate = null; + + @action + selectMonth(month, dropdown) { + this.selectedMonth = month; + // disable current year if selected month is later than current month + this.disabledYear = month.index > this.currentMonthIdx ? this.currentYear : null; + dropdown.close(); + } + + @action + selectYear(year, dropdown) { + this.selectedYear = year; + // disable months after current month if selected year is current year + this.maxMonthIdx = year === this.currentYear ? this.currentMonthIdx : 11; + dropdown.close(); + } + + @action + handleSubmit() { + if (this.args.validateDate) { + this.invalidDate = null; + this.invalidDate = this.args.validateDate(new Date(this.selectedYear, this.selectedMonth.index)); + if (this.invalidDate) return; + } + const { index, name } = this.selectedMonth; + this.args.handleSubmit({ + monthIdx: index, + monthName: name, + year: this.selectedYear, + dateType: this.args.dateType, + }); + this.resetDropdown(); + } + + resetDropdown() { + this.maxMonthIdx = 11; + this.disabledYear = null; + this.selectedMonth = null; + this.selectedYear = null; + this.invalidDate = null; + } +} diff --git a/ui/app/components/generate-credentials.js b/ui/app/components/generate-credentials.js index 4cb4fc282fbf..7c871cd95b01 100644 --- a/ui/app/components/generate-credentials.js +++ b/ui/app/components/generate-credentials.js @@ -4,58 +4,37 @@ */ import { service } from '@ember/service'; -import { action } from '@ember/object'; -import Component from '@glimmer/component'; -import { tracked } from '@glimmer/tracking'; +import { computed, set } from '@ember/object'; +import Component from '@ember/component'; -const CREDENTIAL_TYPES = { - ssh: { +const MODEL_TYPES = { + 'ssh-sign': { + model: 'ssh-sign', + }, + 'ssh-creds': { model: 'ssh-otp-credential', title: 'Generate SSH Credentials', - formFields: ['username', 'ip'], - displayFields: ['username', 'ip', 'key', 'keyType', 'port'], }, - aws: { + 'aws-creds': { model: 'aws-credential', title: 'Generate AWS Credentials', backIsListLink: true, - displayFields: ['accessKey', 'secretKey', 'securityToken', 'leaseId', 'renewable', 'leaseDuration'], - // aws form fields are dynamic - formFields: (model) => { - return { - iam_user: ['credentialType'], - assumed_role: ['credentialType', 'ttl', 'roleArn'], - federation_token: ['credentialType', 'ttl'], - session_token: ['credentialType', 'ttl'], - }[model.credentialType]; - }, }, }; -export default class GenerateCredentials extends Component { - @service controlGroup; - @service store; - @service router; +export default Component.extend({ + controlGroup: service(), + store: service(), + router: service(), + // set on the component + backendType: null, + backendPath: null, + roleName: null, + action: null, - @tracked model; - @tracked loading = false; - @tracked hasGenerated = false; - emptyData = '{\n}'; - - constructor() { - super(...arguments); - const modelType = this.modelForType(); - this.model = this.generateNewModel(modelType); - } - - willDestroy() { - // components are torn down after store is unloaded and will cause an error if attempt to unload record - const noTeardown = this.store && !this.store.isDestroying; - if (noTeardown && !this.model.isDestroyed && !this.model.isDestroying) { - this.model.unloadRecord(); - } - super.willDestroy(); - } + model: null, + loading: false, + emptyData: '{\n}', modelForType() { const type = this.options; @@ -63,37 +42,39 @@ export default class GenerateCredentials extends Component { return type.model; } // if we don't have a mode for that type then redirect them back to the backend list - this.router.transitionTo('vault.cluster.secrets.backend.list-root', this.args.backendPath); - } + this.router.transitionTo('vault.cluster.secrets.backend.list-root', this.backendPath); + }, - get helpText() { - if (this.options?.model === 'aws-credential') { - return 'For Vault roles of credential type iam_user, there are no inputs, just submit the form. Choose a type to change the input options.'; - } - return ''; - } + options: computed('action', 'backendType', function () { + const action = this.action || 'creds'; + return MODEL_TYPES[`${this.backendType}-${action}`]; + }), - get options() { - return CREDENTIAL_TYPES[this.args.backendType]; - } + init() { + this._super(...arguments); + this.createOrReplaceModel(); + }, - get formFields() { - const typeOpts = this.options; - if (typeof typeOpts.formFields === 'function') { - return typeOpts.formFields(this.model); + willDestroy() { + // components are torn down after store is unloaded and will cause an error if attempt to unload record + const noTeardown = this.store && !this.store.isDestroying; + if (noTeardown && !this.model.isDestroyed && !this.model.isDestroying) { + this.model.unloadRecord(); } - return typeOpts.formFields; - } - - get displayFields() { - return this.options.displayFields; - } + this._super(...arguments); + }, - generateNewModel(modelType) { + createOrReplaceModel() { + const modelType = this.modelForType(); + const model = this.model; + const roleName = this.roleName; + const backendPath = this.backendPath; if (!modelType) { return; } - const { roleName, backendPath, awsRoleType } = this.args; + if (model) { + model.unloadRecord(); + } const attrs = { role: { backend: backendPath, @@ -101,60 +82,44 @@ export default class GenerateCredentials extends Component { }, id: `${backendPath}-${roleName}`, }; - if (awsRoleType) { - // this is only set from route if backendType = aws - attrs.credentialType = awsRoleType; - } - return this.store.createRecord(modelType, attrs); - } - - replaceModel() { - const modelType = this.modelForType(); - if (!modelType) { - return; - } - if (this.model) { - this.model.unloadRecord(); - } - this.model = this.generateNewModel(modelType); - } + const newModel = this.store.createRecord(modelType, attrs); + this.set('model', newModel); + }, - @action - create(evt) { - evt.preventDefault(); - this.loading = true; - this.model - .save() - .then(() => { - this.hasGenerated = true; - }) - .catch((error) => { - // Handle control group AdapterError - if (error.message === 'Control Group encountered') { - this.controlGroup.saveTokenFromError(error); - const err = this.controlGroup.logFromError(error); - error.errors = [err.content]; - } - throw error; - }) - .finally(() => { - this.loading = false; - }); - } + actions: { + create() { + const model = this.model; + this.set('loading', true); + this.model + .save() + .then(() => { + model.set('hasGenerated', true); + }) + .catch((error) => { + // Handle control group AdapterError + if (error.message === 'Control Group encountered') { + this.controlGroup.saveTokenFromError(error); + const err = this.controlGroup.logFromError(error); + error.errors = [err.content]; + } + throw error; + }) + .finally(() => { + this.set('loading', false); + }); + }, - @action - codemirrorUpdated(attr, val, codemirror) { - codemirror.performLint(); - const hasErrors = codemirror.state.lint.marked.length > 0; + codemirrorUpdated(attr, val, codemirror) { + codemirror.performLint(); + const hasErrors = codemirror.state.lint.marked.length > 0; - if (!hasErrors) { - this.model[attr] = JSON.parse(val); - } - } + if (!hasErrors) { + set(this.model, attr, JSON.parse(val)); + } + }, - @action - reset() { - this.hasGenerated = false; - this.replaceModel(); - } -} + newModel() { + this.createOrReplaceModel(); + }, + }, +}); diff --git a/ui/app/components/generated-item-list.js b/ui/app/components/generated-item-list.js index 3a971e0e410b..ca6a09cf2bb6 100644 --- a/ui/app/components/generated-item-list.js +++ b/ui/app/components/generated-item-list.js @@ -6,7 +6,7 @@ import { service } from '@ember/service'; import Component from '@glimmer/component'; import { action } from '@ember/object'; -import { getOwner } from '@ember/owner'; +import { getOwner } from '@ember/application'; import { tracked } from '@glimmer/tracking'; /** diff --git a/ui/app/components/modal-form/oidc-key-template.hbs b/ui/app/components/modal-form/oidc-key-template.hbs deleted file mode 100644 index 6e4e9f9103ac..000000000000 --- a/ui/app/components/modal-form/oidc-key-template.hbs +++ /dev/null @@ -1,6 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -~}} - - \ No newline at end of file diff --git a/ui/app/components/modal-form/oidc-key-template.js b/ui/app/components/modal-form/oidc-key-template.js deleted file mode 100644 index d5afc919144b..000000000000 --- a/ui/app/components/modal-form/oidc-key-template.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Component from '@glimmer/component'; -import { action } from '@ember/object'; -import { service } from '@ember/service'; -import { tracked } from '@glimmer/tracking'; - -/** - * @module ModalForm::OidcKeyTemplate - * ModalForm::OidcKeyTemplate components render within a modal and create a model using the input from the search select. The model is passed to the oidc/key-form. - * - * @example - * - * - * @callback onCancel - callback triggered when cancel button is clicked - * @callback onSave - callback triggered when save button is clicked - * @param {string} nameInput - the name of the newly created key - */ - -export default class OidcKeyTemplate extends Component { - @service store; - @tracked key = null; // model record passed to oidc/key-form - - constructor() { - super(...arguments); - this.key = this.store.createRecord('oidc/key', { name: this.args.nameInput }); - } - - @action onSave(keyModel) { - this.args.onSave(keyModel); - // Reset component key for next use - this.key = null; - } -} diff --git a/ui/app/components/mount-backend-form.ts b/ui/app/components/mount-backend-form.js similarity index 80% rename from ui/app/components/mount-backend-form.ts rename to ui/app/components/mount-backend-form.js index abd1edef3faf..7af1542dd884 100644 --- a/ui/app/components/mount-backend-form.ts +++ b/ui/app/components/mount-backend-form.js @@ -12,12 +12,6 @@ import { waitFor } from '@ember/test-waiters'; import { methods } from 'vault/helpers/mountable-auth-methods'; import { isAddonEngine, allEngines } from 'vault/helpers/mountable-secret-engines'; -import type FlashMessageService from 'vault/services/flash-messages'; -import type Store from '@ember-data/store'; - -import type { AuthEnableModel } from 'vault/routes/vault/cluster/settings/auth/enable'; -import type { MountSecretBackendModel } from 'vault/routes/vault/cluster/settings/mount-secret-backend'; - /** * @module MountBackendForm * The `MountBackendForm` is used to mount either a secret or auth backend. @@ -30,17 +24,9 @@ import type { MountSecretBackendModel } from 'vault/routes/vault/cluster/setting * */ -type MountModel = MountSecretBackendModel | AuthEnableModel; - -interface Args { - mountModel: MountModel; - mountType: 'secret' | 'auth'; - onMountSuccess: (type: string, path: string, useEngineRoute: boolean) => void; -} - -export default class MountBackendForm extends Component { - @service declare readonly store: Store; - @service declare readonly flashMessages: FlashMessageService; +export default class MountBackendForm extends Component { + @service store; + @service flashMessages; // validation related properties @tracked modelValidations = null; @@ -54,10 +40,10 @@ export default class MountBackendForm extends Component { if (noTeardown && this.args?.mountModel?.isNew) { this.args.mountModel.unloadRecord(); } - super.willDestroy(); + super.willDestroy(...arguments); } - checkPathChange(type: string) { + checkPathChange(type) { if (!type) return; const mount = this.args.mountModel; const currentPath = mount.path; @@ -72,8 +58,8 @@ export default class MountBackendForm extends Component { } } - typeChangeSideEffect(type: string) { - if (this.args.mountType !== 'secret') return; + typeChangeSideEffect(type) { + if (!this.args.mountType === 'secret') return; if (type === 'pki') { // If type PKI, set max lease to ~10years this.args.mountModel.config.maxLeaseTtl = '3650d'; @@ -83,7 +69,7 @@ export default class MountBackendForm extends Component { } } - checkModelValidity(model: MountModel) { + checkModelValidity(model) { const { isValid, state, invalidFormMessage } = model.validate(); this.modelValidations = state; this.invalidFormAlert = invalidFormMessage; @@ -127,7 +113,7 @@ export default class MountBackendForm extends Component { @task @waitFor - *mountBackend(event: Event) { + *mountBackend(event) { event.preventDefault(); const mountModel = this.args.mountModel; const { type, path } = mountModel; @@ -179,21 +165,15 @@ export default class MountBackendForm extends Component { } @action - onKeyUp(name: string, value: string) { + onKeyUp(name, value) { this.args.mountModel[name] = value; this.checkModelWarnings(); } @action - setMountType(value: string) { + setMountType(value) { this.args.mountModel.type = value; this.typeChangeSideEffect(value); this.checkPathChange(value); } - - @action - handleIdentityTokenKeyChange(value: string[] | string): void { - // if array, it's coming from the search-select component, otherwise it hit the fallback component and will come in as a string. - this.args.mountModel.config.identityTokenKey = Array.isArray(value) ? value[0] : value; - } } diff --git a/ui/app/components/oidc/key-form.js b/ui/app/components/oidc/key-form.js index a596f492c463..9fa7def3718f 100644 --- a/ui/app/components/oidc/key-form.js +++ b/ui/app/components/oidc/key-form.js @@ -22,7 +22,6 @@ import { task } from 'ember-concurrency'; * @param {Object} model - oidc client model * @param {onCancel} onCancel - callback triggered when cancel button is clicked * @param {onSave} onSave - callback triggered on save success - * @param {boolean} [isModalForm=false] - if true, hides inputs related to selecting an application which is only relevant to the OIDC provider workflow. */ export default class OidcKeyForm extends Component { @@ -84,9 +83,7 @@ export default class OidcKeyForm extends Component { `Successfully ${isNew ? 'created' : 'updated'} the key ${name}.` ); - // this form is sometimes used in a modal, passing the model notifies - // the parent if the save was successful - this.args.onSave(this.args.model); + this.args.onSave(); } } catch (error) { const message = error.errors ? error.errors.join('. ') : error.message; diff --git a/ui/app/components/raft-storage-overview.js b/ui/app/components/raft-storage-overview.js index cced87092043..83389d5ef093 100644 --- a/ui/app/components/raft-storage-overview.js +++ b/ui/app/components/raft-storage-overview.js @@ -4,7 +4,7 @@ */ import Component from '@ember/component'; -import { getOwner } from '@ember/owner'; +import { getOwner } from '@ember/application'; import config from '../config/environment'; import { service } from '@ember/service'; diff --git a/ui/app/components/raft-storage-restore.js b/ui/app/components/raft-storage-restore.js index a5a51373916a..f086a456b5ac 100644 --- a/ui/app/components/raft-storage-restore.js +++ b/ui/app/components/raft-storage-restore.js @@ -5,7 +5,7 @@ import Component from '@ember/component'; import { task } from 'ember-concurrency'; -import { getOwner } from '@ember/owner'; +import { getOwner } from '@ember/application'; import { service } from '@ember/service'; import { alias } from '@ember/object/computed'; import { AbortController } from 'fetch'; diff --git a/ui/app/components/secret-create-or-update.js b/ui/app/components/secret-create-or-update.js index 2aa0a7a09d6f..9bc9b056e390 100644 --- a/ui/app/components/secret-create-or-update.js +++ b/ui/app/components/secret-create-or-update.js @@ -35,7 +35,6 @@ import { service } from '@ember/service'; import { tracked } from '@glimmer/tracking'; import { isBlank, isNone } from '@ember/utils'; import { task, waitForEvent } from 'ember-concurrency'; -import { WHITESPACE_WARNING } from 'vault/utils/model-helpers/validators'; const LIST_ROUTE = 'vault.cluster.secrets.backend.list'; const LIST_ROOT_ROUTE = 'vault.cluster.secrets.backend.list-root'; @@ -54,8 +53,6 @@ export default class SecretCreateOrUpdate extends Component { @service router; @service store; - whitespaceWarning = WHITESPACE_WARNING('path'); - @action setup(elem, [secretData, mode]) { this.codemirrorString = secretData.toJSONString(); diff --git a/ui/app/components/secret-engine/configuration-details.hbs b/ui/app/components/secret-engine/configuration-details.hbs deleted file mode 100644 index a65b7cb39b7c..000000000000 --- a/ui/app/components/secret-engine/configuration-details.hbs +++ /dev/null @@ -1,49 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -~}} - -{{#if @configModels.length}} - {{#each @configModels as |configModel|}} - {{#each configModel.attrs as |attr|}} - {{! public key while not sensitive when editing/creating, should be hidden by default on viewing }} - {{#if (or attr.options.sensitive (eq attr.name "publicKey"))}} - - {{#if (or attr.options.sensitive (eq attr.name "publicKey"))}} - - {{/if}} - - {{else}} - - {{/if}} - {{/each}} - {{/each}} -{{else}} - {{! Prompt user to configure the secret engine }} - - - -{{/if}} \ No newline at end of file diff --git a/ui/app/components/secret-engine/configure-aws.hbs b/ui/app/components/secret-engine/configure-aws.hbs deleted file mode 100644 index 46ab7e36c3d9..000000000000 --- a/ui/app/components/secret-engine/configure-aws.hbs +++ /dev/null @@ -1,136 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -~}} - -
-
- - -

- Note: the client uses the official AWS SDK and will use the specified credentials, environment credentials, shared file - credentials, or IAM role/ECS task credentials in that order. -

-
- {{! Root configuration details }} -

- Access to AWS -

-
- {{! WIF is an enterprise only feature. We default to IAM access type for community users and display only those related form fields. }} - {{#if this.version.isEnterprise}} -
- Access Type -

- {{#if this.disableAccessType}} - You cannot edit Access Type if you have already saved access credentials. - {{else}} - Choose the way to configure access to AWS. Access can be configured either with IAM access keys, or using Plugin - Workload Identity Federation (WIF).{{/if}}

-
- - - - - -
-
- {{/if}} - {{#if (eq this.accessType "wif")}} - {{! WIF Fields }} - {{#each @issuerConfig.attrs as |attr|}} - - {{/each}} - - {{else}} - {{! IAM Fields }} - - {{/if}} -
- - {{! Lease configuration details }} -

- Leases -

-
- {{#each @leaseConfig.attrs as |attr|}} - - {{/each}} -
- -
-
- - -
- {{#if this.invalidFormAlert}} - - {{/if}} -
-
- -{{#if this.saveIssuerWarning}} - - - Are you sure? - - -

- {{this.saveIssuerWarning}} -

-
- - - - - - -
-{{/if}} \ No newline at end of file diff --git a/ui/app/components/secret-engine/configure-aws.ts b/ui/app/components/secret-engine/configure-aws.ts deleted file mode 100644 index 995d8d6dac90..000000000000 --- a/ui/app/components/secret-engine/configure-aws.ts +++ /dev/null @@ -1,232 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Component from '@glimmer/component'; -import { action } from '@ember/object'; -import { task } from 'ember-concurrency'; -import { waitFor } from '@ember/test-waiters'; -import { service } from '@ember/service'; -import { tracked } from '@glimmer/tracking'; -import { ValidationMap } from 'vault/vault/app-types'; -import errorMessage from 'vault/utils/error-message'; - -import type LeaseConfigModel from 'vault/models/aws/lease-config'; -import type RootConfigModel from 'vault/models/aws/root-config'; -import type IdentityOidcConfigModel from 'vault/models/identity/oidc/config'; -import type Router from '@ember/routing/router'; -import type StoreService from 'vault/services/store'; -import type VersionService from 'vault/services/version'; -import type FlashMessageService from 'vault/services/flash-messages'; - -/** - * @module ConfigureAwsComponent is used to configure the AWS secret engine - * A user can configure the endpoint root/config and/or lease/config. - * For enterprise users, they will see an additional option to config WIF attributes in place of IAM attributes. - * The fields for these endpoints are on one form. - * - * @example - * ```js - * - * ``` - * - * @param {object} rootConfig - AWS config/root model - * @param {object} leaseConfig - AWS config/lease model - * @param {string} backendPath - name of the AWS secret engine, ex: 'aws-123' - */ - -interface Args { - leaseConfig: LeaseConfigModel; - rootConfig: RootConfigModel; - issuerConfig: IdentityOidcConfigModel; - backendPath: string; - issuer?: string; -} - -export default class ConfigureAwsComponent extends Component { - @service declare readonly router: Router; - @service declare readonly store: StoreService; - @service declare readonly version: VersionService; - @service declare readonly flashMessages: FlashMessageService; - - @tracked errorMessageRoot: string | null = null; - @tracked errorMessageLease: string | null = null; - @tracked invalidFormAlert: string | null = null; - @tracked modelValidationsLease: ValidationMap | null = null; - @tracked accessType = 'iam'; - @tracked saveIssuerWarning = ''; - - disableAccessType = false; - - constructor(owner: unknown, args: Args) { - super(owner, args); - // the following checks are only relevant to enterprise users and those editing an existing root configuration. - if (this.version.isCommunity || this.args.rootConfig.isNew) return; - const { roleArn, identityTokenAudience, identityTokenTtl, accessKey } = this.args.rootConfig; - // do not include issuer in this check. Issuer is a global endpoint and can bet set even if we're not editing wif attributes - const wifAttributesSet = !!roleArn || !!identityTokenAudience || !!identityTokenTtl; - const iamAttributesSet = !!accessKey; - // If any WIF attributes have been set in the rootConfig model, set accessType to 'wif'. - this.accessType = wifAttributesSet ? 'wif' : 'iam'; - // If there are either WIF or IAM attributes set then disable user's ability to change accessType. - this.disableAccessType = wifAttributesSet || iamAttributesSet; - } - - @action continueSubmitForm() { - // called when the user confirms they are okay with the issuer change - this.saveIssuerWarning = ''; - this.save.perform(); - } - - // on form submit - validate inputs and check for issuer changes - submitForm = task( - waitFor(async (event: Event) => { - event?.preventDefault(); - this.resetErrors(); - const { leaseConfig, issuerConfig } = this.args; - // Note: only aws/lease-config model has validations - const isValid = this.validate(leaseConfig); - if (!isValid) return; - if (issuerConfig?.hasDirtyAttributes) { - // if the issuer has changed show modal with warning that the config will change - // if the modal is shown, the user has to click confirm to continue save - this.saveIssuerWarning = `You are updating the global issuer config. This will overwrite Vault's current issuer ${ - issuerConfig.queryIssuerError ? 'if it exists ' : '' - }and may affect other configurations using this value. Continue?`; - // exit task until user confirms - return; - } - await this.save.perform(); - }) - ); - - save = task( - waitFor(async () => { - // when we get here, the models have already been validated so just continue with save - const { leaseConfig, rootConfig, issuerConfig } = this.args; - // Check if any of the models' attributes have changed. - // If no changes to either model, transition and notify user. - // If changes to either model, save the model(s) that changed and notify user. - // Note: "backend" dirties model state so explicity ignore it here. - const leaseAttrChanged = Object.keys(leaseConfig?.changedAttributes()).some( - (item) => item !== 'backend' - ); - const rootAttrChanged = Object.keys(rootConfig?.changedAttributes()).some((item) => item !== 'backend'); - const issuerAttrChanged = issuerConfig?.hasDirtyAttributes; - if (!leaseAttrChanged && !rootAttrChanged && !issuerAttrChanged) { - this.flashMessages.info('No changes detected.'); - this.transition(); - return; - } - // Attempt saves of changed models. If at least one of them succeed, transition - const rootSaved = rootAttrChanged ? await this.saveRoot() : false; - const leaseSaved = leaseAttrChanged ? await this.saveLease() : false; - const issuerSaved = issuerAttrChanged ? await this.updateIssuer() : false; - - if (rootSaved || leaseSaved || issuerSaved) { - this.transition(); - } else { - // otherwise there was a failure and we should not transition and exit the function. - return; - } - }) - ); - - async updateIssuer(): Promise { - try { - await this.args.issuerConfig.save(); - this.flashMessages.success('Issuer saved successfully'); - return true; - } catch (e) { - this.flashMessages.danger(`Issuer was not saved: ${errorMessage(e, 'Check Vault logs for details.')}`); - return false; - } - } - - async saveRoot(): Promise { - const { backendPath, rootConfig } = this.args; - try { - await rootConfig.save(); - this.flashMessages.success(`Successfully saved ${backendPath}'s root configuration.`); - return true; - } catch (error) { - this.errorMessageRoot = errorMessage(error); - this.invalidFormAlert = 'There was an error submitting this form.'; - return false; - } - } - - async saveLease(): Promise { - const { backendPath, leaseConfig } = this.args; - try { - await leaseConfig.save(); - this.flashMessages.success(`Successfully saved ${backendPath}'s lease configuration.`); - return true; - } catch (error) { - // if lease config fails, but there was no error saving rootConfig: notify user of the lease failure with a flash message, save the root config, and transition. - if (!this.errorMessageRoot) { - this.flashMessages.danger(`Lease configuration was not saved: ${errorMessage(error)}`, { - sticky: true, - }); - return true; - } else { - this.errorMessageLease = errorMessage(error); - this.flashMessages.danger( - `Configuration not saved: ${errorMessage(error)}. ${this.errorMessageRoot}` - ); - return false; - } - } - } - - resetErrors() { - this.flashMessages.clearMessages(); - this.errorMessageRoot = null; - this.invalidFormAlert = null; - } - - transition() { - this.router.transitionTo('vault.cluster.secrets.backend.configuration', this.args.backendPath); - } - - validate(model: LeaseConfigModel) { - const { isValid, state, invalidFormMessage } = model.validate(); - this.modelValidationsLease = isValid ? null : state; - this.invalidFormAlert = isValid ? '' : invalidFormMessage; - return isValid; - } - - unloadModels() { - this.args.rootConfig.unloadRecord(); - this.args.leaseConfig.unloadRecord(); - } - - @action - onChangeAccessType(accessType: string) { - this.accessType = accessType; - const { rootConfig } = this.args; - if (accessType === 'iam') { - // reset all WIF attributes - rootConfig.roleArn = rootConfig.identityTokenAudience = rootConfig.identityTokenTtl = undefined; - // for the issuer return to the globally set value (if there is one) on toggle - this.args.issuerConfig.rollbackAttributes(); - } - if (accessType === 'wif') { - // reset all IAM attributes - rootConfig.accessKey = rootConfig.secretKey = undefined; - } - } - - @action - onCancel() { - // clear errors because they're canceling out of the workflow. - this.resetErrors(); - this.unloadModels(); - this.transition(); - } -} diff --git a/ui/app/components/secret-engine/configure-ssh.hbs b/ui/app/components/secret-engine/configure-ssh.hbs deleted file mode 100644 index 6e0b71291baf..000000000000 --- a/ui/app/components/secret-engine/configure-ssh.hbs +++ /dev/null @@ -1,75 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -~}} - -
- - - {{#if @model.isNew}} - {{#each @model.formFields as |attr|}} - - {{/each}} -
- - - - - {{#if this.invalidFormAlert}} - - {{/if}} - {{else}} - {{! Model is not new and keys have already been created. Require user deletes the keys before creating new ones }} -

- NOTE: You must delete your existing certificate and key before saving new values. -

- -
- -
- -
-
- - - - - {{/if}} - \ No newline at end of file diff --git a/ui/app/components/secret-engine/configure-ssh.ts b/ui/app/components/secret-engine/configure-ssh.ts deleted file mode 100644 index 16faab2401a7..000000000000 --- a/ui/app/components/secret-engine/configure-ssh.ts +++ /dev/null @@ -1,119 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Component from '@glimmer/component'; -import { action } from '@ember/object'; -import { task } from 'ember-concurrency'; -import { waitFor } from '@ember/test-waiters'; -import { service } from '@ember/service'; -import { tracked } from '@glimmer/tracking'; -import { ValidationMap } from 'vault/vault/app-types'; -import errorMessage from 'vault/utils/error-message'; - -import type CaConfigModel from 'vault/models/ssh/ca-config'; -import type Router from '@ember/routing/router'; -import type Store from '@ember-data/store'; -import type FlashMessageService from 'vault/services/flash-messages'; - -/** - * @module ConfigureSshComponent is used to configure the SSH secret engine. - * - * @example - * ```js - * - * ``` - * - * @param {string} model - SSH ca-config model - * @param {string} id - name of the SSH secret engine, ex: 'ssh-123' - */ - -interface Args { - model: CaConfigModel; - id: string; -} - -export default class ConfigureSshComponent extends Component { - @service declare readonly router: Router; - @service declare readonly store: Store; - @service declare readonly flashMessages: FlashMessageService; - - @tracked errorMessage: string | null = null; - @tracked invalidFormAlert: string | null = null; - @tracked modelValidations: ValidationMap | null = null; - - @task - @waitFor - *save(event: Event) { - event.preventDefault(); - this.resetErrors(); - const { id, model } = this.args; - const isValid = this.validate(model); - - if (!isValid) return; - // Check if any of the model's attributes have changed. - // If no changes to the model, transition and notify user. - // Otherwise, save the model. - const attributesChanged = Object.keys(model.changedAttributes()).length > 0; - if (!attributesChanged) { - this.flashMessages.info('No changes detected.'); - this.transition(); - } - - try { - yield model.save(); - this.transition(); - this.flashMessages.success(`Successfully saved ${id}'s root configuration.`); - } catch (error) { - this.errorMessage = errorMessage(error); - this.invalidFormAlert = 'There was an error submitting this form.'; - } - } - - resetErrors() { - this.flashMessages.clearMessages(); - this.errorMessage = null; - this.invalidFormAlert = null; - } - - transition(isDelete = false) { - // deleting a key is the only case in which we want to stay on the create/edit page. - const { id } = this.args; - if (isDelete) { - this.router.transitionTo('vault.cluster.secrets.backend.configuration.edit', id); - } else { - this.router.transitionTo('vault.cluster.secrets.backend.configuration', id); - } - } - - validate(model: CaConfigModel) { - const { isValid, state, invalidFormMessage } = model.validate(); - this.modelValidations = isValid ? null : state; - this.invalidFormAlert = isValid ? '' : invalidFormMessage; - return isValid; - } - - @action - onCancel() { - // clear errors because they're canceling out of the workflow. - this.resetErrors(); - this.transition(); - } - - @action - async deleteCaConfig() { - const { model } = this.args; - try { - await model.destroyRecord(); - this.transition(true); - this.flashMessages.success('CA information deleted successfully.'); - } catch (error) { - model.rollbackAttributes(); - this.flashMessages.danger(errorMessage(error)); - } - } -} diff --git a/ui/app/components/sidebar/nav/cluster.hbs b/ui/app/components/sidebar/nav/cluster.hbs index 30f295d3c2df..b966cee19871 100644 --- a/ui/app/components/sidebar/nav/cluster.hbs +++ b/ui/app/components/sidebar/nav/cluster.hbs @@ -9,7 +9,7 @@ @@ -53,7 +53,7 @@ {{#if (or (and this.isRootNamespace (has-permission "status" routeParams=(array "replication" "raft" "license" "seal"))) - (and (has-permission "clients" routeParams="activity") (not this.hasChrootNamespace)) + (has-permission "clients" routeParams="activity") ) }} Monitoring @@ -81,9 +81,7 @@ data-test-sidebar-nav-link="Raft Storage" /> {{/if}} - {{#if - (and (has-permission "clients" routeParams="activity") (not this.cluster.dr.isSecondary) (not this.hasChrootNamespace)) - }} + {{#if (and (has-permission "clients" routeParams="activity") (not this.cluster.dr.isSecondary))}} this.handleSuccess(resp, action), + (...errArgs) => this.handleError(...errArgs) + ); + }, + + onClear() { + this.reset(); + }, + + onBack(properties) { + // only reset specific properties so user can reuse input data and repeat the action + if (this.isDestroyed || this.isDestroying) { + return; + } + properties.forEach((prop) => { + set(this, prop, DEFAULTS[prop]); + }); + }, + + onChange(param, value) { + set(this, param, value); + }, + }, +}); diff --git a/ui/app/components/tool-hash.js b/ui/app/components/tool-hash.js new file mode 100644 index 000000000000..6054baba3ab2 --- /dev/null +++ b/ui/app/components/tool-hash.js @@ -0,0 +1,33 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; + +/** + * @module ToolHash + * ToolHash components are components that sys/wrapping/hash functionality. Most of the functionality is passed through as actions from the tool-actions-form and then called back with properties. + * + * @example + * ```js + * + * ``` + * @param onClear {Function} - parent action that is passed through. Must be passed as {{action "onClear"}} + * @param sum=null {String} - property passed from parent to child and then passed back up to parent. + * @param algorithm {String} - property returned from parent. + * @param format {String} - property returned from parent. + * @param error=null {Object} - errors passed from parent as default then from child back to parent. + */ +export default class ToolHash extends Component { + @action + onClear() { + this.args.onClear(); + } +} diff --git a/ui/app/components/tool-lookup.js b/ui/app/components/tool-lookup.js new file mode 100644 index 000000000000..e1fca415eb9b --- /dev/null +++ b/ui/app/components/tool-lookup.js @@ -0,0 +1,39 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; + +/** + * @module ToolLookup + * ToolLookup components are components that sys/wrapping/lookup functionality. Most of the functionality is passed through as actions from the tool-actions-form and then called back with properties. + * + * @example + * ```js + * + * ``` + * @param creation_time {Function} - parent action that is passed through. + * @param creation_ttl {Function} - parent action that is passed through. + * @param creation_path {Function} - parent action that is passed through. + * @param expirationDate='' {String} - value returned from lookup. + * @param selectedAction="wrap" - passed in from parent. This is the wrap action, others include hash, etc. + * @param token=null {String} - property passed from parent to child and then passed back up to parent + * @param onClear {Function} - parent action that is passed through. Must be passed as {{action "onClear"}} + * @param error=null {Object} - errors passed from parent as default then from child back to parent. + */ +export default class ToolLookup extends Component { + @action + onClear() { + this.args.onClear(); + } +} diff --git a/ui/app/components/tool-random.js b/ui/app/components/tool-random.js new file mode 100644 index 000000000000..6e8422841231 --- /dev/null +++ b/ui/app/components/tool-random.js @@ -0,0 +1,34 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; + +/** + * @module ToolRandom + * ToolRandom components are components that sys/wrapping/random functionality. Most of the functionality is passed through as actions from the tool-actions-form and then called back with properties. + * + * @example + * ```js + * + * ``` + * @param onClear {Function} - parent action that is passed through. Must be passed as {{action "onClear"}} + * @param format {String} - property returned from parent. + * @param bytes {String} - property returned from parent. + * @param random_bytes {String} - property returned from parent. + * @param error=null {Object} - errors passed from parent as default then from child back to parent. + */ + +export default class ToolRandom extends Component { + @action + onClear() { + this.args.onClear(); + } +} diff --git a/ui/app/components/tool-rewrap.js b/ui/app/components/tool-rewrap.js new file mode 100644 index 000000000000..985930fde89c --- /dev/null +++ b/ui/app/components/tool-rewrap.js @@ -0,0 +1,36 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; + +/** + * @module ToolRewrap + * ToolRewrap components are components that sys/wrapping/rewrap functionality. Most of the functionality is passed through as actions from the tool-actions-form and then called back with properties. + * + * @example + * ```js + * + * ``` + * @param onClear {Function} - parent action that is passed through. Must be passed as {{action "onClear"}} + * @param token=null {String} - property passed from parent to child and then passed back up to parent + * @param rewrap_token {String} - property returned from parent. + * @param selectedAction {String} - property returned from parent. + * @param bytes {String} - property returned from parent. + * @param error=null {Object} - errors passed from parent as default then from child back to parent. + */ + +export default class ToolRewrap extends Component { + @action + onClear() { + this.args.onClear(); + } +} diff --git a/ui/app/components/tool-unwrap.js b/ui/app/components/tool-unwrap.js new file mode 100644 index 000000000000..389270e88452 --- /dev/null +++ b/ui/app/components/tool-unwrap.js @@ -0,0 +1,34 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; + +/** + * @module ToolUnwrap + * ToolUnwrap components are components that sys/wrapping/unwrap functionality. Most of the functionality is passed through as actions from the tool-actions-form and then called back with properties. + * + * @example + * ```js + * + * ``` + * @param onClear {Function} - parent action that is passed through. Must be passed as {{action "onClear"}} + * @param token=null {String} - property passed from parent to child and then passed back up to parent + * @param unwrap_data {String} - property returned from parent. + * @param details {String} - property returned from parent. + * @param error=null {Object} - errors passed from parent as default then from child back to parent. + */ + +export default class ToolUnwrap extends Component { + @action + onClear() { + this.args.onClear(); + } +} diff --git a/ui/app/components/tool-wrap.js b/ui/app/components/tool-wrap.js new file mode 100644 index 000000000000..2435b14b247d --- /dev/null +++ b/ui/app/components/tool-wrap.js @@ -0,0 +1,47 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { tracked } from '@glimmer/tracking'; + +/** + * @module ToolWrap + * ToolWrap components are components that sys/wrapping/wrap functionality. Most of the functionality is passed through as actions from the tool-actions-form and then called back with properties. + * + * @example + * + * + * @param {object} errors=null - errors returned if wrap fails + * @param {function} onBack - callback that only clears specific values so the action can be repeated. Must be passed as `{{action "onBack"}}` + * @param {function} onChange - callback that fires when inputs change and passes value and param name back to the parent + * @param {function} onClear - callback that resets all of values to defaults. Must be passed as `{{action "onClear"}}` + * @param {string} token=null - returned after user clicks "Wrap data", if there is a token value it displays instead of the JsonEditor + */ + +export default class ToolWrap extends Component { + @tracked buttonDisabled = false; + + @action + updateTtl(evt) { + if (!evt) return; + const ttl = evt.enabled ? `${evt.seconds}s` : '30m'; + this.args.onChange('wrapTTL', ttl); + } + + @action + codemirrorUpdated(val, codemirror) { + codemirror.performLint(); + const hasErrors = codemirror?.state.lint.marked?.length > 0; + this.buttonDisabled = hasErrors; + this.args.onChange('data', val); + } +} diff --git a/ui/app/components/tools/hash.hbs b/ui/app/components/tools/hash.hbs deleted file mode 100644 index 354fa173a51f..000000000000 --- a/ui/app/components/tools/hash.hbs +++ /dev/null @@ -1,86 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -~}} - - - -

- Hash Data -

-
-
- -{{#if this.sum}} -
-
- - -
-
-
- -
-{{else}} -
-
- -
- -
- - -
-
-
-
-
- -
-
- -
-
-
-
- -
-
- -
-
-
-
-
-
-
- -
-
-{{/if}} \ No newline at end of file diff --git a/ui/app/components/tools/hash.js b/ui/app/components/tools/hash.js deleted file mode 100644 index 0f2ba278a2a1..000000000000 --- a/ui/app/components/tools/hash.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Component from '@glimmer/component'; -import { action } from '@ember/object'; -import { service } from '@ember/service'; -import { tracked } from '@glimmer/tracking'; -import errorMessage from 'vault/utils/error-message'; - -/** - * @module ToolsHash - * ToolsHash components are components that sys/wrapping/hash functionality. - * - * @example - * - */ -export default class ToolsHash extends Component { - @service store; - @service flashMessages; - - @tracked algorithm = 'sha2-256'; - @tracked format = 'base64'; - @tracked hashData = ''; - @tracked sum = null; - @tracked errorMessage = ''; - - @action - reset() { - this.algorithm = 'sha2-256'; - this.format = 'base64'; - this.hashData = ''; - this.sum = null; - this.errorMessage = ''; - } - - @action - handleEvent(evt) { - const { name, value } = evt.target; - this[name] = value; - } - - @action - async handleSubmit(evt) { - evt.preventDefault(); - const data = { - input: this.hashData, - format: this.format, - algorithm: this.algorithm, - }; - - try { - const response = await this.store.adapterFor('tools').toolAction('hash', data); - this.sum = response.data.sum; - this.flashMessages.success('Hash was successful.'); - } catch (error) { - this.errorMessage = errorMessage(error); - } - } -} diff --git a/ui/app/components/tools/lookup.hbs b/ui/app/components/tools/lookup.hbs deleted file mode 100644 index 703370bb936f..000000000000 --- a/ui/app/components/tools/lookup.hbs +++ /dev/null @@ -1,50 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -~}} - - - -

- Lookup Token -

-
-
- -{{#if this.lookupData}} -
- {{#each-in this.lookupData as |key value|}} - {{#let (if (eq key "creation_ttl") "Creation TTL" (to-label key)) as |label|}} - - {{/let}} - {{/each-in}} - {{#if this.expirationDate}} - - - {{/if}} -
-
- -
-{{else}} -
-
- - -
- -
- Enter your wrapped token here to display its information. -
-
- -
-
-
-
-
- -
-
-
-{{/if}} \ No newline at end of file diff --git a/ui/app/components/tools/lookup.js b/ui/app/components/tools/lookup.js deleted file mode 100644 index d812ac92d87f..000000000000 --- a/ui/app/components/tools/lookup.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Component from '@glimmer/component'; -import { service } from '@ember/service'; -import { action } from '@ember/object'; -import { tracked } from '@glimmer/tracking'; -import errorMessage from 'vault/utils/error-message'; -import { addSeconds, parseISO } from 'date-fns'; - -/** - * @module ToolsLookup - * ToolsLookup components are components that sys/wrapping/lookup functionality. - * - * @example - * - */ -export default class ToolsLookup extends Component { - @service store; - @service flashMessages; - - @tracked token = ''; - @tracked lookupData = null; - @tracked errorMessage = ''; - - @action - reset() { - this.token = ''; - this.lookupData = null; - this.errorMessage = ''; - } - - get expirationDate() { - const { creation_time, creation_ttl } = this.lookupData; - if (creation_time && creation_ttl) { - // returns new Date with seconds added. - return addSeconds(parseISO(creation_time), creation_ttl); - } - return null; - } - - @action - async handleSubmit(evt) { - evt.preventDefault(); - const payload = { token: this.token.trim() }; - try { - const resp = await this.store.adapterFor('tools').toolAction('lookup', payload); - this.lookupData = resp.data; - this.flashMessages.success('Lookup was successful.'); - } catch (error) { - this.errorMessage = errorMessage(error); - } - } -} diff --git a/ui/app/components/tools/random.hbs b/ui/app/components/tools/random.hbs deleted file mode 100644 index 43c615d7eda2..000000000000 --- a/ui/app/components/tools/random.hbs +++ /dev/null @@ -1,66 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -~}} - - - -

- Random Bytes -

-
-
- -{{#if this.randomBytes}} -
- - -
-
- -
-{{else}} -
-
- -
-
-
- -
- -
-
-
- -
-
- -
-
-
-
-
-
-
-
- -
-
-
-{{/if}} \ No newline at end of file diff --git a/ui/app/components/tools/random.js b/ui/app/components/tools/random.js deleted file mode 100644 index deb92c997948..000000000000 --- a/ui/app/components/tools/random.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Component from '@glimmer/component'; -import { service } from '@ember/service'; -import { action } from '@ember/object'; -import { tracked } from '@glimmer/tracking'; -import errorMessage from 'vault/utils/error-message'; - -/** - * @module ToolsRandom - * ToolsRandom components are components that perform sys/wrapping/random functionality. - * @example - * - */ - -export default class ToolsRandom extends Component { - @service store; - @service flashMessages; - - @tracked bytes = 32; - @tracked format = 'base64'; - @tracked randomBytes = null; - @tracked errorMessage = ''; - - @action - reset() { - this.bytes = 32; - this.format = 'base64'; - this.randomBytes = null; - this.errorMessage = ''; - } - - @action - handleSelect(evt) { - const { value } = evt.target; - this.format = value; - } - - @action - async handleSubmit(evt) { - evt.preventDefault(); - const data = { bytes: Number(this.bytes), format: this.format }; - try { - const response = await this.store.adapterFor('tools').toolAction('random', data); - this.randomBytes = response.data.random_bytes; - this.flashMessages.success('Generated random bytes successfully.'); - } catch (error) { - this.errorMessage = errorMessage(error); - } - } -} diff --git a/ui/app/components/tools/rewrap.hbs b/ui/app/components/tools/rewrap.hbs deleted file mode 100644 index 675f7163ce70..000000000000 --- a/ui/app/components/tools/rewrap.hbs +++ /dev/null @@ -1,56 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -~}} - - - -

- Rewrap Token -

-
-
- -{{#if this.rewrappedToken}} -
-
- - -
-
-
- -
-{{else}} -
-
- - -
- -
- Enter your wrapped token here to rewrap it and refresh its TTL. -
-
- -
-
-
-
-
- -
-
-
-{{/if}} \ No newline at end of file diff --git a/ui/app/components/tools/rewrap.js b/ui/app/components/tools/rewrap.js deleted file mode 100644 index 8861163c41e1..000000000000 --- a/ui/app/components/tools/rewrap.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Component from '@glimmer/component'; -import { service } from '@ember/service'; -import { action } from '@ember/object'; -import { tracked } from '@glimmer/tracking'; -import errorMessage from 'vault/utils/error-message'; - -/** - * @module ToolsRewrap - * ToolsRewrap components are components that sys/wrapping/rewrap functionality - * - * @example - * - */ - -export default class ToolsRewrap extends Component { - @service store; - @service flashMessages; - - @tracked originalToken = ''; - @tracked rewrappedToken = ''; - @tracked errorMessage = ''; - - @action - reset() { - this.originalToken = ''; - this.rewrappedToken = ''; - this.errorMessage = ''; - } - - @action - async handleSubmit(evt) { - evt.preventDefault(); - const data = { token: this.originalToken.trim() }; - - try { - const response = await this.store.adapterFor('tools').toolAction('rewrap', data); - this.rewrappedToken = response.wrap_info.token; - this.flashMessages.success('Rewrap was successful.'); - } catch (error) { - this.errorMessage = errorMessage(error); - } - } -} diff --git a/ui/app/components/tools/unwrap.hbs b/ui/app/components/tools/unwrap.hbs deleted file mode 100644 index 38ef4aba2895..000000000000 --- a/ui/app/components/tools/unwrap.hbs +++ /dev/null @@ -1,73 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -~}} - - - -

- Unwrap Data -

-
-
- -{{#if this.unwrapData}} - - Data - Wrap Details - - - - -
- {{#each-in this.unwrapDetails as |key detail|}} - - {{/each-in}} -
-
-
- - - - -{{else}} -
-
- - -
- -
- Enter your wrapped token here to unwrap it and return its original value. -
-
- -
-
-
-
-
- -
-
-
-{{/if}} \ No newline at end of file diff --git a/ui/app/components/tools/unwrap.js b/ui/app/components/tools/unwrap.js deleted file mode 100644 index 1d1c30e86c68..000000000000 --- a/ui/app/components/tools/unwrap.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Component from '@glimmer/component'; -import { service } from '@ember/service'; -import { action } from '@ember/object'; -import { tracked } from '@glimmer/tracking'; -import errorMessage from 'vault/utils/error-message'; - -/** - * @module ToolsUnwrap - * ToolsUnwrap components are components that sys/wrapping/rewrap functionality - * - * @example - * - */ - -export default class ToolsUnwrap extends Component { - @service store; - @service flashMessages; - - @tracked token = ''; - @tracked unwrapData = ''; - @tracked unwrapDetails = {}; - @tracked errorMessage = ''; - - @action - reset() { - this.token = ''; - this.unwrapData = ''; - this.unwrapDetails = {}; - this.errorMessage = ''; - } - - @action - async handleSubmit(evt) { - evt.preventDefault(); - const data = { token: this.token.trim() }; - - try { - const resp = await this.store.adapterFor('tools').toolAction('unwrap', data); - this.unwrapData = (resp && resp.data) || resp.auth; - this.unwrapDetails = { - 'Request ID': resp.request_id, - 'Lease ID': resp.lease_id || 'None', - Renewable: resp.renewable, - 'Lease Duration': resp.lease_duration || 'None', - }; - this.flashMessages.success('Unwrap was successful.'); - } catch (error) { - this.errorMessage = errorMessage(error); - } - } -} diff --git a/ui/app/components/tools/wrap.hbs b/ui/app/components/tools/wrap.hbs deleted file mode 100644 index e294aba9ac39..000000000000 --- a/ui/app/components/tools/wrap.hbs +++ /dev/null @@ -1,68 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -~}} - - - -

- Wrap Data -

-
-
- -{{#if this.token}} -
-
- - -
-
-
- - - - -
-{{else}} -
-
- - -
-
- -
-
- -
-
-
- -
-
-
-{{/if}} \ No newline at end of file diff --git a/ui/app/components/tools/wrap.js b/ui/app/components/tools/wrap.js deleted file mode 100644 index 281db49c9c29..000000000000 --- a/ui/app/components/tools/wrap.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Component from '@glimmer/component'; -import { service } from '@ember/service'; -import { action } from '@ember/object'; -import { tracked } from '@glimmer/tracking'; -import errorMessage from 'vault/utils/error-message'; - -/** - * @module ToolsWrap - * ToolsWrap components are components that sys/wrapping/wrap functionality. - * - * @example - * - */ - -export default class ToolsWrap extends Component { - @service store; - @service flashMessages; - - @tracked buttonDisabled = false; - @tracked token = ''; - @tracked wrapTTL = null; - @tracked wrapData = '{\n}'; - @tracked errorMessage = ''; - - @action - reset(clearData = true) { - this.token = ''; - this.errorMessage = ''; - this.wrapTTL = null; - if (clearData) this.wrapData = '{\n}'; - } - - @action - updateTtl(evt) { - if (!evt) return; - this.wrapTTL = evt.enabled ? `${evt.seconds}s` : '30m'; - } - - @action - codemirrorUpdated(val, codemirror) { - codemirror.performLint(); - const hasErrors = codemirror?.state.lint.marked?.length > 0; - this.buttonDisabled = hasErrors; - if (!hasErrors) this.wrapData = val; - } - - @action - async handleSubmit(evt) { - evt.preventDefault(); - const data = JSON.parse(this.wrapData); - const wrapTTL = this.wrapTTL || null; - - try { - const response = await this.store.adapterFor('tools').toolAction('wrap', data, { wrapTTL }); - this.token = response.wrap_info.token; - this.flashMessages.success('Wrap was successful.'); - } catch (error) { - this.errorMessage = errorMessage(error); - } - } -} diff --git a/ui/app/components/transit-edit.js b/ui/app/components/transit-edit.js index 7949912cac66..c3f34b3d8d32 100644 --- a/ui/app/components/transit-edit.js +++ b/ui/app/components/transit-edit.js @@ -60,10 +60,10 @@ export default Component.extend(FocusOnInsertMixin, { models: [this.key.backend, this.key.id], query: { tab: 'details' }, }, - { label: 'Edit' }, + { label: 'edit' }, ]; } else if (this.mode === 'create') { - return [...baseCrumbs, { label: 'Create' }]; + return [...baseCrumbs, { label: 'create' }]; } return baseCrumbs; }, diff --git a/ui/app/components/z-docfy-filter.hbs b/ui/app/components/z-docfy-filter.hbs deleted file mode 100644 index a1a5b88351b3..000000000000 --- a/ui/app/components/z-docfy-filter.hbs +++ /dev/null @@ -1,19 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -~}} - - - - - {{#each this.componentList as |component|}} - - {{component.title}} - - {{/each}} - \ No newline at end of file diff --git a/ui/app/components/z-docfy-filter.js b/ui/app/components/z-docfy-filter.js deleted file mode 100644 index ac26690960a7..000000000000 --- a/ui/app/components/z-docfy-filter.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Component from '@glimmer/component'; -import { action } from '@ember/object'; -import { tracked } from '@glimmer/tracking'; - -// DEVELOPMENT ONLY COMPONENT used for filtering docfy components -export default class ZDocfyFilter extends Component { - @tracked filterValue; - - @action - filterComponents({ target }) { - this.filterValue = target.value; - } - - get componentList() { - return this.filterValue - ? this.args.components.filter((c) => c.title.toLowerCase().includes(this.filterValue.toLowerCase())) - : this.args.components; - } -} diff --git a/ui/app/controllers/application.js b/ui/app/controllers/application.js new file mode 100644 index 000000000000..97e5e50bc3ff --- /dev/null +++ b/ui/app/controllers/application.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { service } from '@ember/service'; +import Controller from '@ember/controller'; +import config from '../config/environment'; + +export default Controller.extend({ + env: config.environment, + auth: service(), + store: service(), +}); diff --git a/ui/app/controllers/application.ts b/ui/app/controllers/application.ts deleted file mode 100644 index c634b41452e0..000000000000 --- a/ui/app/controllers/application.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import { service } from '@ember/service'; -import Controller from '@ember/controller'; -import config from '../config/environment'; -import type AuthService from 'vault/vault/services/auth'; -import type StoreService from 'vault/services/store'; - -export default class ApplicationController extends Controller { - @service declare readonly auth: AuthService; - @service declare readonly store: StoreService; - env = config.environment; -} diff --git a/ui/app/controllers/vault/cluster/access/leases/list.js b/ui/app/controllers/vault/cluster/access/leases/list.js index 6bab2deafd50..12ebef8bdcff 100644 --- a/ui/app/controllers/vault/cluster/access/leases/list.js +++ b/ui/app/controllers/vault/cluster/access/leases/list.js @@ -26,8 +26,8 @@ export default Controller.extend(ListController, { backendCrumb: computed('clusterController.model.name', function () { return { - label: 'Leases', - text: 'Leases', + label: 'leases', + text: 'leases', path: 'vault.cluster.access.leases.list-root', model: this.clusterController.model.name, }; diff --git a/ui/app/controllers/vault/cluster/access/leases/show.js b/ui/app/controllers/vault/cluster/access/leases/show.js index 1838ad3bdc51..2147fb17fbf1 100644 --- a/ui/app/controllers/vault/cluster/access/leases/show.js +++ b/ui/app/controllers/vault/cluster/access/leases/show.js @@ -13,8 +13,8 @@ export default Controller.extend({ backendCrumb: computed('clusterController.model.name', function () { return { - label: 'Leases', - text: 'Leases', + label: 'leases', + text: 'leases', path: 'vault.cluster.access.leases.list-root', model: this.clusterController.model.name, }; diff --git a/ui/app/controllers/vault/cluster/auth.js b/ui/app/controllers/vault/cluster/auth.js index b68f22285ff7..75c5cf52114f 100644 --- a/ui/app/controllers/vault/cluster/auth.js +++ b/ui/app/controllers/vault/cluster/auth.js @@ -26,6 +26,20 @@ export default Controller.extend({ authMethod: '', oidcProvider: '', + get namespaceInput() { + const namespaceQP = this.clusterController.namespaceQueryParam; + if (this.hvdManagedNamespaceRoot) { + // When managed, the user isn't allowed to edit the prefix `admin/` for their nested namespace + const split = namespaceQP.split('/'); + if (split.length > 1) { + split.shift(); + return `/${split.join('/')}`; + } + return ''; + } + return namespaceQP; + }, + fullNamespaceFromInput(value) { const strippedNs = sanitizePath(value); if (this.hvdManagedNamespaceRoot) { @@ -43,30 +57,53 @@ export default Controller.extend({ this.set('namespaceQueryParam', ns); }).restartable(), + authSuccess({ isRoot, namespace }) { + let transition; + this.version.fetchVersion(); + if (this.redirectTo) { + // here we don't need the namespace because it will be encoded in redirectTo + transition = this.router.transitionTo(this.redirectTo); + // reset the value on the controller because it's bound here + this.set('redirectTo', ''); + } else { + transition = this.router.transitionTo('vault.cluster', { queryParams: { namespace } }); + } + transition.followRedirects().then(() => { + if (this.version.isEnterprise) { + this.customMessages.fetchMessages(namespace); + } + + if (isRoot) { + this.auth.set('isRootToken', true); + this.flashMessages.warning( + 'You have logged in with a root token. As a security precaution, this root token will not be stored by your browser and you will need to re-authenticate after the window is closed or refreshed.' + ); + } + }); + }, + actions: { - authSuccess({ isRoot, namespace }) { - let transition; - this.version.fetchVersion(); - if (this.redirectTo) { - // here we don't need the namespace because it will be encoded in redirectTo - transition = this.router.transitionTo(this.redirectTo); - // reset the value on the controller because it's bound here - this.set('redirectTo', ''); + onAuthResponse(authResponse, backend, data) { + const { mfa_requirement } = authResponse; + // if an mfa requirement exists further action is required + if (mfa_requirement) { + this.set('mfaAuthData', { mfa_requirement, backend, data }); } else { - transition = this.router.transitionTo('vault.cluster', { queryParams: { namespace } }); + this.authSuccess(authResponse); } - transition.followRedirects().then(() => { - if (this.version.isEnterprise) { - this.customMessages.fetchMessages(namespace); - } - - if (isRoot) { - this.auth.set('isRootToken', true); - this.flashMessages.warning( - 'You have logged in with a root token. As a security precaution, this root token will not be stored by your browser and you will need to re-authenticate after the window is closed or refreshed.' - ); - } + }, + onMfaSuccess(authResponse) { + this.authSuccess(authResponse); + }, + onMfaErrorDismiss() { + this.setProperties({ + mfaAuthData: null, + mfaErrors: null, }); }, + cancelAuthentication() { + this.set('cancelAuth', true); + this.set('waitingForOktaNumberChallenge', false); + }, }, }); diff --git a/ui/app/controllers/vault/cluster/init.js b/ui/app/controllers/vault/cluster/init.js index ddcd72e5e3de..9083f2dddef8 100644 --- a/ui/app/controllers/vault/cluster/init.js +++ b/ui/app/controllers/vault/cluster/init.js @@ -40,8 +40,7 @@ export default Controller.extend(DEFAULTS, { }), actions: { - initCluster(payload) { - const data = { ...payload }; + initCluster(data) { const isCloudSeal = !!this.model.sealType && this.model.sealType !== 'shamir'; if (data.secret_shares) { const shares = parseInt(data.secret_shares, 10); diff --git a/ui/app/controllers/vault/cluster/secrets/backend/configuration.js b/ui/app/controllers/vault/cluster/secrets/backend/configuration.js new file mode 100644 index 000000000000..771a72f00409 --- /dev/null +++ b/ui/app/controllers/vault/cluster/secrets/backend/configuration.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { computed } from '@ember/object'; +import Controller from '@ember/controller'; + +export default Controller.extend({ + isConfigurable: computed('model.type', function () { + const configurableEngines = ['aws', 'ssh']; + return configurableEngines.includes(this.model.type); + }), +}); diff --git a/ui/app/controllers/vault/cluster/secrets/backend/credentials.js b/ui/app/controllers/vault/cluster/secrets/backend/credentials.js index 9d6c74e99e5b..a4b9d93ea8ed 100644 --- a/ui/app/controllers/vault/cluster/secrets/backend/credentials.js +++ b/ui/app/controllers/vault/cluster/secrets/backend/credentials.js @@ -6,10 +6,11 @@ import Controller from '@ember/controller'; export default Controller.extend({ - queryParams: ['roleType'], - // used for database credentials + queryParams: ['action', 'roleType'], + action: '', roleType: '', reset() { + this.set('action', ''); this.set('roleType', ''); }, }); diff --git a/ui/app/controllers/vault/cluster/secrets/backend/configuration/edit.js b/ui/app/controllers/vault/cluster/settings/configure-secret-backend.js similarity index 58% rename from ui/app/controllers/vault/cluster/secrets/backend/configuration/edit.js rename to ui/app/controllers/vault/cluster/settings/configure-secret-backend.js index 6dbea5516bc4..c0b629a9fe33 100644 --- a/ui/app/controllers/vault/cluster/secrets/backend/configuration/edit.js +++ b/ui/app/controllers/vault/cluster/settings/configure-secret-backend.js @@ -29,6 +29,31 @@ export default Controller.extend(CONFIG_ATTRS, { this.setProperties(CONFIG_ATTRS); }, actions: { + saveConfig(options = { delete: false }) { + const isDelete = options.delete; + if (this.model.type === 'ssh') { + this.set('loading', true); + this.model + .saveCA({ isDelete }) + .then(() => { + this.send('refreshRoute'); + this.set('configured', !isDelete); + if (isDelete) { + this.flashMessages.success('SSH Certificate Authority Configuration deleted!'); + } else { + this.flashMessages.success('SSH Certificate Authority Configuration saved!'); + } + }) + .catch((error) => { + const errorMessage = error.errors ? error.errors.join('. ') : error; + this.flashMessages.danger(errorMessage); + }) + .finally(() => { + this.set('loading', false); + }); + } + }, + save(method, data) { this.set('loading', true); const hasData = Object.keys(data).some((key) => { diff --git a/ui/app/decorators/model-validations.js b/ui/app/decorators/model-validations.js index c28e0620ea78..6be78a132c9c 100644 --- a/ui/app/decorators/model-validations.js +++ b/ui/app/decorators/model-validations.js @@ -4,7 +4,7 @@ */ /* eslint-disable no-console */ -import validators from 'vault/utils/model-helpers/validators'; +import validators from 'vault/utils/validators'; import { get } from '@ember/object'; // see documentation at ui/docs/model-validations.md for detailed usage information diff --git a/ui/lib/core/addon/helpers/await.js b/ui/app/helpers/await.js similarity index 100% rename from ui/lib/core/addon/helpers/await.js rename to ui/app/helpers/await.js diff --git a/ui/app/helpers/aws-regions.js b/ui/app/helpers/aws-regions.js index f5c03c9b7d79..a8e0ade94d7f 100644 --- a/ui/app/helpers/aws-regions.js +++ b/ui/app/helpers/aws-regions.js @@ -7,7 +7,6 @@ import { helper as buildHelper } from '@ember/component/helper'; //list from http://docs.aws.amazon.com/general/latest/gr/rande.html#sts_region const REGIONS = [ - '', // initial region blank 'us-east-1', 'us-east-2', 'us-west-1', diff --git a/ui/lib/core/addon/helpers/date-from-now.js b/ui/app/helpers/date-from-now.js similarity index 100% rename from ui/lib/core/addon/helpers/date-from-now.js rename to ui/app/helpers/date-from-now.js diff --git a/ui/app/helpers/mountable-secret-engines.js b/ui/app/helpers/mountable-secret-engines.js index 216eb960fa96..398ed5e36718 100644 --- a/ui/app/helpers/mountable-secret-engines.js +++ b/ui/app/helpers/mountable-secret-engines.js @@ -134,22 +134,6 @@ const MOUNTABLE_SECRET_ENGINES = [ }, ]; -// A list of Workload Identity Federation engines. Will eventually include Azure and GCP. -export const WIF_ENGINES = ['aws']; - -export function wifEngines() { - return WIF_ENGINES.slice(); -} - -// Secret Engines that have their own configuration page and actions -// These engines do not exist in their own Ember engine. -// Ex: AWS vs. LDAP which is configurable but is handled inside the routing of its own Ember engine. -export const CONFIGURABLE_SECRET_ENGINES = ['aws', 'ssh']; - -export function configurableSecretEngines() { - return MOUNTABLE_SECRET_ENGINES.slice(); -} - export function mountableEngines() { return MOUNTABLE_SECRET_ENGINES.slice(); } diff --git a/ui/app/initializers/deprecation-filter.js b/ui/app/initializers/deprecation-filter.js index 5e163149da38..3063b376152f 100644 --- a/ui/app/initializers/deprecation-filter.js +++ b/ui/app/initializers/deprecation-filter.js @@ -10,8 +10,7 @@ export function initialize() { registerDeprecationHandler((message, options, next) => { // filter deprecations that are scheduled to be removed in a specific version // when upgrading or addressing deprecation warnings be sure to update this or remove if not needed - if (options?.until.includes('6.0')) { - // ignore all deprecations for 6+ + if (options?.until.includes('5.0') && options?.id.startsWith('ember-data')) { return; } next(message, options); diff --git a/ui/app/models/auth-config.js b/ui/app/models/auth-config.js index 46f7318569ec..95e726c80429 100644 --- a/ui/app/models/auth-config.js +++ b/ui/app/models/auth-config.js @@ -6,10 +6,8 @@ import Model, { belongsTo } from '@ember-data/model'; export default Model.extend({ - backend: belongsTo('auth-method', { - inverse: 'authConfigs', - readOnly: true, - async: false, - as: 'auth-config', - }), + backend: belongsTo('auth-method', { inverse: 'authConfigs', readOnly: true, async: false }), + getHelpUrl: function (backend) { + return `/v1/auth/${backend}/config?help=1`; + }, }); diff --git a/ui/app/models/auth-config/azure.js b/ui/app/models/auth-config/azure.js index 300ec7319e34..338a451b1d24 100644 --- a/ui/app/models/auth-config/azure.js +++ b/ui/app/models/auth-config/azure.js @@ -10,6 +10,7 @@ import { combineFieldGroups } from 'vault/utils/openapi-to-attrs'; import fieldToAttrs from 'vault/utils/field-to-attrs'; export default AuthConfig.extend({ + useOpenAPI: true, tenantId: attr('string', { label: 'Tenant ID', helpText: 'The tenant ID for the Azure Active Directory organization', diff --git a/ui/app/models/auth-config/gcp.js b/ui/app/models/auth-config/gcp.js index d69019df7226..f825fb21e987 100644 --- a/ui/app/models/auth-config/gcp.js +++ b/ui/app/models/auth-config/gcp.js @@ -10,6 +10,7 @@ import { combineFieldGroups } from 'vault/utils/openapi-to-attrs'; import fieldToAttrs from 'vault/utils/field-to-attrs'; export default AuthConfig.extend({ + useOpenAPI: true, // We have to leave this here because the backend doesn't support the file type yet. credentials: attr('string', { editType: 'file', diff --git a/ui/app/models/auth-config/github.js b/ui/app/models/auth-config/github.js index ce3f98d8e25f..675741c68143 100644 --- a/ui/app/models/auth-config/github.js +++ b/ui/app/models/auth-config/github.js @@ -10,6 +10,7 @@ import fieldToAttrs from 'vault/utils/field-to-attrs'; import { combineFieldGroups } from 'vault/utils/openapi-to-attrs'; export default AuthConfig.extend({ + useOpenAPI: true, organization: attr('string'), baseUrl: attr('string', { label: 'Base URL', diff --git a/ui/app/models/auth-config/jwt.js b/ui/app/models/auth-config/jwt.js index 934e5163798c..38b8d99ae657 100644 --- a/ui/app/models/auth-config/jwt.js +++ b/ui/app/models/auth-config/jwt.js @@ -10,6 +10,7 @@ import fieldToAttrs from 'vault/utils/field-to-attrs'; import { combineFieldGroups } from 'vault/utils/openapi-to-attrs'; export default AuthConfig.extend({ + useOpenAPI: true, oidcDiscoveryUrl: attr('string', { label: 'OIDC discovery URL', helpText: diff --git a/ui/app/models/auth-config/kubernetes.js b/ui/app/models/auth-config/kubernetes.js index c03caa0b91f1..3129bdb04de0 100644 --- a/ui/app/models/auth-config/kubernetes.js +++ b/ui/app/models/auth-config/kubernetes.js @@ -11,6 +11,7 @@ import { combineFieldGroups } from 'vault/utils/openapi-to-attrs'; import fieldToAttrs from 'vault/utils/field-to-attrs'; export default AuthConfig.extend({ + useOpenAPI: true, kubernetesHost: attr('string', { helpText: 'Host must be a host string, a host:port pair, or a URL to the base of the Kubernetes API server.', diff --git a/ui/app/models/auth-config/ldap.js b/ui/app/models/auth-config/ldap.js index 5cfdf998fec5..fc7261a0b5aa 100644 --- a/ui/app/models/auth-config/ldap.js +++ b/ui/app/models/auth-config/ldap.js @@ -11,6 +11,7 @@ import fieldToAttrs from 'vault/utils/field-to-attrs'; import { combineFieldGroups } from 'vault/utils/openapi-to-attrs'; export default AuthConfig.extend({ + useOpenAPI: true, certificate: attr({ label: 'Certificate', editType: 'file', diff --git a/ui/app/models/auth-config/okta.js b/ui/app/models/auth-config/okta.js index 61db5a3cd844..11a18b1e0a36 100644 --- a/ui/app/models/auth-config/okta.js +++ b/ui/app/models/auth-config/okta.js @@ -10,6 +10,7 @@ import fieldToAttrs from 'vault/utils/field-to-attrs'; import { combineFieldGroups } from 'vault/utils/openapi-to-attrs'; export default AuthConfig.extend({ + useOpenAPI: true, orgName: attr('string', { helpText: 'Name of the organization to be used in the Okta API', }), diff --git a/ui/app/models/auth-config/radius.js b/ui/app/models/auth-config/radius.js index 6d25c3841928..c38d1fbdc432 100644 --- a/ui/app/models/auth-config/radius.js +++ b/ui/app/models/auth-config/radius.js @@ -10,6 +10,7 @@ import { combineFieldGroups } from 'vault/utils/openapi-to-attrs'; import fieldToAttrs from 'vault/utils/field-to-attrs'; export default AuthConfig.extend({ + useOpenAPI: true, host: attr('string'), secret: attr('string'), diff --git a/ui/app/models/auth-method.js b/ui/app/models/auth-method.js index cf11df86434b..d1b64b10bc10 100644 --- a/ui/app/models/auth-method.js +++ b/ui/app/models/auth-method.js @@ -12,14 +12,14 @@ import { allMethods } from 'vault/helpers/mountable-auth-methods'; import lazyCapabilities from 'vault/macros/lazy-capabilities'; import { action } from '@ember/object'; import { camelize } from '@ember/string'; -import { WHITESPACE_WARNING } from 'vault/utils/model-helpers/validators'; const validations = { path: [ { type: 'presence', message: "Path can't be blank." }, { type: 'containsWhiteSpace', - message: WHITESPACE_WARNING('path'), + message: + "Path contains whitespace. If this is desired, you'll need to encode it with %20 in API requests.", level: 'warn', }, ], diff --git a/ui/app/models/aws-credential.js b/ui/app/models/aws-credential.js index 7f5d6f057cc0..7199ad75bf56 100644 --- a/ui/app/models/aws-credential.js +++ b/ui/app/models/aws-credential.js @@ -4,8 +4,8 @@ */ import Model, { attr } from '@ember-data/model'; -import { withExpandedAttributes } from 'vault/decorators/model-expanded-attributes'; - +import { computed } from '@ember/object'; +import { expandAttributeMeta } from 'vault/utils/field-to-attrs'; const CREDENTIAL_TYPES = [ { value: 'iam_user', @@ -25,28 +25,27 @@ const CREDENTIAL_TYPES = [ }, ]; -@withExpandedAttributes() -export default class AwsCredential extends Model { - @attr('object', { +const DISPLAY_FIELDS = ['accessKey', 'secretKey', 'securityToken', 'leaseId', 'renewable', 'leaseDuration']; +export default Model.extend({ + helpText: + 'For Vault roles of credential type iam_user, there are no inputs, just submit the form. Choose a type to change the input options.', + role: attr('object', { readOnly: true, - }) - role; + }), - @attr('string', { + credentialType: attr('string', { defaultValue: 'iam_user', possibleValues: CREDENTIAL_TYPES, readOnly: true, - }) - credentialType; + }), - @attr('string', { + roleArn: attr('string', { label: 'Role ARN', helpText: 'The ARN of the role to assume if credential_type on the Vault role is assumed_role. Optional if the role has a single role ARN; required otherwise.', - }) - roleArn; + }), - @attr({ + ttl: attr({ editType: 'ttl', defaultValue: '3600s', setDefault: true, @@ -54,17 +53,29 @@ export default class AwsCredential extends Model { label: 'TTL', helpText: 'Specifies the TTL for the use of the STS token. Valid only when credential_type is assumed_role, federation_token, or session_token.', - }) - ttl; + }), + leaseId: attr('string'), + renewable: attr('boolean'), + leaseDuration: attr('number'), + accessKey: attr('string'), + secretKey: attr('string'), + securityToken: attr('string'), - @attr('string') leaseId; - @attr('boolean') renewable; - @attr('number') leaseDuration; - @attr('string') accessKey; - @attr('string', { masked: true }) secretKey; - @attr('string', { masked: true }) securityToken; + attrs: computed('credentialType', 'accessKey', 'securityToken', function () { + const type = this.credentialType; + const fieldsForType = { + iam_user: ['credentialType'], + assumed_role: ['credentialType', 'ttl', 'roleArn'], + federation_token: ['credentialType', 'ttl'], + session_token: ['credentialType', 'ttl'], + }; + if (this.accessKey || this.securityToken) { + return expandAttributeMeta(this, DISPLAY_FIELDS.slice(0)); + } + return expandAttributeMeta(this, fieldsForType[type].slice(0)); + }), - get toCreds() { + toCreds: computed('accessKey', 'secretKey', 'securityToken', 'leaseId', function () { const props = { accessKey: this.accessKey, secretKey: this.secretKey, @@ -79,5 +90,5 @@ export default class AwsCredential extends Model { return ret; }, {}); return JSON.stringify(propsWithVals, null, 2); - } -} + }), +}); diff --git a/ui/app/models/aws/lease-config.js b/ui/app/models/aws/lease-config.js deleted file mode 100644 index 3d7c30cf6ee7..000000000000 --- a/ui/app/models/aws/lease-config.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Model, { attr } from '@ember-data/model'; -import { expandAttributeMeta } from 'vault/utils/field-to-attrs'; -import { withModelValidations } from 'vault/decorators/model-validations'; - -const validations = { - lease: [ - { - validator(model) { - const { lease, leaseMax } = model; - return (lease && leaseMax) || (!lease && !leaseMax) ? true : false; - }, - message: 'Lease TTL and Max Lease TTL are both required if one of them is set.', - }, - ], -}; -@withModelValidations(validations) -export default class AwsLeaseConfig extends Model { - @attr('string') backend; // dynamic path of secret -- set on response from value passed to queryRecord - @attr({ - label: 'Max Lease TTL', - editType: 'ttl', - }) - leaseMax; - @attr({ - label: 'Default Lease TTL', - editType: 'ttl', - }) - lease; - - get attrs() { - const keys = ['lease', 'leaseMax']; - return expandAttributeMeta(this, keys); - } -} diff --git a/ui/app/models/aws/root-config.js b/ui/app/models/aws/root-config.js deleted file mode 100644 index 9bd1034e3a05..000000000000 --- a/ui/app/models/aws/root-config.js +++ /dev/null @@ -1,90 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Model, { attr } from '@ember-data/model'; -import fieldToAttrs, { expandAttributeMeta } from 'vault/utils/field-to-attrs'; -import { regions } from 'vault/helpers/aws-regions'; - -export default class AwsRootConfig extends Model { - @attr('string') backend; // dynamic path of secret -- set on response from value passed to queryRecord - - // IAM only fields - @attr('string') accessKey; - @attr('string', { sensitive: true }) secretKey; // obfuscated, never returned by API - - // WIF only fields - @attr('string', { - label: 'Role ARN', - subText: 'Role ARN to assume for plugin workload identity federation.', - }) - roleArn; - @attr('string', { - subText: - 'The audience claim value for plugin identity tokens. Must match an allowed audience configured for the target IAM OIDC identity provider.', - }) - identityTokenAudience; - @attr({ - label: 'Identity token TTL', - helperTextDisabled: - 'The TTL of generated tokens. Defaults to 1 hour, turn on the toggle to specify a different value.', - helperTextEnabled: 'The TTL of generated tokens.', - subText: '', - editType: 'ttl', - }) - identityTokenTtl; - - // Fields that show regardless of access type - @attr('string', { - possibleValues: regions(), - subText: - 'Specifies the AWS region. If not set it will use the AWS_REGION env var, AWS_DEFAULT_REGION env var, or us-east-1 in that order.', - }) - region; - @attr('string', { label: 'IAM endpoint' }) - iamEndpoint; - @attr('string', { label: 'STS endpoint' }) stsEndpoint; - @attr('number', { - label: 'Maximum retries', - subText: 'Number of max retries the client should use for recoverable errors. Default is -1.', - }) - maxRetries; - - get attrs() { - const keys = [ - 'roleArn', - 'identityTokenAudience', - 'identityTokenTtl', - 'accessKey', - 'region', - 'iamEndpoint', - 'stsEndpoint', - 'maxRetries', - ]; - return expandAttributeMeta(this, keys); - } - - // "filedGroupsWif" and "fieldGroupsIam" are passed to the FormFieldGroups component to determine which group to show in the form (ex: @groupName="fieldGroupsWif") - get fieldGroupsWif() { - return fieldToAttrs(this, this.formFieldGroups('wif')); - } - - get fieldGroupsIam() { - return fieldToAttrs(this, this.formFieldGroups('iam')); - } - - formFieldGroups(accessType = 'iam') { - const formFieldGroups = []; - if (accessType === 'wif') { - formFieldGroups.push({ default: ['roleArn', 'identityTokenAudience', 'identityTokenTtl'] }); - } - if (accessType === 'iam') { - formFieldGroups.push({ default: ['accessKey', 'secretKey'] }); - } - formFieldGroups.push({ - 'Root config options': ['region', 'iamEndpoint', 'stsEndpoint', 'maxRetries'], - }); - return formFieldGroups; - } -} diff --git a/ui/app/models/capabilities.js b/ui/app/models/capabilities.js index 80e9e3ccd33b..139d4f194e99 100644 --- a/ui/app/models/capabilities.js +++ b/ui/app/models/capabilities.js @@ -47,13 +47,12 @@ const computedCapability = function (capability) { export default Model.extend({ path: attr('string'), capabilities: attr('array'), - allowedParameters: attr(), - deniedParameters: attr(), + canSudo: computedCapability('sudo'), + canRead: computedCapability('read'), canCreate: computedCapability('create'), + canUpdate: computedCapability('update'), canDelete: computedCapability('delete'), canList: computedCapability('list'), - canPatch: computedCapability('patch'), - canRead: computedCapability('read'), - canSudo: computedCapability('sudo'), - canUpdate: computedCapability('update'), + allowedParameters: attr(), + deniedParameters: attr(), }); diff --git a/ui/app/models/clients/config.js b/ui/app/models/clients/config.js index 26c1663a9740..05c42d57c677 100644 --- a/ui/app/models/clients/config.js +++ b/ui/app/models/clients/config.js @@ -15,10 +15,6 @@ const validations = { message: (model) => `Retention period must be greater than or equal to ${model.minimumRetentionMonths}.`, }, - { - validator: (model) => parseInt(model.retentionMonths) <= 60, - message: 'Retention period must be less than or equal to 60.', - }, ], }; diff --git a/ui/app/models/database/connection.js b/ui/app/models/database/connection.js index e19585f2b84d..fc1a595bcc46 100644 --- a/ui/app/models/database/connection.js +++ b/ui/app/models/database/connection.js @@ -8,7 +8,7 @@ import { computed } from '@ember/object'; import { alias, or } from '@ember/object/computed'; import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities'; import fieldToAttrs, { expandAttributeMeta } from 'vault/utils/field-to-attrs'; -import { AVAILABLE_PLUGIN_TYPES } from '../../utils/model-helpers/database-helpers'; +import { AVAILABLE_PLUGIN_TYPES } from '../../utils/database-helpers'; /** * fieldsToGroups helper fn diff --git a/ui/app/models/database/role.js b/ui/app/models/database/role.js index 79f6fbd727a7..cbf1facfdb7c 100644 --- a/ui/app/models/database/role.js +++ b/ui/app/models/database/role.js @@ -8,7 +8,7 @@ import { computed } from '@ember/object'; import { alias } from '@ember/object/computed'; import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities'; import { expandAttributeMeta } from 'vault/utils/field-to-attrs'; -import { getRoleFields } from 'vault/utils/model-helpers/database-helpers'; +import { getRoleFields } from 'vault/utils/database-helpers'; export default Model.extend({ idPrefix: 'role/', diff --git a/ui/app/models/generated-item.js b/ui/app/models/generated-item.js deleted file mode 100644 index 81aa161a7343..000000000000 --- a/ui/app/models/generated-item.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Model from '@ember-data/model'; -import { tracked } from '@glimmer/tracking'; - -// This model is used for OpenApi-generated models in path-help service's getNewModel method -export default class GeneratedItemModel extends Model { - allFields = []; - - @tracked _id; - get mutableId() { - return this._id || this.id; - } - set mutableId(value) { - this._id = value; - } - - get fieldGroups() { - const groups = { - default: [], - }; - const fieldGroups = []; - this.constructor.eachAttribute((name, attr) => { - // if the attr comes in with a fieldGroup from OpenAPI, - if (attr.options.fieldGroup) { - if (groups[attr.options.fieldGroup]) { - groups[attr.options.fieldGroup].push(attr); - } else { - groups[attr.options.fieldGroup] = [attr]; - } - } else { - // otherwise just add that attr to the default group - groups.default.push(attr); - } - }); - for (const group in groups) { - fieldGroups.push({ [group]: groups[group] }); - } - return fieldGroups; - } -} diff --git a/ui/app/models/identity/oidc/config.js b/ui/app/models/identity/oidc/config.js deleted file mode 100644 index 707ad19eb21c..000000000000 --- a/ui/app/models/identity/oidc/config.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Model, { attr } from '@ember-data/model'; -import { expandAttributeMeta } from 'vault/utils/field-to-attrs'; - -export default class IdentityOidcConfig extends Model { - @attr('string', { - label: 'Issuer', - subText: - "The Issuer URL to be used in configuring Vault as an identity provider in AWS. If not set, Vault's default issuer will be used", - docLink: '/vault/api-docs/secret/identity/tokens#configure-the-identity-tokens-backend', - placeholder: 'https://vault-test.com', - }) - issuer; - - get attrs() { - const keys = ['issuer']; - return expandAttributeMeta(this, keys); - } -} diff --git a/ui/app/models/kmip/config.js b/ui/app/models/kmip/config.js index 61600c7abaf7..8a9fedbb2d5b 100644 --- a/ui/app/models/kmip/config.js +++ b/ui/app/models/kmip/config.js @@ -9,7 +9,11 @@ import { combineFieldGroups } from 'vault/utils/openapi-to-attrs'; import fieldToAttrs from 'vault/utils/field-to-attrs'; export default Model.extend({ + useOpenAPI: true, ca: belongsTo('kmip/ca', { async: false, inverse: 'config' }), + getHelpUrl(path) { + return `/v1/${path}/config?help=1`; + }, fieldGroups: computed('newFields', function () { let groups = [{ default: ['listenAddrs', 'connectionTimeout'] }]; diff --git a/ui/app/models/kmip/role.js b/ui/app/models/kmip/role.js index 2fbace484fa3..572ba22d28f5 100644 --- a/ui/app/models/kmip/role.js +++ b/ui/app/models/kmip/role.js @@ -4,39 +4,55 @@ */ import Model, { attr } from '@ember-data/model'; +import { computed } from '@ember/object'; +import fieldToAttrs, { expandAttributeMeta } from 'vault/utils/field-to-attrs'; import apiPath from 'vault/utils/api-path'; import lazyCapabilities from 'vault/macros/lazy-capabilities'; -import { withExpandedAttributes } from 'vault/decorators/model-expanded-attributes'; -import { - operationFields, - operationFieldsWithoutSpecial, - tlsFields, -} from 'vault/utils/model-helpers/kmip-role-fields'; import { removeManyFromArray } from 'vault/helpers/remove-from-array'; -@withExpandedAttributes() -export default class KmipRoleModel extends Model { - @attr({ readOnly: true }) backend; - @attr({ readOnly: true }) scope; +const COMPUTEDS = { + operationFields: computed('newFields', function () { + return this.newFields.filter((key) => key.startsWith('operation')); + }), - get editableFields() { - return Object.keys(this.allByKey).filter((k) => !['backend', 'scope', 'role'].includes(k)); - } + operationFieldsWithoutSpecial: computed('operationFields', function () { + return removeManyFromArray(this.operationFields, ['operationAll', 'operationNone']); + }), - get fieldGroups() { - const tls = tlsFields(); - const groups = [{ TLS: tls }]; - // op fields are shown in OperationFieldDisplay - const opFields = operationFields(this.editableFields); - // not op fields, tls fields, or role/backend/scope - const defaultFields = this.editableFields.filter((f) => ![...opFields, ...tls].includes(f)); - if (defaultFields.length) { - groups.unshift({ default: defaultFields }); + tlsFields: computed(function () { + return ['tlsClientKeyBits', 'tlsClientKeyType', 'tlsClientTtl']; + }), + + // For rendering on the create/edit pages + defaultFields: computed('newFields', 'operationFields', 'tlsFields', function () { + const excludeFields = ['role'].concat(this.operationFields, this.tlsFields); + return removeManyFromArray(this.newFields, excludeFields); + }), + + // For adapter/serializer + nonOperationFields: computed('newFields', 'operationFields', function () { + return removeManyFromArray(this.newFields, this.operationFields); + }), +}; + +export default Model.extend(COMPUTEDS, { + useOpenAPI: true, + backend: attr({ readOnly: true }), + scope: attr({ readOnly: true }), + name: attr({ readOnly: true }), + getHelpUrl(path) { + return `/v1/${path}/scope/example/role/example?help=1`; + }, + fieldGroups: computed('fields', 'defaultFields.length', 'tlsFields', function () { + const groups = [{ TLS: this.tlsFields }]; + if (this.defaultFields.length) { + groups.unshift({ default: this.defaultFields }); } - return this._expandGroups(groups); - } + const ret = fieldToAttrs(this, groups); + return ret; + }), - get operationFormFields() { + operationFormFields: computed('operationFieldsWithoutSpecial', function () { const objects = [ 'operationCreate', 'operationActivate', @@ -49,7 +65,7 @@ export default class KmipRoleModel extends Model { const attributes = ['operationAddAttribute', 'operationGetAttributes']; const server = ['operationDiscoverVersions']; - const others = removeManyFromArray(operationFieldsWithoutSpecial(this.editableFields), [ + const others = removeManyFromArray(this.operationFieldsWithoutSpecial, [ ...objects, ...attributes, ...server, @@ -64,8 +80,14 @@ export default class KmipRoleModel extends Model { Other: others, }); } - return this._expandGroups(groups); - } + return fieldToAttrs(this, groups); + }), + tlsFormFields: computed('tlsFields', function () { + return expandAttributeMeta(this, this.tlsFields); + }), + fields: computed('defaultFields', function () { + return expandAttributeMeta(this, this.defaultFields); + }), - @lazyCapabilities(apiPath`${'backend'}/scope/${'scope'}/role/${'id'}`, 'backend', 'scope', 'id') updatePath; -} + updatePath: lazyCapabilities(apiPath`${'backend'}/scope/${'scope'}/role/${'id'}`, 'backend', 'scope', 'id'), +}); diff --git a/ui/app/models/kv/data.js b/ui/app/models/kv/data.js index 19b07fac9554..58392bf6b370 100644 --- a/ui/app/models/kv/data.js +++ b/ui/app/models/kv/data.js @@ -8,7 +8,6 @@ import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities'; import { withModelValidations } from 'vault/decorators/model-validations'; import { withFormFields } from 'vault/decorators/model-form-fields'; import { isDeleted } from 'kv/utils/kv-deleted'; -import { WHITESPACE_WARNING } from 'vault/utils/model-helpers/validators'; /* sample response { @@ -36,7 +35,8 @@ const validations = { { type: 'endsInSlash', message: `Path can't end in forward slash '/'.` }, { type: 'containsWhiteSpace', - message: WHITESPACE_WARNING('path'), + message: + "Path contains whitespace. If this is desired, you'll need to encode it with %20 in API requests.", level: 'warn', }, ], @@ -88,7 +88,6 @@ export default class KvSecretDataModel extends Model { @lazyCapabilities(apiPath`${'backend'}/delete/${'path'}`, 'backend', 'path') deletePath; @lazyCapabilities(apiPath`${'backend'}/destroy/${'path'}`, 'backend', 'path') destroyPath; @lazyCapabilities(apiPath`${'backend'}/undelete/${'path'}`, 'backend', 'path') undeletePath; - @lazyCapabilities(apiPath`${'backend'}/subkeys/${'path'}`, 'backend', 'path') subkeysPath; get canDeleteLatestVersion() { return this.dataPath.get('canDelete') !== false; @@ -120,7 +119,4 @@ export default class KvSecretDataModel extends Model { get canDeleteMetadata() { return this.metadataPath.get('canDelete') !== false; } - get canReadSubkeys() { - return this.subkeysPath.get('canRead') !== false; - } } diff --git a/ui/app/models/kv/metadata.js b/ui/app/models/kv/metadata.js index 447c5fa07224..66d1d1b8c0df 100644 --- a/ui/app/models/kv/metadata.js +++ b/ui/app/models/kv/metadata.js @@ -49,8 +49,6 @@ export default class KvSecretMetadataModel extends Model { }) deleteVersionAfter; - // the API returns custom_metadata: null if empty but because the attr is an 'object' ember data transforms it to an empty object. - // this is important because we rely on the empty object as a truthy value in template conditionals @attr('object', { editType: 'kv', isSectionHeader: true, @@ -71,6 +69,11 @@ export default class KvSecretMetadataModel extends Model { return keyIsFolder(this.path); } + // cannot use isDeleted due to ember property conflict + get isSecretDeleted() { + return isDeleted(this.deletionTime); + } + // turns version object into an array for version dropdown menu get sortedVersions() { const array = []; @@ -90,7 +93,6 @@ export default class KvSecretMetadataModel extends Model { return { state, isDeactivated: state !== 'created', - deletionTime: data.deletion_time, }; } diff --git a/ui/app/models/mount-config.js b/ui/app/models/mount-config.js index 5b53be5b8328..d7b3665a70ea 100644 --- a/ui/app/models/mount-config.js +++ b/ui/app/models/mount-config.js @@ -74,14 +74,6 @@ export default class MountConfigModel extends Model { }) pluginVersion; - // identityTokenKey is yielded in a named block on the mount-backend-form component - @attr({ - label: 'Identity token key', - subText: `A named key to sign tokens. If not provided, this will default to Vault's OIDC default key.`, - editType: 'yield', - }) - identityTokenKey; - // Auth mount userLockoutConfig params, added to user_lockout_config object in saveModel method @attr('string', { label: 'Lockout threshold', diff --git a/ui/app/models/pki/certificate/base.js b/ui/app/models/pki/certificate/base.js index a7b6eca18193..72125cfab451 100644 --- a/ui/app/models/pki/certificate/base.js +++ b/ui/app/models/pki/certificate/base.js @@ -4,6 +4,7 @@ */ import Model, { attr } from '@ember-data/model'; +import { assert } from '@ember/debug'; import { service } from '@ember/service'; import { withFormFields } from 'vault/decorators/model-form-fields'; import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities'; @@ -24,9 +25,15 @@ const certDisplayFields = ['certificate', 'commonName', 'revocationTime', 'seria export default class PkiCertificateBaseModel extends Model { @service secretMountPath; + get useOpenAPI() { + return true; + } get backend() { return this.secretMountPath.currentPath; } + getHelpUrl() { + assert('You must provide a helpUrl for OpenAPI', true); + } // The attributes parsed from parse-pki-cert util live here @attr parsedCertificate; diff --git a/ui/app/models/pki/certificate/generate.js b/ui/app/models/pki/certificate/generate.js index daad7c51751c..640695d4f855 100644 --- a/ui/app/models/pki/certificate/generate.js +++ b/ui/app/models/pki/certificate/generate.js @@ -34,5 +34,8 @@ const certDisplayFields = [ ]; @withFormFields(certDisplayFields, generateFromRole) export default class PkiCertificateGenerateModel extends PkiCertificateBaseModel { + getHelpUrl(backend) { + return `/v1/${backend}/issue/example?help=1`; + } @attr('string') role; // role name to issue certificate against for request URL } diff --git a/ui/app/models/pki/certificate/sign.js b/ui/app/models/pki/certificate/sign.js index e25d85ba4493..76fe3156c94a 100644 --- a/ui/app/models/pki/certificate/sign.js +++ b/ui/app/models/pki/certificate/sign.js @@ -23,6 +23,9 @@ const generateFromRole = [ ]; @withFormFields(null, generateFromRole) export default class PkiCertificateSignModel extends PkiCertificateBaseModel { + getHelpUrl(backend) { + return `/v1/${backend}/sign/example?help=1`; + } @attr('string') role; // role name to create certificate against for request URL @attr('string', { diff --git a/ui/app/models/pki/config/acme.js b/ui/app/models/pki/config/acme.js index a0e6898bdeb5..4afffc74e9cd 100644 --- a/ui/app/models/pki/config/acme.js +++ b/ui/app/models/pki/config/acme.js @@ -10,8 +10,16 @@ import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities'; @withFormFields() export default class PkiConfigAcmeModel extends Model { // This model uses the backend value as the model ID + get useOpenAPI() { + return true; + } + + getHelpUrl(backendPath) { + return `/v1/${backendPath}/config/acme?help=1`; + } // attrs order in the form is determined by order here + @attr('boolean', { label: 'ACME enabled', subText: 'When ACME is disabled, all requests to ACME directory URLs will return 404.', diff --git a/ui/app/models/pki/config/cluster.js b/ui/app/models/pki/config/cluster.js index 254b9720b50c..8b4d49f66dee 100644 --- a/ui/app/models/pki/config/cluster.js +++ b/ui/app/models/pki/config/cluster.js @@ -10,6 +10,13 @@ import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities'; @withFormFields() export default class PkiConfigClusterModel extends Model { // This model uses the backend value as the model ID + get useOpenAPI() { + return true; + } + + getHelpUrl(backendPath) { + return `/v1/${backendPath}/config/cluster?help=1`; + } @attr('string', { label: "Mount's API path", diff --git a/ui/app/models/pki/config/urls.js b/ui/app/models/pki/config/urls.js index 5a8699c36e26..924d63b223ff 100644 --- a/ui/app/models/pki/config/urls.js +++ b/ui/app/models/pki/config/urls.js @@ -10,6 +10,12 @@ import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities'; @withFormFields() export default class PkiConfigUrlsModel extends Model { // This model uses the backend value as the model ID + get useOpenAPI() { + return true; + } + getHelpUrl(backendPath) { + return `/v1/${backendPath}/config/urls?help=1`; + } @attr({ label: 'Issuing certificates', diff --git a/ui/app/models/pki/issuer.js b/ui/app/models/pki/issuer.js index dc7ebf46ecdd..6e51d469d5fc 100644 --- a/ui/app/models/pki/issuer.js +++ b/ui/app/models/pki/issuer.js @@ -27,7 +27,10 @@ const displayFields = [ @withFormFields(inputFields, displayFields) export default class PkiIssuerModel extends Model { @service secretMountPath; - + // TODO use openAPI after removing route extension (see pki/roles route for example) + get useOpenAPI() { + return false; + } get backend() { return this.secretMountPath.currentPath; } diff --git a/ui/app/models/pki/role.js b/ui/app/models/pki/role.js index 43165938decc..25704a871900 100644 --- a/ui/app/models/pki/role.js +++ b/ui/app/models/pki/role.js @@ -18,6 +18,14 @@ const validations = { export default class PkiRoleModel extends Model { @service version; // noStoreMetadata is enterprise-only, so we need this available + get useOpenAPI() { + // must be a getter so it can be accessed in path-help.js + return true; + } + getHelpUrl(backend) { + return `/v1/${backend}/roles/example?help=1`; + } + @attr('string', { readOnly: true }) backend; get formFieldGroups() { diff --git a/ui/app/models/pki/sign-intermediate.js b/ui/app/models/pki/sign-intermediate.js index 2dfbb7bf6c9a..53c5b69b1534 100644 --- a/ui/app/models/pki/sign-intermediate.js +++ b/ui/app/models/pki/sign-intermediate.js @@ -25,6 +25,10 @@ const validations = { 'maxPathLength', ]) export default class PkiSignIntermediateModel extends PkiCertificateBaseModel { + getHelpUrl(backend) { + return `/v1/${backend}/issuer/example/sign-intermediate?help=1`; + } + @attr issuerRef; @attr('string', { diff --git a/ui/app/models/pki/tidy.js b/ui/app/models/pki/tidy.js index 7b40ad1c7f58..9efb2e7d852e 100644 --- a/ui/app/models/pki/tidy.js +++ b/ui/app/models/pki/tidy.js @@ -117,11 +117,6 @@ export default class PkiTidyModel extends Model { }) tidyCrossClusterRevokedCerts; // enterprise only - @attr('boolean', { - label: 'Tidy CMPv2 nonce store', - }) - tidyCmpv2NonceStore; // enterprise only - @attr('boolean', { subText: 'Automatically remove expired issuers after the issuer safety buffer duration has elapsed.', }) @@ -150,6 +145,14 @@ export default class PkiTidyModel extends Model { }) tidyRevokedCerts; + get useOpenAPI() { + return true; + } + + getHelpUrl(backend) { + return `/v1/${backend}/config/auto-tidy?help=1`; + } + get allGroups() { const groups = [{ autoTidy: ['enabled', ...this.autoTidyConfigFields] }, ...this.sharedFields]; return this._expandGroups(groups); @@ -186,7 +189,6 @@ export default class PkiTidyModel extends Model { 'Cross-cluster operations': [ 'tidyRevocationQueue', 'tidyCrossClusterRevokedCerts', - 'tidyCmpv2NonceStore', 'revocationQueueSafetyBuffer', ], }); diff --git a/ui/app/models/role-ssh.js b/ui/app/models/role-ssh.js index 1c9ef8accbff..f3b3c18da6a5 100644 --- a/ui/app/models/role-ssh.js +++ b/ui/app/models/role-ssh.js @@ -48,6 +48,10 @@ const CA_FIELDS = [ ]; export default Model.extend({ + useOpenAPI: true, + getHelpUrl: function (backend) { + return `/v1/${backend}/roles/example?help=1`; + }, zeroAddress: attr('boolean', { readOnly: true, }), diff --git a/ui/app/models/secret-engine.js b/ui/app/models/secret-engine.js index 86d497281e57..555918e97ea5 100644 --- a/ui/app/models/secret-engine.js +++ b/ui/app/models/secret-engine.js @@ -10,7 +10,6 @@ import { withModelValidations } from 'vault/decorators/model-validations'; import { withExpandedAttributes } from 'vault/decorators/model-expanded-attributes'; import { supportedSecretBackends } from 'vault/helpers/supported-secret-backends'; import { isAddonEngine, allEngines } from 'vault/helpers/mountable-secret-engines'; -import { WHITESPACE_WARNING } from 'vault/utils/model-helpers/validators'; const LINKED_BACKENDS = supportedSecretBackends(); @@ -23,7 +22,8 @@ const validations = { { type: 'presence', message: "Path can't be blank." }, { type: 'containsWhiteSpace', - message: WHITESPACE_WARNING('path'), + message: + "Path contains whitespace. If this is desired, you'll need to encode it with %20 in API requests.", level: 'warn', }, ], @@ -68,6 +68,14 @@ export default class SecretEngineModel extends Model { }) version; + // SSH specific attributes + @attr('string') privateKey; + @attr('string') publicKey; + @attr('boolean', { + defaultValue: true, + }) + generateSigningKey; + // AWS specific attributes @attr('string') lease; @attr('string') leaseMax; @@ -179,10 +187,6 @@ export default class SecretEngineModel extends Model { if (type === 'kv' && parseInt(this.version, 10) === 2) { fields.push('casRequired', 'deleteVersionAfter', 'maxVersions'); } - // WIF secret engines - if (type === 'aws') { - fields.push('config.identityTokenKey'); - } return fields; } @@ -232,17 +236,6 @@ export default class SecretEngineModel extends Model { // no ttl options for keymgmt optionFields = [...CORE_OPTIONS, 'config.allowedManagedKeys', ...STANDARD_CONFIG]; break; - case 'aws': - defaultFields = ['path']; - optionFields = [ - ...CORE_OPTIONS, - 'config.defaultLeaseTtl', - 'config.maxLeaseTtl', - 'config.identityTokenKey', - 'config.allowedManagedKeys', - ...STANDARD_CONFIG, - ]; - break; default: defaultFields = ['path']; optionFields = [ @@ -264,6 +257,24 @@ export default class SecretEngineModel extends Model { } /* ACTIONS */ + saveCA(options) { + if (this.type !== 'ssh') { + return; + } + if (options.isDelete) { + this.privateKey = null; + this.publicKey = null; + this.generateSigningKey = false; + } + return this.save({ + adapterOptions: { + options: options, + apiPath: 'config/ca', + attrsToSend: ['privateKey', 'publicKey', 'generateSigningKey'], + }, + }); + } + saveZeroAddressConfig() { return this.save({ adapterOptions: { diff --git a/ui/app/models/ssh-otp-credential.js b/ui/app/models/ssh-otp-credential.js index a0576e8acfdf..13b715589d81 100644 --- a/ui/app/models/ssh-otp-credential.js +++ b/ui/app/models/ssh-otp-credential.js @@ -3,25 +3,27 @@ * SPDX-License-Identifier: BUSL-1.1 */ +import { reads } from '@ember/object/computed'; import Model, { attr } from '@ember-data/model'; -import { withExpandedAttributes } from 'vault/decorators/model-expanded-attributes'; +import { computed } from '@ember/object'; +import { expandAttributeMeta } from 'vault/utils/field-to-attrs'; +const CREATE_FIELDS = ['username', 'ip']; -@withExpandedAttributes() -export default class SshOtpCredential extends Model { - @attr('object', { +const DISPLAY_FIELDS = ['username', 'ip', 'key', 'keyType', 'port']; +export default Model.extend({ + role: attr('object', { readOnly: true, - }) - role; - @attr('string', { + }), + ip: attr('string', { label: 'IP Address', - }) - ip; - @attr('string') username; - @attr('string', { masked: true }) key; - @attr('string') keyType; - @attr('number') port; - - get toCreds() { - return this.key; - } -} + }), + username: attr('string'), + key: attr('string'), + keyType: attr('string'), + port: attr('number'), + attrs: computed('key', function () { + const keys = this.key ? DISPLAY_FIELDS.slice(0) : CREATE_FIELDS.slice(0); + return expandAttributeMeta(this, keys); + }), + toCreds: reads('key'), +}); diff --git a/ui/app/models/ssh/ca-config.js b/ui/app/models/ssh/ca-config.js deleted file mode 100644 index 382ed730345b..000000000000 --- a/ui/app/models/ssh/ca-config.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Model, { attr } from '@ember-data/model'; -import { expandAttributeMeta } from 'vault/utils/field-to-attrs'; -import { withModelValidations } from 'vault/decorators/model-validations'; - -const validations = { - generateSigningKey: [ - { - validator(model) { - const { publicKey, privateKey, generateSigningKey } = model; - // if generateSigningKey is false, both public and private keys are required - if (!generateSigningKey && (!publicKey || !privateKey)) { - return false; - } - return true; - }, - message: 'Provide a Public and Private key or set "Generate Signing Key" to true.', - }, - ], - publicKey: [ - { - validator(model) { - const { publicKey, privateKey } = model; - // regardless of generateSigningKey, if one key is set they both need to be set. - return publicKey || privateKey ? publicKey && privateKey : true; - }, - message: 'You must provide a Public and Private keys or leave both unset.', - }, - ], -}; -// there are more options available on the API, but the UI does not support them yet. -@withModelValidations(validations) -export default class SshCaConfig extends Model { - @attr('string') backend; // dynamic path of secret -- set on response from value passed to queryRecord - @attr('string', { sensitive: true }) privateKey; // obfuscated, never returned by API - @attr('string') publicKey; - @attr('boolean', { defaultValue: true }) - generateSigningKey; - - // do not return private key for configuration.index view - get attrs() { - const keys = ['publicKey', 'generateSigningKey']; - return expandAttributeMeta(this, keys); - } - // return private key for edit/create view - get formFields() { - const keys = ['privateKey', 'publicKey', 'generateSigningKey']; - return expandAttributeMeta(this, keys); - } -} diff --git a/ui/app/models/sync/destinations/aws-sm.js b/ui/app/models/sync/destinations/aws-sm.js index 2cb37a79a5dd..4b38875a2616 100644 --- a/ui/app/models/sync/destinations/aws-sm.js +++ b/ui/app/models/sync/destinations/aws-sm.js @@ -7,7 +7,6 @@ import SyncDestinationModel from '../destination'; import { attr } from '@ember-data/model'; import { withFormFields } from 'vault/decorators/model-form-fields'; -// displayFields are used on the destination details view const displayFields = [ // connection details 'name', @@ -21,13 +20,11 @@ const displayFields = [ 'secretNameTemplate', 'customTags', ]; -// formFieldGroups are used on the create-edit destination view const formFieldGroups = [ { - default: ['name', 'region', 'roleArn', 'externalId'], + default: ['name', 'region', 'roleArn', 'externalId', 'granularity', 'secretNameTemplate', 'customTags'], }, { Credentials: ['accessKeyId', 'secretAccessKey'] }, - { 'Advanced configuration': ['granularity', 'secretNameTemplate', 'customTags'] }, ]; @withFormFields(displayFields, formFieldGroups) export default class SyncDestinationsAwsSecretsManagerModel extends SyncDestinationModel { @@ -35,8 +32,6 @@ export default class SyncDestinationsAwsSecretsManagerModel extends SyncDestinat label: 'Access key ID', subText: 'Access key ID to authenticate against the secrets manager. If empty, Vault will use the AWS_ACCESS_KEY_ID environment variable if configured.', - sensitive: true, - noCopy: true, }) accessKeyId; // obfuscated, never returned by API @@ -44,8 +39,6 @@ export default class SyncDestinationsAwsSecretsManagerModel extends SyncDestinat label: 'Secret access key', subText: 'Secret access key to authenticate against the secrets manager. If empty, Vault will use the AWS_SECRET_ACCESS_KEY environment variable if configured.', - sensitive: true, - noCopy: true, }) secretAccessKey; // obfuscated, never returned by API diff --git a/ui/app/models/sync/destinations/azure-kv.js b/ui/app/models/sync/destinations/azure-kv.js index 0fcf98e447a6..42de9a173006 100644 --- a/ui/app/models/sync/destinations/azure-kv.js +++ b/ui/app/models/sync/destinations/azure-kv.js @@ -6,7 +6,7 @@ import SyncDestinationModel from '../destination'; import { attr } from '@ember-data/model'; import { withFormFields } from 'vault/decorators/model-form-fields'; -// displayFields are used on the destination details view + const displayFields = [ // connection details 'name', @@ -20,13 +20,20 @@ const displayFields = [ 'secretNameTemplate', 'customTags', ]; -// formFieldGroups are used on the create-edit destination view const formFieldGroups = [ { - default: ['name', 'keyVaultUri', 'tenantId', 'cloud', 'clientId'], + default: [ + 'name', + 'keyVaultUri', + 'tenantId', + 'cloud', + 'clientId', + 'granularity', + 'secretNameTemplate', + 'customTags', + ], }, { Credentials: ['clientSecret'] }, - { 'Advanced configuration': ['granularity', 'secretNameTemplate', 'customTags'] }, ]; @withFormFields(displayFields, formFieldGroups) export default class SyncDestinationsAzureKeyVaultModel extends SyncDestinationModel { @@ -48,8 +55,6 @@ export default class SyncDestinationsAzureKeyVaultModel extends SyncDestinationM @attr('string', { subText: 'Client secret of an Azure app registration. If empty, Vault will use the AZURE_CLIENT_SECRET environment variable if configured.', - sensitive: true, - noCopy: true, }) clientSecret; // obfuscated, never returned by API diff --git a/ui/app/models/sync/destinations/gcp-sm.js b/ui/app/models/sync/destinations/gcp-sm.js index 784dd24857e2..03f70ac62254 100644 --- a/ui/app/models/sync/destinations/gcp-sm.js +++ b/ui/app/models/sync/destinations/gcp-sm.js @@ -6,7 +6,7 @@ import SyncDestinationModel from '../destination'; import { attr } from '@ember-data/model'; import { withFormFields } from 'vault/decorators/model-form-fields'; -// displayFields are used on the destination details view + const displayFields = [ // connection details 'name', @@ -17,11 +17,9 @@ const displayFields = [ 'secretNameTemplate', 'customTags', ]; -// formFieldGroups are used on the create-edit destination view const formFieldGroups = [ - { default: ['name', 'projectId'] }, + { default: ['name', 'projectId', 'granularity', 'secretNameTemplate', 'customTags'] }, { Credentials: ['credentials'] }, - { 'Advanced configuration': ['granularity', 'secretNameTemplate', 'customTags'] }, ]; @withFormFields(displayFields, formFieldGroups) export default class SyncDestinationsGoogleCloudSecretManagerModel extends SyncDestinationModel { @@ -39,7 +37,7 @@ export default class SyncDestinationsGoogleCloudSecretManagerModel extends SyncD editType: 'file', docLink: '/vault/docs/secrets/gcp#authentication', }) - credentials; // obfuscated, never returned by API. Masking handled by EnableInput component + credentials; // obfuscated, never returned by API @attr('object', { subText: diff --git a/ui/app/models/sync/destinations/gh.js b/ui/app/models/sync/destinations/gh.js index 5815b8e9b097..a8db62a9a804 100644 --- a/ui/app/models/sync/destinations/gh.js +++ b/ui/app/models/sync/destinations/gh.js @@ -6,7 +6,7 @@ import SyncDestinationModel from '../destination'; import { attr } from '@ember-data/model'; import { withFormFields } from 'vault/decorators/model-form-fields'; -// displayFields are used on the destination details view + const displayFields = [ // connection details 'name', @@ -17,12 +17,9 @@ const displayFields = [ 'granularity', 'secretNameTemplate', ]; - -// formFieldGroups are used on the create-edit destination view const formFieldGroups = [ - { default: ['name', 'repositoryOwner', 'repositoryName'] }, + { default: ['name', 'repositoryOwner', 'repositoryName', 'granularity', 'secretNameTemplate'] }, { Credentials: ['accessToken'] }, - { 'Advanced configuration': ['granularity', 'secretNameTemplate'] }, ]; @withFormFields(displayFields, formFieldGroups) @@ -30,8 +27,6 @@ export default class SyncDestinationsGithubModel extends SyncDestinationModel { @attr('string', { subText: 'Personal access token to authenticate to the GitHub repository. If empty, Vault will use the GITHUB_ACCESS_TOKEN environment variable if configured.', - sensitive: true, - noCopy: true, }) accessToken; // obfuscated, never returned by API diff --git a/ui/app/models/sync/destinations/vercel-project.js b/ui/app/models/sync/destinations/vercel-project.js index 8599ff202d4e..aaa88f671c63 100644 --- a/ui/app/models/sync/destinations/vercel-project.js +++ b/ui/app/models/sync/destinations/vercel-project.js @@ -21,7 +21,7 @@ const validations = { // getter/setter for the deploymentEnvironments model attribute deploymentEnvironmentsArray: [{ type: 'presence', message: 'At least one environment is required.' }], }; -// displayFields are used on the destination details view + const displayFields = [ // connection details 'name', @@ -33,19 +33,15 @@ const displayFields = [ 'granularity', 'secretNameTemplate', ]; -// formFieldGroups are used on the create-edit destination view const formFieldGroups = [ - { default: ['name', 'projectId', 'teamId', 'deploymentEnvironments'] }, + { default: ['name', 'projectId', 'teamId', 'deploymentEnvironments', 'granularity', 'secretNameTemplate'] }, { Credentials: ['accessToken'] }, - { 'Advanced configuration': ['granularity', 'secretNameTemplate'] }, ]; @withModelValidations(validations) @withFormFields(displayFields, formFieldGroups) export default class SyncDestinationsVercelProjectModel extends SyncDestinationModel { @attr('string', { subText: 'Vercel API access token with the permissions to manage environment variables.', - sensitive: true, - noCopy: true, }) accessToken; // obfuscated, never returned by API diff --git a/ui/app/router.js b/ui/app/router.js index 0c597e1192e7..879f17542cc5 100644 --- a/ui/app/router.js +++ b/ui/app/router.js @@ -5,7 +5,7 @@ import EmberRouter from '@ember/routing/router'; import config from 'vault/config/environment'; -import { addDocfyRoutes } from '@docfy/ember'; + export default class Router extends EmberRouter { location = config.locationType; rootURL = config.rootURL; @@ -50,6 +50,10 @@ Router.map(function () { }); }); this.route('mount-secret-backend'); + this.route('configure-secret-backend', { path: '/secrets/configure/:backend' }, function () { + this.route('index', { path: '/' }); + this.route('section', { path: '/:section_name' }); + }); }); this.route('unseal'); this.route('tools', function () { @@ -168,10 +172,7 @@ Router.map(function () { this.mount('ldap'); this.mount('pki'); this.route('index', { path: '/' }); - this.route('configuration', function () { - // only CONFIGURABLE_SECRET_ENGINES can be configured and access the edit route - this.route('edit'); - }); + this.route('configuration'); // because globs / params can't be empty, // we have to special-case ids of '' with their own routes this.route('list-root', { path: '/list/' }); @@ -216,7 +217,4 @@ Router.map(function () { }); this.route('not-found', { path: '/*path' }); }); - if (config.environment !== 'production') { - addDocfyRoutes(this); - } }); diff --git a/ui/app/routes/application.js b/ui/app/routes/application.js index 581edcc94232..4916222c4685 100644 --- a/ui/app/routes/application.js +++ b/ui/app/routes/application.js @@ -6,67 +6,66 @@ import { service } from '@ember/service'; import Route from '@ember/routing/route'; import ControlGroupError from 'vault/lib/control-group-error'; -import { action } from '@ember/object'; -export default class ApplicationRoute extends Route { - @service controlGroup; - @service('router') routing; - @service('namespace') namespaceService; - @service('flags') flagsService; +export default Route.extend({ + controlGroup: service(), + routing: service('router'), + namespaceService: service('namespace'), + flagsService: service('flags'), - @action - willTransition() { - window.scrollTo(0, 0); - } - @action - error(error, transition) { - const controlGroup = this.controlGroup; - if (error instanceof ControlGroupError) { - return controlGroup.handleError(error); - } - if (error.path === '/v1/sys/wrapping/unwrap') { - controlGroup.unmarkTokenForUnwrap(); - } + actions: { + willTransition() { + window.scrollTo(0, 0); + }, + error(error, transition) { + const controlGroup = this.controlGroup; + if (error instanceof ControlGroupError) { + return controlGroup.handleError(error); + } + if (error.path === '/v1/sys/wrapping/unwrap') { + controlGroup.unmarkTokenForUnwrap(); + } - const router = this.routing; - //FIXME transition.intent likely needs to be replaced - let errorURL = transition.intent.url; - const { name, contexts, queryParams } = transition.intent; + const router = this.routing; + //FIXME transition.intent likely needs to be replaced + let errorURL = transition.intent.url; + const { name, contexts, queryParams } = transition.intent; - // If the transition is internal to Ember, we need to generate the URL - // from the route parameters ourselves - if (!errorURL) { - try { - errorURL = router.urlFor(name, ...(contexts || []), { queryParams }); - } catch (e) { - // If this fails, something weird is happening with URL transitions - errorURL = null; + // If the transition is internal to Ember, we need to generate the URL + // from the route parameters ourselves + if (!errorURL) { + try { + errorURL = router.urlFor(name, ...(contexts || []), { queryParams }); + } catch (e) { + // If this fails, something weird is happening with URL transitions + errorURL = null; + } + } + // because we're using rootURL, we need to trim this from the front to get + // the ember-routeable url + if (errorURL) { + errorURL = errorURL.replace('/ui', ''); } - } - // because we're using rootURL, we need to trim this from the front to get - // the ember-routeable url - if (errorURL) { - errorURL = errorURL.replace('/ui', ''); - } - error.errorURL = errorURL; + error.errorURL = errorURL; - // if we have queryParams, update the namespace so that the observer can fire on the controller - if (queryParams) { - /* eslint-disable-next-line ember/no-controller-access-in-routes */ - this.controllerFor('vault.cluster').set('namespaceQueryParam', queryParams.namespace || ''); - } + // if we have queryParams, update the namespace so that the observer can fire on the controller + if (queryParams) { + /* eslint-disable-next-line ember/no-controller-access-in-routes */ + this.controllerFor('vault.cluster').set('namespaceQueryParam', queryParams.namespace || ''); + } - // Assuming we have a URL, push it into browser history and update the - // location bar for the user - if (errorURL) { - router.location.setURL(errorURL); - } + // Assuming we have a URL, push it into browser history and update the + // location bar for the user + if (errorURL) { + router.location.setURL(errorURL); + } - return true; - } + return true; + }, + }, beforeModel() { return this.flagsService.fetchFeatureFlags(); - } -} + }, +}); diff --git a/ui/app/routes/vault/cluster/clients/counts.ts b/ui/app/routes/vault/cluster/clients/counts.ts index 50644ed8dc8e..3c87c2922e11 100644 --- a/ui/app/routes/vault/cluster/clients/counts.ts +++ b/ui/app/routes/vault/cluster/clients/counts.ts @@ -5,17 +5,18 @@ import Route from '@ember/routing/route'; import { service } from '@ember/service'; -import { fromUnixTime } from 'date-fns'; +import timestamp from 'core/utils/timestamp'; +import { getUnixTime } from 'date-fns'; -import type AdapterError from '@ember-data/adapter'; import type FlagsService from 'vault/services/flags'; -import type NamespaceService from 'vault/services/namespace'; import type StoreService from 'vault/services/store'; import type VersionService from 'vault/services/version'; import type { ModelFrom } from 'vault/vault/route'; import type ClientsRoute from '../clients'; +import type ClientsActivityModel from 'vault/models/clients/activity'; +import type ClientsConfigModel from 'vault/models/clients/config'; import type ClientsCountsController from 'vault/controllers/vault/cluster/clients/counts'; -import type ClientsActivityModel from 'vault/vault/models/clients/activity'; +import { setStartTimeQuery } from 'core/utils/client-count-utils'; export interface ClientsCountsRouteParams { start_time?: string | number | undefined; @@ -24,24 +25,15 @@ export interface ClientsCountsRouteParams { mountPath?: string | undefined; } -interface ActivityAdapterQuery { - start_time: { timestamp: number } | undefined; - end_time: { timestamp: number } | undefined; - namespace?: string; -} - -export type ClientsCountsRouteModel = ModelFrom; - export default class ClientsCountsRoute extends Route { @service declare readonly flags: FlagsService; - @service declare readonly namespace: NamespaceService; @service declare readonly store: StoreService; @service declare readonly version: VersionService; queryParams = { start_time: { refreshModel: true, replace: true }, end_time: { refreshModel: true, replace: true }, - ns: { refreshModel: true, replace: true }, + ns: { refreshModel: false, replace: true }, mountPath: { refreshModel: false, replace: true }, }; @@ -49,79 +41,38 @@ export default class ClientsCountsRoute extends Route { return this.flags.fetchActivatedFlags(); } - /** - * This method returns the query param timestamp if it exists. If not, it returns the activity timestamp value instead. - */ - paramOrResponseTimestamp( - qpMillisString: string | number | undefined, - activityTimeStamp: string | undefined - ) { - let timestamp: string | undefined; - const millis = Number(qpMillisString); - if (!isNaN(millis)) { - timestamp = fromUnixTime(millis).toISOString(); - } - // fallback to activity timestamp only if there was no query param - if (!timestamp && activityTimeStamp) { - timestamp = activityTimeStamp; - } - return timestamp; - } - - async getActivity(params: ClientsCountsRouteParams): Promise<{ - activity: ClientsActivityModel; - activityError: AdapterError; - }> { + async getActivity(start_time: number | null, end_time: number) { let activity, activityError; - // if CE without start time we want to skip the activity call - // so that the user is forced to choose a date range - if (this.version.isEnterprise || params.start_time) { - const query: ActivityAdapterQuery = { - // start and end params are optional -- if not provided, will fallback to API default - start_time: this.formatTimeQuery(params?.start_time), - end_time: this.formatTimeQuery(params?.end_time), - }; - if (params?.ns) { - // only set explicit namespace if it's a query param - query.namespace = params.ns; - } + // if there is no start_time we want the user to manually choose a date + // in that case bypass the query so that the user isn't stuck viewing the activity error + if (start_time) { try { - activity = await this.store.queryRecord('clients/activity', query); + activity = await this.store.queryRecord('clients/activity', { + start_time: { timestamp: start_time }, + end_time: { timestamp: end_time }, + }); } catch (error) { activityError = error; } } - return { - activity, - activityError, - }; - } - - // Takes the string URL param and formats it as the adapter expects it, - // if it exists and is valid - formatTimeQuery(param: string | number | undefined) { - let timeParam: { timestamp: number } | undefined; - const millis = Number(param); - if (!isNaN(millis)) { - timeParam = { timestamp: millis }; - } - return timeParam; + return { activity, activityError }; } async model(params: ClientsCountsRouteParams) { const { config, versionHistory } = this.modelFor('vault.cluster.clients') as ModelFrom; - const { activity, activityError } = await this.getActivity(params); + // only enterprise versions will have a relevant billing start date, if null users must select initial start time + const startTime = setStartTimeQuery(this.version.isEnterprise, config); + + const startTimestamp = Number(params.start_time) || startTime; + const endTimestamp = Number(params.end_time) || getUnixTime(timestamp.now()); + const { activity, activityError } = await this.getActivity(startTimestamp, endTimestamp); + return { activity, activityError, config, - // activity.startTime corresponds to first month with data, but we want first month returned or requested - // unless no months present, then we can fallback to response's start time - startTimestamp: this.paramOrResponseTimestamp( - params?.start_time, - activity?.byMonth[0]?.timestamp || activity?.startTime - ), - endTimestamp: this.paramOrResponseTimestamp(params?.end_time, activity?.endTime), + endTimestamp, + startTimestamp, versionHistory, }; } diff --git a/ui/app/routes/vault/cluster/secrets/backend/actions.js b/ui/app/routes/vault/cluster/secrets/backend/actions.js index 2171a8e3d6cf..c1b413465096 100644 --- a/ui/app/routes/vault/cluster/secrets/backend/actions.js +++ b/ui/app/routes/vault/cluster/secrets/backend/actions.js @@ -47,7 +47,7 @@ export default EditBase.extend({ models: [model.secret.backend, model.secret.id], }, { - label: 'Actions', + label: 'actions', }, ]); }, diff --git a/ui/app/routes/vault/cluster/secrets/backend/configuration.js b/ui/app/routes/vault/cluster/secrets/backend/configuration.js new file mode 100644 index 000000000000..faaf3e71e63f --- /dev/null +++ b/ui/app/routes/vault/cluster/secrets/backend/configuration.js @@ -0,0 +1,34 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { service } from '@ember/service'; +import Route from '@ember/routing/route'; + +export default Route.extend({ + store: service(), + async model() { + const backend = this.modelFor('vault.cluster.secrets.backend'); + if (backend.isV2KV) { + const canRead = await this.store + .findRecord('capabilities', `${backend.id}/config`) + .then((response) => response.canRead); + // only set these config params if they can read the config endpoint. + if (canRead) { + // design wants specific default to show that can't be set in the model + backend.set('casRequired', backend.casRequired ? backend.casRequired : 'False'); + backend.set( + 'deleteVersionAfter', + backend.deleteVersionAfter !== '0s' ? backend.deleteVersionAfter : 'Never delete' + ); + } else { + // remove the default values from the model if they don't have read access otherwise it will display the defaults even if they've been set (because they error on returning config data) + backend.set('casRequired', null); + backend.set('deleteVersionAfter', null); + backend.set('maxVersions', null); + } + } + return backend; + }, +}); diff --git a/ui/app/routes/vault/cluster/secrets/backend/configuration/edit.ts b/ui/app/routes/vault/cluster/secrets/backend/configuration/edit.ts deleted file mode 100644 index 6160051b31a7..000000000000 --- a/ui/app/routes/vault/cluster/secrets/backend/configuration/edit.ts +++ /dev/null @@ -1,90 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import AdapterError from '@ember-data/adapter/error'; -import { set } from '@ember/object'; -import Route from '@ember/routing/route'; -import { service } from '@ember/service'; -import { CONFIGURABLE_SECRET_ENGINES } from 'vault/helpers/mountable-secret-engines'; -import errorMessage from 'vault/utils/error-message'; -import { action } from '@ember/object'; - -import type Store from '@ember-data/store'; -import type SecretEngineModel from 'vault/models/secret-engine'; -import type VersionService from 'vault/services/version'; - -// This route file is reused for all configurable secret engines. -// It generates config models based on the engine type. -// Saving and updating of those models are done within the engine specific components. - -const CONFIG_ADAPTERS_PATHS: Record = { - aws: ['aws/lease-config', 'aws/root-config'], - ssh: ['ssh/ca-config'], -}; - -export default class SecretsBackendConfigurationEdit extends Route { - @service declare readonly store: Store; - @service declare readonly version: VersionService; - - async model() { - const { backend } = this.paramsFor('vault.cluster.secrets.backend'); - const secretEngineRecord = this.modelFor('vault.cluster.secrets.backend') as SecretEngineModel; - const type = secretEngineRecord.type; - - // if the engine type is not configurable, return a 404. - if (!secretEngineRecord || !CONFIGURABLE_SECRET_ENGINES.includes(type)) { - const error = new AdapterError(); - set(error, 'httpStatus', 404); - throw error; - } - // generate the model based on the engine type. - // and pre-set model with type and backend e.g. {type: ssh, id: ssh-123} - const model: Record = { type, id: backend }; - for (const adapterPath of CONFIG_ADAPTERS_PATHS[type] as string[]) { - // convert the adapterPath with a name that can be passed to the components - // ex: adapterPath = ssh/ca-config, convert to: ssh-ca-config so that you can pass to component @model={{this.model.ssh-ca-config}} - const standardizedKey = adapterPath.replace(/\//g, '-'); - try { - model[standardizedKey] = await this.store.queryRecord(adapterPath, { - backend, - type, - }); - } catch (e: AdapterError) { - // For most models if the adapter returns a 404, we want to create a new record. - // The ssh secret engine however returns a 400 if the CA is not configured. - // For ssh's 400 error, we want to create the CA config model. - if ( - e.httpStatus === 404 || - (type === 'ssh' && e.httpStatus === 400 && errorMessage(e) === `keys haven't been configured yet`) - ) { - model[standardizedKey] = await this.store.createRecord(adapterPath, { - backend, - type, - }); - } else { - throw e; - } - } - } - // if the type is AWS and it's enterprise, we also fetch the issuer - // from a global endpoint which has no associated model/adapter - if (type === 'aws' && this.version.isEnterprise) { - try { - const response = await this.store.queryRecord('identity/oidc/config', {}); - model['identity-oidc-config'] = response; - } catch (e) { - // return a property called queryIssuerError and let the component handle it. - model['identity-oidc-config'] = { queryIssuerError: true }; - } - } - return model; - } - - @action - willTransition() { - // catch the transition and refresh model so the route shows the most recent model data. - this.refresh(); - } -} diff --git a/ui/app/routes/vault/cluster/secrets/backend/configuration/index.js b/ui/app/routes/vault/cluster/secrets/backend/configuration/index.js deleted file mode 100644 index 747892a5b096..000000000000 --- a/ui/app/routes/vault/cluster/secrets/backend/configuration/index.js +++ /dev/null @@ -1,136 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import { service } from '@ember/service'; -import Route from '@ember/routing/route'; -import { CONFIGURABLE_SECRET_ENGINES } from 'vault/helpers/mountable-secret-engines'; -import { allEngines } from 'vault/helpers/mountable-secret-engines'; -import { reject } from 'rsvp'; - -/** - * This route is responsible for fetching all configuration model(s). - * This includes the mount-configuration model attached to the secret-engine model via a belongsTo relationship. - * As well as any additional configuration models if the engine is a configurable engine. - */ - -export default class SecretsBackendConfigurationRoute extends Route { - @service store; - @service version; - - async model() { - const secretEngineModel = this.modelFor('vault.cluster.secrets.backend'); - if (secretEngineModel.isV2KV) { - const canRead = await this.store - .findRecord('capabilities', `${secretEngineModel.id}/config`) - .then((response) => response.canRead); - // only set these config params if they can read the config endpoint. - if (canRead) { - // design wants specific default to show that can't be set in the model - secretEngineModel.casRequired = secretEngineModel.casRequired - ? secretEngineModel.casRequired - : 'False'; - secretEngineModel.deleteVersionAfter = secretEngineModel.deleteVersionAfter - ? secretEngineModel.deleteVersionAfter - : 'Never delete'; - } else { - // remove the default values from the model if they don't have read access otherwise it will display the defaults even if they've been set (because they error on returning config data) - secretEngineModel.set('casRequired', null); - secretEngineModel.set('deleteVersionAfter', null); - secretEngineModel.set('maxVersions', null); - } - } - // If the engine is configurable fetch the config model(s) for the engine and return it alongside the model - if (CONFIGURABLE_SECRET_ENGINES.includes(secretEngineModel.type)) { - let configModels = await this.fetchConfig(secretEngineModel.type, secretEngineModel.id); - configModels = this.standardizeConfigModels(configModels); - - return { - secretEngineModel, - configModels, - }; - } - return { secretEngineModel }; - } - - standardizeConfigModels(configModels) { - // standardize the configModels to an array so that the component can handle it correctly - Array.isArray(configModels) ? configModels : (configModels = [configModels]); - // make sure no items in the array are null or undefined - return configModels.filter((configModel) => { - return !!configModel; - }); - } - - fetchConfig(type, id) { - switch (type) { - case 'aws': - return this.fetchAwsConfigs(id); - case 'ssh': - return this.fetchSshCaConfig(id); - default: - return reject({ httpStatus: 404, message: 'not found', path: id }); - } - } - - async fetchAwsConfigs(id) { - // AWS has two configuration endpoints root and lease, as well as a separate endpoint for the issuer. - // return an array of these responses. - const configArray = []; - const configRoot = await this.fetchAwsConfig(id, 'aws/root-config'); - const configLease = await this.fetchAwsConfig(id, 'aws/lease-config'); - let issuer = null; - if (this.version.isEnterprise && configRoot) { - // Issuer is an enterprise only related feature - // Issuer is also a global endpoint that doesn't mean anything in the AWS secret details context if WIF related fields on the rootConfig have not been set. - const WIF_FIELDS = ['roleArn', 'identityTokenAudience', 'identityTokenTtl']; - WIF_FIELDS.some((field) => configRoot[field]) ? (issuer = await this.fetchIssuer()) : null; - } - configArray.push(configRoot, configLease, issuer); - return configArray; - } - - async fetchAwsConfig(id, modelPath) { - try { - return await this.store.queryRecord(modelPath, { backend: id }); - } catch (e) { - if (e.httpStatus === 404) { - // a 404 error is thrown when the lease config hasn't been set yet. - return; - } - throw e; - } - } - - async fetchIssuer() { - try { - return await this.store.queryRecord('identity/oidc/config', {}); - } catch (e) { - // silently fail if the endpoint is not available or the user doesn't have permission to access it. - return; - } - } - - async fetchSshCaConfig(id) { - try { - return await this.store.queryRecord('ssh/ca-config', { backend: id }); - } catch (e) { - if (e.httpStatus === 400 && e.errors[0] === `keys haven't been configured yet`) { - // When first mounting a SSH engine it throws a 400 error with this specific message. - // We want to catch this situation and return nothing so that the component can handle it correctly. - return; - } - throw e; - } - } - - setupController(controller, resolvedModel) { - super.setupController(controller, resolvedModel); - controller.typeDisplay = allEngines().find( - (engine) => engine.type === resolvedModel.secretEngineModel.type - )?.displayName; - controller.isConfigurable = CONFIGURABLE_SECRET_ENGINES.includes(resolvedModel.secretEngineModel.type); - controller.modelId = resolvedModel.secretEngineModel.id; - } -} diff --git a/ui/app/routes/vault/cluster/secrets/backend/credentials.js b/ui/app/routes/vault/cluster/secrets/backend/credentials.js index 2ae4d76d28dd..8607d0c1b1b0 100644 --- a/ui/app/routes/vault/cluster/secrets/backend/credentials.js +++ b/ui/app/routes/vault/cluster/secrets/backend/credentials.js @@ -17,15 +17,12 @@ export default Route.extend({ store: service(), beforeModel() { - const { id: backendPath, type: backendType } = this.modelFor('vault.cluster.secrets.backend'); - // redirect if the backend type does not support credentials - if (!SUPPORTED_DYNAMIC_BACKENDS.includes(backendType)) { - return this.router.transitionTo('vault.cluster.secrets.backend.list-root', backendPath); - } - // hydrate model if backend type is ssh - if (backendType === 'ssh') { - this.pathHelp.hydrateModel('ssh-otp-credential', backendPath); + const { backend } = this.paramsFor('vault.cluster.secrets.backend'); + if (backend != 'ssh') { + return; } + const modelType = 'ssh-otp-credential'; + return this.pathHelp.getNewModel(modelType, backend); }, getDatabaseCredential(backend, secret, roleType = '') { @@ -54,34 +51,23 @@ export default Route.extend({ }); }, - async getAwsRole(backend, id) { - try { - const role = await this.store.queryRecord('role-aws', { backend, id }); - return role; - } catch (e) { - // swallow error, non-essential data - return; - } - }, - async model(params) { const role = params.secret; const { id: backendPath, type: backendType } = this.modelFor('vault.cluster.secrets.backend'); const roleType = params.roleType; - let dbCred, awsRole; + let dbCred; if (backendType === 'database') { dbCred = await this.getDatabaseCredential(backendPath, role, roleType); - } else if (backendType === 'aws') { - awsRole = await this.getAwsRole(backendPath, role); } - + if (!SUPPORTED_DYNAMIC_BACKENDS.includes(backendType)) { + return this.router.transitionTo('vault.cluster.secrets.backend.list-root', backendPath); + } return resolve({ backendPath, backendType, roleName: role, roleType, dbCred, - awsRoleType: awsRole?.credentialType, }); }, diff --git a/ui/app/routes/vault/cluster/secrets/backend/list.js b/ui/app/routes/vault/cluster/secrets/backend/list.js index f2ee9eb71b1d..fe744044c390 100644 --- a/ui/app/routes/vault/cluster/secrets/backend/list.js +++ b/ui/app/routes/vault/cluster/secrets/backend/list.js @@ -101,7 +101,7 @@ export default Route.extend({ return this.router.transitionTo('vault.cluster.secrets.backend.kv.list', backend); } const modelType = this.getModelType(backend, tab); - return this.pathHelp.hydrateModel(modelType, backend).then(() => { + return this.pathHelp.getNewModel(modelType, backend).then(() => { this.store.unloadAll('capabilities'); }); }, diff --git a/ui/app/routes/vault/cluster/secrets/backend/secret-edit.js b/ui/app/routes/vault/cluster/secrets/backend/secret-edit.js index 767dc10dfdbf..0373a25759c0 100644 --- a/ui/app/routes/vault/cluster/secrets/backend/secret-edit.js +++ b/ui/app/routes/vault/cluster/secrets/backend/secret-edit.js @@ -81,27 +81,17 @@ export default Route.extend({ const mode = this.routeName.split('.').pop(); // for kv v2, redirect users from the old url to the new engine url (1.15.0 +) if (secretEngine.type === 'kv' && secretEngine.version === 2) { - let route, params; - switch (true) { - case !secret: - // if no secret param redirect to the create route - route = 'vault.cluster.secrets.backend.kv.create'; - params = [secretEngine.id]; - break; - case this.routeName === 'vault.cluster.secrets.backend.show': - route = 'vault.cluster.secrets.backend.kv.secret.index'; - params = [secretEngine.id, secret]; - break; - case this.routeName === 'vault.cluster.secrets.backend.edit': - route = 'vault.cluster.secrets.backend.kv.secret.details.edit'; - params = [secretEngine.id, secret]; - break; - default: - route = 'vault.cluster.secrets.backend.kv.secret.index'; - params = [secretEngine.id, secret]; - break; + // if no secret param redirect to the create route + // if secret param they are either viewing or editing secret so navigate to the details route + if (!secret) { + this.router.transitionTo('vault.cluster.secrets.backend.kv.create', secretEngine.id); + } else { + this.router.transitionTo( + 'vault.cluster.secrets.backend.kv.secret.details', + secretEngine.id, + secret + ); } - this.router.transitionTo(route, ...params); return; } if (mode === 'edit' && keyIsFolder(secret)) { @@ -121,7 +111,7 @@ export default Route.extend({ if (modelType === 'secret') { return resolve(); } - return this.pathHelp.hydrateModel(modelType, backend); + return this.pathHelp.getNewModel(modelType, backend); }, modelType(backend, secret, options = {}) { diff --git a/ui/app/routes/vault/cluster/settings/auth/configure/section.js b/ui/app/routes/vault/cluster/settings/auth/configure/section.js index 0111f636ee1c..a17da81fb293 100644 --- a/ui/app/routes/vault/cluster/settings/auth/configure/section.js +++ b/ui/app/routes/vault/cluster/settings/auth/configure/section.js @@ -9,7 +9,6 @@ import { set } from '@ember/object'; import Route from '@ember/routing/route'; import RSVP from 'rsvp'; import UnloadModelRoute from 'vault/mixins/unload-model-route'; -import { getHelpUrlForModel } from 'vault/utils/openapi-helpers'; export default Route.extend(UnloadModelRoute, { modelPath: 'model.model', @@ -42,11 +41,6 @@ export default Route.extend(UnloadModelRoute, { const { method } = this.paramsFor('vault.cluster.settings.auth.configure'); const backend = this.modelFor('vault.cluster.settings.auth.configure'); const modelType = this.modelType(backend.type, section_name); - // If this method returns a string it means we expect to hydrate it with OpenAPI - if (getHelpUrlForModel(modelType)) { - return this.pathHelp.hydrateModel(modelType, method); - } - // if no helpUrl is defined, this is a fully generated model return this.pathHelp.getNewModel(modelType, method, backend.apiPath); }, diff --git a/ui/app/routes/vault/cluster/settings/auth/enable.ts b/ui/app/routes/vault/cluster/settings/auth/enable.js similarity index 65% rename from ui/app/routes/vault/cluster/settings/auth/enable.ts rename to ui/app/routes/vault/cluster/settings/auth/enable.js index c564e6b3e75c..808a908360b6 100644 --- a/ui/app/routes/vault/cluster/settings/auth/enable.ts +++ b/ui/app/routes/vault/cluster/settings/auth/enable.js @@ -6,13 +6,8 @@ import Route from '@ember/routing/route'; import { service } from '@ember/service'; -import type { ModelFrom } from 'vault/vault/route'; -import type Store from '@ember-data/store'; - -export type AuthEnableModel = ModelFrom; - export default class VaultClusterSettingsAuthEnableRoute extends Route { - @service declare readonly store: Store; + @service store; model() { const authMethod = this.store.createRecord('auth-method'); diff --git a/ui/app/routes/vault/cluster/settings/configure-secret-backend.js b/ui/app/routes/vault/cluster/settings/configure-secret-backend.js new file mode 100644 index 000000000000..10117b6c37c5 --- /dev/null +++ b/ui/app/routes/vault/cluster/settings/configure-secret-backend.js @@ -0,0 +1,70 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import AdapterError from '@ember-data/adapter/error'; +import { set } from '@ember/object'; +import Route from '@ember/routing/route'; +import { service } from '@ember/service'; +const CONFIGURABLE_BACKEND_TYPES = ['aws', 'ssh']; + +export default Route.extend({ + store: service(), + + model() { + const { backend } = this.paramsFor(this.routeName); + return this.store.query('secret-engine', { path: backend }).then((modelList) => { + const model = modelList && modelList[0]; + if (!model || !CONFIGURABLE_BACKEND_TYPES.includes(model.type)) { + const error = new AdapterError(); + set(error, 'httpStatus', 404); + throw error; + } + return this.store.findRecord('secret-engine', backend).then( + () => { + return model; + }, + () => { + return model; + } + ); + }); + }, + + afterModel(model) { + const type = model.type; + + if (type === 'aws') { + return this.store + .queryRecord('secret-engine', { + backend: model.id, + type, + }) + .then( + () => model, + () => model + ); + } + return model; + }, + + setupController(controller, model) { + if (model.publicKey) { + controller.set('configured', true); + } + return this._super(...arguments); + }, + + resetController(controller, isExiting) { + if (isExiting) { + controller.reset(); + } + }, + + actions: { + refreshRoute() { + this.refresh(); + }, + }, +}); diff --git a/ui/app/routes/vault/cluster/settings/mount-secret-backend.ts b/ui/app/routes/vault/cluster/settings/mount-secret-backend.js similarity index 64% rename from ui/app/routes/vault/cluster/settings/mount-secret-backend.ts rename to ui/app/routes/vault/cluster/settings/mount-secret-backend.js index a375136accb9..851a9078c60d 100644 --- a/ui/app/routes/vault/cluster/settings/mount-secret-backend.ts +++ b/ui/app/routes/vault/cluster/settings/mount-secret-backend.js @@ -6,13 +6,8 @@ import Route from '@ember/routing/route'; import { service } from '@ember/service'; -import type { ModelFrom } from 'vault/vault/route'; -import type Store from '@ember-data/store'; - -export type MountSecretBackendModel = ModelFrom; - export default class VaultClusterSettingsMountSecretBackendRoute extends Route { - @service declare readonly store: Store; + @service store; model() { const secretEngine = this.store.createRecord('secret-engine'); diff --git a/ui/app/serializers/aws/root-config.js b/ui/app/serializers/aws/root-config.js deleted file mode 100644 index ea97fa7b0187..000000000000 --- a/ui/app/serializers/aws/root-config.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import ApplicationSerializer from '../application'; - -export default class AwsRootConfigSerializer extends ApplicationSerializer { - normalizeResponse(store, primaryModelClass, payload, id, requestType) { - if (!payload.data) { - return super.normalizeResponse(...arguments); - } - // remove identityTokenTtl and maxRetries if the API's default value of 0 or -1, respectively. We don't want to display this value on configuration details if they haven't changed the default value - if (payload.data.identity_token_ttl === 0) { - delete payload.data.identity_token_ttl; - } - if (payload.data.max_retries === -1) { - delete payload.data.max_retries; - } - const normalizedPayload = { - id: payload.id, - backend: payload.backend, - data: { - ...payload.data, - }, - }; - return super.normalizeResponse(store, primaryModelClass, normalizedPayload, id, requestType); - } -} diff --git a/ui/app/serializers/capabilities.js b/ui/app/serializers/capabilities.js index 045407811495..18b2820cb63e 100644 --- a/ui/app/serializers/capabilities.js +++ b/ui/app/serializers/capabilities.js @@ -9,21 +9,14 @@ export default ApplicationSerializer.extend({ primaryKey: 'path', normalizeResponse(store, primaryModelClass, payload, id, requestType) { - let response; - // queryRecord will already have set path, and we won't have an id here - if (id) payload.path = id; - - if (requestType === 'query') { - // each key on the response is a path with an array of capabilities as its value - response = Object.keys(payload.data).map((fullPath) => { - // we use pathMap to normalize a namespace-prefixed path back to the relative path - // this is okay because we clear capabilities when moving between namespaces - const path = payload.pathMap ? payload.pathMap[fullPath] : fullPath; - return { capabilities: payload.data[fullPath], path }; - }); - } else { - response = { ...payload.data, path: payload.path }; + // queryRecord will already have set this, and we won't have an id here + if (id) { + payload.path = id; } + const response = { + ...payload.data, + path: payload.path, + }; return this._super(store, primaryModelClass, response, id, requestType); }, diff --git a/ui/app/serializers/database/connection.js b/ui/app/serializers/database/connection.js index 92951ccf5da8..96aaae8a0de9 100644 --- a/ui/app/serializers/database/connection.js +++ b/ui/app/serializers/database/connection.js @@ -4,7 +4,7 @@ */ import RESTSerializer from '@ember-data/serializer/rest'; -import { AVAILABLE_PLUGIN_TYPES } from '../../utils/model-helpers/database-helpers'; +import { AVAILABLE_PLUGIN_TYPES } from '../../utils/database-helpers'; export default RESTSerializer.extend({ primaryKey: 'name', diff --git a/ui/app/serializers/secret-engine.js b/ui/app/serializers/secret-engine.js index eff2ebe5491d..bebfb1526b1c 100644 --- a/ui/app/serializers/secret-engine.js +++ b/ui/app/serializers/secret-engine.js @@ -5,7 +5,6 @@ import ApplicationSerializer from './application'; import { EmbeddedRecordsMixin } from '@ember-data/serializer/rest'; -import { WIF_ENGINES } from 'vault/helpers/mountable-secret-engines'; export default ApplicationSerializer.extend(EmbeddedRecordsMixin, { attrs: { @@ -85,13 +84,6 @@ export default ApplicationSerializer.extend(EmbeddedRecordsMixin, { data.options = data.version ? { version: data.version } : {}; delete data.version; - if (!WIF_ENGINES.includes(type)) { - // only send identity_token_key if it's set on a WIF secret engine. - // because of issues with the model unloading with a belongsTo relationships - // identity_token_key can accidentally carry over if a user backs out of the form and changes the type from WIF to non-WIF. - delete data.config.identity_token_key; - } - if (type !== 'kv' || data.options.version === 1) { // These items are on the model, but used by the kv-v2 config endpoint only delete data.max_versions; diff --git a/ui/app/services/auth.js b/ui/app/services/auth.js index 5f33a5a5e173..e3f91aa24098 100644 --- a/ui/app/services/auth.js +++ b/ui/app/services/auth.js @@ -5,7 +5,7 @@ import Ember from 'ember'; import { task, timeout } from 'ember-concurrency'; -import { getOwner } from '@ember/owner'; +import { getOwner } from '@ember/application'; import { isArray } from '@ember/array'; import { computed, get } from '@ember/object'; import { alias } from '@ember/object/computed'; @@ -371,7 +371,6 @@ export default Service.extend({ shouldRenew() { const now = this.now(); const lastFetch = this.lastFetch; - // renewAfterEpoch is a unix timestamp of login time + half of ttl const renewTime = this.renewAfterEpoch; if (!this.currentTokenName || this.tokenExpired || this.allowExpiration || !renewTime) { return false; diff --git a/ui/app/services/capabilities.ts b/ui/app/services/capabilities.ts deleted file mode 100644 index d7fbb6df367d..000000000000 --- a/ui/app/services/capabilities.ts +++ /dev/null @@ -1,120 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Service, { service } from '@ember/service'; -import { assert } from '@ember/debug'; - -import type AdapterError from '@ember-data/adapter/error'; -import type CapabilitiesModel from 'vault/vault/models/capabilities'; -import type StoreService from 'vault/services/store'; - -interface Capabilities { - canCreate: boolean; - canDelete: boolean; - canList: boolean; - canPatch: boolean; - canRead: boolean; - canSudo: boolean; - canUpdate: boolean; -} - -interface MultipleCapabilities { - [key: string]: Capabilities; -} - -export default class CapabilitiesService extends Service { - @service declare readonly store: StoreService; - - async request(query: { paths?: string[]; path?: string }) { - if (query?.paths) { - const { paths } = query; - return this.store.query('capabilities', { paths }); - } - if (query?.path) { - const { path } = query; - const storeData = await this.store.peekRecord('capabilities', path); - return storeData ? storeData : this.store.findRecord('capabilities', path); - } - return assert('query object must contain "paths" or "path" key', false); - } - - async fetchMultiplePaths(paths: string[]): Promise { - // if the request to capabilities-self fails, silently catch - // all of path capabilities default to "true" - const resp: CapabilitiesModel[] = await this.request({ paths }).catch(() => []); - return paths.reduce((obj: MultipleCapabilities, apiPath: string) => { - // path is the model's primaryKey (id) - const model = resp.find((m) => m.path === apiPath); - if (model) { - const { canCreate, canDelete, canList, canPatch, canRead, canSudo, canUpdate } = model; - obj[apiPath] = { canCreate, canDelete, canList, canPatch, canRead, canSudo, canUpdate }; - } else { - // default to true if there is a problem fetching the model - // since we can rely on the API to gate as a fallback - obj[apiPath] = { - canCreate: true, - canDelete: true, - canList: true, - canPatch: true, - canRead: true, - canSudo: true, - canUpdate: true, - }; - } - return obj; - }, {}); - } - - /* - this method returns all of the capabilities for a singular path - */ - fetchPathCapabilities(path: string): Promise | AdapterError { - try { - return this.request({ path }); - } catch (error) { - return error; - } - } - - /* - internal method for specific capability checks below - checks the capability model for the passed capability, ie "canRead" - */ - async _fetchSpecificCapability( - path: string, - capability: string - ): Promise | AdapterError { - try { - const capabilities = await this.request({ path }); - return capabilities[capability]; - } catch (e) { - return e; - } - } - - canRead(path: string) { - try { - return this._fetchSpecificCapability(path, 'canRead'); - } catch (e) { - return e; - } - } - - canUpdate(path: string) { - try { - return this._fetchSpecificCapability(path, 'canUpdate'); - } catch (e) { - return e; - } - } - - canPatch(path: string) { - try { - return this._fetchSpecificCapability(path, 'canPatch'); - } catch (e) { - return e; - } - } -} diff --git a/ui/app/services/console.js b/ui/app/services/console.js index 47f653e1e59b..664e49e329a2 100644 --- a/ui/app/services/console.js +++ b/ui/app/services/console.js @@ -6,7 +6,7 @@ // Low level service that allows users to input paths to make requests to vault // this service provides the UI synecdote to the cli commands read, write, delete, and list import Service from '@ember/service'; -import { getOwner } from '@ember/owner'; +import { getOwner } from '@ember/application'; import { shiftCommandIndex } from 'vault/lib/console-helpers'; import { encodePath } from 'vault/utils/path-encoding-helpers'; import { sanitizePath, ensureTrailingSlash } from 'core/utils/sanitize-path'; diff --git a/ui/app/services/control-group.js b/ui/app/services/control-group.js index f0649e3aa23a..7ea218fbfbe9 100644 --- a/ui/app/services/control-group.js +++ b/ui/app/services/control-group.js @@ -135,10 +135,6 @@ export default Service.extend({ return { type: 'error-with-html', content: lines.join('\n'), - href, - token, - accessor, - creation_path, }; }, }); diff --git a/ui/app/services/download.ts b/ui/app/services/download.ts index 3ca9546c51c6..537069da279b 100644 --- a/ui/app/services/download.ts +++ b/ui/app/services/download.ts @@ -11,7 +11,6 @@ interface Extensions { hcl: string; sentinel: string; json: string; - jsonl: string; pem: string; txt: string; } @@ -22,7 +21,6 @@ const EXTENSION_TO_MIME: Extensions = { hcl: 'text/plain', sentinel: 'text/plain', json: 'application/json', - jsonl: 'application/json', pem: 'application/x-pem-file', txt: 'text/plain', }; diff --git a/ui/app/services/path-help.js b/ui/app/services/path-help.js index 3d05344a93de..03b8284a775a 100644 --- a/ui/app/services/path-help.js +++ b/ui/app/services/path-help.js @@ -8,139 +8,74 @@ shape of data at a specific path to hydrate a model with attrs it has less (or no) information about. */ -import Model, { attr } from '@ember-data/model'; +import Model from '@ember-data/model'; import Service from '@ember/service'; -import { getOwner } from '@ember/owner'; +import { encodePath } from 'vault/utils/path-encoding-helpers'; +import { getOwner } from '@ember/application'; +import { expandOpenApiProps, combineAttributes } from 'vault/utils/openapi-to-attrs'; +import fieldToAttrs from 'vault/utils/field-to-attrs'; import { resolve, reject } from 'rsvp'; import { debug } from '@ember/debug'; import { capitalize } from '@ember/string'; import { computed } from '@ember/object'; // eslint-disable-line +import { withModelValidations } from 'vault/decorators/model-validations'; +import generatedItemAdapter from 'vault/adapters/generated-item-list'; +import { sanitizePath } from 'core/utils/sanitize-path'; import { filterPathsByItemType, pathToHelpUrlSegment, reducePathsByPathName, - getHelpUrlForModel, - combineOpenApiAttrs, - expandOpenApiProps, } from 'vault/utils/openapi-helpers'; -import GeneratedItemModel from 'vault/models/generated-item'; -import GeneratedItemListAdapter from 'vault/adapters/generated-item-list'; +import { isPresent } from '@ember/utils'; -export default class PathHelpService extends Service { +export default Service.extend({ + attrs: null, + dynamicApiPath: '', ajax(url, options = {}) { const appAdapter = getOwner(this).lookup(`adapter:application`); const { data } = options; return appAdapter.ajax(url, 'GET', { data, }); - } + }, /** - * Registers new ModelClass at specified model type, and busts cache - */ - _registerModel(owner, NewKlass, modelType, isNew = false) { - const store = owner.lookup('service:store'); - // bust cache in ember's registry - if (!isNew) { - owner.unregister('model:' + modelType); - } - owner.register('model:' + modelType, NewKlass); - - // bust cache in EmberData's model lookup - delete store._modelFactoryCache[modelType]; - - // bust cache in schema service - const schemas = store.getSchemaDefinitionService?.(); - if (schemas) { - delete schemas._relationshipsDefCache[modelType]; - delete schemas._attributesDefCache[modelType]; - } - } - - /** - * upgradeModelSchema takes an existing ModelClass and hydrates it with the passed attributes - * @param {ModelClass} Klass model class retrieved with store.modelFor(modelType) - * @param {Attribute[]} attrs array of attributes {name, type, options} - * @returns new ModelClass extended from passed one, with the passed attributes added - */ - _upgradeModelSchema(Klass, attrs, newFields) { - // extending the class will ensure that static schema lookups regenerate - const NewKlass = class extends Klass {}; - - for (const { name, type, options } of attrs) { - const decorator = attr(type, options); - const descriptor = decorator(NewKlass.prototype, name, {}); - Object.defineProperty(NewKlass.prototype, name, descriptor); - } - - // newFields is used in combineFieldGroups within various models - if (newFields) { - NewKlass.prototype.newFields = newFields; - } - - // Ensure this class doesn't get re-hydrated - NewKlass.merged = true; - - return NewKlass; - } - - /** - * hydrateModel instantiates models which use OpenAPI partially - * @param {string} modelType path for model, eg pki/role - * @param {string} backend path, which will be used for the generated helpUrl - * @returns void - as side effect, re-registers model via upgradeModelSchema - */ - async hydrateModel(modelType, backend) { - const owner = getOwner(this); - const helpUrl = getHelpUrlForModel(modelType, backend); - const store = owner.lookup('service:store'); - const Klass = store.modelFor(modelType); - - if (Klass?.merged || !helpUrl) { - // if the model is already merged, we don't need to do anything - return resolve(); - } - debug(`Hydrating model ${modelType} at backend ${backend}`); - - // fetch props from openAPI - const props = await this.getProps(helpUrl); - // combine existing attributes with openAPI data - const { attrs, newFields } = combineOpenApiAttrs(Klass.attributes, props); - debug(`${modelType} has ${newFields.length} new fields: ${newFields.join(', ')}`); - - // hydrate model - const HydratedKlass = this._upgradeModelSchema(Klass, attrs, newFields); - - this._registerModel(owner, HydratedKlass, modelType); - } - - /** - * getNewModel instantiates models which use OpenAPI to generate the model fully + * getNewModel instantiates models which use OpenAPI fully or partially * @param {string} modelType * @param {string} backend - * @param {string} apiPath this method will call getPaths and build submodels for item types + * @param {string} apiPath (optional) if passed, this method will call getPaths and build submodels for item types * @param {*} itemType (optional) used in getPaths for additional models - * @returns void - as side effect, registers model via registerNewModelWithAttrs + * @returns void - as side effect, registers model via registerNewModelWithProps */ getNewModel(modelType, backend, apiPath, itemType) { const owner = getOwner(this); const modelName = `model:${modelType}`; const modelFactory = owner.factoryFor(modelName); - + let newModel, helpUrl; + // if we have a factory, we need to take the existing model into account if (modelFactory) { - // if the modelFactory already exists, it means either this model was already - // generated or the model exists in the code already. In either case resolve - - if (!modelFactory.class.merged) { - // no merged flag means this model was not previously generated - debug(`Model exists for ${modelType} -- use hydrateModel instead`); + debug(`Model factory found for ${modelType}`); + newModel = modelFactory.class; + const modelProto = newModel.proto(); + if (newModel.merged || modelProto.useOpenAPI !== true) { + return resolve(); } - return resolve(); + + helpUrl = modelProto.getHelpUrl(backend); + return this.registerNewModelWithProps(helpUrl, backend, newModel, modelName); + } else { + debug(`Creating new Model for ${modelType}`); + newModel = Model.extend({}); + } + + // we don't have an apiPath for dynamic secrets + // and we don't need paths for them yet + if (!apiPath) { + helpUrl = newModel.proto().getHelpUrl(backend); + return this.registerNewModelWithProps(helpUrl, backend, newModel, modelName); } - debug(`Creating new Model for ${modelType}`); - let newModel = Model.extend({}); // use paths to dynamically create our openapi help url // if we have a brand new model @@ -163,16 +98,16 @@ export default class PathHelpService extends Service { return reject(); } - const helpUrl = `/v1/${apiPath}${path.slice(1)}?help=true`; + helpUrl = `/v1/${apiPath}${path.slice(1)}?help=true` || newModel.proto().getHelpUrl(backend); pathInfo.paths = paths; newModel = newModel.extend({ paths: pathInfo }); - return this.registerNewModelWithAttrs(helpUrl, modelType); + return this.registerNewModelWithProps(helpUrl, backend, newModel, modelName); }) .catch((err) => { // TODO: we should handle the error better here console.error(err); // eslint-disable-line }); - } + }, /** * getPaths is used to fetch all the openAPI paths available for an auth method, @@ -201,16 +136,16 @@ export default class PathHelpService extends Service { itemID, }); }); - } + }, // Makes a call to grab the OpenAPI document. // Returns relevant information from OpenAPI // as determined by the expandOpenApiProps util - getProps(helpUrl) { + getProps(helpUrl, backend) { // add name of thing you want - debug(`Fetching schema properties from ${helpUrl}`); + debug(`Fetching schema properties for ${backend} from ${helpUrl}`); - return this.ajax(helpUrl).then((help) => { + return this.ajax(helpUrl, backend).then((help) => { // paths is an array but it will have a single entry // for the scope we're in const path = Object.keys(help.openapi.paths)[0]; // do this or look at name @@ -246,16 +181,17 @@ export default class PathHelpService extends Service { } else if (schema.properties) { props = schema.properties; } - // put url params (e.g. {name}, {role}) at the front of the props list + // put url params (e.g. {name}, {role}) + // at the front of the props list const newProps = { ...paramProp, ...props }; return expandOpenApiProps(newProps); }); - } + }, getNewAdapter(pathInfo, itemType) { // we need list and create paths to set the correct urls for actions const paths = filterPathsByItemType(pathInfo, itemType); - const { apiPath } = pathInfo; + let { apiPath } = pathInfo; const getPath = paths.find((path) => path.operations.includes('get')); // the action might be "Generate" or something like that so we'll grab the first post endpoint if there @@ -264,28 +200,140 @@ export default class PathHelpService extends Service { const createPath = paths.find((path) => path.action === 'Create' || path.operations.includes('post')); const deletePath = paths.find((path) => path.operations.includes('delete')); - return class NewAdapter extends GeneratedItemListAdapter { - apiPath = apiPath; + return generatedItemAdapter.extend({ + urlForItem(id, isList, dynamicApiPath) { + const itemType = sanitizePath(getPath.path); + let url; + id = encodePath(id); + // the apiPath changes when you switch between routes but the apiPath variable does not unless the model is reloaded + // overwrite apiPath if dynamicApiPath exist. + // dynamicApiPath comes from the model->adapter + if (dynamicApiPath) { + apiPath = dynamicApiPath; + } + // isList indicates whether we are viewing the list page + // of a top-level item such as userpass + if (isList) { + url = `${this.buildURL()}/${apiPath}${itemType}/`; + } else { + // build the URL for the show page of a nested item + // such as a userpass group + url = `${this.buildURL()}/${apiPath}${itemType}/${id}`; + } - paths = { - createPath: createPath?.path, - deletePath: deletePath?.path, - getPath: getPath?.path, - }; + return url; + }, + + urlForQueryRecord(id, modelName) { + return this.urlForItem(id, modelName); + }, + + urlForUpdateRecord(id) { + const itemType = createPath.path.slice(1, createPath.path.indexOf('{') - 1); + return `${this.buildURL()}/${apiPath}${itemType}/${id}`; + }, + + urlForCreateRecord(modelType, snapshot) { + const id = snapshot.record.mutableId; // computed property that returns either id or private settable _id value + const path = createPath.path.slice(1, createPath.path.indexOf('{') - 1); + return `${this.buildURL()}/${apiPath}${path}/${id}`; + }, + + urlForDeleteRecord(id) { + const path = deletePath.path.slice(1, deletePath.path.indexOf('{') - 1); + return `${this.buildURL()}/${apiPath}${path}/${id}`; + }, + + createRecord(store, type, snapshot) { + return this._super(...arguments).then((response) => { + // if the server does not return an id and one has not been set on the model we need to set it manually from the mutableId value + if (!response?.id && !snapshot.record.id) { + snapshot.record.id = snapshot.record.mutableId; + snapshot.id = snapshot.record.id; + } + return response; + }); + }, + }); + }, + + registerNewModelWithProps(helpUrl, backend, newModel, modelName) { + return this.getProps(helpUrl, backend).then((props) => { + const { attrs, newFields } = combineAttributes(newModel.attributes, props); + const owner = getOwner(this); + newModel = newModel.extend(attrs, { newFields }); + // if our newModel doesn't have fieldGroups already + // we need to create them + try { + // Initialize prototype to access field groups + let fieldGroups = newModel.proto().fieldGroups; + if (!fieldGroups) { + debug(`Constructing fieldGroups for ${backend}`); + fieldGroups = this.getFieldGroups(newModel); + newModel = newModel.extend({ fieldGroups }); + // Build and add validations on model + // NOTE: For initial phase, initialize validations only for user pass auth + if (backend === 'userpass') { + const validations = { + password: [ + { + validator(model) { + return ( + !(isPresent(model.password) && isPresent(model.passwordHash)) && + (isPresent(model.password) || isPresent(model.passwordHash)) + ); + }, + message: 'You must provide either password or password hash, but not both.', + }, + ], + }; + @withModelValidations(validations) + class GeneratedItemModel extends newModel {} + newModel = GeneratedItemModel; + } + } + } catch (err) { + // eat the error, fieldGroups is computed in the model definition + } + // attempting to set the id prop on a model will trigger an error + // this computed will be used in place of the the id fieldValue -- see openapi-to-attrs + newModel.reopen({ + mutableId: computed('id', '_id', { + get() { + return this._id || this.id; + }, + set(key, value) { + return (this._id = value); + }, + }), + }); + newModel.reopenClass({ merged: true }); + owner.unregister(modelName); + owner.register(modelName, newModel); + }); + }, + getFieldGroups(newModel) { + const groups = { + default: [], }; - } - - /** - * registerNewModelWithAttrs takes the helpUrl of the given model type, - * fetches props, and registers the model hydrated with the provided attrs - * @param {string} helpUrl like /v1/auth/userpass2/users/example?help=true - * @param {string} modelType like generated-user-userpass - */ - async registerNewModelWithAttrs(helpUrl, modelType) { - const owner = getOwner(this); - const props = await this.getProps(helpUrl); - const { attrs, newFields } = combineOpenApiAttrs(new Map(), props); - const NewKlass = this._upgradeModelSchema(GeneratedItemModel, attrs, newFields); - this._registerModel(owner, NewKlass, modelType, true); - } -} + const fieldGroups = []; + newModel.attributes.forEach((attr) => { + // if the attr comes in with a fieldGroup from OpenAPI, + // add it to that group + if (attr.options.fieldGroup) { + if (groups[attr.options.fieldGroup]) { + groups[attr.options.fieldGroup].push(attr.name); + } else { + groups[attr.options.fieldGroup] = [attr.name]; + } + } else { + // otherwise just add that attr to the default group + groups.default.push(attr.name); + } + }); + for (const group in groups) { + fieldGroups.push({ [group]: groups[group] }); + } + return fieldToAttrs(newModel, fieldGroups); + }, +}); diff --git a/ui/app/styles/app.scss b/ui/app/styles/app.scss index 8a0a248c7d45..56a186eb089b 100644 --- a/ui/app/styles/app.scss +++ b/ui/app/styles/app.scss @@ -6,15 +6,13 @@ @import './reset'; @import 'ember-basic-dropdown'; @import 'ember-power-select'; +@import '@hashicorp/design-system-components'; @import './core'; -@import './docs'; @mixin font-face($name) { @font-face { font-family: $name; - src: - url('/ui/fonts/#{$name}.woff2') format('woff2'), - url('/ui/fonts/#{$name}.woff') format('woff'); + src: url('/ui/fonts/#{$name}.woff2') format('woff2'), url('/ui/fonts/#{$name}.woff') format('woff'); } } diff --git a/ui/app/styles/components/chart-container.scss b/ui/app/styles/components/chart-container.scss index 75c1928c8a17..c8e7673e806a 100644 --- a/ui/app/styles/components/chart-container.scss +++ b/ui/app/styles/components/chart-container.scss @@ -21,6 +21,13 @@ } } +.dual-chart-grid { + display: grid; + grid-template-columns: repeat(6, 1fr); + grid-template-rows: 0.7fr 1fr 1fr 1fr 0.3fr; + width: 100%; +} + .chart-header { grid-column-start: 1; grid-column-end: span col4-end; diff --git a/ui/app/styles/components/clients-date-range.scss b/ui/app/styles/components/clients-date-range.scss deleted file mode 100644 index e908211109c5..000000000000 --- a/ui/app/styles/components/clients-date-range.scss +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -.clients-date-range-display { - display: flex; - align-items: bottom; - > * { - margin-right: $spacing-8; - vertical-align: bottom; - align-self: end; - } -} diff --git a/ui/app/styles/components/kmip-role-edit.scss b/ui/app/styles/components/kmip-role-edit.scss index f4fc884be41f..a517c1a54313 100644 --- a/ui/app/styles/components/kmip-role-edit.scss +++ b/ui/app/styles/components/kmip-role-edit.scss @@ -3,14 +3,11 @@ * SPDX-License-Identifier: BUSL-1.1 */ -.kmip-role-operations { - column-count: 2; -} .kmip-role-allowed-operations { @extend .box; flex: 1 1 auto; box-shadow: none; - padding: $spacing-4 0; + padding: 0; } .kmip-role-allowed-operations .field { margin-bottom: $spacing-4; diff --git a/ui/app/styles/components/replication-mode-summary.scss b/ui/app/styles/components/replication-mode-summary.scss new file mode 100644 index 000000000000..a96a3d15c67b --- /dev/null +++ b/ui/app/styles/components/replication-mode-summary.scss @@ -0,0 +1,16 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +.replication-description { + flex-shrink: 1; + + .title { + margin-bottom: $spacing-8; + } + + .detail-tags { + margin-bottom: $spacing-16; + } +} diff --git a/ui/app/styles/components/tool-tip.scss b/ui/app/styles/components/tool-tip.scss index 4f4851d4cfb4..e77d90033e4e 100644 --- a/ui/app/styles/components/tool-tip.scss +++ b/ui/app/styles/components/tool-tip.scss @@ -63,9 +63,7 @@ } .ember-basic-dropdown-content--above.tool-tip { @include css-bottom-arrow(8px, $black, 1px, $black); - & { - margin-top: -8px; - } + margin-top: -8px; } .ember-basic-dropdown-content--above.ember-basic-dropdown-content--right.tool-tip { @include css-bottom-arrow(8px, $black, 1px, $black, calc(100% - 20px)); diff --git a/ui/app/styles/core.scss b/ui/app/styles/core.scss index 73d9e179635a..84882a7bd34c 100644 --- a/ui/app/styles/core.scss +++ b/ui/app/styles/core.scss @@ -59,7 +59,6 @@ @import './components/box-label'; @import './components/calendar-widget'; @import './components/chart-container'; -@import './components/clients-date-range'; @import './components/cluster-banners'; @import './components/codemirror'; @import './components/console-ui-panel'; @@ -91,6 +90,7 @@ @import './components/read-more'; @import './components/regex-validator'; @import './components/replication-dashboard'; +@import './components/replication-mode-summary'; @import './components/replication-page'; @import './components/replication-summary'; @import './components/role-item'; diff --git a/ui/app/styles/core/charts-lineal.scss b/ui/app/styles/core/charts-lineal.scss index 047062e71fe6..ca0c1638e05a 100644 --- a/ui/app/styles/core/charts-lineal.scss +++ b/ui/app/styles/core/charts-lineal.scss @@ -46,13 +46,3 @@ color: var(--token-color-palette-blue-200); fill: var(--token-color-palette-blue-200); } - -// custom bar class for manually applying bar styles -.custom-bar-clients { - color: var(--token-color-palette-blue-200); - fill: var(--token-color-palette-blue-200); -} -.custom-bar-new_clients { - color: var(--token-color-palette-blue-100); - fill: var(--token-color-palette-blue-100); -} diff --git a/ui/app/styles/core/charts.scss b/ui/app/styles/core/charts.scss index 86b4ab559139..11169ca7075e 100644 --- a/ui/app/styles/core/charts.scss +++ b/ui/app/styles/core/charts.scss @@ -23,13 +23,6 @@ &.dot-3 { background-color: var(--token-color-palette-neutral-500); } - // custom naming for running totals, which matches the custom-bar naming - &.dot-clients { - background-color: var(--token-color-palette-blue-200); - } - &.dot-new_clients { - background-color: var(--token-color-palette-blue-100); - } } .legend-label { @@ -90,6 +83,13 @@ // RESPONSIVE STYLING // @media only screen and (max-width: 950px) { + .dual-chart-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + grid-template-rows: 0.2fr 0.75fr 0.75fr 0.2fr; + width: 100%; + } + .chart-container-left { grid-column-start: 1; grid-column-end: 4; diff --git a/ui/app/styles/docs.scss b/ui/app/styles/docs.scss deleted file mode 100644 index 0ccb3aecfcfd..000000000000 --- a/ui/app/styles/docs.scss +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -.docs-collapse-toggle { - .hds-button { - color: var(--token-side-nav-color-foreground-primary); - background: var(--token-side-nav-color-surface-primary); - border-color: transparent; - border-radius: var(--token-side-nav-body-list-item-border-radius); - &:hover { - background: var(--token-side-nav-color-surface-interactive-hover); - border-color: transparent; - } - } -} - -#docfy-content { - font-size: 16px; - font-family: var(--token-typography-display-300-font-family); - margin-left: 1.5rem; - margin-right: 2rem; - margin-top: 1.5rem; - max-width: 90%; - - h1, - h2, - h3 { - border-bottom: 1px solid $grey-light; - padding-bottom: 0.5rem; - } - - h1 { - margin-bottom: 1.15rem; - font-size: var(--token-typography-display-500-font-size); - line-height: var(--token-typography-display-500-line-height); - } - - h2 { - padding-top: 1rem; - font-size: var(--token-typography-display-400-font-size); - line-height: var(--token-typography-display-400-line-height); - } - - ul { - list-style: disc; - li { - margin-top: 1rem; - } - } - - ul, - ol { - padding-left: $spacing-16; - padding-bottom: $spacing-16; - } - - pre, - code { - background-color: $ui-gray-100; - } - - blockquote { - margin-left: 1rem; - padding: 0.5rem; - background: $ui-gray-010; - border-radius: 6px; - } - - code { - font-size: var(--token-typography-body-300-font-size); - font-family: var(--token-typography-font-stack-code); - } - - pre code { - overflow-x: scroll; - max-width: 700px; - white-space: pre-line; - } - - pre, - table { - margin-top: 1rem; - margin-bottom: 1rem; - padding: 1rem; - text-align: left; - border-radius: 6px; - } - - table { - border: none; - border-collapse: collapse; - td { - padding-left: 0.5rem; - padding-right: 0.5rem; - code { - background: none; - } - } - tr { - border-bottom: 1px solid $grey-light; - } - } - - .docfy-demo { - border: 1px solid $grey-lightest; - border-radius: 6px; - padding: 1rem; - overflow: scroll; - - .docfy-demo__example { - & pre, - code { - background: none; - margin: 0; - padding: 0; - } - } - } -} diff --git a/ui/app/styles/helper-classes/layout.scss b/ui/app/styles/helper-classes/layout.scss index 25b307fecd71..fa654da798d4 100644 --- a/ui/app/styles/helper-classes/layout.scss +++ b/ui/app/styles/helper-classes/layout.scss @@ -60,15 +60,11 @@ width: 100%; } -.three-fourths-width { +.is-three-fourths-width { width: 75%; } -.one-fourth-width { - width: 25%; -} - -.two-thirds-width { +.is-two-thirds-width { width: 66%; } diff --git a/ui/app/styles/helper-classes/spacing.scss b/ui/app/styles/helper-classes/spacing.scss index 47e4064c613c..8d95939e537f 100644 --- a/ui/app/styles/helper-classes/spacing.scss +++ b/ui/app/styles/helper-classes/spacing.scss @@ -3,11 +3,7 @@ * SPDX-License-Identifier: BUSL-1.1 */ -/* - Helpers that define margin and padding in pixels - *New pattern* Use the numerical value in the name for class selectors - i.e. "has-padding-24" instead of "has-padding-l" - */ +/* Helpers that define margin and padding in pixels */ .is-paddingless { padding: 0 !important; @@ -37,6 +33,9 @@ .has-padding-m { padding: $spacing-16; } +.has-padding-l { + padding: $spacing-24; +} .has-padding-l { padding: $spacing-24; @@ -58,10 +57,6 @@ padding-top: $spacing-8; } -.top-padding-4 { - padding-top: $spacing-4; -} - .has-top-padding-s { padding-top: $spacing-12; } @@ -95,7 +90,6 @@ margin: 0 !important; } -// spacing-18 is between medium + large .has-top-bottom-margin { margin: $spacing-18 0rem; } @@ -104,11 +98,6 @@ margin: $spacing-4 0; } -// moving towards numerical class names (i.e. -12) and away from s/m/l etc. -.has-top-bottom-margin-12 { - margin: $spacing-12 0; -} - .has-top-margin-negative-m { margin-top: -$spacing-16; } diff --git a/ui/app/styles/helper-classes/typography.scss b/ui/app/styles/helper-classes/typography.scss index 3a8f050641f5..8466b0c29440 100644 --- a/ui/app/styles/helper-classes/typography.scss +++ b/ui/app/styles/helper-classes/typography.scss @@ -61,9 +61,6 @@ .is-no-underline { text-decoration: none; } -.line-through { - text-decoration: line-through; -} // Text transformations .is-lowercase { diff --git a/ui/app/templates/components/auth-form.hbs b/ui/app/templates/components/auth-form.hbs index f9fee4c71ff3..66f135f2e940 100644 --- a/ui/app/templates/components/auth-form.hbs +++ b/ui/app/templates/components/auth-form.hbs @@ -3,192 +3,202 @@ SPDX-License-Identifier: BUSL-1.1 ~}}
- {{#if this.hasMethodsWithPath}} -
+ {{/if}}
\ No newline at end of file diff --git a/ui/app/templates/components/configure-aws-secret.hbs b/ui/app/templates/components/configure-aws-secret.hbs new file mode 100644 index 000000000000..52403a12a336 --- /dev/null +++ b/ui/app/templates/components/configure-aws-secret.hbs @@ -0,0 +1,159 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +~}} + +
+ +
+ +{{#if (eq @tab "leases")}} +
+
+ + +

+ If you do not supply lease settings, we will use the default values in AWS. +

+
+ + +
+ +
+ +{{else}} +
+
+ +

+ Note: the client uses the official AWS SDK and will use the specified credentials, environment credentials, shared + file credentials, or IAM role/ECS task credentials in that order. +

+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ + + {{#if this.showOptions}} +
+
+ +
+
+ +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ {{/if}} + +
+ +
+ +{{/if}} \ No newline at end of file diff --git a/ui/app/templates/components/configure-ssh-secret.hbs b/ui/app/templates/components/configure-ssh-secret.hbs new file mode 100644 index 000000000000..d8ef22eba208 --- /dev/null +++ b/ui/app/templates/components/configure-ssh-secret.hbs @@ -0,0 +1,89 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +~}} + +{{#if @configured}} +
+
+ +
+ +
+
+
+
+ + + + +
+{{else}} +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+ +
+
+ +
+
+{{else}} +
+ +
+ +
+ +
+
+
+ +
+
+ +
+
+{{else}} +
+ +
+
+
+ +
+ +
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+ +
+
+{{/if}} \ No newline at end of file diff --git a/ui/app/templates/components/tool-rewrap.hbs b/ui/app/templates/components/tool-rewrap.hbs new file mode 100644 index 000000000000..07fd050e40c8 --- /dev/null +++ b/ui/app/templates/components/tool-rewrap.hbs @@ -0,0 +1,62 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +~}} + + + +

+ Rewrap Token +

+
+
+ +{{#if @rewrap_token}} +
+
+ +
+