AzureMonitor: Remove support for different credentials for Azure Monitor Logs (#35121)

pull/35805/head
Andres Martinez Gotor 4 years ago committed by GitHub
parent abe35c8c01
commit b1a839825f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      public/app/plugins/datasource/grafana-azure-monitor-datasource/__mocks__/instanceSettings.ts
  2. 15
      public/app/plugins/datasource/grafana-azure-monitor-datasource/api/routes.ts
  3. 4
      public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.test.ts
  4. 18
      public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.ts
  5. 34
      public/app/plugins/datasource/grafana-azure-monitor-datasource/components/AnalyticsConfig.test.tsx
  6. 96
      public/app/plugins/datasource/grafana-azure-monitor-datasource/components/AnalyticsConfig.tsx
  7. 24
      public/app/plugins/datasource/grafana-azure-monitor-datasource/components/AzureCredentialsForm.test.tsx
  8. 18
      public/app/plugins/datasource/grafana-azure-monitor-datasource/components/AzureCredentialsForm.tsx
  9. 6
      public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ConfigEditor.tsx
  10. 7
      public/app/plugins/datasource/grafana-azure-monitor-datasource/components/InsightsConfig.tsx
  11. 330
      public/app/plugins/datasource/grafana-azure-monitor-datasource/components/__snapshots__/AnalyticsConfig.test.tsx.snap
  12. 36
      public/app/plugins/datasource/grafana-azure-monitor-datasource/components/__snapshots__/InsightsConfig.test.tsx.snap
  13. 117
      public/app/plugins/datasource/grafana-azure-monitor-datasource/credentials.ts
  14. 86
      public/app/plugins/datasource/grafana-azure-monitor-datasource/plugin.json
  15. 4
      public/app/plugins/datasource/grafana-azure-monitor-datasource/resourcePicker/resourcePickerData.ts
  16. 7
      public/app/plugins/datasource/grafana-azure-monitor-datasource/types/index.ts

@ -17,8 +17,5 @@ export const createMockInstanceSetttings = (): AzureDataSourceInstanceSettings =
tenantId: 'abc-123', tenantId: 'abc-123',
clientId: 'def-456', clientId: 'def-456',
subscriptionId: 'ghi-789', subscriptionId: 'ghi-789',
// logs
azureLogAnalyticsSameAs: true,
}, },
}); });

@ -13,21 +13,6 @@ export function getManagementApiRoute(azureCloud: string): string {
} }
} }
export function getLogAnalyticsManagementApiRoute(azureCloud: string): string {
switch (azureCloud) {
case 'azuremonitor':
return 'workspacesloganalytics';
case 'chinaazuremonitor':
return 'chinaworkspacesloganalytics';
case 'govazuremonitor':
return 'govworkspacesloganalytics';
case 'germanyazuremonitor':
return 'germanyworkspacesloganalytics';
default:
throw new Error('The cloud not supported.');
}
}
export function getLogAnalyticsApiRoute(azureCloud: string): string { export function getLogAnalyticsApiRoute(azureCloud: string): string {
switch (azureCloud) { switch (azureCloud) {
case 'azuremonitor': case 'azuremonitor':

@ -33,7 +33,7 @@ describe('AzureLogAnalyticsDatasource', () => {
beforeEach(() => { beforeEach(() => {
ctx.instanceSettings = { ctx.instanceSettings = {
jsonData: { logAnalyticsSubscriptionId: 'xxx', azureLogAnalyticsSameAs: false }, jsonData: { subscriptionId: 'xxx' },
url: 'http://azureloganalyticsapi', url: 'http://azureloganalyticsapi',
}; };
@ -93,7 +93,7 @@ describe('AzureLogAnalyticsDatasource', () => {
it('should use the loganalyticsazure plugin route', async () => { it('should use the loganalyticsazure plugin route', async () => {
await ctx.ds.metricFindQuery('workspace("aworkspace").AzureActivity | distinct Category'); await ctx.ds.metricFindQuery('workspace("aworkspace").AzureActivity | distinct Category');
expect(workspacesUrl).toContain('workspacesloganalytics'); expect(workspacesUrl).toContain('azuremonitor');
expect(azureLogAnalyticsUrl).toContain('loganalyticsazure'); expect(azureLogAnalyticsUrl).toContain('loganalyticsazure');
}); });
}); });

@ -18,8 +18,8 @@ import {
import { getBackendSrv, getTemplateSrv, DataSourceWithBackend, FetchResponse } from '@grafana/runtime'; import { getBackendSrv, getTemplateSrv, DataSourceWithBackend, FetchResponse } from '@grafana/runtime';
import { Observable, from } from 'rxjs'; import { Observable, from } from 'rxjs';
import { mergeMap } from 'rxjs/operators'; import { mergeMap } from 'rxjs/operators';
import { getAuthType, getAzureCloud, isLogAnalyticsSameAs } from '../credentials'; import { getAuthType, getAzureCloud } from '../credentials';
import { getLogAnalyticsApiRoute, getLogAnalyticsManagementApiRoute } from '../api/routes'; import { getLogAnalyticsApiRoute, getManagementApiRoute } from '../api/routes';
import { AzureLogAnalyticsMetadata } from '../types/logAnalyticsMetadata'; import { AzureLogAnalyticsMetadata } from '../types/logAnalyticsMetadata';
import { isGUIDish } from '../components/ResourcePicker/utils'; import { isGUIDish } from '../components/ResourcePicker/utils';
@ -51,17 +51,11 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
const logAnalyticsRoute = getLogAnalyticsApiRoute(cloud); const logAnalyticsRoute = getLogAnalyticsApiRoute(cloud);
this.baseUrl = `/${logAnalyticsRoute}`; this.baseUrl = `/${logAnalyticsRoute}`;
const managementRoute = getLogAnalyticsManagementApiRoute(cloud); const managementRoute = getManagementApiRoute(cloud);
this.azureMonitorUrl = `/${managementRoute}/subscriptions`; this.azureMonitorUrl = `/${managementRoute}/subscriptions`;
this.url = instanceSettings.url || ''; this.url = instanceSettings.url || '';
this.defaultSubscriptionId = this.instanceSettings.jsonData.subscriptionId || '';
const sameAsMonitor = isLogAnalyticsSameAs(instanceSettings);
this.defaultSubscriptionId = sameAsMonitor
? instanceSettings.jsonData.subscriptionId
: instanceSettings.jsonData.logAnalyticsSubscriptionId;
this.defaultOrFirstWorkspace = this.instanceSettings.jsonData.logAnalyticsDefaultWorkspace || ''; this.defaultOrFirstWorkspace = this.instanceSettings.jsonData.logAnalyticsDefaultWorkspace || '';
} }
@ -485,14 +479,14 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
const authType = getAuthType(this.instanceSettings); const authType = getAuthType(this.instanceSettings);
if (authType === 'clientsecret') { if (authType === 'clientsecret') {
if (!this.isValidConfigField(this.instanceSettings.jsonData.logAnalyticsTenantId)) { if (!this.isValidConfigField(this.instanceSettings.jsonData.tenantId)) {
return { return {
status: 'error', status: 'error',
message: 'The Tenant Id field is required.', message: 'The Tenant Id field is required.',
}; };
} }
if (!this.isValidConfigField(this.instanceSettings.jsonData.logAnalyticsClientId)) { if (!this.isValidConfigField(this.instanceSettings.jsonData.clientId)) {
return { return {
status: 'error', status: 'error',
message: 'The Client Id field is required.', message: 'The Client Id field is required.',

@ -22,18 +22,11 @@ const setup = (propsFunc?: (props: Props) => Props) => {
basicAuthPassword: '', basicAuthPassword: '',
withCredentials: false, withCredentials: false,
isDefault: false, isDefault: false,
secureJsonFields: { secureJsonFields: {},
logAnalyticsClientSecret: false,
},
jsonData: { jsonData: {
cloudName: '', cloudName: '',
subscriptionId: '', subscriptionId: '',
azureLogAnalyticsSameAs: false,
logAnalyticsDefaultWorkspace: '', logAnalyticsDefaultWorkspace: '',
logAnalyticsTenantId: '',
},
secureJsonData: {
logAnalyticsClientSecret: '',
}, },
version: 1, version: 1,
readOnly: false, readOnly: false,
@ -80,10 +73,10 @@ describe('Render', () => {
...props.options.jsonData, ...props.options.jsonData,
azureLogAnalyticsSameAs: false, azureLogAnalyticsSameAs: false,
logAnalyticsDefaultWorkspace: '', logAnalyticsDefaultWorkspace: '',
logAnalyticsTenantId: 'e7f3f661-a933-4b3f-8176-51c4f982ec48', tenantId: 'e7f3f661-a933-4b3f-8176-51c4f982ec48',
logAnalyticsClientId: '44693801-6ee6-49de-9b2d-9106972f9572', clientId: '44693801-6ee6-49de-9b2d-9106972f9572',
logAnalyticsSubscriptionId: 'e3fe4fde-ad5e-4d60-9974-e2f3562ffdf2', subscriptionId: 'e3fe4fde-ad5e-4d60-9974-e2f3562ffdf2',
logAnalyticsClientSecret: 'cddcc020-2c94-460a-a3d0-df3147ffa792', clientSecret: 'cddcc020-2c94-460a-a3d0-df3147ffa792',
}, },
}, },
})); }));
@ -91,18 +84,8 @@ describe('Render', () => {
}); });
it('should not render the Switch to use different creds for log analytics by default', () => { it('should not render the Switch to use different creds for log analytics by default', () => {
setup((props) => ({ setup();
...props, expect(screen.queryByText('is no longer supported', { exact: false })).not.toBeInTheDocument();
options: {
...props.options,
jsonData: {
...props.options.jsonData,
azureLogAnalyticsSameAs: undefined,
},
},
}));
expect(screen.queryByLabelText('Same details as Azure Monitor API')).not.toBeInTheDocument();
expect(screen.queryByText('is deprecated', { exact: false })).not.toBeInTheDocument();
}); });
// Remove this test with deprecated code // Remove this test with deprecated code
@ -117,7 +100,6 @@ describe('Render', () => {
}, },
}, },
})); }));
expect(screen.queryByLabelText('Same details as Azure Monitor API')).toBeInTheDocument(); expect(screen.queryByText('is no longer supported', { exact: false })).toBeInTheDocument();
expect(screen.queryByText('is deprecated', { exact: false })).toBeInTheDocument();
}); });
}); });

