diff --git a/ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/lib/actions.js b/ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/lib/actions.js new file mode 100644 index 0000000000000000000000000000000000000000..30f610bdcb66feba3278c27366b22f05a4ff231e --- /dev/null +++ b/ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/lib/actions.js @@ -0,0 +1,52 @@ +export const USER_TYPE = 'user'; +const GROUP_TYPE = 'group'; + +/* + Return the ids for all approvers of the group type. +*/ +export function groupIds(approvers) { + return approvers + .filter((approver) => approver.type === GROUP_TYPE) + .map((approver) => approver.id); +} + +/* + Return the ids for all approvers of the user type. +*/ +export function userIds(approvers) { + return approvers.filter((approver) => approver.type === USER_TYPE).map((approver) => approver.id); +} + +/* + Group existing approvers into a single array. +*/ +export function groupApprovers(existingApprovers) { + const approvers = [...existingApprovers]; + const userUniqKeys = ['state', 'username']; + const groupUniqKeys = ['full_name', 'full_path']; + + return approvers.map((approver) => { + const approverKeys = Object.keys(approver); + + if (approverKeys.includes(...groupUniqKeys)) { + return { ...approver, type: GROUP_TYPE }; + } else if (approverKeys.includes(...userUniqKeys)) { + return { ...approver, type: USER_TYPE }; + } + return approver; + }); +} + +/* + Convert approvers into yaml fields (user_approvers, users_approvers_ids) in relation to action. +*/ +export function decomposeApprovers(action, approvers) { + const newAction = { ...action }; + delete newAction.group_approvers; + delete newAction.user_approvers; + return { + ...newAction, + user_approvers_ids: userIds(approvers), + group_approvers_ids: groupIds(approvers), + }; +} diff --git a/ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/lib/from_yaml.js b/ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/lib/from_yaml.js index b93cf76c241f148543f5443b7fb5b9cbfc404055..c29681ddd3081e70f1f6f9a1eb43e662190d0b56 100644 --- a/ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/lib/from_yaml.js +++ b/ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/lib/from_yaml.js @@ -1,8 +1,50 @@ import { safeLoad } from 'js-yaml'; +/** + * Checks for parameters unsupported by the scan result policy "Rule Mode" + * @param {String} manifest YAML of scan result policy + * @returns {Boolean} whether the YAML is valid to be parsed into "Rule Mode" + */ +const hasUnsupportedAttribute = (manifest) => { + const primaryKeys = ['type', 'name', 'description', 'enabled', 'rules', 'actions']; + const rulesKeys = [ + 'type', + 'branches', + 'scanners', + 'vulnerabilities_allowed', + 'severity_levels', + 'vulnerability_states', + ]; + const actionsKeys = [ + 'type', + 'approvals_required', + 'user_approvers', + 'group_approvers', + 'user_approvers_ids', + 'group_approvers_ids', + ]; + + let isUnsupported = false; + const hasInvalidKey = (object, allowedValues) => { + return !Object.keys(object).every((item) => allowedValues.includes(item)); + }; + + isUnsupported = hasInvalidKey(manifest, primaryKeys); + + if (manifest?.rules && !isUnsupported) { + isUnsupported = manifest.rules.find((rule) => hasInvalidKey(rule, rulesKeys)); + } + if (manifest?.actions && !isUnsupported) { + isUnsupported = manifest.actions.find((action) => hasInvalidKey(action, actionsKeys)); + } + + return isUnsupported; +}; + /* Construct a policy object expected by the policy editor from a yaml manifest. */ export const fromYaml = (manifest) => { - return safeLoad(manifest, { json: true }); + const policy = safeLoad(manifest, { json: true }); + return hasUnsupportedAttribute(policy) ? { error: true } : policy; }; diff --git a/ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/policy_action_builder.vue b/ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/policy_action_builder.vue new file mode 100644 index 0000000000000000000000000000000000000000..c1fd280427af1fd1bc5e8ac967f6e0ea3836997d --- /dev/null +++ b/ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/policy_action_builder.vue @@ -0,0 +1,124 @@ + + + diff --git a/ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/scan_result_policy_editor.vue b/ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/scan_result_policy_editor.vue index 811e5ccec3d6991d595a786b7dfa4fb55cf8169b..f11806712d019bb26cd4c3a04463687d22f4d3c4 100644 --- a/ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/scan_result_policy_editor.vue +++ b/ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/scan_result_policy_editor.vue @@ -1,31 +1,58 @@