Fixed various bugs with preventing prompting for credential passwords on schedules and workflow nodes

This commit is contained in:
mabashian 2018-05-31 13:19:32 -04:00
parent 09ee140fb4
commit 68ac23dd46
4 changed files with 135 additions and 60 deletions

View File

@ -33,7 +33,7 @@ function TemplatesStrings (BaseString) {
NO_INVENTORY_SELECTED: t.s('No inventory selected'),
REVERT: t.s('REVERT'),
CREDENTIAL_TYPE: t.s('Credential Type'),
CREDENTIAL_PASSWORD_WARNING: t.s('Credentials that require passwords on launch are not permitted for template schedules and workflow nodes. The following credentials must be removed or replaced to proceed:'),
CREDENTIAL_PASSWORD_WARNING: t.s('Credentials that require passwords on launch are not permitted for template schedules and workflow nodes. The following credentials must be replaced to proceed:'),
PASSWORDS_REQUIRED_HELP: t.s('Launching this job requires the passwords listed below. Enter and confirm each password before continuing.'),
PLEASE_ENTER_PASSWORD: t.s('Please enter a password.'),
credential_passwords: {
@ -93,7 +93,8 @@ function TemplatesStrings (BaseString) {
};
ns.workflows = {
INVALID_JOB_TEMPLATE: t.s('This Job Template is missing a default inventory or project. This must be addressed in the Job Template form before this node can be saved.')
INVALID_JOB_TEMPLATE: t.s('This Job Template is missing a default inventory or project. This must be addressed in the Job Template form before this node can be saved.'),
CREDENTIAL_WITH_PASS: t.s('This Job Template has a credential that requires a password. Credentials requiring passwords on launch are not permitted on workflow nodes.')
};
}

View File

@ -73,61 +73,65 @@ export default [ 'Rest', 'GetBasePath', 'ProcessErrors', 'CredentialTypeModel',
vm.promptDataClone.prompts.credentials.passwords = {};
if(vm.promptDataClone.launchConf.passwords_needed_to_start) {
let machineCredPassObj = null;
vm.promptDataClone.launchConf.passwords_needed_to_start.forEach((passwordNeeded) => {
if (passwordNeeded === "ssh_password" ||
passwordNeeded === "become_password" ||
passwordNeeded === "ssh_key_unlock"
) {
if (!machineCredPassObj) {
vm.promptDataClone.prompts.credentials.value.forEach((defaultCredential) => {
if (defaultCredential.kind && defaultCredential.kind === "ssh") {
machineCredPassObj = {
id: defaultCredential.id,
name: defaultCredential.name
};
} else if (defaultCredential.passwords_needed) {
defaultCredential.passwords_needed.forEach((neededPassword) => {
if (neededPassword === passwordNeeded) {
machineCredPassObj = {
id: defaultCredential.id,
name: defaultCredential.name
};
}
});
}
});
}
vm.promptDataClone.prompts.credentials.passwords[passwordNeeded] = angular.copy(machineCredPassObj);
} else if (passwordNeeded.startsWith("vault_password")) {
let vault_id = null;
if (passwordNeeded.includes('.')) {
vault_id = passwordNeeded.split(/\.(.+)/)[1];
}
if (!vm.promptDataClone.prompts.credentials.passwords.vault) {
vm.promptDataClone.prompts.credentials.value.forEach((credential) => {
if(credential.inputs) {
if(credential.inputs.password && credential.inputs.password === "ASK") {
vm.promptDataClone.prompts.credentials.passwords.ssh_password = {
id: credential.id,
name: credential.name
};
}
if(credential.inputs.become_password && credential.inputs.become_password === "ASK") {
vm.promptDataClone.prompts.credentials.passwords.become_password = {
id: credential.id,
name: credential.name
};
}
if(credential.inputs.ssh_key_unlock && credential.inputs.ssh_key_unlock === "ASK") {
vm.promptDataClone.prompts.credentials.passwords.ssh_key_unlock = {
id: credential.id,
name: credential.name
};
}
if(credential.inputs.vault_password && credential.inputs.vault_password === "ASK") {
if(!vm.promptDataClone.prompts.credentials.passwords.vault) {
vm.promptDataClone.prompts.credentials.passwords.vault = [];
}
// Loop across the default credentials to find the name of the
// credential that requires a password
vm.promptDataClone.prompts.credentials.value.forEach((defaultCredential) => {
if (vm.promptDataClone.prompts.credentials.credentialTypes[defaultCredential.credential_type] === "vault") {
let defaultCredVaultId = defaultCredential.vault_id || _.get(defaultCredential, 'inputs.vault_id') || null;
if (defaultCredVaultId === vault_id) {
vm.promptDataClone.prompts.credentials.passwords.vault.push({
id: defaultCredential.id,
name: defaultCredential.name,
vault_id: defaultCredVaultId
});
}
}
vm.promptDataClone.prompts.credentials.passwords.vault.push({
id: credential.id,
name: credential.name,
vault_id: credential.inputs.vault_id
});
}
});
}
} else if(credential.passwords_needed && credential.passwords_needed.length > 0) {
credential.passwords_needed.forEach((passwordNeeded) => {
if (passwordNeeded === "ssh_password" ||
passwordNeeded === "become_password" ||
passwordNeeded === "ssh_key_unlock"
) {
vm.promptDataClone.prompts.credentials.passwords[passwordNeeded] = {
id: credential.id,
name: credential.name
};
} else if (passwordNeeded.startsWith("vault_password")) {
let vault_id = null;
if (passwordNeeded.includes('.')) {
vault_id = passwordNeeded.split(/\.(.+)/)[1];
}
if (!vm.promptDataClone.prompts.credentials.passwords.vault) {
vm.promptDataClone.prompts.credentials.passwords.vault = [];
}
vm.promptDataClone.prompts.credentials.passwords.vault.push({
id: credential.id,
name: credential.name,
vault_id: vault_id
});
}
});
}
});
vm.promptDataClone.credentialTypeMissing = [];
@ -141,7 +145,13 @@ export default [ 'Rest', 'GetBasePath', 'ProcessErrors', 'CredentialTypeModel',
};
order++;
}
if(vm.promptDataClone.launchConf.ask_credential_on_launch || (vm.promptDataClone.launchConf.passwords_needed_to_start && vm.promptDataClone.launchConf.passwords_needed_to_start.length > 0)) {
if (vm.promptDataClone.launchConf.ask_credential_on_launch ||
(_.has(vm, 'promptDataClone.prompts.credentials.passwords.vault') &&
vm.promptDataClone.prompts.credentials.passwords.vault.length > 0) ||
_.has(vm.promptDataClone.prompts.credentials.passwords.ssh_key_unlock) ||
_.has(vm.promptDataClone.prompts.credentials.passwords.become_password) ||
_.has(vm.promptDataClone.prompts.credentials.passwords.ssh_password)
) {
vm.steps.credential.includeStep = true;
vm.steps.credential.tab = {
_active: order === 1 ? true : false,

View File

@ -11,7 +11,7 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
$state, ProcessErrors, CreateSelect2, $q, JobTemplate,
Empty, PromptService, Rest, TemplatesStrings, $timeout) {
let promptWatcher, surveyQuestionWatcher;
let promptWatcher, surveyQuestionWatcher, credentialsWatcher;
$scope.strings = TemplatesStrings;
$scope.preventCredsWithPasswords = true;
@ -341,6 +341,20 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
});
};
let checkCredentialsForRequiredPasswords = () => {
let credentialRequiresPassword = false;
$scope.promptData.prompts.credentials.value.forEach((credential) => {
if ((credential.passwords_needed &&
credential.passwords_needed.length > 0) ||
(_.has(credential, 'inputs.vault_password') &&
credential.inputs.vault_password === "ASK")
) {
credentialRequiresPassword = true;
}
});
$scope.credentialRequiresPassword = credentialRequiresPassword;
};
let watchForPromptChanges = () => {
let promptDataToWatch = [
'promptData.prompts.inventory.value',
@ -357,6 +371,12 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
}
$scope.promptModalMissingReqFields = missingPromptValue;
});
if ($scope.promptData.launchConf.ask_credential_on_launch && $scope.credentialRequiresPassword) {
credentialsWatcher = $scope.$watch('promptData.prompts.credentials', () => {
checkCredentialsForRequiredPasswords();
});
}
};
$scope.closeWorkflowMaker = function() {
@ -537,6 +557,10 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
surveyQuestionWatcher();
}
if (credentialsWatcher) {
credentialsWatcher();
}
$scope.promptData = null;
// Reset the edgeConflict flag
@ -564,6 +588,10 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
surveyQuestionWatcher();
}
if (credentialsWatcher) {
credentialsWatcher();
}
$scope.promptData = null;
$scope.selectedTemplateInvalid = false;
$scope.showPromptButton = false;
@ -671,6 +699,24 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
$scope.selectedTemplateInvalid = false;
}
let credentialRequiresPassword = false;
prompts.credentials.value.forEach((credential) => {
if(credential.inputs) {
if ((credential.inputs.password && credential.inputs.password === "ASK") ||
(credential.inputs.become_password && credential.inputs.become_password === "ASK") ||
(credential.inputs.ssh_key_unlock && credential.inputs.ssh_key_unlock === "ASK") ||
(credential.inputs.vault_password && credential.inputs.vault_password === "ASK")
) {
credentialRequiresPassword = true;
}
} else if (credential.passwords_needed && credential.passwords_needed.length > 0) {
credentialRequiresPassword = true;
}
});
$scope.credentialRequiresPassword = credentialRequiresPassword;
if (!launchConf.survey_enabled &&
!launchConf.ask_inventory_on_launch &&
!launchConf.ask_credential_on_launch &&
@ -682,7 +728,6 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
!launchConf.ask_diff_mode_on_launch &&
!launchConf.survey_enabled &&
!launchConf.credential_needed_to_start &&
launchConf.passwords_needed_to_start.length === 0 &&
launchConf.variables_needed_to_start.length === 0) {
$scope.showPromptButton = false;
$scope.promptModalMissingReqFields = false;
@ -727,6 +772,8 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
$scope.missingSurveyValue = missingSurveyValue;
}, true);
checkCredentialsForRequiredPasswords();
watchForPromptChanges();
});
} else {
@ -736,6 +783,9 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
prompts: prompts,
template: $scope.nodeBeingEdited.unifiedJobTemplate.id
};
checkCredentialsForRequiredPasswords();
watchForPromptChanges();
}
}
@ -980,6 +1030,10 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
surveyQuestionWatcher();
}
if (credentialsWatcher) {
credentialsWatcher();
}
if (selectedTemplate.type === "job_template") {
let jobTemplate = new JobTemplate();
@ -993,6 +1047,12 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
$scope.selectedTemplateInvalid = false;
}
if (launchConf.passwords_needed_to_start && launchConf.passwords_needed_to_start.length > 0) {
$scope.credentialRequiresPassword = true;
} else {
$scope.credentialRequiresPassword = false;
}
$scope.selectedTemplate = angular.copy(selectedTemplate);
if (!launchConf.survey_enabled &&
@ -1006,7 +1066,6 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
!launchConf.ask_diff_mode_on_launch &&
!launchConf.survey_enabled &&
!launchConf.credential_needed_to_start &&
launchConf.passwords_needed_to_start.length === 0 &&
launchConf.variables_needed_to_start.length === 0) {
$scope.showPromptButton = false;
$scope.promptModalMissingReqFields = false;
@ -1069,7 +1128,6 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
}
});
} else {
// TODO - clear out prompt data?
$scope.selectedTemplate = angular.copy(selectedTemplate);
$scope.selectedTemplateInvalid = false;
$scope.showPromptButton = false;

View File

@ -99,7 +99,13 @@
<span>{{:: strings.get('workflows.INVALID_JOB_TEMPLATE') }}</span>
</div>
</div>
<div class="form-group Form-formGroup Form-formGroup--singleColumn" ng-show="selectedTemplate && !selectedTemplateInvalid">
<div ng-if="selectedTemplate && credentialRequiresPassword">
<div class="WorkflowMaker-invalidJobTemplateWarning">
<span class="fa fa-warning"></span>
<span>{{:: strings.get('workflows.CREDENTIAL_WITH_PASS') }}</span>
</div>
</div>
<div class="form-group Form-formGroup Form-formGroup--singleColumn" ng-show="selectedTemplate && !selectedTemplateInvalid && !(credentialRequiresPassword && !promptData.launchConf.ask_credential_on_launch)">
<label for="verbosity" class="Form-inputLabelContainer">
<span class="Form-requiredAsterisk">*</span>
<span class="Form-inputLabel">RUN</span>
@ -121,7 +127,7 @@
<button type="button" class="btn btn-sm Form-primaryButton Form-primaryButton--noMargin" id="workflow_maker_prompt_btn" ng-show="showPromptButton" ng-click="openPromptModal()"> Prompt</button>
<button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_cancel_btn" ng-show="(workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)" ng-click="cancelNodeForm()"> Cancel</button>
<button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_close_btn" ng-show="!(workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)" ng-click="cancelNodeForm()"> Close</button>
<button type="button" class="btn btn-sm Form-saveButton" id="workflow_maker_select_btn" ng-show="(workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate) && !selectedTemplateInvalid" ng-click="confirmNodeForm()" ng-disabled="!selectedTemplate || promptModalMissingReqFields"> Select</button>
<button type="button" class="btn btn-sm Form-saveButton" id="workflow_maker_select_btn" ng-show="(workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate) && !selectedTemplateInvalid && !(credentialRequiresPassword && !promptData.launchConf.ask_credential_on_launch)" ng-click="confirmNodeForm()" ng-disabled="!selectedTemplate || promptModalMissingReqFields || credentialRequiresPassword"> Select</button>
</div>
</div>
</div>