@ -2,15 +2,9 @@ import React, { FunctionComponent, useEffect, useMemo, useReducer, useState } fr
import { SelectableValue } from '@grafana/data'; import { SelectableValue } from '@grafana/data';
import { AzureCredentialsForm } from './AzureCredentialsForm'; import { AzureCredentialsForm } from './AzureCredentialsForm';
import { InlineFormLabel, LegacyForms, Button, Alert } from '@grafana/ui'; import { InlineFormLabel, LegacyForms, Button, Alert } from '@grafana/ui';
const { Select, Switch } = LegacyForms; const { Select } = LegacyForms;
import { AzureDataSourceSettings, AzureCredentials } from '../types'; import { AzureDataSourceSettings } from '../types';
import { import { getCredentials, isCredentialsComplete } from '../credentials';
getCredentials,
getLogAnalyticsCredentials,
isCredentialsComplete,
updateLogAnalyticsCredentials,
updateLogAnalyticsSameAs,
} from '../credentials';
export interface Props { export interface Props {
options: AzureDataSourceSettings; options: AzureDataSourceSettings;
@ -22,22 +16,16 @@ export interface Props {
export const AnalyticsConfig: FunctionComponent<Props> = (props: Props) => { export const AnalyticsConfig: FunctionComponent<Props> = (props: Props) => {
const { updateOptions, getSubscriptions, getWorkspaces } = props; const { updateOptions, getSubscriptions, getWorkspaces } = props;
const primaryCredentials = useMemo(() => getCredentials(props.options), [props.options]); const primaryCredentials = useMemo(() => getCredentials(props.options), [props.options]);
const logAnalyticsCredentials = useMemo(() => getLogAnalyticsCredentials(props.options), [props.options]);
const subscriptionId = logAnalyticsCredentials const subscriptionId = primaryCredentials.defaultSubscriptionId;
? logAnalyticsCredentials.defaultSubscriptionId
: primaryCredentials.defaultSubscriptionId;
// Only show a section for setting LogAnalytics credentials if they were set from before // Only show a section for setting LogAnalytics credentials if
// And the authType is supported // they were set from before with different values and the
const [credentialsUsed, _] = useState(!!logAnalyticsCredentials); // authType is supported
const credentialsEnabled = credentialsUsed && primaryCredentials.authType === 'clientsecret'; const logCredentialsEnabled =
primaryCredentials.authType === 'clientsecret' && props.options.jsonData.azureLogAnalyticsSameAs === false;
const hasRequiredFields = const hasRequiredFields = subscriptionId && isCredentialsComplete(primaryCredentials);
subscriptionId &&
(logAnalyticsCredentials
? isCredentialsComplete(logAnalyticsCredentials)
: isCredentialsComplete(primaryCredentials));
const defaultWorkspace = props.options.jsonData.logAnalyticsDefaultWorkspace; const defaultWorkspace = props.options.jsonData.logAnalyticsDefaultWorkspace;
@ -91,18 +79,6 @@ export const AnalyticsConfig: FunctionComponent<Props> = (props: Props) => {
} }
}; };
const [sameAsSwitched, setSameAsSwitched] = useState(false);
const onCredentialsChange = (updatedCredentials: AzureCredentials) => {
updateOptions((options) => updateLogAnalyticsCredentials(options, updatedCredentials));
};
const onLogAnalyticsSameAsChange = (event: React.SyntheticEvent<HTMLInputElement>) => {
const sameAs = event.currentTarget.checked;
updateOptions((options) => updateLogAnalyticsSameAs(options, sameAs));
setSameAsSwitched(true);
};
const onDefaultWorkspaceChange = (selected: SelectableValue<string>) => { const onDefaultWorkspaceChange = (selected: SelectableValue<string>) => {
updateOptions((options) => { updateOptions((options) => {
return { return {
@ -115,57 +91,31 @@ export const AnalyticsConfig: FunctionComponent<Props> = (props: Props) => {
}); });
}; };
const tooltipAttribute = {
...(!logAnalyticsCredentials && {
tooltip: 'Workspaces are pulled from default subscription selected above.',
}),
};
const showSameAsHelpMsg =
credentialsEnabled &&
sameAsSwitched &&
primaryCredentials.authType === 'clientsecret' &&
!primaryCredentials.clientSecret;
return ( return (
<> <>
<h3 className="page-heading">Azure Monitor Logs</h3> <h3 className="page-heading">Azure Monitor Logs</h3>
{credentialsEnabled && ( {logCredentialsEnabled && (
<> <>
<Switch <Alert severity="error" title="Deprecated">
label="Same details as Azure Monitor API" Using different credentials for Azure Monitor Logs is no longer supported. Authentication information above
checked={!logAnalyticsCredentials} will be used instead. Please create a new data source with the credentials below.
onChange={onLogAnalyticsSameAsChange}
{...tooltipAttribute}
/>
{showSameAsHelpMsg && (
<div className="grafana-info-box m-t-2">
<div className="alert-body">
<p>Re-enter your Azure Monitor Client Secret to use this setting.</p>
</div>
</div>
)}
{logAnalyticsCredentials && (
<>
<Alert severity="info" title="Deprecated">
Using different credentials for Azure Monitor Logs is deprecated and will be removed in a future
version.
<br />
Create a different Data Source if you need to use different credentials.
</Alert> </Alert>
<AzureCredentialsForm <AzureCredentialsForm
managedIdentityEnabled={false} managedIdentityEnabled={false}
credentials={logAnalyticsCredentials} credentials={{
onCredentialsChange={onCredentialsChange} ...primaryCredentials,
authType: 'clientsecret',
// Use deprecated Log Analytics credentials read-only
// to help with a possible migration
tenantId: props.options.jsonData.logAnalyticsTenantId,
clientId: props.options.jsonData.logAnalyticsClientId,
}}
getSubscriptions={getSubscriptions} getSubscriptions={getSubscriptions}
disabled={true}
/> />
</> </>
)} )}
</>
)}
<div className="gf-form-group"> <div className="gf-form-group">
<div className="gf-form-inline"> <div className="gf-form-inline">
<div className="gf-form"> <div className="gf-form">

@ -1,6 +1,8 @@
import React from 'react'; import React from 'react';
import { shallow } from 'enzyme'; import { shallow } from 'enzyme';
import AzureCredentialsForm, { Props } from './AzureCredentialsForm'; import AzureCredentialsForm, { Props } from './AzureCredentialsForm';
import { LegacyForms, Button } from '@grafana/ui';
const { Input } = LegacyForms;
const setup = (propsFunc?: (props: Props) => Props) => { const setup = (propsFunc?: (props: Props) => Props) => {
let props: Props = { let props: Props = {
@ -63,4 +65,26 @@ describe('Render', () => {
})); }));
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
describe('when disabled', () => {
it('should disable inputs', () => {
const wrapper = setup((props) => ({
...props,
disabled: true,
}));
const inputs = wrapper.find(Input);
expect(inputs.length).toBeGreaterThan(1);
inputs.forEach((input) => {
expect(input.prop('disabled')).toBe(true);
});
});
it('should remove buttons', () => {
const wrapper = setup((props) => ({
...props,
disabled: true,
}));
expect(wrapper.find(Button).exists()).toBe(false);
});
});
}); });

@ -9,8 +9,9 @@ export interface Props {
managedIdentityEnabled: boolean; managedIdentityEnabled: boolean;
credentials: AzureCredentials; credentials: AzureCredentials;
azureCloudOptions?: SelectableValue[]; azureCloudOptions?: SelectableValue[];
onCredentialsChange: (updatedCredentials: AzureCredentials) => void; onCredentialsChange?: (updatedCredentials: AzureCredentials) => void;
getSubscriptions?: () => Promise<SelectableValue[]>; getSubscriptions?: () => Promise<SelectableValue[]>;
disabled?: boolean;
} }
const authTypeOptions: Array<SelectableValue<AzureAuthType>> = [ const authTypeOptions: Array<SelectableValue<AzureAuthType>> = [
@ -25,7 +26,7 @@ const authTypeOptions: Array<SelectableValue<AzureAuthType>> = [
]; ];
export const AzureCredentialsForm: FunctionComponent<Props> = (props: Props) => { export const AzureCredentialsForm: FunctionComponent<Props> = (props: Props) => {
const { credentials, azureCloudOptions, onCredentialsChange, getSubscriptions } = props; const { credentials, azureCloudOptions, onCredentialsChange, getSubscriptions, disabled } = props;
const hasRequiredFields = isCredentialsComplete(credentials); const hasRequiredFields = isCredentialsComplete(credentials);
const [subscriptions, setSubscriptions] = useState<Array<SelectableValue<string>>>([]); const [subscriptions, setSubscriptions] = useState<Array<SelectableValue<string>>>([]);
@ -189,6 +190,7 @@ export const AzureCredentialsForm: FunctionComponent<Props> = (props: Props) =>
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value={credentials.tenantId || ''} value={credentials.tenantId || ''}
onChange={onTenantIdChange} onChange={onTenantIdChange}
disabled={disabled}
/> />
</div> </div>
</div> </div>
@ -202,11 +204,13 @@ export const AzureCredentialsForm: FunctionComponent<Props> = (props: Props) =>
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value={credentials.clientId || ''} value={credentials.clientId || ''}
onChange={onClientIdChange} onChange={onClientIdChange}
disabled={disabled}
/> />
</div> </div>
</div> </div>
</div> </div>
{typeof credentials.clientSecret === 'symbol' ? ( {!disabled &&
(typeof credentials.clientSecret === 'symbol' ? (
<div className="gf-form-inline"> <div className="gf-form-inline">
<div className="gf-form"> <div className="gf-form">
<InlineFormLabel className="width-12">Client Secret</InlineFormLabel> <InlineFormLabel className="width-12">Client Secret</InlineFormLabel>
@ -214,7 +218,7 @@ export const AzureCredentialsForm: FunctionComponent<Props> = (props: Props) =>
</div> </div>
<div className="gf-form"> <div className="gf-form">
<div className="max-width-30 gf-form-inline"> <div className="max-width-30 gf-form-inline">
<Button variant="secondary" type="button" onClick={onClientSecretReset}> <Button variant="secondary" type="button" onClick={onClientSecretReset} disabled={disabled}>
reset reset
</Button> </Button>
</div> </div>
@ -230,11 +234,12 @@ export const AzureCredentialsForm: FunctionComponent<Props> = (props: Props) =>
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value={credentials.clientSecret || ''} value={credentials.clientSecret || ''}
onChange={onClientSecretChange} onChange={onClientSecretChange}
disabled={disabled}
/> />
</div> </div>
</div> </div>
</div> </div>
)} ))}
</> </>
)} )}
{getSubscriptions && ( {getSubscriptions && (
@ -251,10 +256,12 @@ export const AzureCredentialsForm: FunctionComponent<Props> = (props: Props) =>
} }
options={subscriptions} options={subscriptions}
onChange={onSubscriptionChange} onChange={onSubscriptionChange}
isDisabled={disabled}
/> />
</div> </div>
</div> </div>
</div> </div>
{!disabled && (
<div className="gf-form-inline"> <div className="gf-form-inline">
<div className="gf-form"> <div className="gf-form">
<div className="max-width-30 gf-form-inline"> <div className="max-width-30 gf-form-inline">
@ -270,6 +277,7 @@ export const AzureCredentialsForm: FunctionComponent<Props> = (props: Props) =>
</div> </div>
</div> </div>
</div> </div>
)}
</> </>
)} )}
</div> </div>

