* wip: consume aws-sdk config in auth http settings
* fix typings
* use sdk regions
* use latest version of grafana/aws-sdk
* use newest sdk
* add comment
* bump sdk
* fix yarn lock file
* fix storybook issue
* upgrade aws-sdk. also use it in grafana ui
* remove not used config
* add aws-sdk as an external dep for grafana in the grafana ui rollup
Co-authored-by: Will Browne <will.browne@grafana.com>
(cherry picked from commit f0d6f132ae)
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
"@grafana/e2e-selectors": "7.5.1",
|
||||
"@grafana/slate-react": "0.22.9-grafana",
|
||||
"@grafana/tsconfig": "^1.0.0-rc1",
|
||||
"@grafana/aws-sdk": "0.0.3",
|
||||
"@iconscout/react-unicons": "1.1.4",
|
||||
"@popperjs/core": "2.5.4",
|
||||
"@sentry/browser": "5.25.0",
|
||||
|
||||
@@ -28,6 +28,7 @@ const buildCjsPackage = ({ env }) => {
|
||||
external: [
|
||||
'react',
|
||||
'react-dom',
|
||||
'@grafana/aws-sdk',
|
||||
'@grafana/data',
|
||||
'@grafana/e2e-selectors',
|
||||
'moment',
|
||||
|
||||
@@ -1,253 +1,70 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { HttpSettingsProps } from './types';
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { Button, InlineFormLabel, Input } from '..';
|
||||
import Select from '../Forms/Legacy/Select/Select';
|
||||
import React from 'react';
|
||||
import { HttpSettingsBaseProps } from './types';
|
||||
import { DataSourceSettings } from '@grafana/data';
|
||||
import {
|
||||
AwsAuthDataSourceSecureJsonData,
|
||||
AwsAuthDataSourceJsonData,
|
||||
ConnectionConfig,
|
||||
ConnectionConfigProps,
|
||||
} from '@grafana/aws-sdk';
|
||||
|
||||
export const SigV4AuthSettings: React.FC<HttpSettingsProps> = (props) => {
|
||||
export const SigV4AuthSettings: React.FC<HttpSettingsBaseProps> = (props) => {
|
||||
const { dataSourceConfig, onChange } = props;
|
||||
|
||||
const authProviderOptions = [
|
||||
{ label: 'AWS SDK Default', value: 'default' },
|
||||
{ label: 'Access & secret key', value: 'keys' },
|
||||
{ label: 'Credentials file', value: 'credentials' },
|
||||
] as SelectableValue[];
|
||||
|
||||
const regions = [
|
||||
{ value: 'af-south-1', label: 'af-south-1' },
|
||||
{ value: 'ap-east-1', label: 'ap-east-1' },
|
||||
{ value: 'ap-northeast-1', label: 'ap-northeast-1' },
|
||||
{ value: 'ap-northeast-2', label: 'ap-northeast-2' },
|
||||
{ value: 'ap-northeast-3', label: 'ap-northeast-3' },
|
||||
{ value: 'ap-south-1', label: 'ap-south-1' },
|
||||
{ value: 'ap-southeast-1', label: 'ap-southeast-1' },
|
||||
{ value: 'ap-southeast-2', label: 'ap-southeast-2' },
|
||||
{ value: 'ca-central-1', label: 'ca-central-1' },
|
||||
{ value: 'cn-north-1', label: 'cn-north-1' },
|
||||
{ value: 'cn-northwest-1', label: 'cn-northwest-1' },
|
||||
{ value: 'eu-central-1', label: 'eu-central-1' },
|
||||
{ value: 'eu-north-1', label: 'eu-north-1' },
|
||||
{ value: 'eu-west-1', label: 'eu-west-1' },
|
||||
{ value: 'eu-west-2', label: 'eu-west-2' },
|
||||
{ value: 'eu-west-3', label: 'eu-west-3' },
|
||||
{ value: 'me-south-1', label: 'me-south-1' },
|
||||
{ value: 'sa-east-1', label: 'sa-east-1' },
|
||||
{ value: 'us-east-1', label: 'us-east-1' },
|
||||
{ value: 'us-east-2', label: 'us-east-2' },
|
||||
{ value: 'us-gov-east-1', label: 'us-gov-east-1' },
|
||||
{ value: 'us-gov-west-1', label: 'us-gov-west-1' },
|
||||
{ value: 'us-iso-east-1', label: 'us-iso-east-1' },
|
||||
{ value: 'us-isob-east-1', label: 'us-isob-east-1' },
|
||||
{ value: 'us-west-1', label: 'us-west-1' },
|
||||
{ value: 'us-west-2', label: 'us-west-2' },
|
||||
] as SelectableValue[];
|
||||
|
||||
// Apply some defaults on initial render
|
||||
useEffect(() => {
|
||||
const sigV4AuthType = dataSourceConfig.jsonData.sigV4AuthType || 'default';
|
||||
onJsonDataChange('sigV4AuthType', sigV4AuthType);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const onSecureJsonDataReset = (fieldName: string) => {
|
||||
const state = {
|
||||
...dataSourceConfig,
|
||||
secureJsonData: {
|
||||
...dataSourceConfig.secureJsonData,
|
||||
[fieldName]: '',
|
||||
},
|
||||
secureJsonFields: {
|
||||
...dataSourceConfig.secureJsonFields,
|
||||
[fieldName]: false,
|
||||
},
|
||||
};
|
||||
|
||||
onChange(state);
|
||||
};
|
||||
|
||||
const onSecureJsonDataChange = (fieldName: string, fieldValue: string) => {
|
||||
const state = {
|
||||
...dataSourceConfig,
|
||||
secureJsonData: {
|
||||
...dataSourceConfig.secureJsonData,
|
||||
[fieldName]: fieldValue,
|
||||
},
|
||||
};
|
||||
|
||||
onChange(state);
|
||||
};
|
||||
|
||||
const onJsonDataChange = (fieldName: string, fieldValue: string) => {
|
||||
const state = {
|
||||
// The @grafana/aws-sdk ConnectionConfig is designed to be rendered in a ConfigEditor,
|
||||
// taking DataSourcePluginOptionsEditorProps as props. We therefore need to map the props accordingly.
|
||||
const connectionConfigProps: ConnectionConfigProps<AwsAuthDataSourceJsonData, AwsAuthDataSourceSecureJsonData> = {
|
||||
onOptionsChange: (awsDataSourceSettings) => {
|
||||
const dataSourceSettings: DataSourceSettings<any, any> = {
|
||||
...dataSourceConfig,
|
||||
jsonData: {
|
||||
...dataSourceConfig.jsonData,
|
||||
sigV4AuthType: awsDataSourceSettings.jsonData.authType,
|
||||
sigV4Profile: awsDataSourceSettings.jsonData.profile,
|
||||
sigV4AssumeRoleArn: awsDataSourceSettings.jsonData.assumeRoleArn,
|
||||
sigV4ExternalId: awsDataSourceSettings.jsonData.externalId,
|
||||
sigV4Region: awsDataSourceSettings.jsonData.defaultRegion,
|
||||
sigV4Endpoint: awsDataSourceSettings.jsonData.endpoint,
|
||||
},
|
||||
secureJsonFields: {
|
||||
sigV4AccessKey: awsDataSourceSettings.secureJsonFields?.accessKey,
|
||||
sigV4SecretKey: awsDataSourceSettings.secureJsonFields?.secretKey,
|
||||
},
|
||||
secureJsonData: {
|
||||
sigV4AccessKey: awsDataSourceSettings.secureJsonData?.accessKey,
|
||||
sigV4SecretKey: awsDataSourceSettings.secureJsonData?.secretKey,
|
||||
},
|
||||
};
|
||||
onChange(dataSourceSettings);
|
||||
},
|
||||
options: {
|
||||
...dataSourceConfig,
|
||||
jsonData: {
|
||||
...dataSourceConfig.jsonData,
|
||||
[fieldName]: fieldValue,
|
||||
authType: dataSourceConfig.jsonData.sigV4AuthType,
|
||||
profile: dataSourceConfig.jsonData.sigV4Profile,
|
||||
assumeRoleArn: dataSourceConfig.jsonData.sigV4AssumeRoleArn,
|
||||
externalId: dataSourceConfig.jsonData.sigV4ExternalId,
|
||||
defaultRegion: dataSourceConfig.jsonData.sigV4Region,
|
||||
endpoint: dataSourceConfig.jsonData.sigV4Endpoint,
|
||||
},
|
||||
};
|
||||
|
||||
onChange(state);
|
||||
secureJsonFields: {
|
||||
accessKey: dataSourceConfig.secureJsonFields?.sigV4AccessKey,
|
||||
secretKey: dataSourceConfig.secureJsonFields?.sigV4SecretKey,
|
||||
},
|
||||
secureJsonData: {
|
||||
accessKey: dataSourceConfig.secureJsonData?.sigV4AccessKey,
|
||||
secretKey: dataSourceConfig.secureJsonData?.sigV4SecretKey,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<h6>SigV4 Auth Details</h6>
|
||||
<div className="gf-form-group">
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form">
|
||||
<InlineFormLabel
|
||||
className="width-14"
|
||||
tooltip="Which AWS credentials chain to use. AWS SDK Default is the recommended option for EKS, ECS, or if you've attached an IAM role to your EC2 instance."
|
||||
>
|
||||
Authentication Provider
|
||||
</InlineFormLabel>
|
||||
<Select
|
||||
className="width-30"
|
||||
value={authProviderOptions.find(
|
||||
(authProvider) => authProvider.value === dataSourceConfig.jsonData.sigV4AuthType
|
||||
)}
|
||||
options={authProviderOptions}
|
||||
defaultValue={dataSourceConfig.jsonData.sigV4AuthType || ''}
|
||||
onChange={(option) => {
|
||||
onJsonDataChange('sigV4AuthType', option.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{dataSourceConfig.jsonData.sigV4AuthType === 'credentials' && (
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form">
|
||||
<InlineFormLabel
|
||||
className="width-14"
|
||||
tooltip="Credentials profile name, as specified in ~/.aws/credentials, leave blank for default."
|
||||
>
|
||||
Credentials Profile Name
|
||||
</InlineFormLabel>
|
||||
<div className="width-30">
|
||||
<Input
|
||||
className="width-30"
|
||||
placeholder="default"
|
||||
value={dataSourceConfig.jsonData.sigV4Profile || ''}
|
||||
onChange={(e) => onJsonDataChange('sigV4Profile', e.currentTarget.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{dataSourceConfig.jsonData.sigV4AuthType === 'keys' && (
|
||||
<div>
|
||||
{dataSourceConfig.secureJsonFields?.sigV4AccessKey ? (
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form">
|
||||
<InlineFormLabel className="width-14">Access Key ID</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={(e) => onSecureJsonDataReset('sigV4AccessKey')}>
|
||||
Reset
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form">
|
||||
<InlineFormLabel className="width-14">Access Key ID</InlineFormLabel>
|
||||
<div className="width-30">
|
||||
<Input
|
||||
className="width-30"
|
||||
value={dataSourceConfig.secureJsonData?.sigV4AccessKey || ''}
|
||||
onChange={(e) => onSecureJsonDataChange('sigV4AccessKey', e.currentTarget.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{dataSourceConfig.secureJsonFields?.sigV4SecretKey ? (
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form">
|
||||
<InlineFormLabel className="width-14">Secret Access Key</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={(e) => onSecureJsonDataReset('sigV4SecretKey')}>
|
||||
Reset
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form">
|
||||
<InlineFormLabel className="width-14">Secret Access Key</InlineFormLabel>
|
||||
<div className="width-30">
|
||||
<Input
|
||||
className="width-30"
|
||||
value={dataSourceConfig.secureJsonData?.sigV4SecretKey || ''}
|
||||
onChange={(e) => onSecureJsonDataChange('sigV4SecretKey', e.currentTarget.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form">
|
||||
<InlineFormLabel
|
||||
className="width-14"
|
||||
tooltip="ARN of the role to assume. Specifying a role here ensures that the selected authentication provider is used to assume the role rather than using the credentials directly. Leave blank if you don't need to assume a role."
|
||||
>
|
||||
Assume Role ARN
|
||||
</InlineFormLabel>
|
||||
<div className="width-30">
|
||||
<Input
|
||||
className="width-30"
|
||||
placeholder="arn:aws:iam:*"
|
||||
value={dataSourceConfig.jsonData.sigV4AssumeRoleArn || ''}
|
||||
onChange={(e) => onJsonDataChange('sigV4AssumeRoleArn', e.currentTarget.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form">
|
||||
<InlineFormLabel
|
||||
className="width-14"
|
||||
tooltip="If you are assuming a role in another account, that was created with an external ID, specify the external ID here."
|
||||
>
|
||||
External ID
|
||||
</InlineFormLabel>
|
||||
<div className="width-30">
|
||||
<Input
|
||||
className="width-30"
|
||||
placeholder="External ID"
|
||||
value={dataSourceConfig.jsonData.sigV4ExternalId || ''}
|
||||
onChange={(e) => onJsonDataChange('sigV4ExternalId', e.currentTarget.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form">
|
||||
<InlineFormLabel
|
||||
className="width-14"
|
||||
tooltip="Specify the region, for example, use ` us-west-2 ` for US West (Oregon)."
|
||||
>
|
||||
Default Region
|
||||
</InlineFormLabel>
|
||||
<Select
|
||||
className="width-30"
|
||||
value={regions.find((region) => region.value === dataSourceConfig.jsonData.sigV4Region)}
|
||||
options={regions}
|
||||
defaultValue={dataSourceConfig.jsonData.sigV4Region || ''}
|
||||
onChange={(option) => onJsonDataChange('sigV4Region', option.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="gf-form">
|
||||
<h6>SigV4 Auth Details</h6>
|
||||
</div>
|
||||
<ConnectionConfig {...connectionConfigProps} skipHeader skipEndpoint></ConnectionConfig>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user