Commit d948f526 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 26804e91
......@@ -2,7 +2,7 @@
import { mapState, mapActions } from 'vuex';
import createFlash from '~/flash';
import { s__ } from '~/locale';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import Badge from './badge.vue';
import BadgeForm from './badge_form.vue';
import BadgeList from './badge_list.vue';
......@@ -13,7 +13,7 @@ export default {
Badge,
BadgeForm,
BadgeList,
GlModal,
GlModal: DeprecatedModal2,
},
computed: {
...mapState(['badgeInModal', 'isEditing']),
......
/* eslint-disable class-methods-use-this */
import $ from 'jquery';
import '~/gl_dropdown';
export default class TemplateSelector {
constructor({ dropdown, data, pattern, wrapper, editor, $input } = {}) {
......
import _ from 'underscore';
import '~/gl_dropdown';
export default class CreateItemDropdown {
/**
......
<script>
/* eslint-disable @gitlab/vue-i18n/no-bare-strings */
import { GlTooltipDirective } from '@gitlab/ui';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import { s__, sprintf } from '~/locale';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import eventHub from '../event_hub';
......@@ -11,7 +11,7 @@ export default {
name: 'StopEnvironmentModal',
components: {
GlModal,
GlModal: DeprecatedModal2,
LoadingButton,
},
......
......@@ -3,7 +3,7 @@ import $ from 'jquery';
import { mapActions } from 'vuex';
import { __, sprintf } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import ListItem from './list_item.vue';
......@@ -11,7 +11,7 @@ export default {
components: {
Icon,
ListItem,
GlModal,
GlModal: DeprecatedModal2,
},
directives: {
tooltip,
......
......@@ -4,12 +4,12 @@ import { mapActions } from 'vuex';
import { sprintf, __ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
export default {
components: {
Icon,
GlModal,
GlModal: DeprecatedModal2,
},
directives: {
tooltip,
......
......@@ -3,12 +3,12 @@ import $ from 'jquery';
import flash from '~/flash';
import { __, sprintf, s__ } from '~/locale';
import { mapActions, mapState, mapGetters } from 'vuex';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import { modalTypes } from '../../constants';
export default {
components: {
GlModal,
GlModal: DeprecatedModal2,
},
data() {
return {
......
/* eslint-disable func-names, no-else-return, prefer-template, prefer-arrow-callback */
import $ from 'jquery';
import '~/gl_dropdown';
import Api from './api';
import { mergeUrlParams } from './lib/utils/url_utility';
import { parseBoolean } from '~/lib/utils/common_utils';
......
<script>
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import { redirectTo } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
export default {
components: {
GlModal,
GlModal: DeprecatedModal2,
},
props: {
url: {
......
/* eslint-disable class-methods-use-this, no-unneeded-ternary */
import $ from 'jquery';
import '~/gl_dropdown';
import { visitUrl } from '~/lib/utils/url_utility';
import UsersSelect from '~/users_select';
import { isMetaClick } from '~/lib/utils/common_utils';
......
<script>
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import { s__, sprintf } from '~/locale';
import { visitUrl } from '~/lib/utils/url_utility';
import eventHub from '../event_hub';
export default {
components: {
GlModal,
GlModal: DeprecatedModal2,
},
props: {
milestoneTitle: {
......
......@@ -2,14 +2,14 @@
import _ from 'underscore';
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import { s__, sprintf } from '~/locale';
import { visitUrl } from '~/lib/utils/url_utility';
import eventHub from '../event_hub';
export default {
components: {
GlModal,
GlModal: DeprecatedModal2,
},
props: {
url: {
......
import $ from 'jquery';
import '~/gl_dropdown';
import Flash from '~/flash';
import Api from '~/api';
import { __ } from '~/locale';
......
<script>
import GlModal from '~/vue_shared/components/gl_modal.vue';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
GlModal,
GlModal: DeprecatedModal2,
Icon,
},
props: {
......
<script>
import _ from 'underscore';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import { GlLink } from '@gitlab/ui';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
......@@ -13,7 +13,7 @@ import { s__, sprintf } from '~/locale';
*/
export default {
components: {
GlModal,
GlModal: DeprecatedModal2,
GlLink,
ClipboardButton,
CiIcon,
......
<script>
import _ from 'underscore';
import axios from '~/lib/utils/axios_utils';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import { s__, sprintf } from '~/locale';
import Flash from '~/flash';
export default {
components: {
GlModal,
GlModal: DeprecatedModal2,
},
props: {
actionUrl: {
......
import $ from 'jquery';
import '~/gl_dropdown';
class RefSelectDropdown {
constructor($dropdownButton, availableRefs) {
......
<script>
// import { sprintf, __ } from '~/locale';
import Modal from '~/vue_shared/components/gl_modal.vue';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import CodeBlock from '~/vue_shared/components/code_block.vue';
import { fieldTypes } from '../constants';
export default {
components: {
Modal,
Modal: DeprecatedModal2,
LoadingButton,
CodeBlock,
},
......
import $ from 'jquery';
import '~/gl_dropdown';
import _ from 'underscore';
import { __ } from '~/locale';
......
<script>
import $ from 'jquery';
const buttonVariants = ['danger', 'primary', 'success', 'warning'];
const sizeVariants = ['sm', 'md', 'lg', 'xl'];
export default {
name: 'DeprecatedModal2', // use GlModal instead
props: {
id: {
type: String,
required: false,
default: null,
},
modalSize: {
type: String,
required: false,
default: 'md',
validator: value => sizeVariants.includes(value),
},
headerTitleText: {
type: String,
required: false,
default: '',
},
footerPrimaryButtonVariant: {
type: String,
required: false,
default: 'primary',
validator: value => buttonVariants.includes(value),
},
footerPrimaryButtonText: {
type: String,
required: false,
default: '',
},
},
computed: {
modalSizeClass() {
return this.modalSize === 'md' ? '' : `modal-${this.modalSize}`;
},
},
mounted() {
$(this.$el)
.on('shown.bs.modal', this.opened)
.on('hidden.bs.modal', this.closed);
},
beforeDestroy() {
$(this.$el)
.off('shown.bs.modal', this.opened)
.off('hidden.bs.modal', this.closed);
},
methods: {
emitCancel(event) {
this.$emit('cancel', event);
},
emitSubmit(event) {
this.$emit('submit', event);
},
opened() {
this.$emit('open');
},
closed() {
this.$emit('closed');
},
},
};
</script>
<template>
<div :id="id" class="modal fade" tabindex="-1" role="dialog">
<div :class="modalSizeClass" class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<slot name="header">
<h4 class="modal-title">
<slot name="title"> {{ headerTitleText }} </slot>
</h4>
<button
:aria-label="s__('Modal|Close')"
type="button"
class="close js-modal-close-action"
data-dismiss="modal"
@click="emitCancel($event)"
>
<span aria-hidden="true">&times;</span>
</button>
</slot>
</div>
<div class="modal-body"><slot></slot></div>
<div class="modal-footer">
<slot name="footer">
<button
type="button"
class="btn js-modal-cancel-action qa-modal-cancel-button"
data-dismiss="modal"
@click="emitCancel($event)"
>
{{ s__('Modal|Cancel') }}
</button>
<button
:class="`btn-${footerPrimaryButtonVariant}`"
type="button"
class="btn js-modal-primary-action qa-modal-primary-button"
data-dismiss="modal"
@click="emitSubmit($event)"
>
{{ footerPrimaryButtonText }}
</button>
</slot>
</div>
</div>
</div>
</div>
</template>
<script>
import $ from 'jquery';
// This file was only introduced to not break master and shall be delete soon.
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
const buttonVariants = ['danger', 'primary', 'success', 'warning'];
const sizeVariants = ['sm', 'md', 'lg', 'xl'];
export default {
name: 'GlModal',
props: {
id: {
type: String,
required: false,
default: null,
},
modalSize: {
type: String,
required: false,
default: 'md',
validator: value => sizeVariants.includes(value),
},
headerTitleText: {
type: String,
required: false,
default: '',
},
footerPrimaryButtonVariant: {
type: String,
required: false,
default: 'primary',
validator: value => buttonVariants.includes(value),
},
footerPrimaryButtonText: {
type: String,
required: false,
default: '',
},
},
computed: {
modalSizeClass() {
return this.modalSize === 'md' ? '' : `modal-${this.modalSize}`;
},
},
mounted() {
$(this.$el)
.on('shown.bs.modal', this.opened)
.on('hidden.bs.modal', this.closed);
},
beforeDestroy() {
$(this.$el)
.off('shown.bs.modal', this.opened)
.off('hidden.bs.modal', this.closed);
},
methods: {
emitCancel(event) {
this.$emit('cancel', event);
},
emitSubmit(event) {
this.$emit('submit', event);
},
opened() {
this.$emit('open');
},
closed() {
this.$emit('closed');
},
},
};
export default DeprecatedModal2;
</script>
<template>
<div :id="id" class="modal fade" tabindex="-1" role="dialog">
<div :class="modalSizeClass" class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<slot name="header">
<h4 class="modal-title">
<slot name="title"> {{ headerTitleText }} </slot>
</h4>
<button
:aria-label="s__('Modal|Close')"
type="button"
class="close js-modal-close-action"
data-dismiss="modal"
@click="emitCancel($event)"
>
<span aria-hidden="true">&times;</span>
</button>
</slot>
</div>
<div class="modal-body"><slot></slot></div>
<div class="modal-footer">
<slot name="footer">
<button
type="button"
class="btn js-modal-cancel-action qa-modal-cancel-button"
data-dismiss="modal"
@click="emitCancel($event)"
>
{{ s__('Modal|Cancel') }}
</button>
<button
:class="`btn-${footerPrimaryButtonVariant}`"
type="button"
class="btn js-modal-primary-action qa-modal-primary-button"
data-dismiss="modal"
@click="emitSubmit($event)"
>
{{ footerPrimaryButtonText }}
</button>
</slot>
</div>
</div>
</div>
</div>
</template>
......@@ -52,7 +52,7 @@ export default {
this.$emit('projectClicked', project);
},
isSelected(project) {
return Boolean(_.findWhere(this.selectedProjects, { id: project.id }));
return Boolean(_.find(this.selectedProjects, { id: project.id }));
},
onInput: _.debounce(function debouncedOnInput() {
this.$emit('searched', this.searchQuery);
......
---
title: Add DAST full scan domain validation
merge_request: 16680
author:
type: added
---
title: Upgrade to Gitaly v1.65.0
merge_request: 17135
author:
type: changed
......@@ -3,7 +3,6 @@
## Contents
- [Dropdowns](#dropdowns)
- [Modals](#modals)
## Dropdowns
......@@ -39,25 +38,3 @@ See also the [corresponding UX guide](https://design.gitlab.com/#/components/dro
```
[bootstrap-dropdowns]: https://getbootstrap.com/docs/3.3/javascript/#dropdowns
## Modals
See also the [corresponding UX guide](https://design.gitlab.com/#/components/modals).
We have a reusable Vue component for modals: [vue_shared/components/gl_modal.vue](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/javascripts/vue_shared/components/gl_modal.vue)
Here is an example of how to use it:
```html
<gl-modal
id="dogs-out-modal"
:header-title-text="s__('ModalExample|Let the dogs out?')"
footer-primary-button-variant="danger"
:footer-primary-button-text="s__('ModalExample|Let them out')"
@submit="letOut(theDogs)"
>
{{ s__('ModalExample|You’re about to let the dogs out.') }}
</gl-modal>
```
![example modal](img/gl-modal.png)
......@@ -84,7 +84,7 @@ There are two ways to define the URL to be scanned by DAST:
- Set the `DAST_WEBSITE` [variable](../../../ci/yaml/README.md#variables).
- Add it in an `environment_url.txt` file at the root of your project.
If both values are set, the `DAST_WEBSITE` value will take precedence.
If both values are set, the `DAST_WEBSITE` value will take precedence.
The included template will create a `dast` job in your CI/CD pipeline and scan
your project's source code for possible vulnerabilities.
......@@ -132,6 +132,115 @@ variables:
DAST_FULL_SCAN_ENABLED: "true"
```
#### Domain validation
The DAST job can be run anywhere, which means you can accidentally hit live web servers
and potentially damage them. You could even take down your production environment.
For that reason, you should use domain validation.
Domain validation is not required by default. It can be required by setting the [environment variable](#available-variables) `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` to true.
```yaml
include:
template: DAST.gitlab-ci.yml
variables:
DAST_FULL_SCAN_ENABLED: "true"
DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED: "true"
```
Since ZAP full scan actively attacks the target application, DAST sends a ping to the target (normally defined in `DAST_WEBSITE` or `environment_url.txt`) beforehand.
If `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` is false or unset, the scan will _proceed_ unless the response to the ping
includes a `Gitlab-DAST-Permission` header with a value of `deny`.
If `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` is true, the scan will _exit_ unless the response to the ping
includes a `Gitlab-DAST-Permission` header with a value of `allow`.
Here are some examples of adding the `Gitlab-DAST-Permission` header to a response in Rails, Django, and Node (with Express).
##### Ruby on Rails
Here's how you would add a [custom header in Ruby on Rails](https://guides.rubyonrails.org/action_controller_overview.html#setting-custom-headers):
```ruby
class DastWebsiteTargetController < ActionController::Base
def dast_website_target
response.headers['Gitlab-DAST-Permission'] = 'allow'
head :ok
end
end
```
##### Django
Here's how you would add a [custom header in Django](https://docs.djangoproject.com/en/2.2/ref/request-response/#setting-header-fields):
```python
class DastWebsiteTargetView(View):
def head(self, *args, **kwargs):
response = HttpResponse()
response['Gitlab-Dast-Permission'] = 'allow'
return response
```
##### Node (with Express)
Here's how you would add a [custom header in Node (with Express)](http://expressjs.com/en/5x/api.html#res.append):
```javascript
app.get('/dast-website-target', function(req, res) {
res.append('Gitlab-DAST-Permission', 'allow')
res.send('Respond to DAST ping')
})
```
##### Domain validation header via a proxy
It's also possible to add the `Gitlab-DAST-Permission` header via a proxy.
###### NGINX
The following config allows NGINX to act as a reverse proxy and add the `Gitlab-DAST-Permission` [header](http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header):
```
# default.conf
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://test-application;
add_header Gitlab-DAST-Permission allow;
}
}
```
###### Apache
Apache can also be used as a [reverse proxy](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html)
to add the Gitlab-DAST-Permission [header](https://httpd.apache.org/docs/current/mod/mod_headers.html).
To do so, add the following lines to `httpd.conf`:
```
# httpd.conf
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_http_module modules/mod_proxy_http.so
<VirtualHost *:80>
ProxyPass "/" "http://test-application.com/"
ProxyPassReverse "/" "http://test-application.com/"
Header set Gitlab-DAST-Permission "allow"
</VirtualHost>
```
[This snippet](https://gitlab.com/gitlab-org/security-products/dast/snippets/1894732) contains a complete `httpd.conf` file
configured to act as a remote proxy and add the `Gitlab-DAST-Permission` header.
### Customizing the DAST settings
The DAST settings can be changed through environment variables by using the
......@@ -194,6 +303,7 @@ variable value.
| `DAST_AUTH_EXCLUDE_URLS` | no | The URLs to skip during the authenticated scan; comma-separated, no spaces in between. |
| `DAST_TARGET_AVAILABILITY_TIMEOUT` | no | Time limit in seconds to wait for target availability. Scan is attempted nevertheless if it runs out. Integer. Defaults to `60`. |
| `DAST_FULL_SCAN_ENABLED` | no | Switches the tool to execute [ZAP Full Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan) instead of [ZAP Baseline Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan). Boolean. `true`, `True`, or `1` are considered as true value, otherwise false. Defaults to `false`. |
| `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` | no | Requires [domain validation](#domain-validation) when running DAST full scans. Boolean. `true`, `True`, or `1` are considered as true value, otherwise false. Defaults to `false`. |
## Security Dashboard
......
......@@ -10627,6 +10627,9 @@ msgstr ""
msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
msgid "Only 'Reporter' roles and above on tiers Premium / Silver and above can see Cycle Analytics."
msgstr ""
msgid "Only Project Members"
msgstr ""
......@@ -17984,6 +17987,9 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
msgid "You don’t have access to Cycle Analytics for this group"
msgstr ""
msgid "You don’t have access to Productivity Analytics in this group"
msgstr ""
......
import $ from 'jquery';
import Vue from 'vue';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
const modalComponent = Vue.extend(GlModal);
const modalComponent = Vue.extend(DeprecatedModal2);
describe('GlModal', () => {
describe('DeprecatedModal2', () => {
let vm;
afterEach(() => {
......@@ -153,17 +153,17 @@ describe('GlModal', () => {
let template;
if (slotName) {
template = `
<gl-modal>
<deprecated-modal-2>
<template slot="${slotName}">${slotContent}</template>
</gl-modal>
</deprecated-modal-2>
`;
} else {
template = `<gl-modal>${slotContent}</gl-modal>`;
template = `<deprecated-modal-2>${slotContent}</deprecated-modal-2>`;
}
return Vue.extend({
components: {
GlModal,
DeprecatedModal2,
},
template,
});
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment