mirror of
https://github.com/grafana/grafana.git
synced 2024-12-30 10:47:30 -06:00
CloudWatch: Make it possible to specify custom api endpoint (#31402)
* wip: add endpoint field * add endpoint to config and make sure it's part of the cache key * update docs * improve endpoint paragraph * Update docs/sources/datasources/cloudwatch.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update public/app/plugins/datasource/cloudwatch/components/ConfigEditor.tsx Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * goimports * Update docs/sources/datasources/cloudwatch.md Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> * update snapshot * Update docs/sources/datasources/cloudwatch.md Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com> Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> Co-authored-by: Ursula Kallio <73951760+osg-grafana@users.noreply.github.com>
This commit is contained in:
parent
8f7e26cd01
commit
055590890c
@ -105,6 +105,10 @@ Here is a minimal policy example:
|
|||||||
|
|
||||||
The `Assume Role ARN` field allows you to specify which IAM role to assume, if any. When left blank, the provided credentials are used directly and the associated role or user should have the required permissions. If this field is non-blank, on the other hand, the provided credentials are used to perform an [sts:AssumeRole](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) call.
|
The `Assume Role ARN` field allows you to specify which IAM role to assume, if any. When left blank, the provided credentials are used directly and the associated role or user should have the required permissions. If this field is non-blank, on the other hand, the provided credentials are used to perform an [sts:AssumeRole](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) call.
|
||||||
|
|
||||||
|
### Endpoint
|
||||||
|
|
||||||
|
The `Endpoint` field allows you to specify a custom endpoint URL that overrides the default generated endpoint for the CloudWatch API. Leave this field blank if you want to use the default generated endpoint. For more information on why and how to use Service endpoints, refer to the [AWS service endpoints documentation](https://docs.aws.amazon.com/general/latest/gr/rande.html).
|
||||||
|
|
||||||
### EKS IAM roles for service accounts
|
### EKS IAM roles for service accounts
|
||||||
|
|
||||||
The Grafana process in the container runs as user 472 (called "grafana"). When Kubernetes mounts your projected credentials, they will by default only be available to the root user. In order to allow user 472 to access the credentials (and avoid it falling back to the IAM role attached to the EC2 instance), you will need to provide a [security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) for your pod.
|
The Grafana process in the container runs as user 472 (called "grafana"). When Kubernetes mounts your projected credentials, they will by default only be available to the root user. In order to allow user 472 to access the credentials (and avoid it falling back to the IAM role attached to the EC2 instance), you will need to provide a [security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) for your pod.
|
||||||
|
@ -38,6 +38,7 @@ type datasourceInfo struct {
|
|||||||
AssumeRoleARN string
|
AssumeRoleARN string
|
||||||
ExternalID string
|
ExternalID string
|
||||||
Namespace string
|
Namespace string
|
||||||
|
Endpoint string
|
||||||
|
|
||||||
AccessKey string
|
AccessKey string
|
||||||
SecretKey string
|
SecretKey string
|
||||||
@ -96,7 +97,7 @@ func (e *cloudWatchExecutor) newSession(region string) (*session.Session, error)
|
|||||||
|
|
||||||
bldr := strings.Builder{}
|
bldr := strings.Builder{}
|
||||||
for i, s := range []string{
|
for i, s := range []string{
|
||||||
dsInfo.AuthType.String(), dsInfo.AccessKey, dsInfo.Profile, dsInfo.AssumeRoleARN, region,
|
dsInfo.AuthType.String(), dsInfo.AccessKey, dsInfo.Profile, dsInfo.AssumeRoleARN, region, dsInfo.Endpoint,
|
||||||
} {
|
} {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
bldr.WriteString(":")
|
bldr.WriteString(":")
|
||||||
@ -130,6 +131,10 @@ func (e *cloudWatchExecutor) newSession(region string) (*session.Session, error)
|
|||||||
cfgs = append(cfgs, regionCfg)
|
cfgs = append(cfgs, regionCfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if dsInfo.Endpoint != "" {
|
||||||
|
cfgs = append(cfgs, &aws.Config{Endpoint: aws.String(dsInfo.Endpoint)})
|
||||||
|
}
|
||||||
|
|
||||||
switch dsInfo.AuthType {
|
switch dsInfo.AuthType {
|
||||||
case authTypeSharedCreds:
|
case authTypeSharedCreds:
|
||||||
plog.Debug("Authenticating towards AWS with shared credentials", "profile", dsInfo.Profile,
|
plog.Debug("Authenticating towards AWS with shared credentials", "profile", dsInfo.Profile,
|
||||||
@ -413,6 +418,7 @@ func (e *cloudWatchExecutor) getDSInfo(region string) *datasourceInfo {
|
|||||||
atStr := e.DataSource.JsonData.Get("authType").MustString()
|
atStr := e.DataSource.JsonData.Get("authType").MustString()
|
||||||
assumeRoleARN := e.DataSource.JsonData.Get("assumeRoleArn").MustString()
|
assumeRoleARN := e.DataSource.JsonData.Get("assumeRoleArn").MustString()
|
||||||
externalID := e.DataSource.JsonData.Get("externalId").MustString()
|
externalID := e.DataSource.JsonData.Get("externalId").MustString()
|
||||||
|
endpoint := e.DataSource.JsonData.Get("endpoint").MustString()
|
||||||
decrypted := e.DataSource.DecryptedValues()
|
decrypted := e.DataSource.DecryptedValues()
|
||||||
accessKey := decrypted["accessKey"]
|
accessKey := decrypted["accessKey"]
|
||||||
secretKey := decrypted["secretKey"]
|
secretKey := decrypted["secretKey"]
|
||||||
@ -445,6 +451,7 @@ func (e *cloudWatchExecutor) getDSInfo(region string) *datasourceInfo {
|
|||||||
ExternalID: externalID,
|
ExternalID: externalID,
|
||||||
AccessKey: accessKey,
|
AccessKey: accessKey,
|
||||||
SecretKey: secretKey,
|
SecretKey: secretKey,
|
||||||
|
Endpoint: endpoint,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,6 +315,21 @@ export class ConfigEditor extends PureComponent<Props, State> {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="gf-form-inline">
|
||||||
|
<div className="gf-form">
|
||||||
|
<InlineFormLabel className="width-14" tooltip="Optionally, specify a custom endpoint for the service.">
|
||||||
|
Endpoint
|
||||||
|
</InlineFormLabel>
|
||||||
|
<div className="width-30">
|
||||||
|
<Input
|
||||||
|
className="width-30"
|
||||||
|
placeholder={'https://{service}.{region}.amazonaws.com'}
|
||||||
|
value={options.jsonData.endpoint || ''}
|
||||||
|
onChange={onUpdateDatasourceJsonDataOption(this.props, 'endpoint')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -225,6 +225,30 @@ exports[`Render should disable access key id field 1`] = `
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
className="gf-form-inline"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="gf-form"
|
||||||
|
>
|
||||||
|
<FormLabel
|
||||||
|
className="width-14"
|
||||||
|
tooltip="Optionally, specify a custom endpoint for the service."
|
||||||
|
>
|
||||||
|
Endpoint
|
||||||
|
</FormLabel>
|
||||||
|
<div
|
||||||
|
className="width-30"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
className="width-30"
|
||||||
|
onChange={[Function]}
|
||||||
|
placeholder="https://{service}.{region}.amazonaws.com"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
`;
|
`;
|
||||||
@ -454,6 +478,30 @@ exports[`Render should render component 1`] = `
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
className="gf-form-inline"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="gf-form"
|
||||||
|
>
|
||||||
|
<FormLabel
|
||||||
|
className="width-14"
|
||||||
|
tooltip="Optionally, specify a custom endpoint for the service."
|
||||||
|
>
|
||||||
|
Endpoint
|
||||||
|
</FormLabel>
|
||||||
|
<div
|
||||||
|
className="width-30"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
className="width-30"
|
||||||
|
onChange={[Function]}
|
||||||
|
placeholder="https://{service}.{region}.amazonaws.com"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
`;
|
`;
|
||||||
@ -683,6 +731,30 @@ exports[`Render should show access key and secret access key fields 1`] = `
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
className="gf-form-inline"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="gf-form"
|
||||||
|
>
|
||||||
|
<FormLabel
|
||||||
|
className="width-14"
|
||||||
|
tooltip="Optionally, specify a custom endpoint for the service."
|
||||||
|
>
|
||||||
|
Endpoint
|
||||||
|
</FormLabel>
|
||||||
|
<div
|
||||||
|
className="width-30"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
className="width-30"
|
||||||
|
onChange={[Function]}
|
||||||
|
placeholder="https://{service}.{region}.amazonaws.com"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
`;
|
`;
|
||||||
@ -912,6 +984,30 @@ exports[`Render should show arn role field 1`] = `
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
className="gf-form-inline"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="gf-form"
|
||||||
|
>
|
||||||
|
<FormLabel
|
||||||
|
className="width-14"
|
||||||
|
tooltip="Optionally, specify a custom endpoint for the service."
|
||||||
|
>
|
||||||
|
Endpoint
|
||||||
|
</FormLabel>
|
||||||
|
<div
|
||||||
|
className="width-30"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
className="width-30"
|
||||||
|
onChange={[Function]}
|
||||||
|
placeholder="https://{service}.{region}.amazonaws.com"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
`;
|
`;
|
||||||
@ -1141,6 +1237,30 @@ exports[`Render should show credentials profile name field 1`] = `
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
className="gf-form-inline"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="gf-form"
|
||||||
|
>
|
||||||
|
<FormLabel
|
||||||
|
className="width-14"
|
||||||
|
tooltip="Optionally, specify a custom endpoint for the service."
|
||||||
|
>
|
||||||
|
Endpoint
|
||||||
|
</FormLabel>
|
||||||
|
<div
|
||||||
|
className="width-30"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
className="width-30"
|
||||||
|
onChange={[Function]}
|
||||||
|
placeholder="https://{service}.{region}.amazonaws.com"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
`;
|
`;
|
||||||
|
@ -62,6 +62,7 @@ export interface CloudWatchJsonData extends DataSourceJsonData {
|
|||||||
externalId?: string;
|
externalId?: string;
|
||||||
database?: string;
|
database?: string;
|
||||||
customMetricsNamespaces?: string;
|
customMetricsNamespaces?: string;
|
||||||
|
endpoint?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CloudWatchSecureJsonData {
|
export interface CloudWatchSecureJsonData {
|
||||||
|
Loading…
Reference in New Issue
Block a user