diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index ecadd5414e63..bae5b53211c5 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -82245,6 +82245,61 @@ components: description: The title of the event. example: "The event title" type: string + ValidateV2Attributes: + description: Attributes of the API key validation response. + properties: + api_key_id: + description: The UUID of the API key. + example: "a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6" + type: string + api_key_scopes: + description: List of scope names associated with the API key. + example: + - "remote_config_read" + items: + type: string + type: array + valid: + description: Whether the API key is valid. + example: true + type: boolean + required: + - valid + - api_key_scopes + - api_key_id + type: object + ValidateV2Data: + description: Data object containing the API key validation result. + properties: + attributes: + $ref: "#/components/schemas/ValidateV2Attributes" + id: + description: The UUID of the organization associated with the API key. + example: "550e8400-e29b-41d4-a716-446655440000" + type: string + type: + $ref: "#/components/schemas/ValidateV2Type" + required: + - id + - type + - attributes + type: object + ValidateV2Response: + description: Response for the API key validation endpoint. + properties: + data: + $ref: "#/components/schemas/ValidateV2Data" + required: + - data + type: object + ValidateV2Type: + description: Resource type for the API key validation response. + enum: + - validate_v2 + example: validate_v2 + type: string + x-enum-varnames: + - ValidateV2 ValidationError: description: Represents a single validation error, including a human-readable title and metadata. properties: @@ -144871,6 +144926,47 @@ paths: operator: OR permissions: - teams_read + /api/v2/validate: + get: + description: Check if the API key is valid. Returns the organization UUID, API key ID, and associated scopes. + operationId: Validate + responses: + "200": + content: + application/json: + examples: + default: + value: + data: + attributes: + api_key_id: "a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6" + api_key_scopes: + - "remote_config_read" + valid: true + id: "550e8400-e29b-41d4-a716-446655440000" + type: "validate_v2" + schema: + $ref: "#/components/schemas/ValidateV2Response" + description: OK + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/JSONAPIErrorResponse" + description: Forbidden + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + summary: Validate API key + tags: + - Key Management + "x-permission": + operator: OPEN + permissions: [] + x-unstable: |- + **Note**: This endpoint is in preview and is subject to change. + If you have any feedback, contact [Datadog support](https://docs.datadoghq.com/help/). /api/v2/widgets/{experience_type}: get: description: |- diff --git a/features/v2/key_management.feature b/features/v2/key_management.feature index 365c53ed7c27..3be38cccd51e 100644 --- a/features/v2/key_management.feature +++ b/features/v2/key_management.feature @@ -9,19 +9,20 @@ Feature: Key Management Background: Given a valid "apiKeyAuth" key in the system - And a valid "appKeyAuth" key in the system And an instance of "KeyManagement" API @generated @skip @team:DataDog/credentials-management Scenario: Create a personal access token returns "Bad Request" response - Given new "CreatePersonalAccessToken" request + Given a valid "appKeyAuth" key in the system + And new "CreatePersonalAccessToken" request And body with value {"data": {"attributes": {"expires_at": "2025-12-31T23:59:59+00:00", "name": "My Personal Access Token", "scopes": ["dashboards_read", "dashboards_write"]}, "type": "personal_access_tokens"}} When the request is sent Then the response status is 400 Bad Request @team:DataDog/credentials-management Scenario: Create a personal access token returns "Created" response - Given new "CreatePersonalAccessToken" request + Given a valid "appKeyAuth" key in the system + And new "CreatePersonalAccessToken" request And body with value {"data": {"type": "personal_access_tokens", "attributes": {"name": "{{ unique }}", "scopes": ["dashboards_read"], "expires_at": "{{ timeISO('now+365d') }}"}}} When the request is sent Then the response status is 201 Created @@ -32,14 +33,16 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Create an API key returns "Bad Request" response - Given new "CreateAPIKey" request + Given a valid "appKeyAuth" key in the system + And new "CreateAPIKey" request And body with value {"data": {"attributes": {"name": "API Key for submitting metrics"}, "type": "api_keys"}} When the request is sent Then the response status is 400 Bad Request @team:DataDog/credentials-management Scenario: Create an API key returns "Created" response - Given new "CreateAPIKey" request + Given a valid "appKeyAuth" key in the system + And new "CreateAPIKey" request And body with value {"data": {"type": "api_keys", "attributes": {"name": "{{ unique }}"}}} When the request is sent Then the response status is 201 Created @@ -48,7 +51,8 @@ Feature: Key Management @team:DataDog/credentials-management Scenario: Create an Application key with scopes for current user returns "Created" response - Given new "CreateCurrentUserApplicationKey" request + Given a valid "appKeyAuth" key in the system + And new "CreateCurrentUserApplicationKey" request And body with value {"data": {"type": "application_keys", "attributes": {"name": "{{ unique }}", "scopes": ["dashboards_read", "dashboards_write", "dashboards_public_share"]}}} When the request is sent Then the response status is 201 Created @@ -57,14 +61,16 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Create an application key for current user returns "Bad Request" response - Given new "CreateCurrentUserApplicationKey" request + Given a valid "appKeyAuth" key in the system + And new "CreateCurrentUserApplicationKey" request And body with value {"data": {"attributes": {"name": "Application Key for managing dashboards", "scopes": ["dashboards_read", "dashboards_write", "dashboards_public_share"]}, "type": "application_keys"}} When the request is sent Then the response status is 400 Bad Request @team:DataDog/credentials-management Scenario: Create an application key for current user returns "Created" response - Given new "CreateCurrentUserApplicationKey" request + Given a valid "appKeyAuth" key in the system + And new "CreateCurrentUserApplicationKey" request And body with value {"data": {"type": "application_keys", "attributes": {"name": "{{ unique }}"}}} When the request is sent Then the response status is 201 Created @@ -73,7 +79,8 @@ Feature: Key Management @team:DataDog/credentials-management Scenario: Delete an API key returns "No Content" response - Given there is a valid "api_key" in the system + Given a valid "appKeyAuth" key in the system + And there is a valid "api_key" in the system And new "DeleteAPIKey" request And request contains "api_key_id" parameter from "api_key.data.id" When the request is sent @@ -81,14 +88,16 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Delete an API key returns "Not Found" response - Given new "DeleteAPIKey" request + Given a valid "appKeyAuth" key in the system + And new "DeleteAPIKey" request And request contains "api_key_id" parameter from "REPLACE.ME" When the request is sent Then the response status is 404 Not Found @team:DataDog/credentials-management Scenario: Delete an application key owned by current user returns "No Content" response - Given there is a valid "application_key" in the system + Given a valid "appKeyAuth" key in the system + And there is a valid "application_key" in the system And new "DeleteCurrentUserApplicationKey" request And request contains "app_key_id" parameter from "application_key.data.id" When the request is sent @@ -96,14 +105,16 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Delete an application key owned by current user returns "Not Found" response - Given new "DeleteCurrentUserApplicationKey" request + Given a valid "appKeyAuth" key in the system + And new "DeleteCurrentUserApplicationKey" request And request contains "app_key_id" parameter from "REPLACE.ME" When the request is sent Then the response status is 404 Not Found @team:DataDog/credentials-management Scenario: Delete an application key returns "No Content" response - Given there is a valid "application_key" in the system + Given a valid "appKeyAuth" key in the system + And there is a valid "application_key" in the system And new "DeleteApplicationKey" request And request contains "app_key_id" parameter from "application_key.data.id" When the request is sent @@ -111,14 +122,16 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Delete an application key returns "Not Found" response - Given new "DeleteApplicationKey" request + Given a valid "appKeyAuth" key in the system + And new "DeleteApplicationKey" request And request contains "app_key_id" parameter from "REPLACE.ME" When the request is sent Then the response status is 404 Not Found @generated @skip @team:DataDog/credentials-management Scenario: Edit an API key returns "Bad Request" response - Given new "UpdateAPIKey" request + Given a valid "appKeyAuth" key in the system + And new "UpdateAPIKey" request And request contains "api_key_id" parameter from "REPLACE.ME" And body with value {"data": {"attributes": {"name": "API Key for submitting metrics"}, "id": "00112233-4455-6677-8899-aabbccddeeff", "type": "api_keys"}} When the request is sent @@ -126,7 +139,8 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Edit an API key returns "Not Found" response - Given new "UpdateAPIKey" request + Given a valid "appKeyAuth" key in the system + And new "UpdateAPIKey" request And request contains "api_key_id" parameter from "REPLACE.ME" And body with value {"data": {"attributes": {"name": "API Key for submitting metrics"}, "id": "00112233-4455-6677-8899-aabbccddeeff", "type": "api_keys"}} When the request is sent @@ -134,7 +148,8 @@ Feature: Key Management @team:DataDog/credentials-management Scenario: Edit an API key returns "OK" response - Given there is a valid "api_key" in the system + Given a valid "appKeyAuth" key in the system + And there is a valid "api_key" in the system And new "UpdateAPIKey" request And request contains "api_key_id" parameter from "api_key.data.id" And body with value {"data": {"type": "api_keys", "id": "{{ api_key.data.id }}", "attributes": {"name": "{{ unique }}"}}} @@ -146,7 +161,8 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Edit an application key owned by current user returns "Bad Request" response - Given new "UpdateCurrentUserApplicationKey" request + Given a valid "appKeyAuth" key in the system + And new "UpdateCurrentUserApplicationKey" request And request contains "app_key_id" parameter from "REPLACE.ME" And body with value {"data": {"attributes": {"name": "Application Key for managing dashboards", "scopes": ["dashboards_read", "dashboards_write", "dashboards_public_share"]}, "id": "00112233-4455-6677-8899-aabbccddeeff", "type": "application_keys"}} When the request is sent @@ -154,7 +170,8 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Edit an application key owned by current user returns "Not Found" response - Given new "UpdateCurrentUserApplicationKey" request + Given a valid "appKeyAuth" key in the system + And new "UpdateCurrentUserApplicationKey" request And request contains "app_key_id" parameter from "REPLACE.ME" And body with value {"data": {"attributes": {"name": "Application Key for managing dashboards", "scopes": ["dashboards_read", "dashboards_write", "dashboards_public_share"]}, "id": "00112233-4455-6677-8899-aabbccddeeff", "type": "application_keys"}} When the request is sent @@ -162,7 +179,8 @@ Feature: Key Management @team:DataDog/credentials-management Scenario: Edit an application key owned by current user returns "OK" response - Given there is a valid "application_key" in the system + Given a valid "appKeyAuth" key in the system + And there is a valid "application_key" in the system And new "UpdateCurrentUserApplicationKey" request And request contains "app_key_id" parameter from "application_key.data.id" And body with value {"data": {"id": "{{ application_key.data.id }}", "type": "application_keys", "attributes": {"name" : "{{ application_key.data.attributes.name }}-updated"}}} @@ -174,7 +192,8 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Edit an application key returns "Bad Request" response - Given new "UpdateApplicationKey" request + Given a valid "appKeyAuth" key in the system + And new "UpdateApplicationKey" request And request contains "app_key_id" parameter from "REPLACE.ME" And body with value {"data": {"attributes": {"name": "Application Key for managing dashboards", "scopes": ["dashboards_read", "dashboards_write", "dashboards_public_share"]}, "id": "00112233-4455-6677-8899-aabbccddeeff", "type": "application_keys"}} When the request is sent @@ -182,7 +201,8 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Edit an application key returns "Not Found" response - Given new "UpdateApplicationKey" request + Given a valid "appKeyAuth" key in the system + And new "UpdateApplicationKey" request And request contains "app_key_id" parameter from "REPLACE.ME" And body with value {"data": {"attributes": {"name": "Application Key for managing dashboards", "scopes": ["dashboards_read", "dashboards_write", "dashboards_public_share"]}, "id": "00112233-4455-6677-8899-aabbccddeeff", "type": "application_keys"}} When the request is sent @@ -190,7 +210,8 @@ Feature: Key Management @team:DataDog/credentials-management Scenario: Edit an application key returns "OK" response - Given there is a valid "application_key" in the system + Given a valid "appKeyAuth" key in the system + And there is a valid "application_key" in the system And new "UpdateApplicationKey" request And request contains "app_key_id" parameter from "application_key.data.id" And body with value {"data": {"id": "{{ application_key.data.id }}", "type": "application_keys", "attributes": {"name" : "{{ application_key.data.attributes.name }}-updated"}}} @@ -202,14 +223,16 @@ Feature: Key Management @team:DataDog/credentials-management Scenario: Get API key returns "Not Found" response - Given new "GetAPIKey" request + Given a valid "appKeyAuth" key in the system + And new "GetAPIKey" request And request contains "api_key_id" parameter with value "invalidId" When the request is sent Then the response status is 404 Not Found @team:DataDog/credentials-management Scenario: Get API key returns "OK" response - Given there is a valid "api_key" in the system + Given a valid "appKeyAuth" key in the system + And there is a valid "api_key" in the system And new "GetAPIKey" request And request contains "api_key_id" parameter from "api_key.data.id" When the request is sent @@ -220,14 +243,16 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Get a personal access token returns "Not Found" response - Given new "GetPersonalAccessToken" request + Given a valid "appKeyAuth" key in the system + And new "GetPersonalAccessToken" request And request contains "pat_id" parameter from "REPLACE.ME" When the request is sent Then the response status is 404 Not Found @team:DataDog/credentials-management Scenario: Get a personal access token returns "OK" response - Given there is a valid "personal_access_token" in the system + Given a valid "appKeyAuth" key in the system + And there is a valid "personal_access_token" in the system And new "GetPersonalAccessToken" request And request contains "pat_id" parameter from "personal_access_token.data.id" When the request is sent @@ -237,13 +262,15 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Get all API keys returns "Bad Request" response - Given new "ListAPIKeys" request + Given a valid "appKeyAuth" key in the system + And new "ListAPIKeys" request When the request is sent Then the response status is 400 Bad Request @team:DataDog/credentials-management Scenario: Get all API keys returns "OK" response - Given there is a valid "api_key" in the system + Given a valid "appKeyAuth" key in the system + And there is a valid "api_key" in the system And new "ListAPIKeys" request And request contains "filter" parameter from "api_key.data.attributes.name" When the request is sent @@ -253,19 +280,22 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Get all application keys owned by current user returns "Bad Request" response - Given new "ListCurrentUserApplicationKeys" request + Given a valid "appKeyAuth" key in the system + And new "ListCurrentUserApplicationKeys" request When the request is sent Then the response status is 400 Bad Request @generated @skip @team:DataDog/credentials-management Scenario: Get all application keys owned by current user returns "Not Found" response - Given new "ListCurrentUserApplicationKeys" request + Given a valid "appKeyAuth" key in the system + And new "ListCurrentUserApplicationKeys" request When the request is sent Then the response status is 404 Not Found @team:DataDog/credentials-management Scenario: Get all application keys owned by current user returns "OK" response - Given new "ListCurrentUserApplicationKeys" request + Given a valid "appKeyAuth" key in the system + And new "ListCurrentUserApplicationKeys" request When the request is sent Then the response status is 200 OK And the response "data[0].type" is equal to "application_keys" @@ -273,19 +303,22 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Get all application keys returns "Bad Request" response - Given new "ListApplicationKeys" request + Given a valid "appKeyAuth" key in the system + And new "ListApplicationKeys" request When the request is sent Then the response status is 400 Bad Request @generated @skip @team:DataDog/credentials-management Scenario: Get all application keys returns "Not Found" response - Given new "ListApplicationKeys" request + Given a valid "appKeyAuth" key in the system + And new "ListApplicationKeys" request When the request is sent Then the response status is 404 Not Found @team:DataDog/credentials-management Scenario: Get all application keys returns "OK" response - Given there is a valid "application_key" in the system + Given a valid "appKeyAuth" key in the system + And there is a valid "application_key" in the system And new "ListApplicationKeys" request When the request is sent Then the response status is 200 OK @@ -294,13 +327,15 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Get all personal access tokens returns "Bad Request" response - Given new "ListPersonalAccessTokens" request + Given a valid "appKeyAuth" key in the system + And new "ListPersonalAccessTokens" request When the request is sent Then the response status is 400 Bad Request @team:DataDog/credentials-management Scenario: Get all personal access tokens returns "OK" response - Given there is a valid "personal_access_token" in the system + Given a valid "appKeyAuth" key in the system + And there is a valid "personal_access_token" in the system And new "ListPersonalAccessTokens" request When the request is sent Then the response status is 200 OK @@ -308,21 +343,24 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Get an application key returns "Bad Request" response - Given new "GetApplicationKey" request + Given a valid "appKeyAuth" key in the system + And new "GetApplicationKey" request And request contains "app_key_id" parameter from "REPLACE.ME" When the request is sent Then the response status is 400 Bad Request @team:DataDog/credentials-management Scenario: Get an application key returns "Not Found" response - Given new "GetApplicationKey" request + Given a valid "appKeyAuth" key in the system + And new "GetApplicationKey" request And request contains "app_key_id" parameter with value "invalidId" When the request is sent Then the response status is 404 Not Found @team:DataDog/credentials-management Scenario: Get an application key returns "OK" response - Given there is a valid "application_key" in the system + Given a valid "appKeyAuth" key in the system + And there is a valid "application_key" in the system And new "GetApplicationKey" request And request contains "app_key_id" parameter from "application_key.data.id" When the request is sent @@ -333,14 +371,16 @@ Feature: Key Management @team:DataDog/credentials-management Scenario: Get one application key owned by current user returns "Not Found" response - Given new "GetCurrentUserApplicationKey" request + Given a valid "appKeyAuth" key in the system + And new "GetCurrentUserApplicationKey" request And request contains "app_key_id" parameter with value "incorrectId" When the request is sent Then the response status is 404 Not Found @team:DataDog/credentials-management Scenario: Get one application key owned by current user returns "OK" response - Given there is a valid "application_key" in the system + Given a valid "appKeyAuth" key in the system + And there is a valid "application_key" in the system And new "GetCurrentUserApplicationKey" request And request contains "app_key_id" parameter from "application_key.data.id" When the request is sent @@ -353,7 +393,8 @@ Feature: Key Management @team:DataDog/credentials-management Scenario: Revoke a personal access token returns "No Content" response - Given there is a valid "personal_access_token" in the system + Given a valid "appKeyAuth" key in the system + And there is a valid "personal_access_token" in the system And new "RevokePersonalAccessToken" request And request contains "pat_id" parameter from "personal_access_token.data.id" When the request is sent @@ -361,14 +402,16 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Revoke a personal access token returns "Not Found" response - Given new "RevokePersonalAccessToken" request + Given a valid "appKeyAuth" key in the system + And new "RevokePersonalAccessToken" request And request contains "pat_id" parameter from "REPLACE.ME" When the request is sent Then the response status is 404 Not Found @generated @skip @team:DataDog/credentials-management Scenario: Update a personal access token returns "Bad Request" response - Given new "UpdatePersonalAccessToken" request + Given a valid "appKeyAuth" key in the system + And new "UpdatePersonalAccessToken" request And request contains "pat_id" parameter from "REPLACE.ME" And body with value {"data": {"attributes": {"name": "Updated Personal Access Token", "scopes": ["dashboards_read", "dashboards_write"]}, "id": "00112233-4455-6677-8899-aabbccddeeff", "type": "personal_access_tokens"}} When the request is sent @@ -376,7 +419,8 @@ Feature: Key Management @generated @skip @team:DataDog/credentials-management Scenario: Update a personal access token returns "Not Found" response - Given new "UpdatePersonalAccessToken" request + Given a valid "appKeyAuth" key in the system + And new "UpdatePersonalAccessToken" request And request contains "pat_id" parameter from "REPLACE.ME" And body with value {"data": {"attributes": {"name": "Updated Personal Access Token", "scopes": ["dashboards_read", "dashboards_write"]}, "id": "00112233-4455-6677-8899-aabbccddeeff", "type": "personal_access_tokens"}} When the request is sent @@ -384,10 +428,18 @@ Feature: Key Management @team:DataDog/credentials-management Scenario: Update a personal access token returns "OK" response - Given there is a valid "personal_access_token" in the system + Given a valid "appKeyAuth" key in the system + And there is a valid "personal_access_token" in the system And new "UpdatePersonalAccessToken" request And request contains "pat_id" parameter from "personal_access_token.data.id" And body with value {"data": {"type": "personal_access_tokens", "id": "{{ personal_access_token.data.id }}", "attributes": {"name": "{{ unique }}-updated"}}} When the request is sent Then the response status is 200 OK And the response "data.attributes.name" is equal to "{{ unique }}-updated" + + @generated @skip @team:DataDog/identity-platform + Scenario: Validate API key returns "OK" response + Given operation "Validate" enabled + And new "Validate" request + When the request is sent + Then the response status is 200 OK diff --git a/features/v2/undo.json b/features/v2/undo.json index 96d9f3eb5d14..78df9b7b2efa 100644 --- a/features/v2/undo.json +++ b/features/v2/undo.json @@ -7146,6 +7146,12 @@ "type": "safe" } }, + "Validate": { + "tag": "Key Management", + "undo": { + "type": "safe" + } + }, "SearchWidgets": { "tag": "Widgets", "undo": { diff --git a/private/bdd_runner/src/support/scenarios_model_mapping.ts b/private/bdd_runner/src/support/scenarios_model_mapping.ts index 8ef3cdeb5bfe..15fc1e53c589 100644 --- a/private/bdd_runner/src/support/scenarios_model_mapping.ts +++ b/private/bdd_runner/src/support/scenarios_model_mapping.ts @@ -3553,6 +3553,9 @@ export const ScenariosModelMappings: { [key: string]: OperationMapping } = { }, operationResponseType: "PersonalAccessTokenResponse", }, + "KeyManagementApi.V2.Validate": { + operationResponseType: "ValidateV2Response", + }, "APIManagementApi.V2.ListAPIs": { query: { type: "string", diff --git a/services/key_management/src/v2/KeyManagementApi.ts b/services/key_management/src/v2/KeyManagementApi.ts index 24c771ffe418..c3e4403ba6a4 100644 --- a/services/key_management/src/v2/KeyManagementApi.ts +++ b/services/key_management/src/v2/KeyManagementApi.ts @@ -32,6 +32,7 @@ import { ApplicationKeyCreateRequest } from "./models/ApplicationKeyCreateReques import { ApplicationKeyResponse } from "./models/ApplicationKeyResponse"; import { ApplicationKeysSort } from "./models/ApplicationKeysSort"; import { ApplicationKeyUpdateRequest } from "./models/ApplicationKeyUpdateRequest"; +import { JSONAPIErrorResponse } from "./models/JSONAPIErrorResponse"; import { ListApplicationKeysResponse } from "./models/ListApplicationKeysResponse"; import { ListPersonalAccessTokensResponse } from "./models/ListPersonalAccessTokensResponse"; import { PersonalAccessTokenCreateRequest } from "./models/PersonalAccessTokenCreateRequest"; @@ -39,6 +40,7 @@ import { PersonalAccessTokenCreateResponse } from "./models/PersonalAccessTokenC import { PersonalAccessTokenResponse } from "./models/PersonalAccessTokenResponse"; import { PersonalAccessTokensSort } from "./models/PersonalAccessTokensSort"; import { PersonalAccessTokenUpdateRequest } from "./models/PersonalAccessTokenUpdateRequest"; +import { ValidateV2Response } from "./models/ValidateV2Response"; import { version } from "../version"; export class KeyManagementApiRequestFactory extends BaseAPIRequestFactory { @@ -1198,6 +1200,42 @@ export class KeyManagementApiRequestFactory extends BaseAPIRequestFactory { return requestContext; } + + public async validate(_options?: Configuration): Promise { + const _config = _options || this.configuration; + + if (!_config.unstableOperations["KeyManagementApi.v2.validate"]) { + throw new Error( + "Unstable operation 'validate' is disabled. Enable it by setting `configuration.unstableOperations['KeyManagementApi.v2.validate'] = true`", + ); + } + + // Path Params + const localVarPath = "/api/v2/validate"; + + // Make Request Context + const { server, overrides } = _config.getServerAndOverrides( + "KeyManagementApi.v2.validate", + KeyManagementApi.operationServers, + ); + const requestContext = server.makeRequestContext( + localVarPath, + HttpMethod.GET, + overrides, + ); + requestContext.setHeaderParam("Accept", "application/json"); + requestContext.setHttpConfig(_config.httpConfig); + + // Set User-Agent + if (this.userAgent) { + requestContext.setHeaderParam("User-Agent", this.userAgent); + } + + // Apply auth methods + applySecurityAuthentication(_config, requestContext, ["apiKeyAuth"]); + + return requestContext; + } } export class KeyManagementApiResponseProcessor { @@ -2297,6 +2335,83 @@ export class KeyManagementApiResponseProcessor { 'Unknown API Status Code!\nBody: "' + body + '"', ); } + + /** + * Unwraps the actual response sent by the server from the response context and deserializes the response content + * to the expected objects + * + * @params response Response returned by the server for a request to validate + * @throws ApiException if the response code was not in [200, 299] + */ + public async validate( + response: ResponseContext, + ): Promise { + const contentType = normalizeMediaType(response.headers["content-type"]); + if (response.httpStatusCode === 200) { + const body: ValidateV2Response = deserialize( + parse(await response.body.text(), contentType), + TypingInfo, + "ValidateV2Response", + ) as ValidateV2Response; + return body; + } + if (response.httpStatusCode === 403) { + const bodyText = parse(await response.body.text(), contentType); + let body: JSONAPIErrorResponse; + try { + body = deserialize( + bodyText, + TypingInfo, + "JSONAPIErrorResponse", + ) as JSONAPIErrorResponse; + } catch (error) { + logger.debug(`Got error deserializing error: ${error}`); + throw new ApiException( + response.httpStatusCode, + bodyText, + ); + } + throw new ApiException( + response.httpStatusCode, + body, + ); + } + if (response.httpStatusCode === 429) { + const bodyText = parse(await response.body.text(), contentType); + let body: APIErrorResponse; + try { + body = deserialize( + bodyText, + TypingInfo, + "APIErrorResponse", + ) as APIErrorResponse; + } catch (error) { + logger.debug(`Got error deserializing error: ${error}`); + throw new ApiException( + response.httpStatusCode, + bodyText, + ); + } + throw new ApiException(response.httpStatusCode, body); + } + + // Work around for missing responses in specification, e.g. for petstore.yaml + if (response.httpStatusCode >= 200 && response.httpStatusCode <= 299) { + const body: ValidateV2Response = deserialize( + parse(await response.body.text(), contentType), + TypingInfo, + "ValidateV2Response", + "", + ) as ValidateV2Response; + return body; + } + + const body = (await response.body.text()) || ""; + throw new ApiException( + response.httpStatusCode, + 'Unknown API Status Code!\nBody: "' + body + '"', + ); + } } export interface KeyManagementApiCreateAPIKeyRequest { @@ -3080,4 +3195,19 @@ export class KeyManagementApi { }); }); } + + /** + * Check if the API key is valid. Returns the organization UUID, API key ID, and associated scopes. + * @param param The request object + */ + public validate(options?: Configuration): Promise { + const requestContextPromise = this.requestFactory.validate(options); + return requestContextPromise.then((requestContext) => { + return this.configuration.httpApi + .send(requestContext) + .then((responseContext) => { + return this.responseProcessor.validate(responseContext); + }); + }); + } } diff --git a/services/key_management/src/v2/index.ts b/services/key_management/src/v2/index.ts index 2824bf2dcaf0..bc0c8b4620ad 100644 --- a/services/key_management/src/v2/index.ts +++ b/services/key_management/src/v2/index.ts @@ -55,6 +55,9 @@ export { FullApplicationKey } from "./models/FullApplicationKey"; export { FullApplicationKeyAttributes } from "./models/FullApplicationKeyAttributes"; export { FullPersonalAccessToken } from "./models/FullPersonalAccessToken"; export { FullPersonalAccessTokenAttributes } from "./models/FullPersonalAccessTokenAttributes"; +export { JSONAPIErrorItem } from "./models/JSONAPIErrorItem"; +export { JSONAPIErrorItemSource } from "./models/JSONAPIErrorItemSource"; +export { JSONAPIErrorResponse } from "./models/JSONAPIErrorResponse"; export { LeakedKey } from "./models/LeakedKey"; export { LeakedKeyAttributes } from "./models/LeakedKeyAttributes"; export { LeakedKeyType } from "./models/LeakedKeyType"; @@ -101,3 +104,7 @@ export { User } from "./models/User"; export { UserAttributes } from "./models/UserAttributes"; export { UserResponseRelationships } from "./models/UserResponseRelationships"; export { UsersType } from "./models/UsersType"; +export { ValidateV2Attributes } from "./models/ValidateV2Attributes"; +export { ValidateV2Data } from "./models/ValidateV2Data"; +export { ValidateV2Response } from "./models/ValidateV2Response"; +export { ValidateV2Type } from "./models/ValidateV2Type"; diff --git a/services/key_management/src/v2/models/JSONAPIErrorItem.ts b/services/key_management/src/v2/models/JSONAPIErrorItem.ts new file mode 100644 index 000000000000..a1ca45cd463c --- /dev/null +++ b/services/key_management/src/v2/models/JSONAPIErrorItem.ts @@ -0,0 +1,78 @@ +import { AttributeTypeMap } from "@datadog/datadog-api-client"; + +import { JSONAPIErrorItemSource } from "./JSONAPIErrorItemSource"; + +/** + * API error response body + */ +export class JSONAPIErrorItem { + /** + * A human-readable explanation specific to this occurrence of the error. + */ + "detail"?: string; + /** + * Non-standard meta-information about the error + */ + "meta"?: { [key: string]: any }; + /** + * References to the source of the error. + */ + "source"?: JSONAPIErrorItemSource; + /** + * Status code of the response. + */ + "status"?: string; + /** + * Short human-readable summary of the error. + */ + "title"?: string; + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + "additionalProperties"?: { [key: string]: any }; + /** + * @ignore + */ + "_unparsed"?: boolean; + + /** + * @ignore + */ + static readonly attributeTypeMap: AttributeTypeMap = { + detail: { + baseName: "detail", + type: "string", + }, + meta: { + baseName: "meta", + type: "{ [key: string]: any; }", + }, + source: { + baseName: "source", + type: "JSONAPIErrorItemSource", + }, + status: { + baseName: "status", + type: "string", + }, + title: { + baseName: "title", + type: "string", + }, + additionalProperties: { + baseName: "additionalProperties", + type: "{ [key: string]: any; }", + }, + }; + + /** + * @ignore + */ + static getAttributeTypeMap(): AttributeTypeMap { + return JSONAPIErrorItem.attributeTypeMap; + } + + public constructor() {} +} diff --git a/services/key_management/src/v2/models/JSONAPIErrorItemSource.ts b/services/key_management/src/v2/models/JSONAPIErrorItemSource.ts new file mode 100644 index 000000000000..5889114315fa --- /dev/null +++ b/services/key_management/src/v2/models/JSONAPIErrorItemSource.ts @@ -0,0 +1,60 @@ +import { AttributeTypeMap } from "@datadog/datadog-api-client"; + +/** + * References to the source of the error. + */ +export class JSONAPIErrorItemSource { + /** + * A string indicating the name of a single request header which caused the error. + */ + "header"?: string; + /** + * A string indicating which URI query parameter caused the error. + */ + "parameter"?: string; + /** + * A JSON pointer to the value in the request document that caused the error. + */ + "pointer"?: string; + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + "additionalProperties"?: { [key: string]: any }; + /** + * @ignore + */ + "_unparsed"?: boolean; + + /** + * @ignore + */ + static readonly attributeTypeMap: AttributeTypeMap = { + header: { + baseName: "header", + type: "string", + }, + parameter: { + baseName: "parameter", + type: "string", + }, + pointer: { + baseName: "pointer", + type: "string", + }, + additionalProperties: { + baseName: "additionalProperties", + type: "{ [key: string]: any; }", + }, + }; + + /** + * @ignore + */ + static getAttributeTypeMap(): AttributeTypeMap { + return JSONAPIErrorItemSource.attributeTypeMap; + } + + public constructor() {} +} diff --git a/services/key_management/src/v2/models/JSONAPIErrorResponse.ts b/services/key_management/src/v2/models/JSONAPIErrorResponse.ts new file mode 100644 index 000000000000..68aa04ffc27b --- /dev/null +++ b/services/key_management/src/v2/models/JSONAPIErrorResponse.ts @@ -0,0 +1,47 @@ +import { AttributeTypeMap } from "@datadog/datadog-api-client"; + +import { JSONAPIErrorItem } from "./JSONAPIErrorItem"; + +/** + * API error response. + */ +export class JSONAPIErrorResponse { + /** + * A list of errors. + */ + "errors": Array; + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + "additionalProperties"?: { [key: string]: any }; + /** + * @ignore + */ + "_unparsed"?: boolean; + + /** + * @ignore + */ + static readonly attributeTypeMap: AttributeTypeMap = { + errors: { + baseName: "errors", + type: "Array", + required: true, + }, + additionalProperties: { + baseName: "additionalProperties", + type: "{ [key: string]: any; }", + }, + }; + + /** + * @ignore + */ + static getAttributeTypeMap(): AttributeTypeMap { + return JSONAPIErrorResponse.attributeTypeMap; + } + + public constructor() {} +} diff --git a/services/key_management/src/v2/models/TypingInfo.ts b/services/key_management/src/v2/models/TypingInfo.ts index 10e53d66a57b..d94b1181bca8 100644 --- a/services/key_management/src/v2/models/TypingInfo.ts +++ b/services/key_management/src/v2/models/TypingInfo.ts @@ -28,6 +28,9 @@ import { FullApplicationKey } from "./FullApplicationKey"; import { FullApplicationKeyAttributes } from "./FullApplicationKeyAttributes"; import { FullPersonalAccessToken } from "./FullPersonalAccessToken"; import { FullPersonalAccessTokenAttributes } from "./FullPersonalAccessTokenAttributes"; +import { JSONAPIErrorItem } from "./JSONAPIErrorItem"; +import { JSONAPIErrorItemSource } from "./JSONAPIErrorItemSource"; +import { JSONAPIErrorResponse } from "./JSONAPIErrorResponse"; import { LeakedKey } from "./LeakedKey"; import { LeakedKeyAttributes } from "./LeakedKeyAttributes"; import { ListApplicationKeysResponse } from "./ListApplicationKeysResponse"; @@ -67,6 +70,9 @@ import { RoleResponseRelationships } from "./RoleResponseRelationships"; import { User } from "./User"; import { UserAttributes } from "./UserAttributes"; import { UserResponseRelationships } from "./UserResponseRelationships"; +import { ValidateV2Attributes } from "./ValidateV2Attributes"; +import { ValidateV2Data } from "./ValidateV2Data"; +import { ValidateV2Response } from "./ValidateV2Response"; export const TypingInfo: ModelTypingInfo = { enumsMap: { @@ -104,6 +110,7 @@ export const TypingInfo: ModelTypingInfo = { PersonalAccessTokensType: ["personal_access_tokens"], RolesType: ["roles"], UsersType: ["users"], + ValidateV2Type: ["validate_v2"], }, oneOfMap: { APIKeyResponseIncludedItem: ["User", "LeakedKey"], @@ -138,6 +145,9 @@ export const TypingInfo: ModelTypingInfo = { FullApplicationKeyAttributes: FullApplicationKeyAttributes, FullPersonalAccessToken: FullPersonalAccessToken, FullPersonalAccessTokenAttributes: FullPersonalAccessTokenAttributes, + JSONAPIErrorItem: JSONAPIErrorItem, + JSONAPIErrorItemSource: JSONAPIErrorItemSource, + JSONAPIErrorResponse: JSONAPIErrorResponse, LeakedKey: LeakedKey, LeakedKeyAttributes: LeakedKeyAttributes, ListApplicationKeysResponse: ListApplicationKeysResponse, @@ -177,5 +187,8 @@ export const TypingInfo: ModelTypingInfo = { User: User, UserAttributes: UserAttributes, UserResponseRelationships: UserResponseRelationships, + ValidateV2Attributes: ValidateV2Attributes, + ValidateV2Data: ValidateV2Data, + ValidateV2Response: ValidateV2Response, }, }; diff --git a/services/key_management/src/v2/models/ValidateV2Attributes.ts b/services/key_management/src/v2/models/ValidateV2Attributes.ts new file mode 100644 index 000000000000..b064e5f98d2b --- /dev/null +++ b/services/key_management/src/v2/models/ValidateV2Attributes.ts @@ -0,0 +1,63 @@ +import { AttributeTypeMap } from "@datadog/datadog-api-client"; + +/** + * Attributes of the API key validation response. + */ +export class ValidateV2Attributes { + /** + * The UUID of the API key. + */ + "apiKeyId": string; + /** + * List of scope names associated with the API key. + */ + "apiKeyScopes": Array; + /** + * Whether the API key is valid. + */ + "valid": boolean; + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + "additionalProperties"?: { [key: string]: any }; + /** + * @ignore + */ + "_unparsed"?: boolean; + + /** + * @ignore + */ + static readonly attributeTypeMap: AttributeTypeMap = { + apiKeyId: { + baseName: "api_key_id", + type: "string", + required: true, + }, + apiKeyScopes: { + baseName: "api_key_scopes", + type: "Array", + required: true, + }, + valid: { + baseName: "valid", + type: "boolean", + required: true, + }, + additionalProperties: { + baseName: "additionalProperties", + type: "{ [key: string]: any; }", + }, + }; + + /** + * @ignore + */ + static getAttributeTypeMap(): AttributeTypeMap { + return ValidateV2Attributes.attributeTypeMap; + } + + public constructor() {} +} diff --git a/services/key_management/src/v2/models/ValidateV2Data.ts b/services/key_management/src/v2/models/ValidateV2Data.ts new file mode 100644 index 000000000000..fd121b843c0c --- /dev/null +++ b/services/key_management/src/v2/models/ValidateV2Data.ts @@ -0,0 +1,66 @@ +import { AttributeTypeMap } from "@datadog/datadog-api-client"; + +import { ValidateV2Attributes } from "./ValidateV2Attributes"; +import { ValidateV2Type } from "./ValidateV2Type"; + +/** + * Data object containing the API key validation result. + */ +export class ValidateV2Data { + /** + * Attributes of the API key validation response. + */ + "attributes": ValidateV2Attributes; + /** + * The UUID of the organization associated with the API key. + */ + "id": string; + /** + * Resource type for the API key validation response. + */ + "type": ValidateV2Type; + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + "additionalProperties"?: { [key: string]: any }; + /** + * @ignore + */ + "_unparsed"?: boolean; + + /** + * @ignore + */ + static readonly attributeTypeMap: AttributeTypeMap = { + attributes: { + baseName: "attributes", + type: "ValidateV2Attributes", + required: true, + }, + id: { + baseName: "id", + type: "string", + required: true, + }, + type: { + baseName: "type", + type: "ValidateV2Type", + required: true, + }, + additionalProperties: { + baseName: "additionalProperties", + type: "{ [key: string]: any; }", + }, + }; + + /** + * @ignore + */ + static getAttributeTypeMap(): AttributeTypeMap { + return ValidateV2Data.attributeTypeMap; + } + + public constructor() {} +} diff --git a/services/key_management/src/v2/models/ValidateV2Response.ts b/services/key_management/src/v2/models/ValidateV2Response.ts new file mode 100644 index 000000000000..d2f5929b1b2d --- /dev/null +++ b/services/key_management/src/v2/models/ValidateV2Response.ts @@ -0,0 +1,47 @@ +import { AttributeTypeMap } from "@datadog/datadog-api-client"; + +import { ValidateV2Data } from "./ValidateV2Data"; + +/** + * Response for the API key validation endpoint. + */ +export class ValidateV2Response { + /** + * Data object containing the API key validation result. + */ + "data": ValidateV2Data; + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + "additionalProperties"?: { [key: string]: any }; + /** + * @ignore + */ + "_unparsed"?: boolean; + + /** + * @ignore + */ + static readonly attributeTypeMap: AttributeTypeMap = { + data: { + baseName: "data", + type: "ValidateV2Data", + required: true, + }, + additionalProperties: { + baseName: "additionalProperties", + type: "{ [key: string]: any; }", + }, + }; + + /** + * @ignore + */ + static getAttributeTypeMap(): AttributeTypeMap { + return ValidateV2Response.attributeTypeMap; + } + + public constructor() {} +} diff --git a/services/key_management/src/v2/models/ValidateV2Type.ts b/services/key_management/src/v2/models/ValidateV2Type.ts new file mode 100644 index 000000000000..1e67e532e2ff --- /dev/null +++ b/services/key_management/src/v2/models/ValidateV2Type.ts @@ -0,0 +1,7 @@ +import { UnparsedObject } from "@datadog/datadog-api-client"; + +/** + * Resource type for the API key validation response. + */ +export type ValidateV2Type = typeof ValidateV2 | UnparsedObject; +export const ValidateV2 = "validate_v2";