@ -14,7 +14,7 @@ import { InsightsConfig } from './InsightsConfig';
import ResponseParser from '../azure_monitor/response_parser'; import ResponseParser from '../azure_monitor/response_parser';
import { AzureDataSourceJsonData, AzureDataSourceSecureJsonData, AzureDataSourceSettings } from '../types'; import { AzureDataSourceJsonData, AzureDataSourceSecureJsonData, AzureDataSourceSettings } from '../types';
import { getAzureCloud, isAppInsightsConfigured } from '../credentials'; import { getAzureCloud, isAppInsightsConfigured } from '../credentials';
import { getLogAnalyticsManagementApiRoute, getManagementApiRoute } from '../api/routes'; import { getManagementApiRoute } from '../api/routes';
export type Props = DataSourcePluginOptionsEditorProps<AzureDataSourceJsonData, AzureDataSourceSecureJsonData>; export type Props = DataSourcePluginOptionsEditorProps<AzureDataSourceJsonData, AzureDataSourceSecureJsonData>;
@ -77,7 +77,7 @@ export class ConfigEditor extends PureComponent<Props, State> {
await this.saveOptions(); await this.saveOptions();
const cloud = getAzureCloud(this.props.options); const cloud = getAzureCloud(this.props.options);
const route = getLogAnalyticsManagementApiRoute(cloud); const route = getManagementApiRoute(cloud);
const url = `/${route}/subscriptions?api-version=2019-03-01`; const url = `/${route}/subscriptions?api-version=2019-03-01`;
const result = await getBackendSrv().datasourceRequest({ const result = await getBackendSrv().datasourceRequest({
@ -92,7 +92,7 @@ export class ConfigEditor extends PureComponent<Props, State> {
await this.saveOptions(); await this.saveOptions();
const cloud = getAzureCloud(this.props.options); const cloud = getAzureCloud(this.props.options);
const route = getLogAnalyticsManagementApiRoute(cloud); const route = getManagementApiRoute(cloud);
const url = `/${route}/subscriptions/${subscriptionId}/providers/Microsoft.OperationalInsights/workspaces?api-version=2017-04-26-preview`; const url = `/${route}/subscriptions/${subscriptionId}/providers/Microsoft.OperationalInsights/workspaces?api-version=2017-04-26-preview`;
const result = await getBackendSrv().datasourceRequest({ const result = await getBackendSrv().datasourceRequest({

@ -23,6 +23,9 @@ export class InsightsConfig extends PureComponent<Props> {
return ( return (
<> <>
<h3 className="page-heading">Azure Application Insights</h3> <h3 className="page-heading">Azure Application Insights</h3>
<Alert severity="info" title="Application Insights credentials are deprecated">
Configure using Azure AD App Registration above and update existing queries to use Metrics or Logs.
</Alert>
<div className="gf-form-group"> <div className="gf-form-group">
{options.secureJsonFields.appInsightsApiKey ? ( {options.secureJsonFields.appInsightsApiKey ? (
<div className="gf-form-inline"> <div className="gf-form-inline">
@ -66,10 +69,6 @@ export class InsightsConfig extends PureComponent<Props> {
</div> </div>
</div> </div>
</div> </div>
<Alert severity="info" title="Application Insights credentials are deprecated">
Configure using Azure AD App Registration above and update existing queries to use Metrics or Logs.
</Alert>
</> </>
); );
} }

@ -65,7 +65,7 @@ exports[`Render should disable log analytics credentials form 1`] = `
autocapitalize="none" autocapitalize="none"
autocomplete="off" autocomplete="off"
autocorrect="off" autocorrect="off"
id="react-select-4-input" id="react-select-3-input"
spellcheck="false" spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;" style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0" tabindex="0"
@ -128,36 +128,11 @@ exports[`Render should enable azure log analytics load workspaces button 1`] = `
Azure Monitor Logs Azure Monitor Logs
</h3> </h3>
<div <div
class="gf-form-switch-container-react" aria-label="Alert error"
>
<label
class="gf-form gf-form-switch-container "
for="2"
>
<div
class="gf-form-label pointer"
>
Same details as Azure Monitor API
</div>
<div
class="gf-form-switch "
>
<input
id="2"
type="checkbox"
/>
<span
class="gf-form-switch__slider"
/>
</div>
</label>
</div>
<div
aria-label="Alert info"
class="css-7gef9a" class="css-7gef9a"
> >
<div <div
class="css-ed9azx" class="css-a4coia"
> >
<div <div
class="css-1vzus6i-Icon" class="css-1vzus6i-Icon"
@ -174,9 +149,7 @@ exports[`Render should enable azure log analytics load workspaces button 1`] = `
<div <div
class="css-1b0c7i6" class="css-1b0c7i6"
> >
Using different credentials for Azure Monitor Logs is deprecated and will be removed in a future version. Using different credentials for Azure Monitor Logs is no longer supported. Authentication information above will be used instead. Please create a new data source with the credentials below.
<br />
Create a different Data Source if you need to use different credentials.
</div> </div>
</div> </div>
</div> </div>
@ -202,8 +175,9 @@ exports[`Render should enable azure log analytics load workspaces button 1`] = `
> >
<input <input
class="gf-form-input width-30" class="gf-form-input width-30"
disabled=""
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value="e7f3f661-a933-4b3f-8176-51c4f982ec48" value=""
/> />
</div> </div>
</div> </div>
@ -228,32 +202,7 @@ exports[`Render should enable azure log analytics load workspaces button 1`] = `
> >
<input <input
class="gf-form-input width-30" class="gf-form-input width-30"
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" disabled=""
value="44693801-6ee6-49de-9b2d-9106972f9572"
/>
</div>
</div>
</div>
</div>
<div
class="gf-form-inline"
>
<div
class="gf-form"
>
<label
class="width-12 gf-form-label width-10"
>
Client Secret
</label>
<div
class="width-15"
>
<div
style="flex-grow: 1;"
>
<input
class="gf-form-input width-30"
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value="" value=""
/> />
@ -277,7 +226,7 @@ exports[`Render should enable azure log analytics load workspaces button 1`] = `
> >
<div> <div>
<div <div
class="gf-form-input gf-form-input--form-dropdown css-1daubv-SelectContainer" class="gf-form-input gf-form-input--form-dropdown gf-form-select-box--is-disabled css-1daubv-SelectContainer"
> >
<span <span
aria-atomic="false" aria-atomic="false"
@ -286,7 +235,7 @@ exports[`Render should enable azure log analytics load workspaces button 1`] = `
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"
/> />
<div <div
class="gf-form-select-box__control css-1g8ily9-Control" class="gf-form-select-box__control gf-form-select-box__control--is-disabled css-1g8ily9-Control"
> >
<div <div
class="gf-form-select-box__value-container css-pilx6v-ValueContainer" class="gf-form-select-box__value-container css-pilx6v-ValueContainer"
@ -308,7 +257,8 @@ exports[`Render should enable azure log analytics load workspaces button 1`] = `
autocapitalize="none" autocapitalize="none"
autocomplete="off" autocomplete="off"
autocorrect="off" autocorrect="off"
id="react-select-5-input" disabled=""
id="react-select-4-input"
spellcheck="false" spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;" style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0" tabindex="0"
@ -334,29 +284,6 @@ exports[`Render should enable azure log analytics load workspaces button 1`] = `
</div> </div>
</div> </div>
</div> </div>
<div
class="gf-form-inline"
>
<div
class="gf-form"
>
<div
class="max-width-30 gf-form-inline"
>
<button
class="css-191ipe8-button"
disabled=""
type="button"
>
<span
class="css-1mhnkuh"
>
Load Subscriptions
</span>
</button>
</div>
</div>
</div>
</div> </div>
<div <div
class="gf-form-group" class="gf-form-group"
@ -415,7 +342,7 @@ exports[`Render should enable azure log analytics load workspaces button 1`] = `
autocapitalize="none" autocapitalize="none"
autocomplete="off" autocomplete="off"
autocorrect="off" autocorrect="off"
id="react-select-6-input" id="react-select-5-input"
spellcheck="false" spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;" style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0" tabindex="0"
@ -477,237 +404,6 @@ exports[`Render should render component 1`] = `
> >
Azure Monitor Logs Azure Monitor Logs
</h3> </h3>
<div
class="gf-form-switch-container-react"
>
<label
class="gf-form gf-form-switch-container "
for="1"
>
<div
class="gf-form-label pointer"
>
Same details as Azure Monitor API
</div>
<div
class="gf-form-switch "
>
<input
id="1"
type="checkbox"
/>
<span
class="gf-form-switch__slider"
/>
</div>
</label>
</div>
<div
aria-label="Alert info"
class="css-7gef9a"
>
<div
class="css-ed9azx"
>
<div
class="css-1vzus6i-Icon"
/>
</div>
<div
class="css-zmuccj"
>
<div
class="css-hui7p1"
>
Deprecated
</div>
<div
class="css-1b0c7i6"
>
Using different credentials for Azure Monitor Logs is deprecated and will be removed in a future version.
<br />
Create a different Data Source if you need to use different credentials.
</div>
</div>
</div>
<div
class="gf-form-group"
>
<div
class="gf-form-inline"
>
<div
class="gf-form"
>
<label
class="width-12 gf-form-label width-10"
>
Directory (tenant) ID
</label>
<div
class="width-15"
>
<div
style="flex-grow: 1;"
>
<input
class="gf-form-input width-30"
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value=""
/>
</div>
</div>
</div>
</div>
<div
class="gf-form-inline"
>
<div
class="gf-form"
>
<label
class="width-12 gf-form-label width-10"
>
Application (client) ID
</label>
<div
class="width-15"
>
<div
style="flex-grow: 1;"
>
<input
class="gf-form-input width-30"
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value=""
/>
</div>
</div>
</div>
</div>
<div
class="gf-form-inline"
>
<div
class="gf-form"
>
<label
class="width-12 gf-form-label width-10"
>
Client Secret
</label>
<div
class="width-15"
>
<div
style="flex-grow: 1;"
>
<input
class="gf-form-input width-30"
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value=""
/>
</div>
</div>
</div>
</div>
<div
class="gf-form-inline"
>
<div
class="gf-form"
>
<label
class="width-12 gf-form-label width-10"
>
Default Subscription
</label>
<div
class="width-25"
>
<div>
<div
class="gf-form-input gf-form-input--form-dropdown css-1daubv-SelectContainer"
>
<span
aria-atomic="false"
aria-live="polite"
aria-relevant="additions text"
class="css-1f43avz-a11yText-A11yText"
/>
<div
class="gf-form-select-box__control css-1g8ily9-Control"
>
<div
class="gf-form-select-box__value-container css-pilx6v-ValueContainer"
>
<div
class="gf-form-select-box__placeholder css-ovmm9z-Placeholder"
>
Choose
</div>
<div
class="css-17yls17-Input"
>
<div
class="gf-form-select-box__input"
style="display: inline-block;"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="react-select-2-input"
spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0"
type="text"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
</div>
<div
class="gf-form-select-box__indicators css-1pmvkci-IndicatorsContainer"
>
<div
class="css-1vzus6i-Icon"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class="gf-form-inline"
>
<div
class="gf-form"
>
<div
class="max-width-30 gf-form-inline"
>
<button
class="css-191ipe8-button"
disabled=""
type="button"
>
<span
class="css-1mhnkuh"
>
Load Subscriptions
</span>
</button>
</div>
</div>
</div>
</div>
<div <div
class="gf-form-group" class="gf-form-group"
> >
@ -765,7 +461,7 @@ exports[`Render should render component 1`] = `
autocapitalize="none" autocapitalize="none"
autocomplete="off" autocomplete="off"
autocorrect="off" autocorrect="off"
id="react-select-3-input" id="react-select-2-input"
spellcheck="false" spellcheck="false"
style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;" style="box-sizing: content-box; width: 2px; border: 0px; opacity: 1; outline: 0; padding: 0px;"
tabindex="0" tabindex="0"

@ -7,6 +7,12 @@ exports[`Render should disable insights api key input 1`] = `
> >
Azure Application Insights Azure Application Insights
</h3> </h3>
<Alert
severity="info"
title="Application Insights credentials are deprecated"
>
Configure using Azure AD App Registration above and update existing queries to use Metrics or Logs.
</Alert>
<div <div
className="gf-form-group" className="gf-form-group"
> >
@ -65,12 +71,6 @@ exports[`Render should disable insights api key input 1`] = `
</div> </div>
</div> </div>
</div> </div>
<Alert
severity="info"
title="Application Insights credentials are deprecated"
>
Configure using Azure AD App Registration above and update existing queries to use Metrics or Logs.
</Alert>
</Fragment> </Fragment>
`; `;
@ -81,6 +81,12 @@ exports[`Render should enable insights api key input 1`] = `
> >
Azure Application Insights Azure Application Insights
</h3> </h3>
<Alert
severity="info"
title="Application Insights credentials are deprecated"
>
Configure using Azure AD App Registration above and update existing queries to use Metrics or Logs.
</Alert>
<div <div
className="gf-form-group" className="gf-form-group"
> >
@ -128,12 +134,6 @@ exports[`Render should enable insights api key input 1`] = `
</div> </div>
</div> </div>
</div> </div>
<Alert
severity="info"
title="Application Insights credentials are deprecated"
>
Configure using Azure AD App Registration above and update existing queries to use Metrics or Logs.
</Alert>
</Fragment> </Fragment>
`; `;
@ -144,6 +144,12 @@ exports[`Render should render component 1`] = `
> >
Azure Application Insights Azure Application Insights
</h3> </h3>
<Alert
severity="info"
title="Application Insights credentials are deprecated"
>
Configure using Azure AD App Registration above and update existing queries to use Metrics or Logs.
</Alert>
<div <div
className="gf-form-group" className="gf-form-group"
> >
@ -191,11 +197,5 @@ exports[`Render should render component 1`] = `
</div> </div>
</div> </div>
</div> </div>
<Alert
severity="info"
title="Application Insights credentials are deprecated"
>
Configure using Azure AD App Registration above and update existing queries to use Metrics or Logs.
</Alert>
</Fragment> </Fragment>
`; `;

@ -64,20 +64,6 @@ function getSecret(options: AzureDataSourceSettings): undefined | string | Conce
} }
} }
function getLogAnalyticsSecret(options: AzureDataSourceSettings): undefined | string | ConcealedSecret {
if (options.secureJsonFields.logAnalyticsClientSecret) {
// The secret is concealed on server
return concealed;
} else {
const secret = options.secureJsonData?.logAnalyticsClientSecret;
return typeof secret === 'string' && secret.length > 0 ? secret : undefined;
}
}
export function isLogAnalyticsSameAs(options: AzureDataSourceSettings | AzureDataSourceInstanceSettings): boolean {
return typeof options.jsonData.azureLogAnalyticsSameAs !== 'boolean' || options.jsonData.azureLogAnalyticsSameAs;
}
export function isCredentialsComplete(credentials: AzureCredentials): boolean { export function isCredentialsComplete(credentials: AzureCredentials): boolean {
switch (credentials.authType) { switch (credentials.authType) {
case 'msi': case 'msi':
@ -116,29 +102,6 @@ export function getCredentials(options: AzureDataSourceSettings): AzureCredentia
} }
} }
export function getLogAnalyticsCredentials(options: AzureDataSourceSettings): AzureCredentials | undefined {
const authType = getAuthType(options);
if (authType !== 'clientsecret') {
// Only app registration (client secret) authentication supports different credentials for Log Analytics
// for backward compatibility
return undefined;
}
if (isLogAnalyticsSameAs(options)) {
return undefined;
}
return {
authType: 'clientsecret',
azureCloud: options.jsonData.cloudName || getDefaultAzureCloud(),
tenantId: options.jsonData.logAnalyticsTenantId,
clientId: options.jsonData.logAnalyticsClientId,
clientSecret: getLogAnalyticsSecret(options),
defaultSubscriptionId: options.jsonData.logAnalyticsSubscriptionId,
};
}
export function updateCredentials( export function updateCredentials(
options: AzureDataSourceSettings, options: AzureDataSourceSettings,
credentials: AzureCredentials credentials: AzureCredentials
@ -158,12 +121,6 @@ export function updateCredentials(
}, },
}; };
if (!isLogAnalyticsSameAs(options)) {
options = updateLogAnalyticsSameAs(options, true);
} else {
options = updateLogAnalyticsCredentials(options, credentials);
}
return options; return options;
case 'clientsecret': case 'clientsecret':
@ -190,82 +147,8 @@ export function updateCredentials(
}, },
}; };
if (isLogAnalyticsSameAs(options)) {
options = updateLogAnalyticsCredentials(options, credentials);
}
return options;
}
}
export function updateLogAnalyticsCredentials(
options: AzureDataSourceSettings,
credentials: AzureCredentials
): AzureDataSourceSettings {
// Log Analytics credentials only used if primary credentials are App Registration (client secret)
if (credentials.authType === 'clientsecret') {
options = {
...options,
jsonData: {
...options.jsonData,
logAnalyticsTenantId: credentials.tenantId,
logAnalyticsClientId: credentials.clientId,
},
secureJsonData: {
...options.secureJsonData,
logAnalyticsClientSecret:
typeof credentials.clientSecret === 'string' && credentials.clientSecret.length > 0
? credentials.clientSecret
: undefined,
},
secureJsonFields: {
...options.secureJsonFields,
logAnalyticsClientSecret: typeof credentials.clientSecret === 'symbol',
},
};
}
// Default subscription
options = {
...options,
jsonData: {
...options.jsonData,
logAnalyticsSubscriptionId: credentials.defaultSubscriptionId,
},
};
return options; return options;
}
export function updateLogAnalyticsSameAs(options: AzureDataSourceSettings, sameAs: boolean): AzureDataSourceSettings {
if (sameAs !== isLogAnalyticsSameAs(options)) {
// Update the 'Same As' switch
options = {
...options,
jsonData: {
...options.jsonData,
azureLogAnalyticsSameAs: sameAs,
},
};
if (sameAs) {
// Get the primary credentials
let credentials = getCredentials(options);
// Check whether the primary client secret is concealed
if (credentials.authType === 'clientsecret' && typeof credentials.clientSecret === 'symbol') {
// Log Analytics credentials need to be synchronized but the client secret is concealed,
// so we have to reset the primary client secret to ensure that user enters a new secret
credentials.clientSecret = undefined;
options = updateCredentials(options, credentials);
} }
// Synchronize the Log Analytics credentials with primary credentials
options = updateLogAnalyticsCredentials(options, credentials);
}
}
return options;
} }
export function isAppInsightsConfigured(options: AzureDataSourceSettings) { export function isAppInsightsConfigured(options: AzureDataSourceSettings) {

@ -115,74 +115,6 @@
{ "name": "x-ms-app", "content": "Grafana" } { "name": "x-ms-app", "content": "Grafana" }
] ]
}, },
{
"path": "workspacesloganalytics",
"method": "*",
"url": "https://management.azure.com",
"authType": "azure",
"tokenAuth": {
"scopes": ["https://management.azure.com/.default"],
"params": {
"azure_auth_type": "{{.JsonData.azureAuthType | orEmpty}}",
"azure_cloud": "AzureCloud",
"tenant_id": "{{.JsonData.logAnalyticsTenantId | orEmpty}}",
"client_id": "{{.JsonData.logAnalyticsClientId | orEmpty}}",
"client_secret": "{{.SecureJsonData.logAnalyticsClientSecret | orEmpty}}"
}
},
"headers": [{ "name": "x-ms-app", "content": "Grafana" }]
},
{
"path": "chinaworkspacesloganalytics",
"method": "*",
"url": "https://management.chinacloudapi.cn",
"authType": "azure",
"tokenAuth": {
"scopes": ["https://management.chinacloudapi.cn/.default"],
"params": {
"azure_auth_type": "{{.JsonData.azureAuthType | orEmpty}}",
"azure_cloud": "AzureChinaCloud",
"tenant_id": "{{.JsonData.logAnalyticsTenantId | orEmpty}}",
"client_id": "{{.JsonData.logAnalyticsClientId | orEmpty}}",
"client_secret": "{{.SecureJsonData.logAnalyticsClientSecret | orEmpty}}"
}
},
"headers": [{ "name": "x-ms-app", "content": "Grafana" }]
},
{
"path": "govworkspacesloganalytics",
"method": "*",
"url": "https://management.usgovcloudapi.net",
"authType": "azure",
"tokenAuth": {
"scopes": ["https://management.usgovcloudapi.net/.default"],
"params": {
"azure_auth_type": "{{.JsonData.azureAuthType | orEmpty}}",
"azure_cloud": "AzureUSGovernment",
"tenant_id": "{{.JsonData.logAnalyticsTenantId | orEmpty}}",
"client_id": "{{.JsonData.logAnalyticsClientId | orEmpty}}",
"client_secret": "{{.SecureJsonData.logAnalyticsClientSecret | orEmpty}}"
}
},
"headers": [{ "name": "x-ms-app", "content": "Grafana" }]
},
{
"path": "germanyworkspacesloganalytics",
"method": "*",
"url": "https://management.microsoftazure.de",
"authType": "azure",
"tokenAuth": {
"scopes": ["https://management.microsoftazure.de/.default"],
"params": {
"azure_auth_type": "{{.JsonData.azureAuthType | orEmpty}}",
"azure_cloud": "AzureUSGovernment",
"tenant_id": "{{.JsonData.logAnalyticsTenantId | orEmpty}}",
"client_id": "{{.JsonData.logAnalyticsClientId | orEmpty}}",
"client_secret": "{{.SecureJsonData.logAnalyticsClientSecret | orEmpty}}"
}
},
"headers": [{ "name": "x-ms-app", "content": "Grafana" }]
},
{ {
"path": "loganalyticsazure", "path": "loganalyticsazure",
"method": "GET", "method": "GET",
@ -193,9 +125,9 @@
"params": { "params": {
"azure_auth_type": "{{.JsonData.azureAuthType | orEmpty}}", "azure_auth_type": "{{.JsonData.azureAuthType | orEmpty}}",
"azure_cloud": "AzureCloud", "azure_cloud": "AzureCloud",
"tenant_id": "{{.JsonData.logAnalyticsTenantId | orEmpty}}", "tenant_id": "{{.JsonData.tenantId | orEmpty}}",
"client_id": "{{.JsonData.logAnalyticsClientId | orEmpty}}", "client_id": "{{.JsonData.clientId | orEmpty}}",
"client_secret": "{{.SecureJsonData.logAnalyticsClientSecret | orEmpty}}" "client_secret": "{{.SecureJsonData.clientSecret | orEmpty}}"
} }
}, },
"headers": [ "headers": [
@ -213,9 +145,9 @@
"params": { "params": {
"azure_auth_type": "{{.JsonData.azureAuthType | orEmpty}}", "azure_auth_type": "{{.JsonData.azureAuthType | orEmpty}}",
"azure_cloud": "AzureChinaCloud", "azure_cloud": "AzureChinaCloud",
"tenant_id": "{{.JsonData.logAnalyticsTenantId | orEmpty}}", "tenant_id": "{{.JsonData.tenantId | orEmpty}}",
"client_id": "{{.JsonData.logAnalyticsClientId | orEmpty}}", "client_id": "{{.JsonData.clientId | orEmpty}}",
"client_secret": "{{.SecureJsonData.logAnalyticsClientSecret | orEmpty}}" "client_secret": "{{.SecureJsonData.clientSecret | orEmpty}}"
} }
}, },
"headers": [ "headers": [
@ -233,9 +165,9 @@
"params": { "params": {
"azure_auth_type": "{{.JsonData.azureAuthType | orEmpty}}", "azure_auth_type": "{{.JsonData.azureAuthType | orEmpty}}",
"azure_cloud": "AzureUSGovernment", "azure_cloud": "AzureUSGovernment",
"tenant_id": "{{.JsonData.logAnalyticsTenantId | orEmpty}}", "tenant_id": "{{.JsonData.tenantId | orEmpty}}",
"client_id": "{{.JsonData.logAnalyticsClientId | orEmpty}}", "client_id": "{{.JsonData.clientId | orEmpty}}",
"client_secret": "{{.SecureJsonData.logAnalyticsClientSecret | orEmpty}}" "client_secret": "{{.SecureJsonData.clientSecret | orEmpty}}"
} }
}, },
"headers": [ "headers": [

@ -1,5 +1,5 @@
import { FetchResponse, getBackendSrv } from '@grafana/runtime'; import { FetchResponse, getBackendSrv } from '@grafana/runtime';
import { getLogAnalyticsManagementApiRoute } from '../api/routes'; import { getManagementApiRoute } from '../api/routes';
import { import {
locationDisplayNames, locationDisplayNames,
logsSupportedLocationsKusto, logsSupportedLocationsKusto,
@ -148,7 +148,7 @@ export default class ResourcePickerData {
try { try {
return await getBackendSrv() return await getBackendSrv()
.fetch<AzureGraphResponse<T>>({ .fetch<AzureGraphResponse<T>>({
url: this.proxyUrl + '/' + getLogAnalyticsManagementApiRoute(this.cloud) + RESOURCE_GRAPH_URL, url: this.proxyUrl + '/' + getManagementApiRoute(this.cloud) + RESOURCE_GRAPH_URL,
method: 'POST', method: 'POST',
data: { data: {
query: query, query: query,

@ -83,11 +83,15 @@ export interface AzureDataSourceJsonData extends DataSourceJsonData {
subscriptionId?: string; subscriptionId?: string;
// logs // logs
logAnalyticsDefaultWorkspace?: string;
/** @deprecated Azure Logs credentials */
azureLogAnalyticsSameAs?: boolean; azureLogAnalyticsSameAs?: boolean;
/** @deprecated Azure Logs credentials */
logAnalyticsTenantId?: string; logAnalyticsTenantId?: string;
/** @deprecated Azure Logs credentials */
logAnalyticsClientId?: string; logAnalyticsClientId?: string;
/** @deprecated Azure Logs credentials */
logAnalyticsSubscriptionId?: string; logAnalyticsSubscriptionId?: string;
logAnalyticsDefaultWorkspace?: string;
// App Insights // App Insights
appInsightsAppId?: string; appInsightsAppId?: string;
@ -95,7 +99,6 @@ export interface AzureDataSourceJsonData extends DataSourceJsonData {
export interface AzureDataSourceSecureJsonData { export interface AzureDataSourceSecureJsonData {
clientSecret?: string; clientSecret?: string;
logAnalyticsClientSecret?: string;
appInsightsApiKey?: string; appInsightsApiKey?: string;
} }

Loading…
Cancel
Save