mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 11:38:02 +00:00
UI: glimmerize generate credentials component (#27405)
This commit is contained in:
@@ -4,56 +4,49 @@
|
||||
*/
|
||||
|
||||
import { service } from '@ember/service';
|
||||
import { computed, set } from '@ember/object';
|
||||
import Component from '@ember/component';
|
||||
import { action } from '@ember/object';
|
||||
import Component from '@glimmer/component';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
|
||||
const MODEL_TYPES = {
|
||||
'ssh-sign': {
|
||||
model: 'ssh-sign',
|
||||
},
|
||||
'ssh-creds': {
|
||||
const CREDENTIAL_TYPES = {
|
||||
ssh: {
|
||||
model: 'ssh-otp-credential',
|
||||
title: 'Generate SSH Credentials',
|
||||
formFields: ['username', 'ip'],
|
||||
displayFields: ['username', 'ip', 'key', 'keyType', 'port'],
|
||||
},
|
||||
'aws-creds': {
|
||||
aws: {
|
||||
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 Component.extend({
|
||||
controlGroup: service(),
|
||||
store: service(),
|
||||
router: service(),
|
||||
// set on the component
|
||||
backendType: null,
|
||||
backendPath: null,
|
||||
roleName: null,
|
||||
action: null,
|
||||
export default class GenerateCredentials extends Component {
|
||||
@service controlGroup;
|
||||
@service store;
|
||||
@service router;
|
||||
|
||||
model: null,
|
||||
loading: false,
|
||||
emptyData: '{\n}',
|
||||
@tracked model;
|
||||
@tracked loading = false;
|
||||
@tracked hasGenerated = false;
|
||||
emptyData = '{\n}';
|
||||
|
||||
modelForType() {
|
||||
const type = this.options;
|
||||
if (type) {
|
||||
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.backendPath);
|
||||
},
|
||||
|
||||
options: computed('action', 'backendType', function () {
|
||||
const action = this.action || 'creds';
|
||||
return MODEL_TYPES[`${this.backendType}-${action}`];
|
||||
}),
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
this.createOrReplaceModel();
|
||||
},
|
||||
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
|
||||
@@ -61,20 +54,46 @@ export default Component.extend({
|
||||
if (noTeardown && !this.model.isDestroyed && !this.model.isDestroying) {
|
||||
this.model.unloadRecord();
|
||||
}
|
||||
this._super(...arguments);
|
||||
},
|
||||
super.willDestroy();
|
||||
}
|
||||
|
||||
createOrReplaceModel() {
|
||||
const modelType = this.modelForType();
|
||||
const model = this.model;
|
||||
const roleName = this.roleName;
|
||||
const backendPath = this.backendPath;
|
||||
modelForType() {
|
||||
const type = this.options;
|
||||
if (type) {
|
||||
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);
|
||||
}
|
||||
|
||||
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 '';
|
||||
}
|
||||
|
||||
get options() {
|
||||
return CREDENTIAL_TYPES[this.args.backendType];
|
||||
}
|
||||
|
||||
get formFields() {
|
||||
const typeOpts = this.options;
|
||||
if (typeof typeOpts.formFields === 'function') {
|
||||
return typeOpts.formFields(this.model);
|
||||
}
|
||||
return typeOpts.formFields;
|
||||
}
|
||||
|
||||
get displayFields() {
|
||||
return this.options.displayFields;
|
||||
}
|
||||
|
||||
generateNewModel(modelType) {
|
||||
if (!modelType) {
|
||||
return;
|
||||
}
|
||||
if (model) {
|
||||
model.unloadRecord();
|
||||
}
|
||||
const { roleName, backendPath, awsRoleType } = this.args;
|
||||
const attrs = {
|
||||
role: {
|
||||
backend: backendPath,
|
||||
@@ -82,44 +101,60 @@ export default Component.extend({
|
||||
},
|
||||
id: `${backendPath}-${roleName}`,
|
||||
};
|
||||
const newModel = this.store.createRecord(modelType, attrs);
|
||||
this.set('model', newModel);
|
||||
},
|
||||
if (awsRoleType) {
|
||||
// this is only set from route if backendType = aws
|
||||
attrs.credentialType = awsRoleType;
|
||||
}
|
||||
return this.store.createRecord(modelType, attrs);
|
||||
}
|
||||
|
||||
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);
|
||||
});
|
||||
},
|
||||
replaceModel() {
|
||||
const modelType = this.modelForType();
|
||||
if (!modelType) {
|
||||
return;
|
||||
}
|
||||
if (this.model) {
|
||||
this.model.unloadRecord();
|
||||
}
|
||||
this.model = this.generateNewModel(modelType);
|
||||
}
|
||||
|
||||
codemirrorUpdated(attr, val, codemirror) {
|
||||
codemirror.performLint();
|
||||
const hasErrors = codemirror.state.lint.marked.length > 0;
|
||||
@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;
|
||||
});
|
||||
}
|
||||
|
||||
if (!hasErrors) {
|
||||
set(this.model, attr, JSON.parse(val));
|
||||
}
|
||||
},
|
||||
@action
|
||||
codemirrorUpdated(attr, val, codemirror) {
|
||||
codemirror.performLint();
|
||||
const hasErrors = codemirror.state.lint.marked.length > 0;
|
||||
|
||||
newModel() {
|
||||
this.createOrReplaceModel();
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!hasErrors) {
|
||||
this.model[attr] = JSON.parse(val);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
reset() {
|
||||
this.hasGenerated = false;
|
||||
this.replaceModel();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user