123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- import React, { ChangeEvent, FunctionComponent, useEffect, useReducer, useState } 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 { AzureAuthType, AzureCredentials, isCredentialsComplete } from './AzureCredentials';
- export interface Props {
- managedIdentityEnabled: boolean;
- credentials: AzureCredentials;
- azureCloudOptions?: SelectableValue[];
- onCredentialsChange: (updatedCredentials: AzureCredentials) => void;
- getSubscriptions?: () => Promise<SelectableValue[]>;
- }
- const authTypeOptions: Array<SelectableValue<AzureAuthType>> = [
- {
- value: 'msi',
- label: 'Managed Identity',
- },
- {
- value: 'clientsecret',
- label: 'App Registration',
- },
- ];
- export const AzureCredentialsForm: FunctionComponent<Props> = (props: Props) => {
- const { credentials, azureCloudOptions, onCredentialsChange, getSubscriptions } = props;
- const hasRequiredFields = isCredentialsComplete(credentials);
- const [subscriptions, setSubscriptions] = useState<Array<SelectableValue<string>>>([]);
- const [loadSubscriptionsClicked, onLoadSubscriptions] = useReducer((val) => val + 1, 0);
- useEffect(() => {
- if (!getSubscriptions || !hasRequiredFields) {
- updateSubscriptions([]);
- return;
- }
- let canceled = false;
- getSubscriptions().then((result) => {
- if (!canceled) {
- updateSubscriptions(result, loadSubscriptionsClicked);
- }
- });
- return () => {
- canceled = true;
- };
- // This effect is intended to be called only once initially and on Load Subscriptions click
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [loadSubscriptionsClicked]);
- const updateSubscriptions = (received: Array<SelectableValue<string>>, autoSelect = false) => {
- setSubscriptions(received);
- if (getSubscriptions) {
- if (autoSelect && !credentials.defaultSubscriptionId && received.length > 0) {
- // Selecting the default subscription if subscriptions received but no default subscription selected
- onSubscriptionChange(received[0]);
- } else if (credentials.defaultSubscriptionId) {
- const found = received.find((opt) => opt.value === credentials.defaultSubscriptionId);
- if (!found) {
- // Unselecting the default subscription if it isn't found among the received subscriptions
- onSubscriptionChange(undefined);
- }
- }
- }
- };
- const onAuthTypeChange = (selected: SelectableValue<AzureAuthType>) => {
- if (onCredentialsChange) {
- setSubscriptions([]);
- const updated: AzureCredentials = {
- ...credentials,
- authType: selected.value || 'msi',
- defaultSubscriptionId: undefined,
- };
- onCredentialsChange(updated);
- }
- };
- const onAzureCloudChange = (selected: SelectableValue<string>) => {
- if (onCredentialsChange && credentials.authType === 'clientsecret') {
- setSubscriptions([]);
- const updated: AzureCredentials = {
- ...credentials,
- azureCloud: selected.value,
- defaultSubscriptionId: undefined,
- };
- onCredentialsChange(updated);
- }
- };
- const onTenantIdChange = (event: ChangeEvent<HTMLInputElement>) => {
- if (onCredentialsChange && credentials.authType === 'clientsecret') {
- setSubscriptions([]);
- const updated: AzureCredentials = {
- ...credentials,
- tenantId: event.target.value,
- defaultSubscriptionId: undefined,
- };
- onCredentialsChange(updated);
- }
- };
- const onClientIdChange = (event: ChangeEvent<HTMLInputElement>) => {
- if (onCredentialsChange && credentials.authType === 'clientsecret') {
- setSubscriptions([]);
- const updated: AzureCredentials = {
- ...credentials,
- clientId: event.target.value,
- defaultSubscriptionId: undefined,
- };
- onCredentialsChange(updated);
- }
- };
- const onClientSecretChange = (event: ChangeEvent<HTMLInputElement>) => {
- if (onCredentialsChange && credentials.authType === 'clientsecret') {
- setSubscriptions([]);
- const updated: AzureCredentials = {
- ...credentials,
- clientSecret: event.target.value,
- defaultSubscriptionId: undefined,
- };
- onCredentialsChange(updated);
- }
- };
- const onClientSecretReset = () => {
- if (onCredentialsChange && credentials.authType === 'clientsecret') {
- setSubscriptions([]);
- const updated: AzureCredentials = {
- ...credentials,
- clientSecret: '',
- defaultSubscriptionId: undefined,
- };
- onCredentialsChange(updated);
- }
- };
- const onSubscriptionChange = (selected: SelectableValue<string> | undefined) => {
- if (onCredentialsChange) {
- const updated: AzureCredentials = {
- ...credentials,
- defaultSubscriptionId: selected?.value,
- };
- onCredentialsChange(updated);
- }
- };
- return (
- <div className="gf-form-group">
- {props.managedIdentityEnabled && (
- <div className="gf-form-inline">
- <div className="gf-form">
- <InlineFormLabel className="width-12" tooltip="Choose the type of authentication to Azure services">
- Authentication
- </InlineFormLabel>
- <Select
- className="width-15"
- value={authTypeOptions.find((opt) => opt.value === credentials.authType)}
- options={authTypeOptions}
- onChange={onAuthTypeChange}
- />
- </div>
- </div>
- )}
- {credentials.authType === 'clientsecret' && (
- <>
- {azureCloudOptions && (
- <div className="gf-form-inline">
- <div className="gf-form">
- <InlineFormLabel className="width-12" tooltip="Choose an Azure Cloud">
- Azure Cloud
- </InlineFormLabel>
- <Select
- className="width-15"
- value={azureCloudOptions.find((opt) => opt.value === credentials.azureCloud)}
- options={azureCloudOptions}
- onChange={onAzureCloudChange}
- />
- </div>
- </div>
- )}
- <div className="gf-form-inline">
- <div className="gf-form">
- <InlineFormLabel className="width-12">Directory (tenant) ID</InlineFormLabel>
- <div className="width-15">
- <Input
- className="width-30"
- placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
- value={credentials.tenantId || ''}
- onChange={onTenantIdChange}
- />
- </div>
- </div>
- </div>
- <div className="gf-form-inline">
- <div className="gf-form">
- <InlineFormLabel className="width-12">Application (client) ID</InlineFormLabel>
- <div className="width-15">
- <Input
- className="width-30"
- placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
- value={credentials.clientId || ''}
- onChange={onClientIdChange}
- />
- </div>
- </div>
- </div>
- {typeof credentials.clientSecret === 'symbol' ? (
- <div className="gf-form-inline">
- <div className="gf-form">
- <InlineFormLabel className="width-12">Client Secret</InlineFormLabel>
- <Input className="width-25" placeholder="configured" disabled={true} />
- </div>
- <div className="gf-form">
- <div className="max-width-30 gf-form-inline">
- <Button variant="secondary" type="button" onClick={onClientSecretReset}>
- reset
- </Button>
- </div>
- </div>
- </div>
- ) : (
- <div className="gf-form-inline">
- <div className="gf-form">
- <InlineFormLabel className="width-12">Client Secret</InlineFormLabel>
- <div className="width-15">
- <Input
- className="width-30"
- placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
- value={credentials.clientSecret || ''}
- onChange={onClientSecretChange}
- />
- </div>
- </div>
- </div>
- )}
- </>
- )}
- {getSubscriptions && (
- <>
- <div className="gf-form-inline">
- <div className="gf-form">
- <InlineFormLabel className="width-12">Default Subscription</InlineFormLabel>
- <div className="width-25">
- <Select
- value={
- credentials.defaultSubscriptionId
- ? subscriptions.find((opt) => opt.value === credentials.defaultSubscriptionId)
- : undefined
- }
- options={subscriptions}
- onChange={onSubscriptionChange}
- />
- </div>
- </div>
- </div>
- <div className="gf-form-inline">
- <div className="gf-form">
- <div className="max-width-30 gf-form-inline">
- <Button
- variant="secondary"
- size="sm"
- type="button"
- onClick={onLoadSubscriptions}
- disabled={!hasRequiredFields}
- >
- Load Subscriptions
- </Button>
- </div>
- </div>
- </div>
- </>
- )}
- </div>
- );
- };
- export default AzureCredentialsForm;
|