Open radu-stefan-dt opened 8 months ago
Simple example on how one might use SDKs to create a platform client for this ticket.
import { QueryExecutionClient } from "@dynatrace-sdk/client-query";
import {
PlatformHttpClient,
RequestBodyTypes,
HttpClientRequestOptions,
HttpClientResponse,
PlatformHttpClientResponse,
} from "@dynatrace-sdk/http-client";
const BASE_URL = "https://base.url.to.dynatrace";
const CLIENT_ID = "dt0s02.XXXXXXXX";
const CLIENT_SECRET = "dt0s02.XXXXXXXX.YYYYYYYYYYYYYYYYYYYYYYY";
const ACCOUNT_URN = "urn:dtaccount:aaaaaa-bbbb-cccc";
// Example for Sprint SSO. In reality, this will have to be dynamic.
const SSO_URL = "https://sso-sprint.dynatracelabs.com/sso/oauth2/token"
class SamplePlatformClient implements PlatformHttpClient {
private readonly ssoUrl = SSO_URL;
private readonly baseUrl: string;
private readonly clientId: string;
private readonly clientSecret: string;
private readonly accountUrn: string;
constructor(baseUrl: string, clientId: string, clientSecret: string, accountUrn: string) {
this.baseUrl = baseUrl;
this.clientId = clientId;
this.clientSecret = clientSecret;
this.accountUrn = accountUrn;
}
private async getBearer() {
const tokenResponse = await fetch(this.ssoUrl, {
method: "POST",
headers: {
"content-type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({
grant_type: "client_credentials",
client_id: this.clientId,
client_secret: this.clientSecret,
scope: "storage:logs:read storage:buckets:read",
resource: this.accountUrn,
}).toString(),
});
const tokenData = (await tokenResponse.json()) as { access_token: string };
return tokenData.access_token;
}
async send<T extends keyof RequestBodyTypes = "json">({
url,
method,
headers,
body,
abortSignal,
}: HttpClientRequestOptions<T>): Promise<HttpClientResponse> {
const token = await this.getBearer();
const requestConfig = {
method: method,
signal: abortSignal,
headers: {
...headers,
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(body),
};
const response = await fetch(`${this.baseUrl}${url}`, requestConfig);
return new PlatformHttpClientResponse(response);
}
}
const httpClient = new SamplePlatformClient(BASE_URL, CLIENT_ID, CLIENT_SECRET, ACCOUNT_URN);
const dqlClient = new QueryExecutionClient(httpClient);
dqlClient
.queryExecute({
body: {
query:
"fetch logs, from: now() - 2h | summarize count=count(), by:{bin(timestamp, 10m), loglevel}",
requestTimeoutMilliseconds: 30000,
},
})
.then(res => {
console.info(res);
})
.catch(err => {
console.error(err);
});
Things to consider:
Summary First part of achieving Dynatrace platform-native support. Platform access is controlled via SDKs or APIs using OAuth authentication scheme. To truly support platform natively we must also have a client that can interact this way with the tenant.
Details SDKs would be preferred here since they tend to offer an easier way to work with these operations but a while back it wasn't possible to use them outside of Apps. APIs would be the alternative.
Sub-tasks for this feature:
Use Cases
Challenges
Other notes SSO Login workflow (like in AppToolkit) might be a solid alternative to OAuth clients. Worth investigating.