From f6a0f6912fe919139374682f1f28c14c55b995c2 Mon Sep 17 00:00:00 2001 From: Gareth Dawson Date: Mon, 23 Oct 2023 11:29:28 +0100 Subject: [PATCH] SQL: Update configuration pages (#75525) * update psql config page to follow guidelines * make small changes to mysql config page * update shared tls config to match guidelines * revert back to text area * remove type assertion * prettier * remove unused imports * update required fields * add secure sox proxy to additional settings * make additional settings collapsible * make user permissions collapsable * make db name and password optional * mysql: move from alert to collapse --- .../configuration/TLSSecretsConfig.tsx | 80 ++- .../configuration/ConfigurationEditor.tsx | 183 ++++--- .../configuration/ConfigurationEditor.tsx | 493 +++++++++++------- 3 files changed, 440 insertions(+), 316 deletions(-) diff --git a/public/app/features/plugins/sql/components/configuration/TLSSecretsConfig.tsx b/public/app/features/plugins/sql/components/configuration/TLSSecretsConfig.tsx index d602c802d1b..f6d1b02a97e 100644 --- a/public/app/features/plugins/sql/components/configuration/TLSSecretsConfig.tsx +++ b/public/app/features/plugins/sql/components/configuration/TLSSecretsConfig.tsx @@ -7,7 +7,8 @@ import { onUpdateDatasourceSecureJsonDataOption, updateDatasourcePluginResetOption, } from '@grafana/data'; -import { InlineField, SecretTextArea } from '@grafana/ui'; +import { Stack } from '@grafana/experimental'; +import { Field, Icon, Label, SecretTextArea, Tooltip } from '@grafana/ui'; export interface Props { editorProps: DataSourcePluginOptionsEditorProps; @@ -18,20 +19,31 @@ export interface Props { } export const TLSSecretsConfig = (props: Props) => { - const { labelWidth, editorProps, showCACert, showKeyPair = true } = props; + const { editorProps, showCACert, showKeyPair = true } = props; const { secureJsonFields } = editorProps.options; return ( <> {showKeyPair ? ( - To authenticate with an TLS/SSL client certificate, provide the client certificate here. + + + TLS/SSL Client Certificate + + To authenticate with an TLS/SSL client certificate, provide the client certificate here. + + } + > + + + + } - labelWidth={labelWidth} - label="TLS/SSL Client Certificate" > { updateDatasourcePluginResetOption(editorProps, 'tlsClientCert'); }} - > - + /> + ) : null} {showCACert ? ( - If the selected TLS/SSL mode requires a server root certificate, provide it here.} - labelWidth={labelWidth} - label="TLS/SSL Root Certificate" + + + TLS/SSL Root Certificate + If the selected TLS/SSL mode requires a server root certificate, provide it here. + } + > + + + + + } > { updateDatasourcePluginResetOption(editorProps, 'tlsCACert'); }} - > - + /> + ) : null} {showKeyPair ? ( - To authenticate with a client TLS/SSL certificate, provide the key here.} - labelWidth={labelWidth} - label="TLS/SSL Client Key" + + + TLS/SSL Client Key + To authenticate with a client TLS/SSL certificate, provide the key here.} + > + + + + + } > { updateDatasourcePluginResetOption(editorProps, 'tlsClientKey'); }} - > - + /> + ) : null} ); diff --git a/public/app/plugins/datasource/mysql/configuration/ConfigurationEditor.tsx b/public/app/plugins/datasource/mysql/configuration/ConfigurationEditor.tsx index 024356a25a0..7f40650211a 100644 --- a/public/app/plugins/datasource/mysql/configuration/ConfigurationEditor.tsx +++ b/public/app/plugins/datasource/mysql/configuration/ConfigurationEditor.tsx @@ -1,4 +1,4 @@ -import React, { SyntheticEvent } from 'react'; +import React, { SyntheticEvent, useState } from 'react'; import { DataSourcePluginOptionsEditorProps, @@ -7,16 +7,15 @@ import { updateDatasourcePluginJsonDataOption, updateDatasourcePluginResetOption, } from '@grafana/data'; -import { ConfigSection, DataSourceDescription, Stack } from '@grafana/experimental'; +import { ConfigSection, ConfigSubSection, DataSourceDescription, Stack } from '@grafana/experimental'; import { config } from '@grafana/runtime'; import { - Alert, + Collapse, Divider, Field, Icon, Input, Label, - Link, SecretInput, SecureSocksProxySettings, Switch, @@ -29,6 +28,8 @@ import { useMigrateDatabaseFields } from 'app/features/plugins/sql/components/co import { MySQLOptions } from '../types'; export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps) => { + const [isOpen, setIsOpen] = useState(true); + const { options, onOptionsChange } = props; const jsonData = options.jsonData; @@ -57,11 +58,22 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps + setIsOpen((x) => !x)}> + The database user should only be granted SELECT permissions on the specified database & 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 MySQL user with restricted + permissions. Check out the docs for more information. +
+ + + - - - - + - + + + + - {config.secureSocksDSProxyEnabled && ( - <> - - - - )} - {jsonData.tlsAuth || jsonData.tlsAuthWithCACert ? ( <> @@ -153,7 +158,7 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps ) : null} @@ -162,84 +167,74 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps - - - - Session timezone - - Specify the time zone used in the database session, e.g. Europe/Berlin or - +02:00. This is necessary, if the timezone of the database (or the host of the - database) is set to something other than UTC. The value is set in the session with - SET time_zone='...'. If you leave this field empty, the timezone is not - updated. You can find more information in the MySQL documentation. - - } - > - - - - - } - > - - + + + + + Session timezone + + Specify the time zone used in the database session, e.g. Europe/Berlin or + +02:00. This is necessary, if the timezone of the database (or the host of the + database) is set to something other than UTC. The value is set in the session with + SET time_zone='...'. If you leave this field empty, the timezone is not + updated. You can find more information in the MySQL documentation. + + } + > + + + + + } + > + + - - - Min time interval - - 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. - - } - > - - - - - } - description="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." - > - - + + + Min time interval + + 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. + + } + > + + + + + } + description="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." + > + + + + + + + {config.secureSocksDSProxyEnabled && ( + + )} - - - - - - - - - The database user should only be granted SELECT permissions on the specified database & 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 MySQL user with restricted permissions. - Check out the{' '} - - MySQL Data Source Docs - {' '} - for more information. - ); }; diff --git a/public/app/plugins/datasource/postgres/configuration/ConfigurationEditor.tsx b/public/app/plugins/datasource/postgres/configuration/ConfigurationEditor.tsx index 0c9baf22211..559d0b63338 100644 --- a/public/app/plugins/datasource/postgres/configuration/ConfigurationEditor.tsx +++ b/public/app/plugins/datasource/postgres/configuration/ConfigurationEditor.tsx @@ -8,17 +8,20 @@ import { updateDatasourcePluginJsonDataOption, updateDatasourcePluginResetOption, } from '@grafana/data'; +import { ConfigSection, ConfigSubSection, DataSourceDescription, Stack } from '@grafana/experimental'; import { config } from '@grafana/runtime'; import { - Alert, - InlineSwitch, - FieldSet, - InlineField, - InlineFieldRow, + Divider, Input, Select, SecretInput, - Link, + Field, + Tooltip, + Label, + Icon, + Switch, + SecureSocksProxySettings, + Collapse, } from '@grafana/ui'; import { ConnectionLimits } from 'app/features/plugins/sql/components/configuration/ConnectionLimits'; import { TLSSecretsConfig } from 'app/features/plugins/sql/components/configuration/TLSSecretsConfig'; @@ -46,9 +49,9 @@ export const postgresVersions: Array> = [ export const PostgresConfigEditor = (props: DataSourcePluginOptionsEditorProps) => { const [versionOptions, setVersionOptions] = useState(postgresVersions); + const [isOpen, setIsOpen] = useState(true); useAutoDetectFeatures({ props, setVersionOptions }); - useMigrateDatabaseFields(props); const { options, onOptionsChange } = props; @@ -86,229 +89,323 @@ export const PostgresConfigEditor = (props: DataSourcePluginOptionsEditorProps

-

- + + + + + setIsOpen((x) => !x)}> + The database user should only be granted SELECT permissions on the specified database & tables you want to + query.
+ Grafana does not validate that queries are safe so queries can contain any SQL statement. For example, + statements like DELETE FROM user; and DROP TABLE user; would be executed.
+ To protect against this we Highly recommend you create a specific PostgreSQL user with + restricted permissions. Check out the docs for more information. +
+ + + + + -
- + /> + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + TLS/SSL Mode + + This option determines whether or with what priority a secure TLS/SSL TCP/IP connection will be + negotiated with the server + + } + > + + + + + } > - + width={WIDTH_LONG} + /> + + {options.jsonData.sslmode !== PostgresTLSModes.disable ? ( - - This option determines how TLS/SSL certifications are configured. Selecting File system path will - allow you to configure certificates by specifying paths to existing certificates on the local file - system where Grafana is running. Be sure that the file is readable by the user executing the Grafana - process. -
-
- Selecting Certificate content will allow you to configure certificates by specifying its content. - The content will be stored encrypted in Grafana's database. When connecting to the database the - certificates will be written as files to Grafana's configured data path on the local file system. - + + + TLS/SSL Method + + This option determines how TLS/SSL certifications are configured. Selecting{' '} + File system path will allow you to configure certificates by specifying paths to existing + certificates on the local file system where Grafana is running. Be sure that the file is + readable by the user executing the Grafana process. +
+
+ Selecting Certificate content will allow you to configure certificates by specifying its + content. The content will be stored encrypted in Grafana's database. When connecting to the + database the certificates will be written as files to Grafana's configured data path on the + local file system. + + } + > + +
+
+ } > -
- ) : null} -
- - {config.secureSocksDSProxyEnabled && ( -
- - - onOptionsChange({ - ...options, - jsonData: { ...options.jsonData, enableSecureSocksProxy: event!.currentTarget.checked }, - }) - } + width={WIDTH_LONG} /> - -
- )} +
+ ) : null} + + {jsonData.sslmode !== PostgresTLSModes.disable ? ( -
- {jsonData.tlsConfigurationMethod === PostgresTLSMethods.fileContent ? ( - - ) : ( - <> - - If the selected TLS/SSL mode requires a server root certificate, provide the path to the file here. - + <> + + + {jsonData.tlsConfigurationMethod === PostgresTLSMethods.fileContent ? ( + - - - - To authenticate with an TLS/SSL client certificate, provide the path to the file here. Be sure that - the file is readable by the user executing the grafana process. - - } - labelWidth={labelWidthSSLDetails} - label="TLS/SSL Client Certificate" - > - - - - To authenticate with a client TLS/SSL certificate, provide the path to the corresponding key file - here. Be sure that the file is only readable by the user executing the grafana process. - - } - labelWidth={labelWidthSSLDetails} - label="TLS/SSL Client Key" - > - - - - )} -
+ editorProps={props} + labelWidth={WIDTH_LONG} + /> + ) : ( + <> + + + TLS/SSL Root Certificate + + If the selected TLS/SSL mode requires a server root certificate, provide the path to the + file here. + + } + > + + + + + } + > + + + + + TLS/SSL Client Certificate + + To authenticate with an TLS/SSL client certificate, provide the path to the file here. Be + sure that the file is readable by the user executing the grafana process. + + } + > + + + + + } + > + + + + + TLS/SSL Client Key + + To authenticate with a client TLS/SSL certificate, provide the path to the corresponding + key file here. Be sure that the file is only readable by the user executing the + grafana process. + + } + > + + + + + } + > + + + + )} + + ) : null} - + -
- - - - - TimescaleDB is a time-series database built as a PostgreSQL extension. If enabled, Grafana will use - time_bucket in the $__timeGroup macro and display TimescaleDB specific aggregate - functions in the query builder. - - } - labelWidth={labelWidthShort} - label="TimescaleDB" - htmlFor="timescaledb" - > - - - - 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. - - } - labelWidth={labelWidthShort} - label="Min time interval" - > - - -
+ + + + + Version + This option controls what functions are available in the PostgreSQL query builder + } + > + + + + + } + > + + + + + TimescaleDB + + TimescaleDB is a time-series database built as a PostgreSQL extension. If enabled, Grafana will + use + time_bucket in the $__timeGroup macro and display TimescaleDB specific + aggregate functions in the query builder. + + } + > + + + + + } + > + + + - - The database user should only be granted SELECT permissions on the specified database & tables you want to - query. Grafana does not validate that queries are safe so queries can contain any SQL statement. For example, - statements like DELETE FROM user; and DROP TABLE user; would be executed. To protect - against this we Highly recommend you create a specific PostgreSQL user with restricted - permissions. Check out the{' '} - - PostgreSQL Data Source Docs - {' '} - for more information. - + + + {config.secureSocksDSProxyEnabled && ( + onOptionsChange(options)} /> + )} + ); };