vault/ui/app/models/ldap/role.js

232 lines
7.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import Model, { attr } from '@ember-data/model';
import { withFormFields } from 'vault/decorators/model-form-fields';
import { withModelValidations } from 'vault/decorators/model-validations';
import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';
const creationLdifExample = `# The example below is treated as a comment and will not be submitted
# dn: cn={{.Username}},ou=users,dc=learn,dc=example
# objectClass: person
# objectClass: top
`;
const deletionLdifExample = `# The example below is treated as a comment and will not be submitted
# dn: cn={{.Username}},ou=users,dc=learn,dc=example
# changetype: delete
`;
const rollbackLdifExample = `# The example below is treated as a comment and will not be submitted
# dn: cn={{.Username}},ou=users,dc=learn,dc=example
# changetype: delete
`;
const validations = {
name: [{ type: 'presence', message: 'Name is required' }],
username: [
{
validator: (model) => (model.isStatic && !model.username ? false : true),
message: 'Username is required.',
},
],
rotation_period: [
{
validator: (model) => (model.isStatic && !model.rotation_period ? false : true),
message: 'Rotation Period is required.',
},
],
creation_ldif: [
{
validator: (model) => (model.isDynamic && !model.creation_ldif ? false : true),
message: 'Creation LDIF is required.',
},
],
deletion_ldif: [
{
validator: (model) => (model.isDynamic && !model.creation_ldif ? false : true),
message: 'Deletion LDIF is required.',
},
],
};
export const staticRoleFields = ['username', 'dn', 'rotation_period'];
export const dynamicRoleFields = [
'default_ttl',
'max_ttl',
'username_template',
'creation_ldif',
'deletion_ldif',
'rollback_ldif',
];
@withModelValidations(validations)
@withFormFields()
export default class LdapRoleModel extends Model {
@attr('string') backend; // dynamic path of secret -- set on response from value passed to queryRecord
@attr('string', {
defaultValue: 'static',
})
type; // this must be set to either static or dynamic in order for the adapter to build the correct url and for the correct form fields to display
@attr('string', {
label: 'Role name',
subText: 'The name of the role that will be used in Vault.',
editDisabled: true,
})
name;
// static role properties
@attr('string', {
label: 'Distinguished name',
subText: 'Distinguished name (DN) of entry Vault should manage.',
})
dn;
@attr('string', {
label: 'Username',
subText:
"The name of the user to be used when logging in. This is useful when DN isn't used for login purposes.",
})
username;
@attr({
editType: 'ttl',
label: 'Rotation period',
helperTextEnabled:
'Specifies the amount of time Vault should wait before rotating the password. The minimum is 5 seconds.',
hideToggle: true,
})
rotation_period;
// dynamic role properties
@attr({
editType: 'ttl',
label: 'Generated credentials time-to-live (TTL)',
detailsLabel: 'TTL',
helperTextDisabled: 'Vault will use the default of 1 hour.',
defaultValue: '1h',
defaultShown: 'Engine default',
})
default_ttl;
@attr({
editType: 'ttl',
label: 'Generated credentials maximum time-to-live (Max TTL)',
detailsLabel: 'Max TTL',
helperTextDisabled: 'Vault will use the engine default of 24 hours.',
defaultValue: '24h',
defaultShown: 'Engine default',
})
max_ttl;
@attr('string', {
editType: 'optionalText',
label: 'Username template',
subText: 'Enter the custom username template to use.',
defaultSubText:
'Template describing how dynamic usernames are generated. Vault will use the default for this plugin.',
docLink: '/vault/docs/concepts/username-templating',
defaultShown: 'Default',
})
username_template;
@attr('string', {
editType: 'json',
label: 'Creation LDIF',
helpText: 'Specifies the LDIF statements executed to create a user. May optionally be base64 encoded.',
example: creationLdifExample,
mode: 'ruby',
sectionHeading: 'LDIF Statements', // render section heading before form field
})
creation_ldif;
@attr('string', {
editType: 'json',
label: 'Deletion LDIF',
helpText:
'Specifies the LDIF statements executed to delete a user once its TTL has expired. May optionally be base64 encoded.',
example: deletionLdifExample,
mode: 'ruby',
})
deletion_ldif;
@attr('string', {
editType: 'json',
label: 'Rollback LDIF',
helpText:
'Specifies the LDIF statement to attempt to rollback any changes if the creation results in an error. May optionally be base64 encoded.',
example: rollbackLdifExample,
mode: 'ruby',
})
rollback_ldif;
get isStatic() {
return this.type === 'static';
}
get isDynamic() {
return this.type === 'dynamic';
}
// this is used to build the form fields as well as serialize the correct payload based on type
// if a new attr is added be sure to add it to the appropriate array
get fieldsForType() {
return this.isStatic
? ['username', 'dn', 'rotation_period']
: ['default_ttl', 'max_ttl', 'username_template', 'creation_ldif', 'deletion_ldif', 'rollback_ldif'];
}
get formFields() {
// filter all fields and return only those relevant to type
return this.allFields.filter((field) => {
// name is the only common field
return field.name === 'name' || this.fieldsForType.includes(field.name);
});
}
get displayFields() {
// insert type after role name
const [name, ...rest] = this.formFields;
const typeField = { name: 'type', options: { label: 'Role type' } };
return [name, typeField, ...rest];
}
get roleUri() {
return this.isStatic ? 'static-role' : 'role';
}
get credsUri() {
return this.isStatic ? 'static-cred' : 'creds';
}
@lazyCapabilities(apiPath`${'backend'}/${'roleUri'}/${'name'}`, 'backend', 'roleUri', 'name') rolePath;
@lazyCapabilities(apiPath`${'backend'}/${'credsUri'}/${'name'}`, 'backend', 'credsUri', 'name') credsPath;
@lazyCapabilities(apiPath`${'backend'}/rotate-role/${'name'}`, 'backend', 'name') staticRotateCredsPath;
get canCreate() {
return this.rolePath.get('canCreate') !== false;
}
get canDelete() {
return this.rolePath.get('canDelete') !== false;
}
get canEdit() {
return this.rolePath.get('canUpdate') !== false;
}
get canRead() {
return this.rolePath.get('canRead') !== false;
}
get canList() {
return this.rolePath.get('canList') !== false;
}
get canReadCreds() {
return this.credsPath.get('canRead') !== false;
}
get canRotateStaticCreds() {
return this.isStatic && this.staticRotateCredsPath.get('canCreate') !== false;
}
fetchCredentials() {
return this.store.adapterFor('ldap/role').fetchCredentials(this.backend, this.type, this.name);
}
rotateStaticPassword() {
return this.store.adapterFor('ldap/role').rotateStaticPassword(this.backend, this.name);
}
}