UI/Serialize DB Connection Attributes (#12770)

* creates serializer and moves available plugin types constant to util

* adds if block catch if no plugin_type, renames util file

* updates imports

* adds changelog

* fixes rendering of default attrs

* checks that plugin exists
This commit is contained in:
claire bontempo 2021-10-11 16:42:11 -07:00 committed by GitHub
parent ef103cc618
commit 3501507557
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 239 additions and 213 deletions

3
changelog/12770.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
ui: Filter DB connection attributes so only relevant attrs POST to backend
```

View File

@ -14,7 +14,7 @@
*/
import Component from '@glimmer/component';
import { getStatementFields, getRoleFields } from '../utils/database-role-fields';
import { getStatementFields, getRoleFields } from '../utils/database-helpers';
export default class DatabaseRoleSettingForm extends Component {
get settingFields() {

View File

@ -3,163 +3,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';
const AVAILABLE_PLUGIN_TYPES = [
{
value: 'mongodb-database-plugin',
displayName: 'MongoDB',
fields: [
{ attr: 'plugin_name' },
{ attr: 'name' },
{ attr: 'connection_url' },
{ attr: 'verify_connection' },
{ attr: 'password_policy' },
{ attr: 'username', group: 'pluginConfig', show: false },
{ attr: 'password', group: 'pluginConfig', show: false },
{ attr: 'write_concern', group: 'pluginConfig' },
{ attr: 'username_template', group: 'pluginConfig' },
{ attr: 'tls', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'tls_ca', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'root_rotation_statements', group: 'statements' },
],
},
{
value: 'mssql-database-plugin',
displayName: 'MSSQL',
fields: [
{ attr: 'plugin_name' },
{ attr: 'name' },
{ attr: 'connection_url' },
{ attr: 'verify_connection' },
{ attr: 'password_policy' },
{ attr: 'username', group: 'pluginConfig', show: false },
{ attr: 'password', group: 'pluginConfig', show: false },
{ attr: 'username_template', group: 'pluginConfig' },
{ attr: 'max_open_connections', group: 'pluginConfig' },
{ attr: 'max_idle_connections', group: 'pluginConfig' },
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
{ attr: 'root_rotation_statements', group: 'statements' },
],
},
{
value: 'mysql-database-plugin',
displayName: 'MySQL/MariaDB',
fields: [
{ attr: 'plugin_name' },
{ attr: 'name' },
{ attr: 'verify_connection' },
{ attr: 'password_policy' },
{ attr: 'connection_url', group: 'pluginConfig' },
{ attr: 'username', group: 'pluginConfig', show: false },
{ attr: 'password', group: 'pluginConfig', show: false },
{ attr: 'max_open_connections', group: 'pluginConfig' },
{ attr: 'max_idle_connections', group: 'pluginConfig' },
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
{ attr: 'username_template', group: 'pluginConfig' },
{ attr: 'tls', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'tls_ca', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'root_rotation_statements', group: 'statements' },
],
},
{
value: 'mysql-aurora-database-plugin',
displayName: 'MySQL (Aurora)',
fields: [
{ attr: 'plugin_name' },
{ attr: 'name' },
{ attr: 'verify_connection' },
{ attr: 'password_policy' },
{ attr: 'connection_url', group: 'pluginConfig' },
{ attr: 'username', group: 'pluginConfig', show: false },
{ attr: 'password', group: 'pluginConfig', show: false },
{ attr: 'max_open_connections', group: 'pluginConfig' },
{ attr: 'max_idle_connections', group: 'pluginConfig' },
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
{ attr: 'username_template', group: 'pluginConfig' },
{ attr: 'tls', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'tls_ca', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'root_rotation_statements', group: 'statements' },
],
},
{
value: 'mysql-rds-database-plugin',
displayName: 'MySQL (RDS)',
fields: [
{ attr: 'plugin_name' },
{ attr: 'name' },
{ attr: 'verify_connection' },
{ attr: 'password_policy' },
{ attr: 'connection_url', group: 'pluginConfig' },
{ attr: 'username', group: 'pluginConfig', show: false },
{ attr: 'password', group: 'pluginConfig', show: false },
{ attr: 'max_open_connections', group: 'pluginConfig' },
{ attr: 'max_idle_connections', group: 'pluginConfig' },
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
{ attr: 'username_template', group: 'pluginConfig' },
{ attr: 'tls', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'tls_ca', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'root_rotation_statements', group: 'statements' },
],
},
{
value: 'mysql-legacy-database-plugin',
displayName: 'MySQL (Legacy)',
fields: [
{ attr: 'plugin_name' },
{ attr: 'name' },
{ attr: 'verify_connection' },
{ attr: 'password_policy' },
{ attr: 'connection_url', group: 'pluginConfig' },
{ attr: 'username', group: 'pluginConfig', show: false },
{ attr: 'password', group: 'pluginConfig', show: false },
{ attr: 'max_open_connections', group: 'pluginConfig' },
{ attr: 'max_idle_connections', group: 'pluginConfig' },
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
{ attr: 'username_template', group: 'pluginConfig' },
{ attr: 'tls', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'tls_ca', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'root_rotation_statements', group: 'statements' },
],
},
{
value: 'elasticsearch-database-plugin',
displayName: 'Elasticsearch',
fields: [
{ attr: 'plugin_name' },
{ attr: 'name' },
{ attr: 'verify_connection' },
{ attr: 'password_policy' },
{ attr: 'url', group: 'pluginConfig' },
{ attr: 'username', group: 'pluginConfig', show: false },
{ attr: 'password', group: 'pluginConfig', show: false },
{ attr: 'ca_cert', group: 'pluginConfig' },
{ attr: 'ca_path', group: 'pluginConfig' },
{ attr: 'client_cert', group: 'pluginConfig' },
{ attr: 'client_key', group: 'pluginConfig' },
{ attr: 'tls_server_name', group: 'pluginConfig' },
{ attr: 'insecure', group: 'pluginConfig' },
{ attr: 'username_template', group: 'pluginConfig' },
],
},
{
value: 'oracle-database-plugin',
displayName: 'Oracle',
fields: [
{ attr: 'plugin_name' },
{ attr: 'name' },
{ attr: 'verify_connection' },
{ attr: 'password_policy' },
{ attr: 'connection_url', group: 'pluginConfig' },
{ attr: 'username', group: 'pluginConfig', show: false },
{ attr: 'password', group: 'pluginConfig', show: false },
{ attr: 'max_open_connections', group: 'pluginConfig' },
{ attr: 'max_idle_connections', group: 'pluginConfig' },
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
{ attr: 'username_template', group: 'pluginConfig' },
{ attr: 'root_rotation_statements', group: 'statements' },
],
}
];
import { AVAILABLE_PLUGIN_TYPES } from '../../utils/database-helpers';
/**
* fieldsToGroups helper fn
@ -275,8 +119,8 @@ export default Model.extend({
defaultValue: '0s',
}),
insecure: attr('boolean', {
defaultValue: false,
label: 'Disable SSL verification',
defaultValue: false,
}),
tls: attr('string', {
label: 'TLS Certificate Key',

View File

@ -3,7 +3,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 '../../utils/database-role-fields';
import { getRoleFields } from '../../utils/database-helpers';
export default Model.extend({
idPrefix: 'role/',

View File

@ -1,4 +1,5 @@
import RESTSerializer from '@ember-data/serializer/rest';
import { AVAILABLE_PLUGIN_TYPES } from '../../utils/database-helpers';
export default RESTSerializer.extend({
primaryKey: 'name',
@ -45,4 +46,25 @@ export default RESTSerializer.extend({
}
return this._super(store, primaryModelClass, transformedPayload, id, requestType);
},
serialize(snapshot, requestType) {
let data = this._super(snapshot, requestType);
if (!data.plugin_name) {
return data;
}
let pluginType = AVAILABLE_PLUGIN_TYPES.find(plugin => plugin.value === data.plugin_name);
if (!pluginType) {
return data;
}
let pluginAttributes = pluginType.fields.map(fields => fields.attr).concat('backend');
// filter data to only allow plugin specific attrs
let allowedAttributes = Object.keys(data).filter(dataAttrs => pluginAttributes.includes(dataAttrs));
for (const key in data) {
if (!allowedAttributes.includes(key)) {
delete data[key];
}
}
return data;
},
});

View File

@ -307,20 +307,20 @@
</EmptyState>
{{else}}
{{#each @model.showAttrs as |attr|}}
{{#let attr.options.defaultDisplay as |defaultDisplay|}}
{{#let attr.options.defaultShown as |defaultDisplay|}}
{{#if (eq attr.type "object")}}
<InfoTableRow
@alwaysRender={{true}}
@defaultShown={{attr.options.defaultShown}}
@defaultShown={{defaultDisplay}}
@label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}
@value={{stringify (get @model attr.name)}}
/>
{{else if (eq attr.type "array")}}
<InfoTableRow
@alwaysRender={{true}}
@defaultShown={{attr.options.defaultShown}}
@defaultShown={{defaultDisplay}}
@label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}
@value={{or (get @model attr.name) defaultDisplay}}
@value={{get @model attr.name}}
@isLink={{true}}
@queryParam="role"
@type={{attr.type}}
@ -328,9 +328,9 @@
{{else}}
<InfoTableRow
@alwaysRender={{true}}
@defaultShown={{attr.options.defaultShown}}
@defaultShown={{defaultDisplay}}
@label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}
@value={{or (get @model attr.name) defaultDisplay}}
@value={{get @model attr.name}}
/>
{{/if}}
{{/let}}

View File

@ -55,20 +55,20 @@
</ToolbarActions>
</Toolbar>
{{#each @model.showFields as |attr|}}
{{#let attr.options.defaultDisplay as |defaultDisplay|}}
{{#let attr.options.defaultShown as |defaultDisplay|}}
{{#if (eq attr.type "object")}}
<InfoTableRow
@alwaysRender={{true}}
@defaultShown={{attr.options.defaultShown}}
@defaultShown={{defaultDisplay}}
@label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}
@value={{stringify (get @model attr.name)}}
/>
{{else}}
<InfoTableRow
@alwaysRender={{true}}
@defaultShown={{attr.options.defaultShown}}
@defaultShown={{defaultDisplay}}
@label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}
@value={{or (get @model attr.name) defaultDisplay}}
@value={{get @model attr.name}}
@isLink={{eq attr.name 'database'}}
/>
{{/if}}

View File

@ -0,0 +1,200 @@
export const AVAILABLE_PLUGIN_TYPES = [
{
value: 'mongodb-database-plugin',
displayName: 'MongoDB',
fields: [
{ attr: 'plugin_name' },
{ attr: 'name' },
{ attr: 'connection_url' },
{ attr: 'verify_connection' },
{ attr: 'password_policy' },
{ attr: 'username', group: 'pluginConfig', show: false },
{ attr: 'password', group: 'pluginConfig', show: false },
{ attr: 'write_concern', group: 'pluginConfig' },
{ attr: 'username_template', group: 'pluginConfig' },
{ attr: 'tls', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'tls_ca', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'root_rotation_statements', group: 'statements' },
],
},
{
value: 'mssql-database-plugin',
displayName: 'MSSQL',
fields: [
{ attr: 'plugin_name' },
{ attr: 'name' },
{ attr: 'connection_url' },
{ attr: 'verify_connection' },
{ attr: 'password_policy' },
{ attr: 'username', group: 'pluginConfig', show: false },
{ attr: 'password', group: 'pluginConfig', show: false },
{ attr: 'username_template', group: 'pluginConfig' },
{ attr: 'max_open_connections', group: 'pluginConfig' },
{ attr: 'max_idle_connections', group: 'pluginConfig' },
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
{ attr: 'root_rotation_statements', group: 'statements' },
],
},
{
value: 'mysql-database-plugin',
displayName: 'MySQL/MariaDB',
fields: [
{ attr: 'plugin_name' },
{ attr: 'name' },
{ attr: 'verify_connection' },
{ attr: 'password_policy' },
{ attr: 'connection_url', group: 'pluginConfig' },
{ attr: 'username', group: 'pluginConfig', show: false },
{ attr: 'password', group: 'pluginConfig', show: false },
{ attr: 'max_open_connections', group: 'pluginConfig' },
{ attr: 'max_idle_connections', group: 'pluginConfig' },
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
{ attr: 'username_template', group: 'pluginConfig' },
{ attr: 'tls', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'tls_ca', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'root_rotation_statements', group: 'statements' },
],
},
{
value: 'mysql-aurora-database-plugin',
displayName: 'MySQL (Aurora)',
fields: [
{ attr: 'plugin_name' },
{ attr: 'name' },
{ attr: 'verify_connection' },
{ attr: 'password_policy' },
{ attr: 'connection_url', group: 'pluginConfig' },
{ attr: 'username', group: 'pluginConfig', show: false },
{ attr: 'password', group: 'pluginConfig', show: false },
{ attr: 'max_open_connections', group: 'pluginConfig' },
{ attr: 'max_idle_connections', group: 'pluginConfig' },
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
{ attr: 'username_template', group: 'pluginConfig' },
{ attr: 'tls', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'tls_ca', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'root_rotation_statements', group: 'statements' },
],
},
{
value: 'mysql-rds-database-plugin',
displayName: 'MySQL (RDS)',
fields: [
{ attr: 'plugin_name' },
{ attr: 'name' },
{ attr: 'verify_connection' },
{ attr: 'password_policy' },
{ attr: 'connection_url', group: 'pluginConfig' },
{ attr: 'username', group: 'pluginConfig', show: false },
{ attr: 'password', group: 'pluginConfig', show: false },
{ attr: 'max_open_connections', group: 'pluginConfig' },
{ attr: 'max_idle_connections', group: 'pluginConfig' },
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
{ attr: 'username_template', group: 'pluginConfig' },
{ attr: 'tls', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'tls_ca', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'root_rotation_statements', group: 'statements' },
],
},
{
value: 'mysql-legacy-database-plugin',
displayName: 'MySQL (Legacy)',
fields: [
{ attr: 'plugin_name' },
{ attr: 'name' },
{ attr: 'verify_connection' },
{ attr: 'password_policy' },
{ attr: 'connection_url', group: 'pluginConfig' },
{ attr: 'username', group: 'pluginConfig', show: false },
{ attr: 'password', group: 'pluginConfig', show: false },
{ attr: 'max_open_connections', group: 'pluginConfig' },
{ attr: 'max_idle_connections', group: 'pluginConfig' },
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
{ attr: 'username_template', group: 'pluginConfig' },
{ attr: 'tls', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'tls_ca', group: 'pluginConfig', subgroup: 'TLS options' },
{ attr: 'root_rotation_statements', group: 'statements' },
],
},
{
value: 'elasticsearch-database-plugin',
displayName: 'Elasticsearch',
fields: [
{ attr: 'plugin_name' },
{ attr: 'name' },
{ attr: 'verify_connection' },
{ attr: 'password_policy' },
{ attr: 'url', group: 'pluginConfig' },
{ attr: 'username', group: 'pluginConfig', show: false },
{ attr: 'password', group: 'pluginConfig', show: false },
{ attr: 'ca_cert', group: 'pluginConfig' },
{ attr: 'ca_path', group: 'pluginConfig' },
{ attr: 'client_cert', group: 'pluginConfig' },
{ attr: 'client_key', group: 'pluginConfig' },
{ attr: 'tls_server_name', group: 'pluginConfig' },
{ attr: 'insecure', group: 'pluginConfig' },
{ attr: 'username_template', group: 'pluginConfig' },
],
},
{
value: 'oracle-database-plugin',
displayName: 'Oracle',
fields: [
{ attr: 'plugin_name' },
{ attr: 'name' },
{ attr: 'verify_connection' },
{ attr: 'password_policy' },
{ attr: 'connection_url', group: 'pluginConfig' },
{ attr: 'username', group: 'pluginConfig', show: false },
{ attr: 'password', group: 'pluginConfig', show: false },
{ attr: 'max_open_connections', group: 'pluginConfig' },
{ attr: 'max_idle_connections', group: 'pluginConfig' },
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
{ attr: 'username_template', group: 'pluginConfig' },
{ attr: 'root_rotation_statements', group: 'statements' },
],
},
];
export const ROLE_FIELDS = {
static: ['username', 'rotation_period'],
dynamic: ['ttl', 'max_ttl'],
};
export const STATEMENT_FIELDS = {
static: {
default: ['rotation_statements'],
'mongodb-database-plugin': [],
'mssql-database-plugin': [],
'mysql-database-plugin': [],
'mysql-aurora-database-plugin': [],
'mysql-rds-database-plugin': [],
'mysql-legacy-database-plugin': [],
'elasticsearch-database-plugin': [],
'oracle-database-plugin': [],
},
dynamic: {
default: ['creation_statements', 'revocation_statements', 'rollback_statements', 'renew_statements'],
'mongodb-database-plugin': ['creation_statement', 'revocation_statement'],
'mssql-database-plugin': ['creation_statements', 'revocation_statements'],
'mysql-database-plugin': ['creation_statements', 'revocation_statements'],
'mysql-aurora-database-plugin': ['creation_statements', 'revocation_statements'],
'mysql-rds-database-plugin': ['creation_statements', 'revocation_statements'],
'mysql-legacy-database-plugin': ['creation_statements', 'revocation_statements'],
'elasticsearch-database-plugin': ['creation_statement'],
'oracle-database-plugin': ['creation_statements', 'revocation_statements'],
},
};
export function getStatementFields(type, plugin) {
if (!type) return null;
let dbValidFields = STATEMENT_FIELDS[type].default;
if (STATEMENT_FIELDS[type][plugin]) {
dbValidFields = STATEMENT_FIELDS[type][plugin];
}
return dbValidFields;
}
export function getRoleFields(type) {
if (!type) return null;
return ROLE_FIELDS[type];
}

View File

@ -1,43 +0,0 @@
export const ROLE_FIELDS = {
static: ['username', 'rotation_period'],
dynamic: ['ttl', 'max_ttl'],
};
export const STATEMENT_FIELDS = {
static: {
default: ['rotation_statements'],
'mongodb-database-plugin': [],
'mssql-database-plugin': [],
'mysql-database-plugin': [],
'mysql-aurora-database-plugin': [],
'mysql-rds-database-plugin': [],
'mysql-legacy-database-plugin': [],
'elasticsearch-database-plugin': [],
'oracle-database-plugin': [],
},
dynamic: {
default: ['creation_statements', 'revocation_statements', 'rollback_statements', 'renew_statements'],
'mongodb-database-plugin': ['creation_statement', 'revocation_statement'],
'mssql-database-plugin': ['creation_statements', 'revocation_statements'],
'mysql-database-plugin': ['creation_statements', 'revocation_statements'],
'mysql-aurora-database-plugin': ['creation_statements', 'revocation_statements'],
'mysql-rds-database-plugin': ['creation_statements', 'revocation_statements'],
'mysql-legacy-database-plugin': ['creation_statements', 'revocation_statements'],
'elasticsearch-database-plugin': ['creation_statement'],
'oracle-database-plugin': ['creation_statements', 'revocation_statements'],
},
};
export function getStatementFields(type, plugin) {
if (!type) return null;
let dbValidFields = STATEMENT_FIELDS[type].default;
if (STATEMENT_FIELDS[type][plugin]) {
dbValidFields = STATEMENT_FIELDS[type][plugin];
}
return dbValidFields;
}
export function getRoleFields(type) {
if (!type) return null;
return ROLE_FIELDS[type];
}