aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSarath Nair <91882341+sarath-nair-sonarsource@users.noreply.github.com>2024-03-08 12:54:05 +0100
committersonartech <sonartech@sonarsource.com>2024-03-08 20:02:34 +0000
commit875ad375ffd8d8323141701b7355a4f10629bb7e (patch)
tree0075771c30f882ac0bed769bc6664ed097f0a20d
parente64df27ae07319d522cb2c486c1031674ae91b23 (diff)
downloadsonarqube-875ad375ffd8d8323141701b7355a4f10629bb7e.tar.gz
sonarqube-875ad375ffd8d8323141701b7355a4f10629bb7e.zip
SONAR-21413 Show insecure configuration warning for GitLab (#10742)
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/authentication/ConfigurationForm.tsx10
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/authentication/ConfirmProvisioningModal.tsx74
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/authentication/GitHubConfirmModal.tsx64
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/authentication/GitLabAuthenticationTab.tsx26
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/authentication/GithubAuthenticationTab.tsx12
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/authentication/__tests__/Authentication-Gitlab-it.tsx43
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties2
7 files changed, 144 insertions, 87 deletions
diff --git a/server/sonar-web/src/main/js/apps/settings/components/authentication/ConfigurationForm.tsx b/server/sonar-web/src/main/js/apps/settings/components/authentication/ConfigurationForm.tsx
index 2cab4f65783..e52fdc491d1 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/authentication/ConfigurationForm.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/authentication/ConfigurationForm.tsx
@@ -28,12 +28,12 @@ import { translate } from '../../../../helpers/l10n';
import { useSaveValuesMutation } from '../../../../queries/settings';
import { AlmKeys } from '../../../../types/alm-settings';
import { ProvisioningType } from '../../../../types/provisioning';
-import { Dict } from '../../../../types/types';
+import { Dict, Provider } from '../../../../types/types';
import { AuthenticationTabs, DOCUMENTATION_LINK_SUFFIXES } from './Authentication';
import AuthenticationFormField from './AuthenticationFormField';
-import GitHubConfirmModal from './GitHubConfirmModal';
import { SettingValue } from './hook/useConfiguration';
import { isAllowToSignUpEnabled, isOrganizationListEmpty } from './hook/useGithubConfiguration';
+import ConfirmProvisioningModal from './ConfirmProvisioningModal';
interface Props {
canBeSave: boolean;
@@ -176,11 +176,13 @@ export default function ConfigurationForm(props: Readonly<Props>) {
}
/>
{showConfirmModal && (
- <GitHubConfirmModal
+ <ConfirmProvisioningModal
+ allowUsersToSignUp={isAllowToSignUpEnabled(values)}
+ isAllowListEmpty={isOrganizationListEmpty(values)}
onClose={() => setShowConfirmModal(false)}
onConfirm={onSave}
+ provider={Provider.Github}
provisioningStatus={provisioningStatus ?? ProvisioningType.jit}
- values={values}
/>
)}
</>
diff --git a/server/sonar-web/src/main/js/apps/settings/components/authentication/ConfirmProvisioningModal.tsx b/server/sonar-web/src/main/js/apps/settings/components/authentication/ConfirmProvisioningModal.tsx
new file mode 100644
index 00000000000..2968b425252
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/settings/components/authentication/ConfirmProvisioningModal.tsx
@@ -0,0 +1,74 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import { FlagMessage } from 'design-system';
+import React from 'react';
+import ConfirmModal from '../../../../components/controls/ConfirmModal';
+import { ProvisioningType } from '../../../../types/provisioning';
+import { Provider } from '../../../../types/types';
+import { useIntl } from 'react-intl';
+
+interface Props {
+ allowUsersToSignUp?: boolean;
+ provider: Provider.Github | Provider.Gitlab;
+ isAllowListEmpty: boolean;
+ onClose: VoidFunction;
+ onConfirm: VoidFunction;
+ hasProvisioningTypeChange?: boolean;
+ provisioningStatus: ProvisioningType;
+}
+
+export default function ConfirmProvisioningModal(props: Readonly<Props>) {
+ const {
+ allowUsersToSignUp,
+ hasProvisioningTypeChange,
+ isAllowListEmpty,
+ onConfirm,
+ onClose,
+ provider,
+ provisioningStatus,
+ } = props;
+
+ const intl = useIntl();
+
+ return (
+ <ConfirmModal
+ onConfirm={onConfirm}
+ header={intl.formatMessage({
+ id: `settings.authentication.${provider}.confirm.${hasProvisioningTypeChange ? provisioningStatus : 'insecure'}`,
+ })}
+ onClose={onClose}
+ confirmButtonText={intl.formatMessage({
+ id: `settings.authentication.${provider}.provisioning_change.confirm_changes`,
+ })}
+ >
+ {hasProvisioningTypeChange &&
+ intl.formatMessage({
+ id: `settings.authentication.${provider}.confirm.${provisioningStatus}.description`,
+ })}
+ {(provisioningStatus === ProvisioningType.auto || allowUsersToSignUp) && isAllowListEmpty && (
+ <FlagMessage className="sw-mt-2" variant="warning">
+ {intl.formatMessage({
+ id: `settings.authentication.${provider}.provisioning_change.insecure_config`,
+ })}
+ </FlagMessage>
+ )}
+ </ConfirmModal>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/authentication/GitHubConfirmModal.tsx b/server/sonar-web/src/main/js/apps/settings/components/authentication/GitHubConfirmModal.tsx
deleted file mode 100644
index 41a55f68e40..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/authentication/GitHubConfirmModal.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import { FlagMessage } from 'design-system';
-import React from 'react';
-import ConfirmModal from '../../../../components/controls/ConfirmModal';
-import { translate } from '../../../../helpers/l10n';
-import { ProvisioningType } from '../../../../types/provisioning';
-import { SettingValue } from './hook/useConfiguration';
-import { isAllowToSignUpEnabled, isOrganizationListEmpty } from './hook/useGithubConfiguration';
-
-interface GithubAuthenticationProps {
- onConfirm: () => void;
- onClose: () => void;
- values: Record<string, SettingValue>;
- hasGithubProvisioningTypeChange?: boolean;
- provisioningStatus: ProvisioningType;
-}
-
-export default function GitHubConfirmModal(props: Readonly<GithubAuthenticationProps>) {
- const { onConfirm, onClose, hasGithubProvisioningTypeChange, provisioningStatus, values } = props;
-
- const organizationListIsEmpty = isOrganizationListEmpty(values);
- const allowToSignUpEnabled = isAllowToSignUpEnabled(values);
-
- return (
- <ConfirmModal
- onConfirm={onConfirm}
- header={translate(
- 'settings.authentication.github.confirm',
- hasGithubProvisioningTypeChange ? provisioningStatus : 'insecure',
- )}
- onClose={onClose}
- confirmButtonText={translate(
- 'settings.authentication.github.provisioning_change.confirm_changes',
- )}
- >
- {hasGithubProvisioningTypeChange &&
- translate('settings.authentication.github.confirm', provisioningStatus, 'description')}
- {(provisioningStatus === ProvisioningType.auto || allowToSignUpEnabled) &&
- organizationListIsEmpty && (
- <FlagMessage className="sw-mt-2" variant="warning">
- {translate('settings.authentication.github.provisioning_change.insecure_config')}
- </FlagMessage>
- )}
- </ConfirmModal>
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/authentication/GitLabAuthenticationTab.tsx b/server/sonar-web/src/main/js/apps/settings/components/authentication/GitLabAuthenticationTab.tsx
index e7e2b41e01e..189ec2d1ab8 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/authentication/GitLabAuthenticationTab.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/authentication/GitLabAuthenticationTab.tsx
@@ -18,13 +18,12 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { Spinner } from 'design-system';
-import { omitBy } from 'lodash';
+import { isEmpty, omitBy } from 'lodash';
import React, { FormEvent, useContext } from 'react';
import { FormattedMessage } from 'react-intl';
import GitLabSynchronisationWarning from '../../../../app/components/GitLabSynchronisationWarning';
import { AvailableFeaturesContext } from '../../../../app/components/available-features/AvailableFeaturesContext';
import DocumentationLink from '../../../../components/common/DocumentationLink';
-import ConfirmModal from '../../../../components/controls/ConfirmModal';
import { translate, translateWithParameters } from '../../../../helpers/l10n';
import { useIdentityProviderQuery } from '../../../../queries/identity-provider/common';
import {
@@ -45,6 +44,7 @@ import GitLabConfigurationForm from './GitLabConfigurationForm';
import GitLabConfigurationValidity from './GitLabConfigurationValidity';
import ProvisioningSection from './ProvisioningSection';
import TabHeader from './TabHeader';
+import ConfirmProvisioningModal from './ConfirmProvisioningModal';
interface ChangesForm {
provisioningType?: GitLabConfigurationUpdateBody['provisioningType'];
@@ -125,7 +125,10 @@ export default function GitLabAuthenticationTab() {
const handleSubmit = (e: FormEvent) => {
e.preventDefault();
- if (changes?.provisioningType !== undefined) {
+ if (
+ changes?.provisioningType !== undefined ||
+ (provisioningType === ProvisioningType.jit && allowUsersToSignUp && isEmpty(allowedGroups))
+ ) {
setShowConfirmProvisioningModal(true);
} else {
updateProvisioning();
@@ -381,16 +384,15 @@ export default function GitLabAuthenticationTab() {
)}
</div>
{showConfirmProvisioningModal && provisioningType && (
- <ConfirmModal
- onConfirm={updateProvisioning}
- header={translate('settings.authentication.gitlab.confirm', provisioningType)}
+ <ConfirmProvisioningModal
+ allowUsersToSignUp={allowUsersToSignUp}
+ hasProvisioningTypeChange={Boolean(changes?.provisioningType)}
+ isAllowListEmpty={isEmpty(allowedGroups)}
onClose={() => setShowConfirmProvisioningModal(false)}
- confirmButtonText={translate(
- 'settings.authentication.gitlab.provisioning_change.confirm_changes',
- )}
- >
- {translate('settings.authentication.gitlab.confirm', provisioningType, 'description')}
- </ConfirmModal>
+ onConfirm={updateProvisioning}
+ provider={Provider.Gitlab}
+ provisioningStatus={provisioningType}
+ />
)}
{openForm && (
<GitLabConfigurationForm data={configuration ?? null} onClose={() => setOpenForm(false)} />
diff --git a/server/sonar-web/src/main/js/apps/settings/components/authentication/GithubAuthenticationTab.tsx b/server/sonar-web/src/main/js/apps/settings/components/authentication/GithubAuthenticationTab.tsx
index d582ecd64a8..2f4937eefba 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/authentication/GithubAuthenticationTab.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/authentication/GithubAuthenticationTab.tsx
@@ -38,7 +38,6 @@ import AutoProvisioningConsent from './AutoProvisionningConsent';
import ConfigurationDetails from './ConfigurationDetails';
import ConfigurationForm from './ConfigurationForm';
import GitHubConfigurationValidity from './GitHubConfigurationValidity';
-import GitHubConfirmModal from './GitHubConfirmModal';
import GitHubMappingModal from './GitHubMappingModal';
import ProvisioningSection from './ProvisioningSection';
import TabHeader from './TabHeader';
@@ -49,6 +48,7 @@ import useGithubConfiguration, {
isAllowToSignUpEnabled,
isOrganizationListEmpty,
} from './hook/useGithubConfiguration';
+import ConfirmProvisioningModal from './ConfirmProvisioningModal';
interface GithubAuthenticationProps {
definitions: ExtendedSettingDefinition[];
@@ -309,11 +309,13 @@ export default function GithubAuthenticationTab(props: GithubAuthenticationProps
}
/>
{showConfirmProvisioningModal && (
- <GitHubConfirmModal
- onConfirm={() => changeProvisioning()}
+ <ConfirmProvisioningModal
+ allowUsersToSignUp={isAllowToSignUpEnabled(values)}
+ hasProvisioningTypeChange={hasGithubProvisioningTypeChange}
+ isAllowListEmpty={isOrganizationListEmpty(values)}
onClose={() => setShowConfirmProvisioningModal(false)}
- values={values}
- hasGithubProvisioningTypeChange={hasGithubProvisioningTypeChange}
+ onConfirm={changeProvisioning}
+ provider={Provider.Github}
provisioningStatus={provisioningStatus}
/>
)}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/authentication/__tests__/Authentication-Gitlab-it.tsx b/server/sonar-web/src/main/js/apps/settings/components/authentication/__tests__/Authentication-Gitlab-it.tsx
index 21cd232a262..0f7cbe05794 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/authentication/__tests__/Authentication-Gitlab-it.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/authentication/__tests__/Authentication-Gitlab-it.tsx
@@ -117,6 +117,9 @@ const ui = {
confirmJitProvisioningDialog: byRole('dialog', {
name: 'settings.authentication.gitlab.confirm.JIT',
}),
+ confirmInsecureProvisioningDialog: byRole('dialog', {
+ name: 'settings.authentication.gitlab.confirm.insecure',
+ }),
confirmProvisioningChange: byRole('button', {
name: 'settings.authentication.gitlab.provisioning_change.confirm_changes',
}),
@@ -329,10 +332,46 @@ it('should change from auto provisioning to JIT with proper validation', async (
expect(await ui.saveProvisioning.find()).toBeEnabled();
- expect(ui.jitAllowUsersToSignUpToggle.get()).toBeInTheDocument();
+ await user.click(ui.jitAllowUsersToSignUpToggle.get());
+ await user.click(ui.deleteGroupButton.get());
+
+ await user.click(ui.saveProvisioning.get());
+ expect(
+ ui.confirmJitProvisioningDialog
+ .byText('settings.authentication.gitlab.provisioning_change.insecure_config')
+ .get(),
+ ).toBeInTheDocument();
+ await user.click(ui.confirmProvisioningChange.get());
+ expect(ui.confirmJitProvisioningDialog.query()).not.toBeInTheDocument();
+
+ expect(ui.jitProvisioningRadioButton.get()).toBeChecked();
+ expect(await ui.saveProvisioning.find()).toBeDisabled();
+});
+
+it('should show configuration warning with jit provisioning and no groups', async () => {
+ handler.setGitlabConfigurations([
+ mockGitlabConfiguration({
+ allowUsersToSignUp: false,
+ enabled: true,
+ provisioningType: ProvisioningType.jit,
+ allowedGroups: [],
+ isProvisioningTokenSet: true,
+ }),
+ ]);
+ const user = userEvent.setup();
+ renderAuthentication([Feature.GitlabProvisioning]);
+
+ expect(await ui.editConfigButton.find()).toBeInTheDocument();
+ await user.click(ui.jitAllowUsersToSignUpToggle.get());
await user.click(ui.saveProvisioning.get());
- expect(ui.confirmJitProvisioningDialog.get()).toBeInTheDocument();
+
+ expect(
+ ui.confirmInsecureProvisioningDialog
+ .byText('settings.authentication.gitlab.provisioning_change.insecure_config')
+ .get(),
+ ).toBeInTheDocument();
+
await user.click(ui.confirmProvisioningChange.get());
expect(ui.confirmJitProvisioningDialog.query()).not.toBeInTheDocument();
diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
index fd3927826d9..d54c9247583 100644
--- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties
+++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
@@ -1607,7 +1607,9 @@ settings.authentication.gitlab.confirm.AUTO_PROVISIONING=Switch to automatic pro
settings.authentication.gitlab.confirm.JIT=Switch to Just-in-Time provisioning
settings.authentication.gitlab.confirm.AUTO_PROVISIONING.description=Once you transition to automatic provisioning users and groups on GitLab projects will be inherited from GitLab. You will no longer have the ability to edit them within SonarQube. Do you want to proceed with this change?
settings.authentication.gitlab.confirm.JIT.description=Switching to Just-in-Time provisioning removes the automatic synchronization of users and groups. Users are provisioned and updated only at user login. Are you sure?
+settings.authentication.gitlab.confirm.insecure=Potentially insecure configuration
settings.authentication.gitlab.provisioning_change.confirm_changes=Confirm Changes
+settings.authentication.gitlab.provisioning_change.insecure_config=Please be aware that your configuration is potentially insecure because you didn't add any groups to the allowlist and you allowed users to sign up. Anyone can install it and gain access to your instance.
settings.authentication.gitlab.form.provisioning_with_gitlab=Automatic user and group provisioning
settings.authentication.gitlab.form.provisioning_with_gitlab.description=Users and groups are automatically provisioned from GitLab. Once activated, users and groups can only be created and modified from GitLab. Existing local users will be kept and can only be deactivated. {documentation}
settings.authentication.gitlab.form.provisioning.disabled=Your current edition does not support provisioning with GitLab. See the {documentation} for more information.