From 61e3f3a059c878a03a2a1ddc1965baa4b1455b78 Mon Sep 17 00:00:00 2001 From: Andreas Christou Date: Mon, 25 Sep 2023 14:14:41 +0100 Subject: [PATCH] MSSQL: `ConfigEditor` updates (#75275) * Add secure json data type * Update Azure credentials form with Field components - Update labels - Update widths - Remove excess code * Update config editor * Fix lint --- .../mssql/azureauth/AzureCredentialsForm.tsx | 212 ++++++------ .../configuration/ConfigurationEditor.tsx | 320 ++++++++++-------- public/app/plugins/datasource/mssql/types.ts | 4 + 3 files changed, 283 insertions(+), 253 deletions(-) diff --git a/public/app/plugins/datasource/mssql/azureauth/AzureCredentialsForm.tsx b/public/app/plugins/datasource/mssql/azureauth/AzureCredentialsForm.tsx index acf68ccca90..5c6e31af1b3 100644 --- a/public/app/plugins/datasource/mssql/azureauth/AzureCredentialsForm.tsx +++ b/public/app/plugins/datasource/mssql/azureauth/AzureCredentialsForm.tsx @@ -1,9 +1,7 @@ import React, { ChangeEvent } from 'react'; import { SelectableValue } from '@grafana/data'; -import { InlineFormLabel, Button } from '@grafana/ui/src/components'; -import { Input } from '@grafana/ui/src/components/Forms/Legacy/Input/Input'; -import { Select } from '@grafana/ui/src/components/Forms/Legacy/Select/Select'; +import { Button, Field, Select, Input } from '@grafana/ui/src/components'; import { AzureCredentialsType, AzureAuthType } from '../types'; @@ -52,117 +50,121 @@ export const AzureCredentialsForm = (props: Props) => { return (
{managedIdentityEnabled && ( -
-
- - Authentication - - opt.value === credentials.authType)} + options={authTypeOptions} + onChange={onAuthTypeChange} + disabled={disabled} + /> + )} {credentials.authType === 'clientsecret' && ( <> {azureCloudOptions && ( -
-
- - Azure Cloud - - opt.value === credentials.azureCloud)} + options={azureCloudOptions} + onChange={(selected: SelectableValue) => { + const value = selected.value || ''; + onInputChange({ property: 'azureCloud', value }); + }} + isDisabled={disabled} + inputId="azure-cloud-type" + aria-label="Azure Cloud" + width={20} + /> + )} -
-
- Directory (tenant) ID -
- ) => { - const value = event.target.value; - onInputChange({ property: 'tenantId', value }); - }} - disabled={disabled} - /> -
-
-
-
-
- Application (client) ID -
- ) => { - const value = event.target.value; - onInputChange({ property: 'clientId', value }); - }} - disabled={disabled} - /> -
-
-
- {typeof credentials.clientSecret === 'symbol' ? ( -
-
- - Client Secret - - -
- {!disabled && ( -
-
- -
-
- )} -
- ) : ( -
-
- Client Secret -
+ + ) => { + const value = event.target.value; + onInputChange({ property: 'tenantId', value }); + }} + disabled={disabled} + aria-label="Tenant ID" + /> + + + ) => { + const value = event.target.value; + onInputChange({ property: 'clientId', value }); + }} + disabled={disabled} + aria-label="Client ID" + /> + + {!disabled && + (typeof credentials.clientSecret === 'symbol' ? ( + +
) => { - const value = event.target.value; - onInputChange({ property: 'clientSecret', value }); + aria-label="Client Secret" + placeholder="configured" + disabled={true} + data-testid={'client-secret'} + width={45} + /> +
-
-
- )} + + ) : ( + + ) => { + const value = event.target.value; + onInputChange({ property: 'clientSecret', value }); + }} + id="client-secret" + disabled={disabled} + /> + + ))} )}
diff --git a/public/app/plugins/datasource/mssql/configuration/ConfigurationEditor.tsx b/public/app/plugins/datasource/mssql/configuration/ConfigurationEditor.tsx index ed6e03b806d..22a56cc03eb 100644 --- a/public/app/plugins/datasource/mssql/configuration/ConfigurationEditor.tsx +++ b/public/app/plugins/datasource/mssql/configuration/ConfigurationEditor.tsx @@ -10,18 +10,19 @@ import { updateDatasourcePluginJsonDataOption, updateDatasourcePluginResetOption, } from '@grafana/data'; +import { ConfigSection, ConfigSubSection, DataSourceDescription } from '@grafana/experimental'; import { Alert, FieldSet, - InlineField, - InlineFieldRow, - InlineSwitch, Input, Link, SecretInput, Select, useStyles2, SecureSocksProxySettings, + Divider, + Field, + Switch, } from '@grafana/ui'; import { NumberInput } from 'app/core/components/OptionsUI/NumberInput'; import { config } from 'app/core/config'; @@ -29,14 +30,18 @@ import { ConnectionLimits } from 'app/features/plugins/sql/components/configurat import { useMigrateDatabaseFields } from 'app/features/plugins/sql/components/configuration/useMigrateDatabaseFields'; import { AzureAuthSettings } from '../azureauth/AzureAuthSettings'; -import { MSSQLAuthenticationType, MSSQLEncryptOptions, MssqlOptions, AzureAuthConfigType } from '../types'; +import { + MSSQLAuthenticationType, + MSSQLEncryptOptions, + MssqlOptions, + AzureAuthConfigType, + MssqlSecureOptions, +} from '../types'; const SHORT_WIDTH = 15; -const LONG_WIDTH = 46; -const LABEL_WIDTH_SSL = 25; -const LABEL_WIDTH_DETAILS = 20; +const LONG_WIDTH = 40; -export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps) => { +export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps) => { useMigrateDatabaseFields(props); const { options: dsSettings, onOptionsChange } = props; @@ -107,8 +112,25 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps -
- + + + The database user should only be granted SELECT permissions on the specified database and tables you want to + query. Grafana does not validate that queries are safe so queries can contain any SQL statement. For example, + statements like USE otherdb; and DROP TABLE user; would be executed. To protect + against this we highly recommend you create a specific MS SQL user with restricted permissions. Check + out the{' '} + + Microsoft SQL Server Data Source Docs + {' '} + for more information. + + + + - - + /> + + - - -
  • - SQL Server Authentication This is the default mechanism to connect to MS SQL Server. Enter the - SQL Server Authentication login or the Windows Authentication login in the DOMAIN\User format. -
  • -
  • - Windows Authentication Windows Integrated Security - single sign on for users who are already - logged onto Windows and have enabled this option for MS SQL Server. -
  • - {azureAuthIsSupported && ( -
  • - Azure Authentication Securely authenticate and access Azure resources and applications using - Azure AD credentials - Managed Service Identity and Client Secret Credentials are supported. -
  • - )} - - } - > - -
    - {/* Basic SQL auth. Render if authType === MSSQLAuthenticationType.sqlAuth OR - if no authType exists, which will be the case when creating a new data source */} - {(jsonData.authenticationType === MSSQLAuthenticationType.sqlAuth || !jsonData.authenticationType) && ( - - - - - - - - - )} -
    + /> + + - {config.secureSocksDSProxyEnabled && ( - - )} - -
    - + Determines whether or to which extent a secure SSL TCP/IP connection will be negotiated with the server.
      @@ -216,23 +179,19 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps - + width={LONG_WIDTH} + /> + {jsonData.encrypt === MSSQLEncryptOptions.true ? ( <> - - - + + + {jsonData.tlsSkipVerify ? null : ( <> - Path to file containing the public key certificate of the CA that signed the SQL Server certificate. Needed when the server certificate is self signed. @@ -244,76 +203,141 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps - - + width={LONG_WIDTH} + /> + + - + width={LONG_WIDTH} + /> + )} ) : null} -
    + - {azureAuthIsSupported && jsonData.authenticationType === MSSQLAuthenticationType.azureAuth && ( -
    - -
    - )} - - - -
    - - A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example - 1m if your data is written every minute. - + + +
  • + SQL Server Authentication This is the default mechanism to connect to MS SQL Server. Enter the + SQL Server Authentication login or the Windows Authentication login in the DOMAIN\User format. +
  • +
  • + Windows Authentication Windows Integrated Security - single sign on for users who are already + logged onto Windows and have enabled this option for MS SQL Server. +
  • + {azureAuthIsSupported && ( +
  • + Azure Authentication Securely authenticate and access Azure resources and applications using + Azure AD credentials - Managed Service Identity and Client Secret Credentials are supported. +
  • + )} + } - label="Min time interval" - labelWidth={LABEL_WIDTH_DETAILS} > - -
    - - The number of seconds to wait before canceling the request when connecting to the database. The default is{' '} - 0, meaning no timeout. - - } - label="Connection timeout" - labelWidth={LABEL_WIDTH_DETAILS} - > - - -
    + + + + + + + )} + + {azureAuthIsSupported && jsonData.authenticationType === MSSQLAuthenticationType.azureAuth && ( +
    + +
    + )} + + + + + + + + + A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example + 1m if your data is written every minute. + + } + label="Min time interval" + > + + + + The number of seconds to wait before canceling the request when connecting to the database. The default + is 0, meaning no timeout. + + } + label="Connection timeout" + > + + + + {config.secureSocksDSProxyEnabled && ( + + )} + ); }; diff --git a/public/app/plugins/datasource/mssql/types.ts b/public/app/plugins/datasource/mssql/types.ts index 393224663bb..d950e4bef09 100644 --- a/public/app/plugins/datasource/mssql/types.ts +++ b/public/app/plugins/datasource/mssql/types.ts @@ -43,6 +43,10 @@ export interface MssqlOptions extends SQLOptions { azureCredentials?: AzureCredentialsType; } +export interface MssqlSecureOptions { + password?: string; +} + export type AzureAuthJSONDataType = DataSourceJsonData & { azureCredentials: AzureCredentialsType; };