mirror of
https://github.com/ansible/awx.git
synced 2026-01-20 14:11:24 -03:30
Fixed various bugs with preventing prompting for credential passwords on schedules and workflow nodes
This commit is contained in:
parent
09ee140fb4
commit
68ac23dd46
@ -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.')
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user