Commit 00ed89bc authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/security/gitlab@13-0-stable-ee

parent 37caeffc
...@@ -108,7 +108,6 @@ export default class Clusters { ...@@ -108,7 +108,6 @@ export default class Clusters {
}); });
this.installApplication = this.installApplication.bind(this); this.installApplication = this.installApplication.bind(this);
this.showToken = this.showToken.bind(this);
this.errorContainer = document.querySelector('.js-cluster-error'); this.errorContainer = document.querySelector('.js-cluster-error');
this.successContainer = document.querySelector('.js-cluster-success'); this.successContainer = document.querySelector('.js-cluster-success');
...@@ -119,7 +118,6 @@ export default class Clusters { ...@@ -119,7 +118,6 @@ export default class Clusters {
); );
this.errorReasonContainer = this.errorContainer.querySelector('.js-error-reason'); this.errorReasonContainer = this.errorContainer.querySelector('.js-error-reason');
this.successApplicationContainer = document.querySelector('.js-cluster-application-notice'); this.successApplicationContainer = document.querySelector('.js-cluster-application-notice');
this.showTokenButton = document.querySelector('.js-show-cluster-token');
this.tokenField = document.querySelector('.js-cluster-token'); this.tokenField = document.querySelector('.js-cluster-token');
this.ingressDomainHelpText = document.querySelector('.js-ingress-domain-help-text'); this.ingressDomainHelpText = document.querySelector('.js-ingress-domain-help-text');
this.ingressDomainSnippet = this.ingressDomainSnippet =
...@@ -258,7 +256,6 @@ export default class Clusters { ...@@ -258,7 +256,6 @@ export default class Clusters {
} }
addListeners() { addListeners() {
if (this.showTokenButton) this.showTokenButton.addEventListener('click', this.showToken);
eventHub.$on('installApplication', this.installApplication); eventHub.$on('installApplication', this.installApplication);
eventHub.$on('updateApplication', data => this.updateApplication(data)); eventHub.$on('updateApplication', data => this.updateApplication(data));
eventHub.$on('saveKnativeDomain', data => this.saveKnativeDomain(data)); eventHub.$on('saveKnativeDomain', data => this.saveKnativeDomain(data));
...@@ -275,7 +272,6 @@ export default class Clusters { ...@@ -275,7 +272,6 @@ export default class Clusters {
} }
removeListeners() { removeListeners() {
if (this.showTokenButton) this.showTokenButton.removeEventListener('click', this.showToken);
eventHub.$off('installApplication', this.installApplication); eventHub.$off('installApplication', this.installApplication);
eventHub.$off('updateApplication', this.updateApplication); eventHub.$off('updateApplication', this.updateApplication);
eventHub.$off('saveKnativeDomain'); eventHub.$off('saveKnativeDomain');
...@@ -344,18 +340,6 @@ export default class Clusters { ...@@ -344,18 +340,6 @@ export default class Clusters {
} }
} }
showToken() {
const type = this.tokenField.getAttribute('type');
if (type === 'password') {
this.tokenField.setAttribute('type', 'text');
this.showTokenButton.textContent = s__('ClusterIntegration|Hide');
} else {
this.tokenField.setAttribute('type', 'password');
this.showTokenButton.textContent = s__('ClusterIntegration|Show');
}
}
hideAll() { hideAll() {
this.errorContainer.classList.add('hidden'); this.errorContainer.classList.add('hidden');
this.successContainer.classList.add('hidden'); this.successContainer.classList.add('hidden');
......
<script> <script>
import { __, s__, sprintf } from '~/locale'; import { __, s__, sprintf } from '~/locale';
import { GlFormGroup, GlFormInput, GlFormRadioGroup, GlFormTextarea } from '@gitlab/ui'; import { GlFormGroup, GlFormInput, GlFormRadioGroup, GlFormTextarea } from '@gitlab/ui';
import { escape as esc } from 'lodash';
const defaultFileName = dashboard => dashboard.path.split('/').reverse()[0]; const defaultFileName = dashboard => dashboard.path.split('/').reverse()[0];
...@@ -42,7 +43,7 @@ export default { ...@@ -42,7 +43,7 @@ export default {
html: sprintf( html: sprintf(
__('Commit to %{branchName} branch'), __('Commit to %{branchName} branch'),
{ {
branchName: `<strong>${this.defaultBranch}</strong>`, branchName: `<strong>${esc(this.defaultBranch)}</strong>`,
}, },
false, false,
), ),
......
...@@ -10,6 +10,12 @@ module Clusters ...@@ -10,6 +10,12 @@ module Clusters
def execute(cluster) def execute(cluster)
if validate_params(cluster) if validate_params(cluster)
token = params.dig(:platform_kubernetes_attributes, :token)
if token.blank?
params[:platform_kubernetes_attributes]&.delete(:token)
end
cluster.update(params) cluster.update(params)
else else
false false
......
...@@ -25,16 +25,10 @@ ...@@ -25,16 +25,10 @@
label: s_('ClusterIntegration|CA Certificate'), label_class: 'label-bold', label: s_('ClusterIntegration|CA Certificate'), label_class: 'label-bold',
input_group_class: 'gl-field-error-anchor', append: copy_ca_cert_btn input_group_class: 'gl-field-error-anchor', append: copy_ca_cert_btn
- show_token_btn = (platform_field.button s_('ClusterIntegration|Show'), = platform_field.password_field :token, type: 'password', class: 'js-select-on-focus js-cluster-token',
type: 'button', class: 'js-show-cluster-token btn btn-default') readonly: cluster.read_only_kubernetes_platform_fields?, autocomplete: 'new-password',
- copy_token_btn = clipboard_button(text: platform.token, title: s_('ClusterIntegration|Copy Service Token'), label: s_('ClusterIntegration|Enter new Service Token'), label_class: 'label-bold',
class: 'input-group-text btn-default') if cluster.read_only_kubernetes_platform_fields? input_group_class: 'gl-field-error-anchor'
= platform_field.text_field :token, type: 'password', class: 'js-select-on-focus js-cluster-token',
required: true, title: s_('ClusterIntegration|Service token is required.'),
readonly: cluster.read_only_kubernetes_platform_fields?,
label: s_('ClusterIntegration|Service Token'), label_class: 'label-bold',
input_group_class: 'gl-field-error-anchor', append: show_token_btn + copy_token_btn
= platform_field.form_group :authorization_type do = platform_field.form_group :authorization_type do
= platform_field.check_box :authorization_type, { disabled: true, label: s_('ClusterIntegration|RBAC-enabled cluster'), = platform_field.check_box :authorization_type, { disabled: true, label: s_('ClusterIntegration|RBAC-enabled cluster'),
......
---
title: Kubernetes cluster details page no longer exposes Service Token
merge_request:
author:
type: security
---
title: Prevent XSS in the monitoring dashboard
merge_request:
author:
type: security
...@@ -1198,7 +1198,7 @@ PUT /projects/:id ...@@ -1198,7 +1198,7 @@ PUT /projects/:id
| `approvals_before_merge` | integer | no | **(STARTER)** How many approvers should approve merge request by default | | `approvals_before_merge` | integer | no | **(STARTER)** How many approvers should approve merge request by default |
| `external_authorization_classification_label` | string | no | **(PREMIUM)** The classification label for the project | | `external_authorization_classification_label` | string | no | **(PREMIUM)** The classification label for the project |
| `mirror` | boolean | no | **(STARTER)** Enables pull mirroring in a project | | `mirror` | boolean | no | **(STARTER)** Enables pull mirroring in a project |
| `mirror_user_id` | integer | no | **(STARTER)** User responsible for all the activity surrounding a pull mirror event | | `mirror_user_id` | integer | no | **(STARTER)** User responsible for all the activity surrounding a pull mirror event. Can only be set by admins. |
| `mirror_trigger_builds` | boolean | no | **(STARTER)** Pull mirroring triggers builds | | `mirror_trigger_builds` | boolean | no | **(STARTER)** Pull mirroring triggers builds |
| `only_mirror_protected_branches` | boolean | no | **(STARTER)** Only mirror protected branches | | `only_mirror_protected_branches` | boolean | no | **(STARTER)** Only mirror protected branches |
| `mirror_overwrites_diverged_branches` | boolean | no | **(STARTER)** Pull mirror overwrites diverged branches | | `mirror_overwrites_diverged_branches` | boolean | no | **(STARTER)** Pull mirror overwrites diverged branches |
......
...@@ -4622,9 +4622,6 @@ msgstr "" ...@@ -4622,9 +4622,6 @@ msgstr ""
msgid "ClusterIntegration|Copy Kubernetes cluster name" msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "" msgstr ""
msgid "ClusterIntegration|Copy Service Token"
msgstr ""
msgid "ClusterIntegration|Could not load IAM roles" msgid "ClusterIntegration|Could not load IAM roles"
msgstr "" msgstr ""
...@@ -4703,6 +4700,9 @@ msgstr "" ...@@ -4703,6 +4700,9 @@ msgstr ""
msgid "ClusterIntegration|Enabled stack" msgid "ClusterIntegration|Enabled stack"
msgstr "" msgstr ""
msgid "ClusterIntegration|Enter new Service Token"
msgstr ""
msgid "ClusterIntegration|Enter the details for your Amazon EKS Kubernetes cluster" msgid "ClusterIntegration|Enter the details for your Amazon EKS Kubernetes cluster"
msgstr "" msgstr ""
...@@ -4787,9 +4787,6 @@ msgstr "" ...@@ -4787,9 +4787,6 @@ msgstr ""
msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts." msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
msgstr "" msgstr ""
msgid "ClusterIntegration|Hide"
msgstr ""
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}." msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr "" msgstr ""
...@@ -5183,9 +5180,6 @@ msgstr "" ...@@ -5183,9 +5180,6 @@ msgstr ""
msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level." msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
msgstr "" msgstr ""
msgid "ClusterIntegration|Show"
msgstr ""
msgid "ClusterIntegration|Something went wrong on our end." msgid "ClusterIntegration|Something went wrong on our end."
msgstr "" msgstr ""
...@@ -22244,9 +22238,6 @@ msgstr "" ...@@ -22244,9 +22238,6 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches." msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr "" msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
msgid "This variable can not be masked." msgid "This variable can not be masked."
msgstr "" msgstr ""
...@@ -25014,6 +25005,9 @@ msgstr "" ...@@ -25014,6 +25005,9 @@ msgstr ""
msgid "You will be removed from existing projects/groups" msgid "You will be removed from existing projects/groups"
msgstr "" msgstr ""
msgid "You will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
msgid "You will first need to set up Jira Integration to use this feature." msgid "You will first need to set up Jira Integration to use this feature."
msgstr "" msgstr ""
......
...@@ -39,7 +39,7 @@ describe 'User Cluster', :js do ...@@ -39,7 +39,7 @@ describe 'User Cluster', :js do
expect(page.find_field('cluster[platform_kubernetes_attributes][api_url]').value) expect(page.find_field('cluster[platform_kubernetes_attributes][api_url]').value)
.to have_content('http://example.com') .to have_content('http://example.com')
expect(page.find_field('cluster[platform_kubernetes_attributes][token]').value) expect(page.find_field('cluster[platform_kubernetes_attributes][token]').value)
.to have_content('my-token') .to be_empty
end end
end end
......
...@@ -46,7 +46,7 @@ describe 'User Cluster', :js do ...@@ -46,7 +46,7 @@ describe 'User Cluster', :js do
expect(page.find_field('cluster[platform_kubernetes_attributes][api_url]').value) expect(page.find_field('cluster[platform_kubernetes_attributes][api_url]').value)
.to have_content('http://example.com') .to have_content('http://example.com')
expect(page.find_field('cluster[platform_kubernetes_attributes][token]').value) expect(page.find_field('cluster[platform_kubernetes_attributes][token]').value)
.to have_content('my-token') .to be_empty
end end
it 'user sees RBAC is enabled by default' do it 'user sees RBAC is enabled by default' do
......
...@@ -82,28 +82,6 @@ describe('Clusters', () => { ...@@ -82,28 +82,6 @@ describe('Clusters', () => {
}); });
}); });
describe('showToken', () => {
it('should update token field type', () => {
cluster.showTokenButton.click();
expect(cluster.tokenField.getAttribute('type')).toEqual('text');
cluster.showTokenButton.click();
expect(cluster.tokenField.getAttribute('type')).toEqual('password');
});
it('should update show token button text', () => {
cluster.showTokenButton.click();
expect(cluster.showTokenButton.textContent).toEqual('Hide');
cluster.showTokenButton.click();
expect(cluster.showTokenButton.textContent).toEqual('Show');
});
});
describe('checkForNewInstalls', () => { describe('checkForNewInstalls', () => {
const INITIAL_APP_MAP = { const INITIAL_APP_MAP = {
helm: { status: null, title: 'Helm Tiller' }, helm: { status: null, title: 'Helm Tiller' },
......
...@@ -3,9 +3,17 @@ import DuplicateDashboardForm from '~/monitoring/components/duplicate_dashboard_ ...@@ -3,9 +3,17 @@ import DuplicateDashboardForm from '~/monitoring/components/duplicate_dashboard_
import { dashboardGitResponse } from '../mock_data'; import { dashboardGitResponse } from '../mock_data';
describe('DuplicateDashboardForm', () => { let wrapper;
let wrapper;
const createMountedWrapper = (props = {}) => {
// Use `mount` to render native input elements
wrapper = mount(DuplicateDashboardForm, {
propsData: { ...props },
sync: false,
});
};
describe('DuplicateDashboardForm', () => {
const defaultBranch = 'master'; const defaultBranch = 'master';
const findByRef = ref => wrapper.find({ ref }); const findByRef = ref => wrapper.find({ ref });
...@@ -20,14 +28,7 @@ describe('DuplicateDashboardForm', () => { ...@@ -20,14 +28,7 @@ describe('DuplicateDashboardForm', () => {
}; };
beforeEach(() => { beforeEach(() => {
// Use `mount` to render native input elements createMountedWrapper({ dashboard: dashboardGitResponse[0], defaultBranch });
wrapper = mount(DuplicateDashboardForm, {
propsData: {
dashboard: dashboardGitResponse[0],
defaultBranch,
},
sync: false,
});
}); });
it('renders correctly', () => { it('renders correctly', () => {
...@@ -146,3 +147,18 @@ describe('DuplicateDashboardForm', () => { ...@@ -146,3 +147,18 @@ describe('DuplicateDashboardForm', () => {
}); });
}); });
}); });
describe('DuplicateDashboardForm escapes elements', () => {
const branchToEscape = "<img/src='x'onerror=alert(document.domain)>";
beforeEach(() => {
createMountedWrapper({ dashboard: dashboardGitResponse[0], defaultBranch: branchToEscape });
});
it('should escape branch name data', () => {
const branchOptionHtml = wrapper.vm.branchOptions[0].html;
const escapedBranch = '&lt;img/src=&#39;x&#39;onerror=alert(document.domain)&gt';
expect(branchOptionHtml).toEqual(expect.stringContaining(escapedBranch));
});
});
...@@ -47,6 +47,39 @@ describe Clusters::UpdateService do ...@@ -47,6 +47,39 @@ describe Clusters::UpdateService do
expect(cluster.platform.namespace).to eq('custom-namespace') expect(cluster.platform.namespace).to eq('custom-namespace')
end end
end end
context 'when service token is empty' do
let(:params) do
{
platform_kubernetes_attributes: {
token: ''
}
}
end
it 'does not update the token' do
current_token = cluster.platform.token
is_expected.to eq(true)
cluster.platform.reload
expect(cluster.platform.token).to eq(current_token)
end
end
context 'when service token is not empty' do
let(:params) do
{
platform_kubernetes_attributes: {
token: 'new secret token'
}
}
end
it 'updates the token' do
is_expected.to eq(true)
expect(cluster.platform.token).to eq('new secret token')
end
end
end end
context 'when invalid params' do context 'when invalid params' do
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
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