mirror of
https://github.com/grafana/grafana.git
synced 2025-08-03 01:56:56 +08:00
Cloudwatch: Upgrade aws-sdk and display external ids for temporary credentials (#72821)
(under a feature toggle, not yet ready for public testing)
This commit is contained in:
@ -261,7 +261,7 @@
|
||||
"@emotion/css": "11.11.2",
|
||||
"@emotion/react": "11.11.1",
|
||||
"@glideapps/glide-data-grid": "^5.2.1",
|
||||
"@grafana/aws-sdk": "0.0.47",
|
||||
"@grafana/aws-sdk": "0.1.1",
|
||||
"@grafana/data": "workspace:*",
|
||||
"@grafana/e2e-selectors": "workspace:*",
|
||||
"@grafana/experimental": "1.6.1",
|
||||
|
@ -1301,6 +1301,7 @@ func (cfg *Cfg) handleAWSConfig() {
|
||||
}
|
||||
|
||||
cfg.AWSExternalId = awsPluginSec.Key("external_id").Value()
|
||||
err = os.Setenv(awsds.GrafanaAssumeRoleExternalIdKeyName, cfg.AWSExternalId)
|
||||
if err != nil {
|
||||
cfg.Logger.Error(fmt.Sprintf("could not set environment variable '%s'", awsds.GrafanaAssumeRoleExternalIdKeyName), err)
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ func (e *cloudWatchExecutor) newResourceMux() *http.ServeMux {
|
||||
mux.HandleFunc("/accounts", routes.ResourceRequestMiddleware(routes.AccountsHandler, logger, e.getRequestContext))
|
||||
mux.HandleFunc("/namespaces", routes.ResourceRequestMiddleware(routes.NamespacesHandler, logger, e.getRequestContext))
|
||||
mux.HandleFunc("/log-group-fields", routes.ResourceRequestMiddleware(routes.LogGroupFieldsHandler, logger, e.getRequestContext))
|
||||
mux.HandleFunc("/external-id", routes.ResourceRequestMiddleware(routes.ExternalIdHandler, logger, e.getRequestContext))
|
||||
|
||||
return mux
|
||||
}
|
||||
|
||||
|
29
pkg/tsdb/cloudwatch/routes/external_id.go
Normal file
29
pkg/tsdb/cloudwatch/routes/external_id.go
Normal file
@ -0,0 +1,29 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/grafana/grafana-aws-sdk/pkg/awsds"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
|
||||
)
|
||||
|
||||
type ExternalIdResponse struct {
|
||||
ExternalId string `json:"externalId"`
|
||||
}
|
||||
|
||||
func ExternalIdHandler(ctx context.Context, pluginCtx backend.PluginContext, reqCtxFactory models.RequestContextFactoryFunc, parameters url.Values) ([]byte, *models.HttpError) {
|
||||
response := ExternalIdResponse{
|
||||
ExternalId: os.Getenv(awsds.GrafanaAssumeRoleExternalIdKeyName),
|
||||
}
|
||||
jsonResponse, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
return nil, models.NewHttpError("error in ExternalIdHandler", http.StatusInternalServerError, err)
|
||||
}
|
||||
|
||||
return jsonResponse, nil
|
||||
}
|
36
pkg/tsdb/cloudwatch/routes/external_id_test.go
Normal file
36
pkg/tsdb/cloudwatch/routes/external_id_test.go
Normal file
@ -0,0 +1,36 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_external_id_route(t *testing.T) {
|
||||
t.Run("successfully returns an external id from the env", func(t *testing.T) {
|
||||
t.Setenv("AWS_AUTH_EXTERNAL_ID", "mock-external-id")
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
handler := http.HandlerFunc(ResourceRequestMiddleware(ExternalIdHandler, logger, nil))
|
||||
req := httptest.NewRequest("GET", "/external-id", nil)
|
||||
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
assert.Equal(t, http.StatusOK, rr.Code)
|
||||
assert.JSONEq(t, `{"externalId":"mock-external-id"}`, rr.Body.String())
|
||||
})
|
||||
|
||||
t.Run("returns an empty string if there is no external id", func(t *testing.T) {
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
handler := http.HandlerFunc(ResourceRequestMiddleware(ExternalIdHandler, logger, nil))
|
||||
req := httptest.NewRequest("GET", "/external-id", nil)
|
||||
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
assert.Equal(t, http.StatusOK, rr.Code)
|
||||
assert.JSONEq(t, `{"externalId":""}`, rr.Body.String())
|
||||
})
|
||||
}
|
@ -36,6 +36,10 @@ jest.mock('@grafana/runtime', () => ({
|
||||
get: getMock,
|
||||
}),
|
||||
getAppEvents: () => mockAppEvents,
|
||||
config: {
|
||||
...jest.requireActual('@grafana/runtime').config,
|
||||
awsAssumeRoleEnabled: true,
|
||||
},
|
||||
}));
|
||||
|
||||
const props: Props = {
|
||||
|
@ -57,6 +57,15 @@ export const ConfigEditor = (props: Props) => {
|
||||
failSubscription.unsubscribe();
|
||||
};
|
||||
}, [options.jsonData.authType, report]);
|
||||
const [externalId, setExternalId] = useState('');
|
||||
useEffect(() => {
|
||||
if (!externalId && datasource) {
|
||||
datasource.resources
|
||||
.getExternalId()
|
||||
.then(setExternalId)
|
||||
.catch(() => setExternalId('Unable to fetch externalId'));
|
||||
}
|
||||
}, [datasource, externalId]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -76,6 +85,7 @@ export const ConfigEditor = (props: Props) => {
|
||||
);
|
||||
})
|
||||
}
|
||||
externalId={externalId}
|
||||
>
|
||||
<InlineField label="Namespaces of Custom Metrics" labelWidth={29} tooltip="Namespaces of Custom Metrics.">
|
||||
<Input
|
||||
|
@ -35,6 +35,10 @@ export class ResourcesAPI extends CloudWatchRequest {
|
||||
return getBackendSrv().get(`/api/datasources/${this.instanceSettings.id}/resources/${subtype}`, parameters);
|
||||
}
|
||||
|
||||
async getExternalId(): Promise<string> {
|
||||
return await this.memoizedGetRequest<{ externalId: string }>('external-id').then(({ externalId }) => externalId);
|
||||
}
|
||||
|
||||
getAccounts({ region }: ResourceRequest): Promise<Account[]> {
|
||||
return this.memoizedGetRequest<Array<ResourceResponse<Account>>>('accounts', {
|
||||
region: this.templateSrv.replace(this.getActualRegion(region)),
|
||||
|
10
yarn.lock
10
yarn.lock
@ -3604,13 +3604,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@grafana/aws-sdk@npm:0.0.47":
|
||||
version: 0.0.47
|
||||
resolution: "@grafana/aws-sdk@npm:0.0.47"
|
||||
"@grafana/aws-sdk@npm:0.1.1":
|
||||
version: 0.1.1
|
||||
resolution: "@grafana/aws-sdk@npm:0.1.1"
|
||||
dependencies:
|
||||
"@grafana/async-query-data": 0.1.4
|
||||
"@grafana/experimental": 1.1.0
|
||||
checksum: 1e9f57bddf08f0c0b432bb8bdd5ad63382c2d40e9d8282469e3add0ea970a80bcd31e852f050412e0d41620d71e53839510261f92333d026bf79a88d7346c626
|
||||
checksum: 12d1b27b0959a4d16ddf643b360ce067f6debd4141eb28652ff36fece98a99087f865aa2b9f6fda78df2b9e38870a6a7cfa48e0fd1a1ec03de63bc340b344f05
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -19268,7 +19268,7 @@ __metadata:
|
||||
"@emotion/eslint-plugin": 11.11.0
|
||||
"@emotion/react": 11.11.1
|
||||
"@glideapps/glide-data-grid": ^5.2.1
|
||||
"@grafana/aws-sdk": 0.0.47
|
||||
"@grafana/aws-sdk": 0.1.1
|
||||
"@grafana/data": "workspace:*"
|
||||
"@grafana/e2e": "workspace:*"
|
||||
"@grafana/e2e-selectors": "workspace:*"
|
||||
|
Reference in New Issue
Block a user