@ -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 < MssqlOptions > ) = > {
export const ConfigurationEditor = ( props : DataSourcePluginOptionsEditorProps < MssqlOptions , MssqlSecureOptions > ) = > {
useMigrateDatabaseFields ( props ) ;
const { options : dsSettings , onOptionsChange } = props ;
@ -107,8 +112,25 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps<Ms
return (
< >
< FieldSet label = "MS SQL Connection" width = { 400 } >
< InlineField labelWidth = { SHORT_WIDTH } label = "Host" >
< DataSourceDescription
dataSourceName = "Microsoft SQL Server"
docsLink = "https://grafana.com/docs/grafana/latest/datasources/mssql/"
hasRequiredFields
/ >
< Alert title = "User Permission" severity = "info" >
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 < code > USE otherdb ; < / code > and < code > DROP TABLE user ; < / code > would be executed . To protect
against this we < em > highly < / em > recommend you create a specific MS SQL user with restricted permissions . Check
out the { ' ' }
< Link rel = "noreferrer" target = "_blank" href = "http://docs.grafana.org/features/datasources/mssql/" >
Microsoft SQL Server Data Source Docs
< / Link > { ' ' }
for more information .
< / Alert >
< Divider / >
< ConfigSection title = "Connection" >
< Field label = "Host" required invalid = { ! dsSettings . url } error = { 'Host is required' } >
< Input
width = { LONG_WIDTH }
name = "host"
@ -116,82 +138,23 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps<Ms
value = { dsSettings . url || '' }
placeholder = "localhost:1433"
onChange = { onDSOptionChanged ( 'url' ) }
> < / Input >
< / Inline Field>
< InlineField labelWidth = { SHORT_WIDTH } label = "Database" >
/ >
< / Field >
< Field label = "Database" required invalid = { ! jsonData . database } error = { 'Database is required' } >
< Input
width = { LONG_WIDTH }
name = "database"
value = { jsonData . database || '' }
placeholder = "database name"
onChange = { onUpdateDatasourceJsonDataOption ( props , 'database' ) }
> < / Input >
< / InlineField >
< InlineField
label = "Authentication"
labelWidth = { SHORT_WIDTH }
htmlFor = "authenticationType"
tooltip = {
< ul className = { styles . ulPadding } >
< li >
< i > SQL Server Authentication < / i > 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 .
< / li >
< li >
< i > Windows Authentication < / i > Windows Integrated Security - single sign on for users who are already
logged onto Windows and have enabled this option for MS SQL Server .
< / li >
{ azureAuthIsSupported && (
< li >
< i > Azure Authentication < / i > Securely authenticate and access Azure resources and applications using
Azure AD credentials - Managed Service Identity and Client Secret Credentials are supported .
< / li >
) }
< / ul >
}
>
< Select
// Default to basic authentication of none is set
value = { jsonData . authenticationType || MSSQLAuthenticationType . sqlAuth }
inputId = "authenticationType"
options = { buildAuthenticationOptions ( ) }
onChange = { onAuthenticationMethodChanged }
> < / Select >
< / InlineField >
{ / * B a s i c S Q L a u t h . R e n d e r i f a u t h T y p e = = = M S S Q L A u t h e n t i c a t i o n T y p e . s q l A u t h O R
if no authType exists , which will be the case when creating a new data source * / }
{ ( jsonData . authenticationType === MSSQLAuthenticationType . sqlAuth || ! jsonData . authenticationType ) && (
< InlineFieldRow >
< InlineField labelWidth = { SHORT_WIDTH } label = "User" >
< Input
width = { SHORT_WIDTH }
value = { dsSettings . user || '' }
placeholder = "user"
onChange = { onDSOptionChanged ( 'user' ) }
> < / Input >
< / InlineField >
< InlineField label = "Password" labelWidth = { SHORT_WIDTH } >
< SecretInput
width = { SHORT_WIDTH }
placeholder = "Password"
isConfigured = { dsSettings . secureJsonFields && dsSettings . secureJsonFields . password }
onReset = { onResetPassword }
onBlur = { onUpdateDatasourceSecureJsonDataOption ( props , 'password' ) }
> < / SecretInput >
< / InlineField >
< / InlineFieldRow >
) }
< / FieldSet >
/ >
< / Field >
< / ConfigSection >
{ config . secureSocksDSProxyEnabled && (
< SecureSocksProxySettings options = { dsSettings } onOptionsChange = { onOptionsChange } / >
) }
< FieldSet label = "TLS/SSL Auth" >
< InlineField
labelWidth = { LABEL_WIDTH_SSL }
< ConfigSection title = "TLS/SSL Auth" >
< Field
htmlFor = "encrypt"
tooltip = {
description = {
< >
Determines whether or to which extent a secure SSL TCP / IP connection will be negotiated with the server .
< ul className = { styles . ulPadding } >
@ -216,23 +179,19 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps<Ms
value = { jsonData . encrypt || MSSQLEncryptOptions . false }
inputId = "encrypt"
onChange = { onEncryptChanged }
> < / Select >
< / InlineField >
width = { LONG_WIDTH }
/ >
< / Field >
{ jsonData . encrypt === MSSQLEncryptOptions . true ? (
< >
< InlineField labelWidth = { LABEL_WIDTH_SSL } htmlFor = "skipTlsVerify" label = "Skip TLS Verify" >
< InlineSwitch
id = "skipTlsVerify"
onChange = { onSkipTLSVerifyChanged }
value = { jsonData . tlsSkipVerify || false }
> < / InlineSwitch >
< / InlineField >
< Field htmlFor = "skipTlsVerify" label = "Skip TLS Verify" >
< Switch id = "skipTlsVerify" onChange = { onSkipTLSVerifyChanged } value = { jsonData . tlsSkipVerify || false } / >
< / Field >
{ jsonData . tlsSkipVerify ? null : (
< >
< InlineField
labelWidth = { LABEL_WIDTH_SSL }
tooltip = {
< Field
description = {
< span >
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<Ms
value = { jsonData . sslRootCertFile || '' }
onChange = { onUpdateDatasourceJsonDataOption ( props , 'sslRootCertFile' ) }
placeholder = "TLS/SSL root certificate file path"
> < / Input >
< / InlineField >
< InlineField labelWidth = { LABEL_WIDTH_SSL } label = "Hostname in server certificate" >
width = { LONG_WIDTH }
/ >
< / Field >
< Field label = "Hostname in server certificate" >
< Input
placeholder = "Common Name (CN) in server certificate"
value = { jsonData . serverName || '' }
onChange = { onUpdateDatasourceJsonDataOption ( props , 'serverName' ) }
> < / Input >
< / InlineField >
width = { LONG_WIDTH }
/ >
< / Field >
< / >
) }
< / >
) : null }
< / FieldSet >
{ azureAuthIsSupported && jsonData . authenticationType === MSSQLAuthenticationType . azureAuth && (
< FieldSet label = "Azure Authentication Settings" >
< azureAuthSettings.azureAuthSettingsUI dataSourceConfig = { dsSettings } onChange = { onOptionsChange } / >
< / FieldSet >
) }
< / ConfigSection >
< ConnectionLimits labelWidth = { SHORT_WIDTH } options = { dsSettings } onOptionsChange = { onOptionsChange } / >
< FieldSet label = "MS SQL details" >
< InlineField
tooltip = {
< span >
A lower limit for the auto group by time interval . Recommended to be set to write frequency , for example
< code > 1 m < / code > if your data is written every minute .
< / span >
}
label = "Min time interval"
labelWidth = { LABEL_WIDTH_DETAILS }
>
< Input
placeholder = "1m"
value = { jsonData . timeInterval || '' }
onChange = { onUpdateDatasourceJsonDataOption ( props , 'timeInterval' ) }
> < / Input >
< / InlineField >
< InlineField
tooltip = {
< span >
The number of seconds to wait before canceling the request when connecting to the database . The default is { ' ' }
< code > 0 < / code > , meaning no timeout .
< / span >
< ConfigSection title = "Authentication" >
< Field
label = "Authentication Type"
htmlFor = "authenticationType"
description = {
< ul className = { styles . ulPadding } >
< li >
< i > SQL Server Authentication < / i > 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 .
< / li >
< li >
< i > Windows Authentication < / i > Windows Integrated Security - single sign on for users who are already
logged onto Windows and have enabled this option for MS SQL Server .
< / li >
{ azureAuthIsSupported && (
< li >
< i > Azure Authentication < / i > Securely authenticate and access Azure resources and applications using
Azure AD credentials - Managed Service Identity and Client Secret Credentials are supported .
< / li >
) }
< / ul >
}
label = "Connection timeout"
labelWidth = { LABEL_WIDTH_DETAILS }
>
< NumberInput
placeholder = "60"
min = { 0 }
value = { jsonData . connectionTimeout }
onChange = { onConnectionTimeoutChanged }
> < / NumberInput >
< / InlineField >
< / FieldSet >
< Select
// Default to basic authentication of none is set
value = { jsonData . authenticationType || MSSQLAuthenticationType . sqlAuth }
inputId = "authenticationType"
options = { buildAuthenticationOptions ( ) }
onChange = { onAuthenticationMethodChanged }
width = { LONG_WIDTH }
/ >
< / Field >
< Alert title = "User Permission" severity = "info" >
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 < code > USE otherdb ; < / code > and < code > DROP TABLE user ; < / code > would be executed . To protect
against this we < em > highly < / em > recommend you create a specific MS SQL user with restricted permissions . Check
out the { ' ' }
< Link rel = "noreferrer" target = "_blank" href = "http://docs.grafana.org/features/datasources/mssql/" >
Microsoft SQL Server Data Source Docs
< / Link > { ' ' }
for more information .
< / Alert >
{ / * B a s i c S Q L a u t h . R e n d e r i f a u t h T y p e = = = M S S Q L A u t h e n t i c a t i o n T y p e . s q l A u t h O R
if no authType exists , which will be the case when creating a new data source * / }
{ ( jsonData . authenticationType === MSSQLAuthenticationType . sqlAuth || ! jsonData . authenticationType ) && (
< >
< Field label = "Username" required invalid = { ! dsSettings . user } error = { 'Username is required' } >
< Input
value = { dsSettings . user || '' }
placeholder = "user"
onChange = { onDSOptionChanged ( 'user' ) }
width = { LONG_WIDTH }
/ >
< / Field >
< Field
label = "Password"
required
invalid = { ! dsSettings . secureJsonFields . password && ! dsSettings . secureJsonData ? . password }
error = { 'Password is required' }
>
< SecretInput
width = { LONG_WIDTH }
placeholder = "Password"
isConfigured = { dsSettings . secureJsonFields && dsSettings . secureJsonFields . password }
onReset = { onResetPassword }
onChange = { onUpdateDatasourceSecureJsonDataOption ( props , 'password' ) }
required
/ >
< / Field >
< / >
) }
{ azureAuthIsSupported && jsonData . authenticationType === MSSQLAuthenticationType . azureAuth && (
< FieldSet label = "Azure Authentication Settings" >
< azureAuthSettings.azureAuthSettingsUI dataSourceConfig = { dsSettings } onChange = { onOptionsChange } / >
< / FieldSet >
) }
< / ConfigSection >
< Divider / >
< ConfigSection
title = "Additional settings"
description = "Additional settings are optional settings that can be configured for more control over your data source. This includes connection limits, connection timeout, group-by time interval, and Secure Socks Proxy."
isCollapsible = { true }
isInitiallyOpen = { true }
>
< ConnectionLimits labelWidth = { SHORT_WIDTH } options = { dsSettings } onOptionsChange = { onOptionsChange } / >
< ConfigSubSection title = "Connection details" >
< Field
description = {
< span >
A lower limit for the auto group by time interval . Recommended to be set to write frequency , for example
< code > 1 m < / code > if your data is written every minute .
< / span >
}
label = "Min time interval"
>
< Input
width = { LONG_WIDTH }
placeholder = "1m"
value = { jsonData . timeInterval || '' }
onChange = { onUpdateDatasourceJsonDataOption ( props , 'timeInterval' ) }
/ >
< / Field >
< Field
description = {
< span >
The number of seconds to wait before canceling the request when connecting to the database . The default
is < code > 0 < / code > , meaning no timeout .
< / span >
}
label = "Connection timeout"
>
< NumberInput
width = { LONG_WIDTH }
placeholder = "60"
min = { 0 }
value = { jsonData . connectionTimeout }
onChange = { onConnectionTimeoutChanged }
/ >
< / Field >
< / ConfigSubSection >
{ config . secureSocksDSProxyEnabled && (
< SecureSocksProxySettings options = { dsSettings } onOptionsChange = { onOptionsChange } / >
) }
< / ConfigSection >
< / >
) ;
} ;