Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
5bc6ae0d
Commit
5bc6ae0d
authored
Jan 24, 2022
by
Zamir Martins
Committed by
Vitaly Slobodin
Jan 24, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add scan result policy into policy editor
EE: true Changelog: changed
parent
2f33a8cb
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
476 additions
and
50 deletions
+476
-50
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/constants.js
...s/threat_monitoring/components/policy_editor/constants.js
+14
-0
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/policy_editor.vue
...eat_monitoring/components/policy_editor/policy_editor.vue
+20
-3
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_execution_policy/lib/constants.js
...ents/policy_editor/scan_execution_policy/lib/constants.js
+0
-14
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_execution_policy/lib/humanize.js
...nents/policy_editor/scan_execution_policy/lib/humanize.js
+1
-1
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_execution_policy/lib/index.js
...mponents/policy_editor/scan_execution_policy/lib/index.js
+0
-3
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_execution_policy/scan_execution_policy_editor.vue
...or/scan_execution_policy/scan_execution_policy_editor.vue
+7
-9
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/lib/constants.js
...ponents/policy_editor/scan_result_policy/lib/constants.js
+0
-3
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/lib/humanize.js
...mponents/policy_editor/scan_result_policy/lib/humanize.js
+1
-1
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/lib/index.js
.../components/policy_editor/scan_result_policy/lib/index.js
+23
-1
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/lib/to_yaml.js
...omponents/policy_editor/scan_result_policy/lib/to_yaml.js
+8
-0
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/scan_result_policy_editor.vue
...y_editor/scan_result_policy/scan_result_policy_editor.vue
+162
-0
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/utils.js
...ripts/threat_monitoring/components/policy_editor/utils.js
+0
-0
ee/spec/frontend/threat_monitoring/components/policy_editor/policy_editor_spec.js
...monitoring/components/policy_editor/policy_editor_spec.js
+60
-2
ee/spec/frontend/threat_monitoring/components/policy_editor/scan_execution_policy/lib/humanize_spec.js
.../policy_editor/scan_execution_policy/lib/humanize_spec.js
+3
-1
ee/spec/frontend/threat_monitoring/components/policy_editor/scan_execution_policy/lib/utils_spec.js
...nts/policy_editor/scan_execution_policy/lib/utils_spec.js
+1
-1
ee/spec/frontend/threat_monitoring/components/policy_editor/scan_execution_policy/scan_execution_policy_editor_spec.js
...can_execution_policy/scan_execution_policy_editor_spec.js
+11
-7
ee/spec/frontend/threat_monitoring/components/policy_editor/scan_result_policy/lib/humanize_spec.js
...nts/policy_editor/scan_result_policy/lib/humanize_spec.js
+3
-1
ee/spec/frontend/threat_monitoring/components/policy_editor/scan_result_policy/scan_result_policy_editor_spec.js
...itor/scan_result_policy/scan_result_policy_editor_spec.js
+132
-0
ee/spec/frontend/threat_monitoring/mocks/mock_data.js
ee/spec/frontend/threat_monitoring/mocks/mock_data.js
+26
-2
locale/gitlab.pot
locale/gitlab.pot
+4
-1
No files found.
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/constants.js
View file @
5bc6ae0d
...
...
@@ -22,3 +22,17 @@ export const DELETE_MODAL_CONFIG = {
text
:
__
(
'
Cancel
'
),
},
};
export
const
DEFAULT_MR_TITLE
=
s__
(
'
SecurityOrchestration|Update scan policies
'
);
export
const
SECURITY_POLICY_ACTIONS
=
Object
.
freeze
({
APPEND
:
'
APPEND
'
,
REMOVE
:
'
REMOVE
'
,
REPLACE
:
'
REPLACE
'
,
});
export
const
GRAPHQL_ERROR_MESSAGE
=
s__
(
'
SecurityOrchestration|There was a problem creating the new security policy
'
,
);
export
const
NO_RULE_MESSAGE
=
s__
(
'
SecurityOrchestration|No rules defined - policy will not run.
'
);
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/policy_editor.vue
View file @
5bc6ae0d
<
script
>
import
{
GlAlert
,
GlFormGroup
,
GlFormSelect
}
from
'
@gitlab/ui
'
;
import
{
s__
}
from
'
~/locale
'
;
import
glFeatureFlagMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
import
{
POLICY_TYPE_COMPONENT_OPTIONS
}
from
'
../constants
'
;
import
EnvironmentPicker
from
'
../environment_picker.vue
'
;
import
NetworkPolicyEditor
from
'
./network_policy/network_policy_editor.vue
'
;
import
ScanExecutionPolicyEditor
from
'
./scan_execution_policy/scan_execution_policy_editor.vue
'
;
import
ScanResultPolicyEditor
from
'
./scan_result_policy/scan_result_policy_editor.vue
'
;
export
default
{
components
:
{
...
...
@@ -14,7 +16,9 @@ export default {
EnvironmentPicker
,
NetworkPolicyEditor
,
ScanExecutionPolicyEditor
,
ScanResultPolicyEditor
,
},
mixins
:
[
glFeatureFlagMixin
()],
inject
:
[
'
policyType
'
],
props
:
{
assignedPolicyProject
:
{
...
...
@@ -38,13 +42,23 @@ export default {
return
this
.
isEditing
?
this
.
policyType
:
this
.
newPolicyType
;
},
isEditing
()
{
if
(
!
this
.
existingPolicy
)
{
return
false
;
}
return
Boolean
(
this
.
existingPolicy
?.
creation_timestamp
||
this
.
existingPolicy
?.
type
===
POLICY_TYPE_COMPONENT_OPTIONS
.
scanExecution
.
urlParameter
,
this
.
existingPolicy
.
creation_timestamp
||
[
POLICY_TYPE_COMPONENT_OPTIONS
.
scanExecution
.
urlParameter
,
POLICY_TYPE_COMPONENT_OPTIONS
.
scanResult
?.
urlParameter
,
].
includes
(
this
.
existingPolicy
.
type
),
);
},
policyTypes
()
{
return
Object
.
values
(
POLICY_TYPE_COMPONENT_OPTIONS
);
const
types
=
Object
.
values
(
POLICY_TYPE_COMPONENT_OPTIONS
);
return
this
.
isScanResultPolicyEnabled
?
types
:
types
.
filter
((
type
)
=>
type
.
value
!==
POLICY_TYPE_COMPONENT_OPTIONS
.
scanResult
?.
value
);
},
policyOptions
()
{
return
(
...
...
@@ -58,6 +72,9 @@ export default {
shouldAllowPolicyTypeSelection
()
{
return
!
this
.
existingPolicy
;
},
isScanResultPolicyEnabled
()
{
return
this
.
glFeatures
.
scanResultPolicy
;
},
},
methods
:
{
setError
(
error
)
{
...
...
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_execution_policy/lib/constants.js
deleted
100644 → 0
View file @
2f33a8cb
import
{
s__
}
from
'
~/locale
'
;
export
const
DEFAULT_MR_TITLE
=
s__
(
'
SecurityOrchestration|Update scan execution policies
'
);
export
const
GRAPHQL_ERROR_MESSAGE
=
s__
(
'
SecurityOrchestration|There was a problem creating the new security policy
'
,
);
export
const
NO_RULE_MESSAGE
=
s__
(
'
SecurityOrchestration|No rules defined - policy will not run.
'
);
export
const
SECURITY_POLICY_ACTIONS
=
{
APPEND
:
'
APPEND
'
,
REMOVE
:
'
REMOVE
'
,
REPLACE
:
'
REPLACE
'
,
};
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_execution_policy/lib/humanize.js
View file @
5bc6ae0d
import
cronstrue
from
'
cronstrue/i18n
'
;
import
{
convertToTitleCase
,
humanize
}
from
'
~/lib/utils/text_utility
'
;
import
{
getPreferredLocales
,
sprintf
,
s__
,
n__
}
from
'
~/locale
'
;
import
{
NO_RULE_MESSAGE
}
from
'
./constants
'
;
import
{
NO_RULE_MESSAGE
}
from
'
.
./..
/constants
'
;
const
getActionText
=
(
scanType
)
=>
sprintf
(
s__
(
'
SecurityOrchestration|Executes a %{scanType} scan
'
),
{
...
...
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_execution_policy/lib/index.js
View file @
5bc6ae0d
export
{
fromYaml
}
from
'
./from_yaml
'
;
export
{
toYaml
}
from
'
./to_yaml
'
;
export
*
from
'
./constants
'
;
export
*
from
'
./humanize
'
;
export
*
from
'
./utils
'
;
export
const
DEFAULT_SCAN_EXECUTION_POLICY
=
`type: scan_execution_policy
name: ''
...
...
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_execution_policy/scan_execution_policy_editor.vue
View file @
5bc6ae0d
...
...
@@ -2,17 +2,15 @@
import
{
GlEmptyState
}
from
'
@gitlab/ui
'
;
import
{
joinPaths
,
visitUrl
}
from
'
~/lib/utils/url_utility
'
;
import
{
__
,
s__
}
from
'
~/locale
'
;
import
{
EDITOR_MODES
,
EDITOR_MODE_YAML
}
from
'
../constants
'
;
import
PolicyEditorLayout
from
'
../policy_editor_layout.vue
'
;
import
{
assignSecurityPolicyProject
,
DEFAULT_SCAN_EXECUTION_POLICY
,
fromYaml
,
GRAPHQL_ERROR_MESSAGE
,
modifyPolicy
,
EDITOR_MODES
,
EDITOR_MODE_YAML
,
SECURITY_POLICY_ACTIONS
,
toYaml
,
}
from
'
./lib
'
;
GRAPHQL_ERROR_MESSAGE
,
}
from
'
../constants
'
;
import
PolicyEditorLayout
from
'
../policy_editor_layout.vue
'
;
import
{
assignSecurityPolicyProject
,
modifyPolicy
}
from
'
../utils
'
;
import
{
DEFAULT_SCAN_EXECUTION_POLICY
,
fromYaml
,
toYaml
}
from
'
./lib
'
;
export
default
{
SECURITY_POLICY_ACTIONS
,
...
...
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/lib/constants.js
deleted
100644 → 0
View file @
2f33a8cb
import
{
s__
}
from
'
~/locale
'
;
export
const
NO_RULE_MESSAGE
=
s__
(
'
SecurityOrchestration|No rules defined - policy will not run.
'
);
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/lib/humanize.js
View file @
5bc6ae0d
import
{
sprintf
,
s__
,
n__
}
from
'
~/locale
'
;
import
{
NO_RULE_MESSAGE
}
from
'
./constants
'
;
import
{
NO_RULE_MESSAGE
}
from
'
.
./..
/constants
'
;
/**
* Simple logic for indefinite articles which does not include the exceptions
...
...
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/lib/index.js
View file @
5bc6ae0d
export
{
fromYaml
}
from
'
./from_yaml
'
;
export
{
toYaml
}
from
'
./to_yaml
'
;
export
*
from
'
./humanize
'
;
export
*
from
'
./constants
'
;
export
const
DEFAULT_SCAN_RESULT_POLICY
=
`type: scan_result_policy
name: ''
description: ''
enabled: false
rules:
- type: scan_finding
branches:
- main
scanners:
- container_scanning
vulnerabilities_allowed: 0
severity_levels:
- critical
vulnerability_states:
- newly_added
actions:
- type: require_approval
approvals_required: 1
user_approvers:
- security_user
`
;
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/lib/to_yaml.js
0 → 100644
View file @
5bc6ae0d
import
{
safeDump
}
from
'
js-yaml
'
;
/*
Return yaml representation of a policy.
*/
export
const
toYaml
=
(
policy
)
=>
{
return
safeDump
(
policy
);
};
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/scan_result_policy/scan_result_policy_editor.vue
0 → 100644
View file @
5bc6ae0d
<
script
>
import
{
GlEmptyState
}
from
'
@gitlab/ui
'
;
import
{
joinPaths
,
visitUrl
}
from
'
~/lib/utils/url_utility
'
;
import
{
__
,
s__
}
from
'
~/locale
'
;
import
{
EDITOR_MODES
,
EDITOR_MODE_YAML
,
SECURITY_POLICY_ACTIONS
,
GRAPHQL_ERROR_MESSAGE
,
}
from
'
../constants
'
;
import
PolicyEditorLayout
from
'
../policy_editor_layout.vue
'
;
import
{
assignSecurityPolicyProject
,
modifyPolicy
}
from
'
../utils
'
;
import
{
DEFAULT_SCAN_RESULT_POLICY
,
fromYaml
,
toYaml
}
from
'
./lib
'
;
export
default
{
SECURITY_POLICY_ACTIONS
,
DEFAULT_EDITOR_MODE
:
EDITOR_MODE_YAML
,
EDITOR_MODES
:
[
EDITOR_MODES
[
1
]],
i18n
:
{
createMergeRequest
:
__
(
'
Create via merge request
'
),
notOwnerButtonText
:
__
(
'
Learn more
'
),
notOwnerDescription
:
s__
(
'
SecurityOrchestration|Scan result policies can only be created by project owners.
'
,
),
},
components
:
{
GlEmptyState
,
PolicyEditorLayout
,
},
inject
:
[
'
disableScanExecutionUpdate
'
,
'
policyEditorEmptyStateSvgPath
'
,
'
projectId
'
,
'
projectPath
'
,
'
scanExecutionDocumentationPath
'
,
],
props
:
{
assignedPolicyProject
:
{
type
:
Object
,
required
:
true
,
},
existingPolicy
:
{
type
:
Object
,
required
:
false
,
default
:
null
,
},
isEditing
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
data
()
{
const
yamlEditorValue
=
this
.
existingPolicy
?
toYaml
(
this
.
existingPolicy
)
:
DEFAULT_SCAN_RESULT_POLICY
;
return
{
error
:
''
,
isCreatingMR
:
false
,
isRemovingPolicy
:
false
,
newlyCreatedPolicyProject
:
null
,
policy
:
fromYaml
(
yamlEditorValue
),
yamlEditorValue
,
};
},
computed
:
{
originalName
()
{
return
this
.
existingPolicy
?.
name
;
},
policyActionName
()
{
return
this
.
isEditing
?
this
.
$options
.
SECURITY_POLICY_ACTIONS
.
REPLACE
:
this
.
$options
.
SECURITY_POLICY_ACTIONS
.
APPEND
;
},
},
methods
:
{
handleError
(
error
)
{
if
(
error
.
message
.
toLowerCase
().
includes
(
'
graphql
'
))
{
this
.
$emit
(
'
error
'
,
GRAPHQL_ERROR_MESSAGE
);
}
else
{
this
.
$emit
(
'
error
'
,
error
.
message
);
}
},
async
getSecurityPolicyProject
()
{
if
(
!
this
.
newlyCreatedPolicyProject
&&
!
this
.
assignedPolicyProject
.
fullPath
)
{
this
.
newlyCreatedPolicyProject
=
await
assignSecurityPolicyProject
(
this
.
projectPath
);
}
return
this
.
newlyCreatedPolicyProject
||
this
.
assignedPolicyProject
;
},
async
handleModifyPolicy
(
act
)
{
const
action
=
act
||
this
.
policyActionName
;
this
.
$emit
(
'
error
'
,
''
);
this
.
setLoadingFlag
(
action
,
true
);
try
{
const
assignedPolicyProject
=
await
this
.
getSecurityPolicyProject
();
const
mergeRequest
=
await
modifyPolicy
({
action
,
assignedPolicyProject
,
name
:
this
.
originalName
||
fromYaml
(
this
.
yamlEditorValue
)?.
name
,
projectPath
:
this
.
projectPath
,
yamlEditorValue
:
this
.
yamlEditorValue
,
});
this
.
redirectToMergeRequest
({
mergeRequest
,
assignedPolicyProject
});
}
catch
(
e
)
{
this
.
handleError
(
e
);
this
.
setLoadingFlag
(
action
,
false
);
}
},
setLoadingFlag
(
action
,
val
)
{
if
(
action
===
SECURITY_POLICY_ACTIONS
.
REMOVE
)
{
this
.
isRemovingPolicy
=
val
;
}
else
{
this
.
isCreatingMR
=
val
;
}
},
redirectToMergeRequest
({
mergeRequest
,
assignedPolicyProject
})
{
visitUrl
(
joinPaths
(
gon
.
relative_url_root
||
'
/
'
,
assignedPolicyProject
.
fullPath
,
'
/-/merge_requests
'
,
mergeRequest
.
id
,
),
);
},
updateYaml
(
manifest
)
{
this
.
yamlEditorValue
=
manifest
;
},
},
};
</
script
>
<
template
>
<policy-editor-layout
v-if=
"!disableScanExecutionUpdate"
:custom-save-button-text=
"$options.i18n.createMergeRequest"
:default-editor-mode=
"$options.DEFAULT_EDITOR_MODE"
:editor-modes=
"$options.EDITOR_MODES"
:is-editing=
"isEditing"
:is-removing-policy=
"isRemovingPolicy"
:is-updating-policy=
"isCreatingMR"
:policy-name=
"policy.name"
:yaml-editor-value=
"yamlEditorValue"
@
remove-policy=
"handleModifyPolicy($options.SECURITY_POLICY_ACTIONS.REMOVE)"
@
save-policy=
"handleModifyPolicy()"
@
update-yaml=
"updateYaml"
/>
<gl-empty-state
v-else
:description=
"$options.i18n.notOwnerDescription"
:primary-button-link=
"scanExecutionDocumentationPath"
:primary-button-text=
"$options.i18n.notOwnerButtonText"
:svg-path=
"policyEditorEmptyStateSvgPath"
title=
""
/>
</
template
>
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/
scan_execution_policy/lib/
utils.js
→
ee/app/assets/javascripts/threat_monitoring/components/policy_editor/utils.js
View file @
5bc6ae0d
File moved
ee/spec/frontend/threat_monitoring/components/policy_editor/policy_editor_spec.js
View file @
5bc6ae0d
...
...
@@ -5,8 +5,13 @@ import EnvironmentPicker from 'ee/threat_monitoring/components/environment_picke
import
NetworkPolicyEditor
from
'
ee/threat_monitoring/components/policy_editor/network_policy/network_policy_editor.vue
'
;
import
PolicyEditor
from
'
ee/threat_monitoring/components/policy_editor/policy_editor.vue
'
;
import
ScanExecutionPolicyEditor
from
'
ee/threat_monitoring/components/policy_editor/scan_execution_policy/scan_execution_policy_editor.vue
'
;
import
ScanResultPolicyEditor
from
'
ee/threat_monitoring/components/policy_editor/scan_result_policy/scan_result_policy_editor.vue
'
;
import
{
DEFAULT_ASSIGNED_POLICY_PROJECT
}
from
'
ee/threat_monitoring/constants
'
;
import
{
mockDastScanExecutionObject
,
mockL3Manifest
}
from
'
../../mocks/mock_data
'
;
import
{
mockDastScanExecutionObject
,
mockL3Manifest
,
mockScanResultObject
,
}
from
'
../../mocks/mock_data
'
;
describe
(
'
PolicyEditor component
'
,
()
=>
{
let
wrapper
;
...
...
@@ -16,6 +21,7 @@ describe('PolicyEditor component', () => {
const
findFormSelect
=
()
=>
wrapper
.
findComponent
(
GlFormSelect
);
const
findNeworkPolicyEditor
=
()
=>
wrapper
.
findComponent
(
NetworkPolicyEditor
);
const
findScanExecutionPolicyEditor
=
()
=>
wrapper
.
findComponent
(
ScanExecutionPolicyEditor
);
const
findScanResultPolicyEditor
=
()
=>
wrapper
.
findComponent
(
ScanResultPolicyEditor
);
const
factory
=
({
propsData
=
{},
provide
=
{}
}
=
{})
=>
{
wrapper
=
shallowMount
(
PolicyEditor
,
{
...
...
@@ -25,6 +31,7 @@ describe('PolicyEditor component', () => {
},
provide
:
{
policyType
:
undefined
,
glFeatures
:
{
scanResultPolicy
:
true
},
...
provide
,
},
stubs
:
{
GlFormSelect
},
...
...
@@ -69,6 +76,7 @@ describe('PolicyEditor component', () => {
policyType | option | findComponent
${
'
container
'
}
|
${
POLICY_TYPE_COMPONENT_OPTIONS
.
container
}
|
${
findNeworkPolicyEditor
}
${
'
scanExecution
'
}
|
${
POLICY_TYPE_COMPONENT_OPTIONS
.
scanExecution
}
|
${
findScanExecutionPolicyEditor
}
${
'
scanResult
'
}
|
${
POLICY_TYPE_COMPONENT_OPTIONS
.
scanResult
}
|
${
findScanResultPolicyEditor
}
`
(
'
renders the policy editor of type $policyType when selected
'
,
async
({
findComponent
,
option
,
policyType
})
=>
{
...
...
@@ -81,6 +89,26 @@ describe('PolicyEditor component', () => {
expect
(
component
.
props
(
'
isEditing
'
)).
toBe
(
false
);
},
);
describe
(
'
with scan_result_policy feature flag disabled
'
,
()
=>
{
beforeEach
(()
=>
{
factory
({
provide
:
{
glFeatures
:
{
scanResultPolicy
:
false
}
}
});
const
formSelect
=
findFormSelect
();
formSelect
.
vm
.
$emit
(
'
change
'
,
POLICY_TYPE_COMPONENT_OPTIONS
.
scanResult
.
value
);
wrapper
.
vm
.
$nextTick
();
});
it
(
'
does not render scan result policy
'
,
()
=>
{
const
component
=
findScanResultPolicyEditor
();
expect
(
component
.
exists
()).
toBe
(
false
);
});
it
(
'
renders network policy with isEditing set to false
'
,
()
=>
{
const
component
=
findNeworkPolicyEditor
();
expect
(
component
.
exists
()).
toBe
(
true
);
expect
(
component
.
props
(
'
isEditing
'
)).
toBe
(
false
);
});
});
});
describe
(
'
when an existing policy is present
'
,
()
=>
{
...
...
@@ -88,10 +116,14 @@ describe('PolicyEditor component', () => {
policyType | option | existingPolicy | findComponent
${
'
container_policy
'
}
|
${
POLICY_TYPE_COMPONENT_OPTIONS
.
container
}
|
${{
manifest
:
mockL3Manifest
,
creation_timestamp
:
'
2020-04-14T00:08:30Z
'
}
} |
${
findNeworkPolicyEditor
}
${
'
scan_execution_policy
'
}
|
${
POLICY_TYPE_COMPONENT_OPTIONS
.
scanExecution
}
|
${
mockDastScanExecutionObject
}
|
${
findScanExecutionPolicyEditor
}
${
'
scan_result_policy
'
}
|
${
POLICY_TYPE_COMPONENT_OPTIONS
.
scanResult
}
|
${
mockScanResultObject
}
|
${
findScanResultPolicyEditor
}
`
(
'
renders the disabled form select for existing policy of type $policyType
'
,
async
({
existingPolicy
,
findComponent
,
option
,
policyType
})
=>
{
factory
({
propsData
:
{
existingPolicy
},
provide
:
{
policyType
}
});
factory
({
propsData
:
{
existingPolicy
},
provide
:
{
policyType
,
glFeatures
:
{
scanResultPolicy
:
true
}
},
});
await
wrapper
.
vm
.
$nextTick
();
const
formSelect
=
findFormSelect
();
expect
(
formSelect
.
exists
()).
toBe
(
true
);
...
...
@@ -102,5 +134,31 @@ describe('PolicyEditor component', () => {
expect
(
component
.
props
(
'
isEditing
'
)).
toBe
(
true
);
},
);
describe
(
'
with scan_result_policy feature flag disabled
'
,
()
=>
{
beforeEach
(()
=>
{
factory
({
propsData
:
{
existingPolicy
:
mockScanResultObject
},
provide
:
{
policyType
:
POLICY_TYPE_COMPONENT_OPTIONS
.
scanResult
.
urlParameter
,
glFeatures
:
{
scanResultPolicy
:
false
},
},
});
});
it
(
'
does not display the scan result as one of the dropdown options
'
,
()
=>
{
const
formSelect
=
findFormSelect
();
expect
(
formSelect
.
vm
.
$attrs
.
options
).
toMatchObject
([
POLICY_TYPE_COMPONENT_OPTIONS
.
container
,
POLICY_TYPE_COMPONENT_OPTIONS
.
scanExecution
,
]);
});
it
(
'
renders network policy with isEditing set to true
'
,
()
=>
{
const
component
=
findNeworkPolicyEditor
();
expect
(
component
.
exists
()).
toBe
(
true
);
expect
(
component
.
props
(
'
isEditing
'
)).
toBe
(
true
);
});
});
});
});
ee/spec/frontend/threat_monitoring/components/policy_editor/scan_execution_policy/lib/humanize_spec.js
View file @
5bc6ae0d
import
{
humanizeActions
,
humanizeRules
,
NO_RULE_MESSAGE
,
}
from
'
ee/threat_monitoring/components/policy_editor/scan_execution_policy/lib
'
;
import
{
NO_RULE_MESSAGE
}
from
'
ee/threat_monitoring/components/policy_editor/constants
'
;
jest
.
mock
(
'
~/locale
'
,
()
=>
({
getPreferredLocales
:
jest
.
fn
().
mockReturnValue
([
'
en
'
]),
sprintf
:
jest
.
requireActual
(
'
~/locale
'
).
sprintf
,
s__
:
jest
.
requireActual
(
'
~/locale
'
).
s__
,
// eslint-disable-line no-underscore-dangle
n__
:
jest
.
requireActual
(
'
~/locale
'
).
n__
,
// eslint-disable-line no-underscore-dangle
__
:
jest
.
requireActual
(
'
~/locale
'
).
__
,
}));
const
mockActions
=
[
...
...
ee/spec/frontend/threat_monitoring/components/policy_editor/scan_execution_policy/lib/utils_spec.js
View file @
5bc6ae0d
import
{
assignSecurityPolicyProject
,
modifyPolicy
,
}
from
'
ee/threat_monitoring/components/policy_editor/
scan_execution_policy/lib/
utils
'
;
}
from
'
ee/threat_monitoring/components/policy_editor/utils
'
;
import
{
DEFAULT_ASSIGNED_POLICY_PROJECT
}
from
'
ee/threat_monitoring/constants
'
;
import
createPolicyProject
from
'
ee/threat_monitoring/graphql/mutations/create_policy_project.mutation.graphql
'
;
import
createScanExecutionPolicy
from
'
ee/threat_monitoring/graphql/mutations/create_scan_execution_policy.mutation.graphql
'
;
...
...
ee/spec/frontend/threat_monitoring/components/policy_editor/scan_execution_policy/scan_execution_policy_editor_spec.js
View file @
5bc6ae0d
...
...
@@ -5,8 +5,6 @@ import PolicyEditorLayout from 'ee/threat_monitoring/components/policy_editor/po
import
{
DEFAULT_SCAN_EXECUTION_POLICY
,
fromYaml
,
modifyPolicy
,
SECURITY_POLICY_ACTIONS
,
}
from
'
ee/threat_monitoring/components/policy_editor/scan_execution_policy/lib
'
;
import
ScanExecutionPolicyEditor
from
'
ee/threat_monitoring/components/policy_editor/scan_execution_policy/scan_execution_policy_editor.vue
'
;
import
{
DEFAULT_ASSIGNED_POLICY_PROJECT
}
from
'
ee/threat_monitoring/constants
'
;
...
...
@@ -16,6 +14,9 @@ import {
}
from
'
ee_jest/threat_monitoring/mocks/mock_data
'
;
import
{
visitUrl
}
from
'
~/lib/utils/url_utility
'
;
import
{
modifyPolicy
}
from
'
ee/threat_monitoring/components/policy_editor/utils
'
;
import
{
SECURITY_POLICY_ACTIONS
}
from
'
ee/threat_monitoring/components/policy_editor/constants
'
;
jest
.
mock
(
'
~/lib/utils/url_utility
'
,
()
=>
({
joinPaths
:
jest
.
requireActual
(
'
~/lib/utils/url_utility
'
).
joinPaths
,
visitUrl
:
jest
.
fn
().
mockName
(
'
visitUrlMock
'
),
...
...
@@ -27,10 +28,6 @@ const newlyCreatedPolicyProject = {
};
jest
.
mock
(
'
ee/threat_monitoring/components/policy_editor/scan_execution_policy/lib
'
,
()
=>
({
assignSecurityPolicyProject
:
jest
.
fn
().
mockResolvedValue
({
branch
:
'
main
'
,
fullPath
:
'
path/to/new-project
'
,
}),
DEFAULT_SCAN_EXECUTION_POLICY
:
jest
.
requireActual
(
'
ee/threat_monitoring/components/policy_editor/scan_execution_policy/lib
'
,
).
DEFAULT_SCAN_EXECUTION_POLICY
,
...
...
@@ -41,8 +38,15 @@ jest.mock('ee/threat_monitoring/components/policy_editor/scan_execution_policy/l
'
ee/threat_monitoring/components/policy_editor/scan_execution_policy/lib
'
,
).
toYaml
,
SECURITY_POLICY_ACTIONS
:
jest
.
requireActual
(
'
ee/threat_monitoring/components/policy_editor/
scan_execution_policy/lib
'
,
'
ee/threat_monitoring/components/policy_editor/
constants
'
,
).
SECURITY_POLICY_ACTIONS
,
}));
jest
.
mock
(
'
ee/threat_monitoring/components/policy_editor/utils
'
,
()
=>
({
assignSecurityPolicyProject
:
jest
.
fn
().
mockResolvedValue
({
branch
:
'
main
'
,
fullPath
:
'
path/to/new-project
'
,
}),
modifyPolicy
:
jest
.
fn
().
mockResolvedValue
({
id
:
'
2
'
}),
}));
...
...
ee/spec/frontend/threat_monitoring/components/policy_editor/scan_result_policy/lib/humanize_spec.js
View file @
5bc6ae0d
import
{
humanizeRules
,
humanizeAction
,
NO_RULE_MESSAGE
,
}
from
'
ee/threat_monitoring/components/policy_editor/scan_result_policy/lib
'
;
import
{
NO_RULE_MESSAGE
}
from
'
ee/threat_monitoring/components/policy_editor/constants
'
;
jest
.
mock
(
'
~/locale
'
,
()
=>
({
getPreferredLocales
:
jest
.
fn
().
mockReturnValue
([
'
en
'
]),
sprintf
:
jest
.
requireActual
(
'
~/locale
'
).
sprintf
,
s__
:
jest
.
requireActual
(
'
~/locale
'
).
s__
,
// eslint-disable-line no-underscore-dangle
n__
:
jest
.
requireActual
(
'
~/locale
'
).
n__
,
// eslint-disable-line no-underscore-dangle
__
:
jest
.
requireActual
(
'
~/locale
'
).
__
,
}));
const
mockActions
=
[
...
...
ee/spec/frontend/threat_monitoring/components/policy_editor/scan_result_policy/scan_result_policy_editor_spec.js
0 → 100644
View file @
5bc6ae0d
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
GlEmptyState
}
from
'
@gitlab/ui
'
;
import
{
nextTick
}
from
'
vue
'
;
import
waitForPromises
from
'
helpers/wait_for_promises
'
;
import
PolicyEditorLayout
from
'
ee/threat_monitoring/components/policy_editor/policy_editor_layout.vue
'
;
import
{
DEFAULT_SCAN_RESULT_POLICY
,
fromYaml
,
}
from
'
ee/threat_monitoring/components/policy_editor/scan_result_policy/lib
'
;
import
ScanResultPolicyEditor
from
'
ee/threat_monitoring/components/policy_editor/scan_result_policy/scan_result_policy_editor.vue
'
;
import
{
DEFAULT_ASSIGNED_POLICY_PROJECT
}
from
'
ee/threat_monitoring/constants
'
;
import
{
mockScanResultManifest
,
mockScanResultObject
,
}
from
'
ee_jest/threat_monitoring/mocks/mock_data
'
;
import
{
visitUrl
}
from
'
~/lib/utils/url_utility
'
;
import
{
modifyPolicy
}
from
'
ee/threat_monitoring/components/policy_editor/utils
'
;
import
{
SECURITY_POLICY_ACTIONS
}
from
'
ee/threat_monitoring/components/policy_editor/constants
'
;
jest
.
mock
(
'
~/lib/utils/url_utility
'
,
()
=>
({
joinPaths
:
jest
.
requireActual
(
'
~/lib/utils/url_utility
'
).
joinPaths
,
visitUrl
:
jest
.
fn
().
mockName
(
'
visitUrlMock
'
),
}));
const
newlyCreatedPolicyProject
=
{
branch
:
'
main
'
,
fullPath
:
'
path/to/new-project
'
,
};
jest
.
mock
(
'
ee/threat_monitoring/components/policy_editor/utils
'
,
()
=>
({
assignSecurityPolicyProject
:
jest
.
fn
().
mockResolvedValue
({
branch
:
'
main
'
,
fullPath
:
'
path/to/new-project
'
,
}),
modifyPolicy
:
jest
.
fn
().
mockResolvedValue
({
id
:
'
2
'
}),
}));
describe
(
'
ScanResultPolicyEditor
'
,
()
=>
{
let
wrapper
;
const
defaultProjectPath
=
'
path/to/project
'
;
const
policyEditorEmptyStateSvgPath
=
'
path/to/svg
'
;
const
scanExecutionDocumentationPath
=
'
path/to/docs
'
;
const
assignedPolicyProject
=
{
branch
:
'
main
'
,
fullPath
:
'
path/to/existing-project
'
,
};
const
factory
=
({
propsData
=
{},
provide
=
{}
}
=
{})
=>
{
wrapper
=
shallowMount
(
ScanResultPolicyEditor
,
{
propsData
:
{
assignedPolicyProject
:
DEFAULT_ASSIGNED_POLICY_PROJECT
,
...
propsData
,
},
provide
:
{
disableScanExecutionUpdate
:
false
,
policyEditorEmptyStateSvgPath
,
projectId
:
1
,
projectPath
:
defaultProjectPath
,
scanExecutionDocumentationPath
,
...
provide
,
},
});
};
const
factoryWithExistingPolicy
=
()
=>
{
return
factory
({
propsData
:
{
assignedPolicyProject
,
existingPolicy
:
mockScanResultObject
,
isEditing
:
true
,
},
});
};
const
findEmptyState
=
()
=>
wrapper
.
findComponent
(
GlEmptyState
);
const
findPolicyEditorLayout
=
()
=>
wrapper
.
findComponent
(
PolicyEditorLayout
);
afterEach
(()
=>
{
wrapper
.
destroy
();
});
describe
(
'
default
'
,
()
=>
{
it
(
'
updates the policy yaml when "update-yaml" is emitted
'
,
async
()
=>
{
factory
();
await
nextTick
();
const
newManifest
=
'
new yaml!
'
;
expect
(
findPolicyEditorLayout
().
attributes
(
'
yamleditorvalue
'
)).
toBe
(
DEFAULT_SCAN_RESULT_POLICY
,
);
await
findPolicyEditorLayout
().
vm
.
$emit
(
'
update-yaml
'
,
newManifest
);
expect
(
findPolicyEditorLayout
().
attributes
(
'
yamleditorvalue
'
)).
toBe
(
newManifest
);
});
it
.
each
`
status | action | event | factoryFn | yamlEditorValue | currentlyAssignedPolicyProject
${
'
to save a new policy
'
}
|
${
SECURITY_POLICY_ACTIONS
.
APPEND
}
|
${
'
save-policy
'
}
|
${
factory
}
|
${
DEFAULT_SCAN_RESULT_POLICY
}
|
${
newlyCreatedPolicyProject
}
${
'
to update an existing policy
'
}
|
${
SECURITY_POLICY_ACTIONS
.
REPLACE
}
|
${
'
save-policy
'
}
|
${
factoryWithExistingPolicy
}
|
${
mockScanResultManifest
}
|
${
assignedPolicyProject
}
${
'
to delete an existing policy
'
}
|
${
SECURITY_POLICY_ACTIONS
.
REMOVE
}
|
${
'
remove-policy
'
}
|
${
factoryWithExistingPolicy
}
|
${
mockScanResultManifest
}
|
${
assignedPolicyProject
}
`
(
'
navigates to the new merge request when "modifyPolicy" is emitted $status
'
,
async
({
action
,
event
,
factoryFn
,
yamlEditorValue
,
currentlyAssignedPolicyProject
})
=>
{
factoryFn
();
await
nextTick
();
findPolicyEditorLayout
().
vm
.
$emit
(
event
);
await
waitForPromises
();
expect
(
modifyPolicy
).
toHaveBeenCalledWith
({
action
,
assignedPolicyProject
:
currentlyAssignedPolicyProject
,
name
:
action
===
SECURITY_POLICY_ACTIONS
.
APPEND
?
fromYaml
(
yamlEditorValue
).
name
:
mockScanResultObject
.
name
,
projectPath
:
defaultProjectPath
,
yamlEditorValue
,
});
expect
(
visitUrl
).
toHaveBeenCalledWith
(
`/
${
currentlyAssignedPolicyProject
.
fullPath
}
/-/merge_requests/2`
,
);
},
);
});
describe
(
'
when a user is not an owner of the project
'
,
()
=>
{
it
(
'
displays the empty state with the appropriate properties
'
,
async
()
=>
{
factory
({
provide
:
{
disableScanExecutionUpdate
:
true
}
});
expect
(
findEmptyState
().
props
()).
toMatchObject
({
primaryButtonLink
:
scanExecutionDocumentationPath
,
svgPath
:
policyEditorEmptyStateSvgPath
,
});
});
});
});
ee/spec/frontend/threat_monitoring/mocks/mock_data.js
View file @
5bc6ae0d
...
...
@@ -200,14 +200,14 @@ export const mockScanExecutionPolicy = {
latestScan
:
{
date
:
new
Date
(
'
2021-06-07T00:00:00.000Z
'
),
pipelineUrl
:
'
path/to/pipeline
'
},
};
export
const
mockScanResultManifest
=
`type: scan_
execution
_policy
export
const
mockScanResultManifest
=
`type: scan_
result
_policy
name: critical vulnerability CS approvals
description: This policy enforces critical vulnerability CS approvals
enabled: true
rules:
- type: scan_finding
branches:
- ma
ster
- ma
in
scanners:
- container_scanning
vulnerability_allowed: 1
...
...
@@ -222,6 +222,30 @@ actions:
- the.one
`
;
export
const
mockScanResultObject
=
{
type
:
'
scan_result_policy
'
,
name
:
'
critical vulnerability CS approvals
'
,
description
:
'
This policy enforces critical vulnerability CS approvals
'
,
enabled
:
true
,
rules
:
[
{
type
:
'
scan_finding
'
,
branches
:
[
'
main
'
],
scanners
:
[
'
container_scanning
'
],
vulnerability_allowed
:
1
,
severity_levels
:
[
'
critical
'
],
vulnerability_states
:
[
'
newly_added
'
],
},
],
actions
:
[
{
type
:
'
require_approval
'
,
approvals_required
:
1
,
user_approvers
:
[
'
the.one
'
],
},
],
};
export
const
mockScanResultPolicy
=
{
__typename
:
'
ScanResultPolicy
'
,
name
:
'
critical vulnerability CS approvals
'
,
...
...
locale/gitlab.pot
View file @
5bc6ae0d
...
...
@@ -31803,6 +31803,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan result"
msgstr ""
msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
msgstr ""
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
...
...
@@ -31848,7 +31851,7 @@ msgstr ""
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
msgid "SecurityOrchestration|Update scan
execution
policies"
msgid "SecurityOrchestration|Update scan policies"
msgstr ""
msgid "SecurityOrchestration|a"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment