mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-30 10:12:35 +00:00
UI: Update PostgreSQL database params (#29200)
* add testing before model changes * add enterprise self_managed attr, update tests * add postgres params * add changelog * update test * cleanup filter function * fix nits
This commit is contained in:
3
changelog/29200.txt
Normal file
3
changelog/29200.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
```release-note:improvement
|
||||||
|
ui: Adds params to postgresql database to improve editing a connection in the web browser.
|
||||||
|
```
|
||||||
@@ -9,6 +9,7 @@ import { alias, or } from '@ember/object/computed';
|
|||||||
import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';
|
import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';
|
||||||
import fieldToAttrs, { expandAttributeMeta } from 'vault/utils/field-to-attrs';
|
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/model-helpers/database-helpers';
|
||||||
|
import { service } from '@ember/service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fieldsToGroups helper fn
|
* fieldsToGroups helper fn
|
||||||
@@ -31,6 +32,8 @@ const fieldsToGroups = function (arr, key = 'subgroup') {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default Model.extend({
|
export default Model.extend({
|
||||||
|
version: service(),
|
||||||
|
|
||||||
backend: attr('string', {
|
backend: attr('string', {
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
}),
|
}),
|
||||||
@@ -77,6 +80,11 @@ export default Model.extend({
|
|||||||
subText: 'The password to use when connecting with the above username.',
|
subText: 'The password to use when connecting with the above username.',
|
||||||
editType: 'password',
|
editType: 'password',
|
||||||
}),
|
}),
|
||||||
|
disable_escaping: attr('boolean', {
|
||||||
|
defaultValue: false,
|
||||||
|
subText: 'Turns off the escaping of special characters inside of the username and password fields.',
|
||||||
|
docLink: 'https://developer.hashicorp.com/vault/docs/secrets/databases#disable-character-escaping',
|
||||||
|
}),
|
||||||
|
|
||||||
// optional
|
// optional
|
||||||
ca_cert: attr('string', {
|
ca_cert: attr('string', {
|
||||||
@@ -125,12 +133,56 @@ export default Model.extend({
|
|||||||
label: 'Disable SSL verification',
|
label: 'Disable SSL verification',
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
}),
|
}),
|
||||||
|
password_authentication: attr('string', {
|
||||||
|
defaultValue: 'password',
|
||||||
|
editType: 'radio',
|
||||||
|
subText: 'The default is "password."',
|
||||||
|
possibleValues: [
|
||||||
|
{
|
||||||
|
value: 'password',
|
||||||
|
helpText:
|
||||||
|
'Passwords will be sent to PostgreSQL in plaintext format and may appear in PostgreSQL logs as-is.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'scram-sha-256',
|
||||||
|
helpText:
|
||||||
|
'When set to "scram-sha-256", passwords will be hashed by Vault and stored as-is by PostgreSQL. Using "scram-sha-256" requires a minimum version of PostgreSQL 10.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
docLink:
|
||||||
|
'https://developer.hashicorp.com/vault/api-docs/secret/databases/postgresql#password_authentication',
|
||||||
|
}),
|
||||||
|
auth_type: attr('string', {
|
||||||
|
subText: 'If set to "gcp_iam", will enable IAM authentication to a Google CloudSQL instance.',
|
||||||
|
docLink: 'https://developer.hashicorp.com/vault/api-docs/secret/databases/postgresql#auth_type',
|
||||||
|
}),
|
||||||
|
service_account_json: attr('string', {
|
||||||
|
label: 'Service account JSON',
|
||||||
|
subText:
|
||||||
|
'JSON encoded credentials for a GCP Service Account to use for IAM authentication. Requires "auth_type" to be "gcp_iam".',
|
||||||
|
editType: 'file',
|
||||||
|
}),
|
||||||
|
use_private_ip: attr('boolean', {
|
||||||
|
label: 'Use private IP',
|
||||||
|
subText:
|
||||||
|
'Enables the option to connect to CloudSQL Instances with Private IP. Requires auth_type to be "gcp_iam".',
|
||||||
|
defaultValue: false,
|
||||||
|
}),
|
||||||
|
private_key: attr('string', {
|
||||||
|
helpText: 'The secret key used for the x509 client certificate. Must be PEM encoded.',
|
||||||
|
editType: 'file',
|
||||||
|
}),
|
||||||
tls: attr('string', {
|
tls: attr('string', {
|
||||||
label: 'TLS Certificate Key',
|
label: 'TLS Certificate Key',
|
||||||
helpText:
|
helpText:
|
||||||
'x509 certificate for connecting to the database. This must be a PEM encoded version of the private key and the certificate combined.',
|
'x509 certificate for connecting to the database. This must be a PEM encoded version of the private key and the certificate combined.',
|
||||||
editType: 'file',
|
editType: 'file',
|
||||||
}),
|
}),
|
||||||
|
tls_certificate: attr('string', {
|
||||||
|
label: 'TLS Certificate Key',
|
||||||
|
helpText: 'The x509 certificate for connecting to the database. Must be PEM encoded.',
|
||||||
|
editType: 'file',
|
||||||
|
}),
|
||||||
tls_ca: attr('string', {
|
tls_ca: attr('string', {
|
||||||
label: 'TLS CA',
|
label: 'TLS CA',
|
||||||
helpText:
|
helpText:
|
||||||
@@ -147,25 +199,28 @@ export default Model.extend({
|
|||||||
defaultShown: 'Default',
|
defaultShown: 'Default',
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
// ENTERPRISE ONLY
|
||||||
|
self_managed: attr('boolean', {
|
||||||
|
subText:
|
||||||
|
'Allows onboarding static roles with a rootless connection configuration. Mutually exclusive with username and password. If true, will force verify_connection to be false.',
|
||||||
|
defaultValue: false,
|
||||||
|
}),
|
||||||
|
|
||||||
isAvailablePlugin: computed('plugin_name', function () {
|
isAvailablePlugin: computed('plugin_name', function () {
|
||||||
return !!AVAILABLE_PLUGIN_TYPES.find((a) => a.value === this.plugin_name);
|
return !!AVAILABLE_PLUGIN_TYPES.find((a) => a.value === this.plugin_name);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
showAttrs: computed('plugin_name', function () {
|
showAttrs: computed('plugin_name', function () {
|
||||||
const fields = AVAILABLE_PLUGIN_TYPES.find((a) => a.value === this.plugin_name)
|
const fields = this._filterFields((f) => f.show !== false).map((f) => f.attr);
|
||||||
.fields.filter((f) => f.show !== false)
|
|
||||||
.map((f) => f.attr);
|
|
||||||
fields.push('allowed_roles');
|
fields.push('allowed_roles');
|
||||||
return expandAttributeMeta(this, fields);
|
return expandAttributeMeta(this, fields);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
// for both create and edit fields
|
||||||
fieldAttrs: computed('plugin_name', function () {
|
fieldAttrs: computed('plugin_name', function () {
|
||||||
// for both create and edit fields
|
|
||||||
let fields = ['plugin_name', 'name', 'connection_url', 'verify_connection', 'password_policy'];
|
let fields = ['plugin_name', 'name', 'connection_url', 'verify_connection', 'password_policy'];
|
||||||
if (this.plugin_name) {
|
if (this.plugin_name) {
|
||||||
fields = AVAILABLE_PLUGIN_TYPES.find((a) => a.value === this.plugin_name)
|
fields = this._filterFields((f) => !f.group).map((f) => f.attr);
|
||||||
.fields.filter((f) => !f.group)
|
|
||||||
.map((field) => field.attr);
|
|
||||||
}
|
}
|
||||||
return expandAttributeMeta(this, fields);
|
return expandAttributeMeta(this, fields);
|
||||||
}),
|
}),
|
||||||
@@ -174,9 +229,7 @@ export default Model.extend({
|
|||||||
if (!this.plugin_name) {
|
if (!this.plugin_name) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const pluginFields = AVAILABLE_PLUGIN_TYPES.find((a) => a.value === this.plugin_name).fields.filter(
|
const pluginFields = this._filterFields((f) => f.group === 'pluginConfig');
|
||||||
(f) => f.group === 'pluginConfig'
|
|
||||||
);
|
|
||||||
const groups = fieldsToGroups(pluginFields, 'subgroup');
|
const groups = fieldsToGroups(pluginFields, 'subgroup');
|
||||||
return fieldToAttrs(this, groups);
|
return fieldToAttrs(this, groups);
|
||||||
}),
|
}),
|
||||||
@@ -185,12 +238,21 @@ export default Model.extend({
|
|||||||
if (!this.plugin_name) {
|
if (!this.plugin_name) {
|
||||||
return expandAttributeMeta(this, ['root_rotation_statements']);
|
return expandAttributeMeta(this, ['root_rotation_statements']);
|
||||||
}
|
}
|
||||||
const fields = AVAILABLE_PLUGIN_TYPES.find((a) => a.value === this.plugin_name)
|
const fields = this._filterFields((f) => f.group === 'statements').map((f) => f.attr);
|
||||||
.fields.filter((f) => f.group === 'statements')
|
|
||||||
.map((field) => field.attr);
|
|
||||||
return expandAttributeMeta(this, fields);
|
return expandAttributeMeta(this, fields);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
// after checking for enterprise, filter callback fires and returns
|
||||||
|
_filterFields(filterCallback) {
|
||||||
|
const plugin = AVAILABLE_PLUGIN_TYPES.find((a) => a.value === this.plugin_name);
|
||||||
|
return plugin.fields.filter((field) => {
|
||||||
|
// return if attribute is enterprise only and we're on community
|
||||||
|
if (field?.isEnterprise && !this.version.isEnterprise) return false;
|
||||||
|
// filter by group, or if there isn't a group
|
||||||
|
return filterCallback(field);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/* CAPABILITIES */
|
/* CAPABILITIES */
|
||||||
editConnectionPath: lazyCapabilities(apiPath`${'backend'}/config/${'id'}`, 'backend', 'id'),
|
editConnectionPath: lazyCapabilities(apiPath`${'backend'}/config/${'id'}`, 'backend', 'id'),
|
||||||
canEdit: alias('editConnectionPath.canUpdate'),
|
canEdit: alias('editConnectionPath.canUpdate'),
|
||||||
|
|||||||
@@ -169,11 +169,20 @@ export const AVAILABLE_PLUGIN_TYPES = [
|
|||||||
{ attr: 'connection_url', group: 'pluginConfig' },
|
{ attr: 'connection_url', group: 'pluginConfig' },
|
||||||
{ attr: 'username', group: 'pluginConfig', show: false },
|
{ attr: 'username', group: 'pluginConfig', show: false },
|
||||||
{ attr: 'password', group: 'pluginConfig', show: false },
|
{ attr: 'password', group: 'pluginConfig', show: false },
|
||||||
|
{ attr: 'password_authentication', group: 'pluginConfig' },
|
||||||
{ attr: 'max_open_connections', group: 'pluginConfig' },
|
{ attr: 'max_open_connections', group: 'pluginConfig' },
|
||||||
{ attr: 'max_idle_connections', group: 'pluginConfig' },
|
{ attr: 'max_idle_connections', group: 'pluginConfig' },
|
||||||
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
|
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
|
||||||
|
{ attr: 'auth_type', group: 'pluginConfig' },
|
||||||
|
{ attr: 'service_account_json', group: 'pluginConfig' },
|
||||||
|
{ attr: 'use_private_ip', group: 'pluginConfig' },
|
||||||
{ attr: 'username_template', group: 'pluginConfig' },
|
{ attr: 'username_template', group: 'pluginConfig' },
|
||||||
|
{ attr: 'disable_escaping', group: 'pluginConfig' },
|
||||||
{ attr: 'root_rotation_statements', group: 'statements' },
|
{ attr: 'root_rotation_statements', group: 'statements' },
|
||||||
|
{ attr: 'self_managed', group: 'pluginConfig', isEnterprise: true },
|
||||||
|
{ attr: 'private_key', group: 'pluginConfig', subgroup: 'TLS options' },
|
||||||
|
{ attr: 'tls_ca', group: 'pluginConfig', subgroup: 'TLS options' },
|
||||||
|
{ attr: 'tls_certificate', group: 'pluginConfig', subgroup: 'TLS options' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
347
ui/tests/helpers/secret-engine/database-helpers.ts
Normal file
347
ui/tests/helpers/secret-engine/database-helpers.ts
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) HashiCorp, Inc.
|
||||||
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
// If we refactor the database/connection model we can move this const to a util and use it in a form component.
|
||||||
|
// The ideal (future) scenario is the API provides this and we don't have to manually write the schema :)
|
||||||
|
export const EXPECTED_FIELDS = {
|
||||||
|
'elasticsearch-database-plugin': {
|
||||||
|
default: [
|
||||||
|
'url',
|
||||||
|
'username',
|
||||||
|
'password',
|
||||||
|
'ca_cert',
|
||||||
|
'ca_path',
|
||||||
|
'client_cert',
|
||||||
|
'client_key',
|
||||||
|
'tls_server_name',
|
||||||
|
'insecure',
|
||||||
|
'username_template',
|
||||||
|
],
|
||||||
|
showAttrs: [
|
||||||
|
'plugin_name',
|
||||||
|
'name',
|
||||||
|
'password_policy',
|
||||||
|
'url',
|
||||||
|
'ca_cert',
|
||||||
|
'ca_path',
|
||||||
|
'client_cert',
|
||||||
|
'client_key',
|
||||||
|
'tls_server_name',
|
||||||
|
'insecure',
|
||||||
|
'username_template',
|
||||||
|
'allowed_roles',
|
||||||
|
],
|
||||||
|
fieldAttrs: ['plugin_name', 'name', 'verify_connection', 'password_policy'],
|
||||||
|
pluginFieldGroups: undefined,
|
||||||
|
statementFields: [],
|
||||||
|
},
|
||||||
|
'mongodb-database-plugin': {
|
||||||
|
default: ['username', 'password', 'write_concern', 'username_template'],
|
||||||
|
showAttrs: [
|
||||||
|
'plugin_name',
|
||||||
|
'name',
|
||||||
|
'connection_url',
|
||||||
|
'password_policy',
|
||||||
|
'write_concern',
|
||||||
|
'username_template',
|
||||||
|
'tls',
|
||||||
|
'tls_ca',
|
||||||
|
'root_rotation_statements',
|
||||||
|
'allowed_roles',
|
||||||
|
],
|
||||||
|
fieldAttrs: ['plugin_name', 'name', 'connection_url', 'verify_connection', 'password_policy'],
|
||||||
|
pluginFieldGroups: ['username', 'password', 'write_concern', 'username_template'],
|
||||||
|
statementFields: [
|
||||||
|
{
|
||||||
|
name: 'root_rotation_statements',
|
||||||
|
options: {
|
||||||
|
defaultShown: 'Default',
|
||||||
|
editType: 'stringArray',
|
||||||
|
subText:
|
||||||
|
"The database statements to be executed to rotate the root user's credentials. If nothing is entered, Vault will use a reasonable default.",
|
||||||
|
},
|
||||||
|
type: undefined,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'TLS options': ['tls', 'tls_ca'],
|
||||||
|
},
|
||||||
|
'mssql-database-plugin': {
|
||||||
|
default: [
|
||||||
|
'username',
|
||||||
|
'password',
|
||||||
|
'username_template',
|
||||||
|
'max_open_connections',
|
||||||
|
'max_idle_connections',
|
||||||
|
'max_connection_lifetime',
|
||||||
|
],
|
||||||
|
showAttrs: [
|
||||||
|
'plugin_name',
|
||||||
|
'name',
|
||||||
|
'connection_url',
|
||||||
|
'password_policy',
|
||||||
|
'username_template',
|
||||||
|
'max_open_connections',
|
||||||
|
'max_idle_connections',
|
||||||
|
'max_connection_lifetime',
|
||||||
|
'root_rotation_statements',
|
||||||
|
'allowed_roles',
|
||||||
|
],
|
||||||
|
fieldAttrs: ['plugin_name', 'name', 'connection_url', 'verify_connection', 'password_policy'],
|
||||||
|
statementFields: [
|
||||||
|
{
|
||||||
|
name: 'root_rotation_statements',
|
||||||
|
options: {
|
||||||
|
defaultShown: 'Default',
|
||||||
|
editType: 'stringArray',
|
||||||
|
subText:
|
||||||
|
"The database statements to be executed to rotate the root user's credentials. If nothing is entered, Vault will use a reasonable default.",
|
||||||
|
},
|
||||||
|
type: undefined,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'mysql-aurora-database-plugin': {
|
||||||
|
default: [
|
||||||
|
'connection_url',
|
||||||
|
'username',
|
||||||
|
'password',
|
||||||
|
'max_open_connections',
|
||||||
|
'max_idle_connections',
|
||||||
|
'max_connection_lifetime',
|
||||||
|
'username_template',
|
||||||
|
],
|
||||||
|
showAttrs: [
|
||||||
|
'plugin_name',
|
||||||
|
'name',
|
||||||
|
'password_policy',
|
||||||
|
'connection_url',
|
||||||
|
'max_open_connections',
|
||||||
|
'max_idle_connections',
|
||||||
|
'max_connection_lifetime',
|
||||||
|
'username_template',
|
||||||
|
'tls',
|
||||||
|
'tls_ca',
|
||||||
|
'root_rotation_statements',
|
||||||
|
'allowed_roles',
|
||||||
|
],
|
||||||
|
fieldAttrs: ['plugin_name', 'name', 'verify_connection', 'password_policy'],
|
||||||
|
statementFields: [
|
||||||
|
{
|
||||||
|
name: 'root_rotation_statements',
|
||||||
|
options: {
|
||||||
|
defaultShown: 'Default',
|
||||||
|
editType: 'stringArray',
|
||||||
|
subText:
|
||||||
|
"The database statements to be executed to rotate the root user's credentials. If nothing is entered, Vault will use a reasonable default.",
|
||||||
|
},
|
||||||
|
type: undefined,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'TLS options': ['tls', 'tls_ca'],
|
||||||
|
},
|
||||||
|
'mysql-legacy-database-plugin': {
|
||||||
|
default: [
|
||||||
|
'connection_url',
|
||||||
|
'username',
|
||||||
|
'password',
|
||||||
|
'max_open_connections',
|
||||||
|
'max_idle_connections',
|
||||||
|
'max_connection_lifetime',
|
||||||
|
'username_template',
|
||||||
|
],
|
||||||
|
showAttrs: [
|
||||||
|
'plugin_name',
|
||||||
|
'name',
|
||||||
|
'password_policy',
|
||||||
|
'connection_url',
|
||||||
|
'max_open_connections',
|
||||||
|
'max_idle_connections',
|
||||||
|
'max_connection_lifetime',
|
||||||
|
'username_template',
|
||||||
|
'tls',
|
||||||
|
'tls_ca',
|
||||||
|
'root_rotation_statements',
|
||||||
|
'allowed_roles',
|
||||||
|
],
|
||||||
|
fieldAttrs: ['plugin_name', 'name', 'verify_connection', 'password_policy'],
|
||||||
|
statementFields: [
|
||||||
|
{
|
||||||
|
name: 'root_rotation_statements',
|
||||||
|
options: {
|
||||||
|
defaultShown: 'Default',
|
||||||
|
editType: 'stringArray',
|
||||||
|
subText:
|
||||||
|
"The database statements to be executed to rotate the root user's credentials. If nothing is entered, Vault will use a reasonable default.",
|
||||||
|
},
|
||||||
|
type: undefined,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'TLS options': ['tls', 'tls_ca'],
|
||||||
|
},
|
||||||
|
'mysql-database-plugin': {
|
||||||
|
default: [
|
||||||
|
'connection_url',
|
||||||
|
'username',
|
||||||
|
'password',
|
||||||
|
'max_open_connections',
|
||||||
|
'max_idle_connections',
|
||||||
|
'max_connection_lifetime',
|
||||||
|
'username_template',
|
||||||
|
],
|
||||||
|
showAttrs: [
|
||||||
|
'plugin_name',
|
||||||
|
'name',
|
||||||
|
'password_policy',
|
||||||
|
'connection_url',
|
||||||
|
'max_open_connections',
|
||||||
|
'max_idle_connections',
|
||||||
|
'max_connection_lifetime',
|
||||||
|
'username_template',
|
||||||
|
'tls',
|
||||||
|
'tls_ca',
|
||||||
|
'root_rotation_statements',
|
||||||
|
'allowed_roles',
|
||||||
|
],
|
||||||
|
fieldAttrs: ['plugin_name', 'name', 'verify_connection', 'password_policy'],
|
||||||
|
statementFields: [
|
||||||
|
{
|
||||||
|
name: 'root_rotation_statements',
|
||||||
|
options: {
|
||||||
|
defaultShown: 'Default',
|
||||||
|
editType: 'stringArray',
|
||||||
|
subText:
|
||||||
|
"The database statements to be executed to rotate the root user's credentials. If nothing is entered, Vault will use a reasonable default.",
|
||||||
|
},
|
||||||
|
type: undefined,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'TLS options': ['tls', 'tls_ca'],
|
||||||
|
},
|
||||||
|
'mysql-rds-database-plugin': {
|
||||||
|
default: [
|
||||||
|
'connection_url',
|
||||||
|
'username',
|
||||||
|
'password',
|
||||||
|
'max_open_connections',
|
||||||
|
'max_idle_connections',
|
||||||
|
'max_connection_lifetime',
|
||||||
|
'username_template',
|
||||||
|
],
|
||||||
|
showAttrs: [
|
||||||
|
'plugin_name',
|
||||||
|
'name',
|
||||||
|
'password_policy',
|
||||||
|
'connection_url',
|
||||||
|
'max_open_connections',
|
||||||
|
'max_idle_connections',
|
||||||
|
'max_connection_lifetime',
|
||||||
|
'username_template',
|
||||||
|
'tls',
|
||||||
|
'tls_ca',
|
||||||
|
'root_rotation_statements',
|
||||||
|
'allowed_roles',
|
||||||
|
],
|
||||||
|
fieldAttrs: ['plugin_name', 'name', 'verify_connection', 'password_policy'],
|
||||||
|
statementFields: [
|
||||||
|
{
|
||||||
|
name: 'root_rotation_statements',
|
||||||
|
options: {
|
||||||
|
defaultShown: 'Default',
|
||||||
|
editType: 'stringArray',
|
||||||
|
subText:
|
||||||
|
"The database statements to be executed to rotate the root user's credentials. If nothing is entered, Vault will use a reasonable default.",
|
||||||
|
},
|
||||||
|
type: undefined,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'TLS options': ['tls', 'tls_ca'],
|
||||||
|
},
|
||||||
|
'vault-plugin-database-oracle': {
|
||||||
|
default: [
|
||||||
|
'connection_url',
|
||||||
|
'username',
|
||||||
|
'password',
|
||||||
|
'max_open_connections',
|
||||||
|
'max_idle_connections',
|
||||||
|
'max_connection_lifetime',
|
||||||
|
'username_template',
|
||||||
|
],
|
||||||
|
showAttrs: [
|
||||||
|
'plugin_name',
|
||||||
|
'name',
|
||||||
|
'password_policy',
|
||||||
|
'connection_url',
|
||||||
|
'max_open_connections',
|
||||||
|
'max_idle_connections',
|
||||||
|
'max_connection_lifetime',
|
||||||
|
'username_template',
|
||||||
|
'root_rotation_statements',
|
||||||
|
'allowed_roles',
|
||||||
|
],
|
||||||
|
fieldAttrs: ['plugin_name', 'name', 'verify_connection', 'password_policy'],
|
||||||
|
statementFields: [
|
||||||
|
{
|
||||||
|
name: 'root_rotation_statements',
|
||||||
|
options: {
|
||||||
|
defaultShown: 'Default',
|
||||||
|
editType: 'stringArray',
|
||||||
|
subText:
|
||||||
|
"The database statements to be executed to rotate the root user's credentials. If nothing is entered, Vault will use a reasonable default.",
|
||||||
|
},
|
||||||
|
type: undefined,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'postgresql-database-plugin': {
|
||||||
|
default: [
|
||||||
|
'connection_url',
|
||||||
|
'username',
|
||||||
|
'password',
|
||||||
|
'password_authentication',
|
||||||
|
'max_open_connections',
|
||||||
|
'max_idle_connections',
|
||||||
|
'max_connection_lifetime',
|
||||||
|
'auth_type',
|
||||||
|
'service_account_json',
|
||||||
|
'use_private_ip',
|
||||||
|
'username_template',
|
||||||
|
'disable_escaping',
|
||||||
|
],
|
||||||
|
showAttrs: [
|
||||||
|
'plugin_name',
|
||||||
|
'name',
|
||||||
|
'password_policy',
|
||||||
|
'connection_url',
|
||||||
|
'password_authentication',
|
||||||
|
'max_open_connections',
|
||||||
|
'max_idle_connections',
|
||||||
|
'max_connection_lifetime',
|
||||||
|
'auth_type',
|
||||||
|
'service_account_json',
|
||||||
|
'use_private_ip',
|
||||||
|
'username_template',
|
||||||
|
'disable_escaping',
|
||||||
|
'root_rotation_statements',
|
||||||
|
'private_key',
|
||||||
|
'tls_ca',
|
||||||
|
'tls_certificate',
|
||||||
|
'allowed_roles',
|
||||||
|
],
|
||||||
|
fieldAttrs: ['plugin_name', 'name', 'verify_connection', 'password_policy'],
|
||||||
|
statementFields: [
|
||||||
|
{
|
||||||
|
name: 'root_rotation_statements',
|
||||||
|
options: {
|
||||||
|
defaultShown: 'Default',
|
||||||
|
editType: 'stringArray',
|
||||||
|
subText:
|
||||||
|
"The database statements to be executed to rotate the root user's credentials. If nothing is entered, Vault will use a reasonable default.",
|
||||||
|
},
|
||||||
|
type: undefined,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
enterpriseOnly: 'self_managed',
|
||||||
|
},
|
||||||
|
};
|
||||||
95
ui/tests/unit/models/database-connection-test.js
Normal file
95
ui/tests/unit/models/database-connection-test.js
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) HashiCorp, Inc.
|
||||||
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { module, test } from 'qunit';
|
||||||
|
import { setupTest } from 'ember-qunit';
|
||||||
|
import { EXPECTED_FIELDS } from 'vault/tests/helpers/secret-engine/database-helpers';
|
||||||
|
|
||||||
|
import { AVAILABLE_PLUGIN_TYPES } from 'vault/utils/model-helpers/database-helpers';
|
||||||
|
|
||||||
|
module('Unit | Model | database/connection', function (hooks) {
|
||||||
|
setupTest(hooks);
|
||||||
|
|
||||||
|
hooks.beforeEach(async function () {
|
||||||
|
this.store = this.owner.lookup('service:store');
|
||||||
|
this.version = this.owner.lookup('service:version');
|
||||||
|
// setting version here so tests can be run locally on CE or ENT
|
||||||
|
this.version.type = 'community';
|
||||||
|
|
||||||
|
this.createModel = (plugin) =>
|
||||||
|
this.store.createRecord('database/connection', {
|
||||||
|
plugin_name: plugin,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const plugin of AVAILABLE_PLUGIN_TYPES.map((p) => p.value)) {
|
||||||
|
module(`it computes fields for plugin_type: ${plugin}`, function (hooks) {
|
||||||
|
hooks.beforeEach(function () {
|
||||||
|
this.model = this.createModel(plugin);
|
||||||
|
this.getActual = (group) => this.model[group];
|
||||||
|
this.getExpected = (group) => EXPECTED_FIELDS[plugin][group];
|
||||||
|
|
||||||
|
const pluginFields = AVAILABLE_PLUGIN_TYPES.find((o) => o.value === plugin).fields;
|
||||||
|
this.pluginHasTlsOptions = pluginFields.some((f) => f.subgroup === 'TLS options');
|
||||||
|
this.pluginHasEnterpriseAttrs = pluginFields.some((f) => f.isEnterprise);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it computes showAttrs', function (assert) {
|
||||||
|
const actual = this.getActual('showAttrs').map((a) => a.name);
|
||||||
|
const expected = this.getExpected('showAttrs');
|
||||||
|
assert.propEqual(actual, expected, 'actual computed attrs match expected');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it computes fieldAttrs', function (assert) {
|
||||||
|
const actual = this.getActual('fieldAttrs').map((a) => a.name);
|
||||||
|
const expected = this.getExpected('fieldAttrs');
|
||||||
|
assert.propEqual(actual, expected, 'actual computed attrs match expected');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it computes default group', function (assert) {
|
||||||
|
// pluginFieldGroups is an array of group objects
|
||||||
|
const [actualDefault] = this.getActual('pluginFieldGroups');
|
||||||
|
|
||||||
|
assert.propEqual(
|
||||||
|
actualDefault.default.map((a) => a.name),
|
||||||
|
this.getExpected('default'),
|
||||||
|
'it has expected default group attributes'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it computes statementFields', function (assert) {
|
||||||
|
const actual = this.getActual('statementFields');
|
||||||
|
const expected = this.getExpected('statementFields');
|
||||||
|
assert.propEqual(actual, expected, 'actual computed attrs match expected');
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.pluginHasTlsOptions) {
|
||||||
|
test('it computes TLS options group', function (assert) {
|
||||||
|
// pluginFieldGroups is an array of group objects
|
||||||
|
const [, actualTlsOptions] = this.getActual('pluginFieldGroups');
|
||||||
|
|
||||||
|
assert.propEqual(
|
||||||
|
actualTlsOptions['TLS options'].map((a) => a.name),
|
||||||
|
this.getExpected('TLS options'),
|
||||||
|
'it has expected TLS options'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.pluginHasEnterpriseAttrs) {
|
||||||
|
test('it includes enterprise fields', function (assert) {
|
||||||
|
this.version.type = 'enterprise';
|
||||||
|
const [actualDefault] = this.getActual('pluginFieldGroups');
|
||||||
|
const expected = this.getExpected('default').push(this.getExpected('enterpriseOnly'));
|
||||||
|
assert.propEqual(
|
||||||
|
actualDefault.default.map((a) => a.name),
|
||||||
|
expected,
|
||||||
|
'it includes enterprise attributes'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user