diff --git a/common/changes/@autorest/openapi-to-typespec/auth_schemes_2024-01-18-03-46.json b/common/changes/@autorest/openapi-to-typespec/auth_schemes_2024-01-18-03-46.json new file mode 100644 index 0000000000..2030593717 --- /dev/null +++ b/common/changes/@autorest/openapi-to-typespec/auth_schemes_2024-01-18-03-46.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@autorest/openapi-to-typespec", + "comment": "Support Auth", + "type": "minor" + } + ], + "packageName": "@autorest/openapi-to-typespec" +} \ No newline at end of file diff --git a/packages/extensions/openapi-to-typespec/src/generate/generate-service-information.ts b/packages/extensions/openapi-to-typespec/src/generate/generate-service-information.ts index 80073defbc..a8b3c7463c 100644 --- a/packages/extensions/openapi-to-typespec/src/generate/generate-service-information.ts +++ b/packages/extensions/openapi-to-typespec/src/generate/generate-service-information.ts @@ -1,4 +1,4 @@ -import { TypespecProgram, EndpointParameter } from "../interfaces"; +import { TypespecProgram, EndpointParameter, Auth } from "../interfaces"; import { getOptions } from "../options"; import { generateDocs } from "../utils/docs"; import { getNamespace } from "../utils/namespace"; @@ -13,6 +13,7 @@ export function generateServiceInformation(program: TypespecProgram) { definitions.push(`@armProviderNamespace`); } + generateUseAuth(serviceInformation.authentication, definitions); definitions.push(`@service({ title: "${serviceInformation.name}" })`); @@ -91,3 +92,30 @@ function getEndpointParameters(endpoint: string) { return params; } + +function generateUseAuth(authDefinitions: Auth[] | undefined, statements: string[]): void { + if (!authDefinitions) { + return; + } + + const authFlows: string[] = []; + + for (const auth of authDefinitions) { + if (auth.kind === "AadOauth2Auth") { + const scopes = `[${auth.scopes.map((s) => `"${s}"`).join()}]`; + authFlows.push(`AadOauth2Auth<${scopes}>`); + } + + if (auth.kind === "ApiKeyAuth") { + authFlows.push(`ApiKeyAuth`); + } + } + + if (!authFlows.length) { + return; + } + + statements.push(`@useAuth(${authFlows.join(" | ")})`); + + return; +} diff --git a/packages/extensions/openapi-to-typespec/src/interfaces.ts b/packages/extensions/openapi-to-typespec/src/interfaces.ts index 99f2f934a3..3b65494ad4 100644 --- a/packages/extensions/openapi-to-typespec/src/interfaces.ts +++ b/packages/extensions/openapi-to-typespec/src/interfaces.ts @@ -63,6 +63,24 @@ export interface TypespecResource { response: TypespecDataType; } +export interface AadOauth2AuthFlow { + kind: "AadOauth2Auth"; + scopes: string[]; +} + +export interface AadTokenAuthFlow { + kind: "AadTokenAuthFlow"; + scopes: string[]; +} + +export interface ApiKeyAuthentication { + kind: "ApiKeyAuth"; + location: "header" | "query" | "cookie"; + name: string; +} + +export type Auth = ApiKeyAuthentication | AadOauth2AuthFlow | AadTokenAuthFlow; + export interface ServiceInformation extends WithDoc { name: string; versions?: string[]; @@ -70,6 +88,7 @@ export interface ServiceInformation extends WithDoc { endpointParameters?: EndpointParameter[]; produces?: string[]; consumes?: string[]; + authentication?: Auth[]; armCommonTypeVersion?: string; } diff --git a/packages/extensions/openapi-to-typespec/src/transforms/transform-service-information.ts b/packages/extensions/openapi-to-typespec/src/transforms/transform-service-information.ts index dd1d3abffd..db0aba0c6d 100644 --- a/packages/extensions/openapi-to-typespec/src/transforms/transform-service-information.ts +++ b/packages/extensions/openapi-to-typespec/src/transforms/transform-service-information.ts @@ -1,6 +1,14 @@ -import { CodeModel, ImplementationLocation, ParameterLocation } from "@autorest/codemodel"; +import { + CodeModel, + ImplementationLocation, + KeySecurityScheme, + OAuth2SecurityScheme, + ParameterLocation, + SecurityScheme, + codeModelSchema, +} from "@autorest/codemodel"; import { getArmCommonTypeVersion } from "../autorest-session"; -import { EndpointParameter, ServiceInformation } from "../interfaces"; +import { AadOauth2AuthFlow, ApiKeyAuthentication, Auth, EndpointParameter, ServiceInformation } from "../interfaces"; import { getOptions } from "../options"; import { getFirstEndpoint } from "../utils/get-endpoint"; import { isConstantSchema } from "../utils/schemas"; @@ -14,9 +22,54 @@ export function transformServiceInformation(model: CodeModel): ServiceInformatio endpointParameters: transformEndpointParameters(model), versions: getApiVersions(model), armCommonTypeVersion: isArm ? getArmCommonTypeVersion() : undefined, + authentication: getAuth(model), }; } +function getAuth(model: CodeModel): Auth[] | undefined { + if (!model.security.schemes?.length) { + return undefined; + } + + const distinctSchemes = getDistinctAuthSchemes(model); + const auths: Auth[] = []; + for (const scheme of distinctSchemes) { + if (isAadOauth2Auth(scheme)) { + const aadOauth: AadOauth2AuthFlow = { + kind: "AadOauth2Auth", + scopes: scheme.scopes, + }; + + auths.push(aadOauth); + } + + if (isKeyAuth(scheme)) { + const azureApiKeyAuthentication: ApiKeyAuthentication = { + kind: "ApiKeyAuth", + location: scheme.in, + name: scheme.name, + }; + + auths.push(azureApiKeyAuthentication); + } + } + + return auths; +} + +function getDistinctAuthSchemes(model: CodeModel): SecurityScheme[] { + const distinct = Array.from(new Set(model.security.schemes?.map((s) => JSON.stringify(s)) ?? [])); + return distinct.map((s) => JSON.parse(s)); +} + +function isAadOauth2Auth(scheme: SecurityScheme): scheme is OAuth2SecurityScheme { + return scheme.type === "OAuth2"; +} + +function isKeyAuth(scheme: SecurityScheme): scheme is KeySecurityScheme { + return scheme.type === "Key"; +} + export function transformEndpointParameters(model: CodeModel): EndpointParameter[] { const globalParameters = (model.globalParameters ?? []).filter( (p) => p.implementation === "Client" && p.protocol?.http?.in === "uri", diff --git a/packages/extensions/openapi-to-typespec/test/analyzeText/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/analyzeText/tsp-output/main.tsp index 6f7a6a666a..f31ff42e94 100644 --- a/packages/extensions/openapi-to-typespec/test/analyzeText/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/analyzeText/tsp-output/main.tsp @@ -12,6 +12,7 @@ using TypeSpec.Http; * documentation can be found in https://docs.microsoft.com/en-us/azure/cognitive-services/language-service/overview. */ +@useAuth(ApiKeyAuth) @service({ title: "Microsoft Cognitive Language Service - Analyze Text Authoring", }) diff --git a/packages/extensions/openapi-to-typespec/test/anomalyDetector/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/anomalyDetector/tsp-output/main.tsp index 53a386f128..4fdd110072 100644 --- a/packages/extensions/openapi-to-typespec/test/anomalyDetector/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/anomalyDetector/tsp-output/main.tsp @@ -22,6 +22,7 @@ using TypeSpec.Http; * a set of time series. By using anomaly detector service, business customers can * discover incidents and establish a logic flow for root cause analysis. */ +@useAuth(ApiKeyAuth) @service({ title: "Anomaly Detector Client", }) diff --git a/packages/extensions/openapi-to-typespec/test/arm-agrifood/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/arm-agrifood/tsp-output/main.tsp index b308e0123d..3a0a12898f 100644 --- a/packages/extensions/openapi-to-typespec/test/arm-agrifood/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/arm-agrifood/tsp-output/main.tsp @@ -23,6 +23,7 @@ using TypeSpec.Versioning; * APIs documentation for Microsoft Azure Data Manager for Agriculture Service. */ @armProviderNamespace +@useAuth(AadOauth2Auth<["user_impersonation"]>) @service({ title: "Azure AgFoodPlatform RP Service", }) diff --git a/packages/extensions/openapi-to-typespec/test/arm-analysisservices/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/arm-analysisservices/tsp-output/main.tsp index 26d471907f..7b05960d4a 100644 --- a/packages/extensions/openapi-to-typespec/test/arm-analysisservices/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/arm-analysisservices/tsp-output/main.tsp @@ -15,6 +15,7 @@ using TypeSpec.Versioning; * The Azure Analysis Services Web API provides a RESTful set of web services that enables users to create, retrieve, update, and delete Analysis Services servers */ @armProviderNamespace +@useAuth(AadOauth2Auth<["user_impersonation"]>) @service({ title: "AzureAnalysisServices", }) diff --git a/packages/extensions/openapi-to-typespec/test/arm-apimanagement/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/arm-apimanagement/tsp-output/main.tsp index 99ec8ded33..d8e87ba19c 100644 --- a/packages/extensions/openapi-to-typespec/test/arm-apimanagement/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/arm-apimanagement/tsp-output/main.tsp @@ -64,6 +64,7 @@ using TypeSpec.Versioning; * ApiManagement Client */ @armProviderNamespace +@useAuth(AadOauth2Auth<["user_impersonation"]>) @service({ title: "ApiManagementClient", }) diff --git a/packages/extensions/openapi-to-typespec/test/arm-authorization/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/arm-authorization/tsp-output/main.tsp index 6c72b9d04e..0fa7e521ef 100644 --- a/packages/extensions/openapi-to-typespec/test/arm-authorization/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/arm-authorization/tsp-output/main.tsp @@ -27,6 +27,7 @@ using TypeSpec.Versioning; * Role based access control provides you a way to apply granular level policy administration down to individual resources or resource groups. These operations enable you to manage role definitions and role assignments. A role definition describes the set of actions that can be performed on resources. A role assignment grants access to Azure Active Directory users. */ @armProviderNamespace +@useAuth(AadOauth2Auth<["user_impersonation"]>) @service({ title: "AuthorizationManagementClient", }) diff --git a/packages/extensions/openapi-to-typespec/test/arm-azureintegrationspaces/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/arm-azureintegrationspaces/tsp-output/main.tsp index 58d44b714d..587d7d2d78 100644 --- a/packages/extensions/openapi-to-typespec/test/arm-azureintegrationspaces/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/arm-azureintegrationspaces/tsp-output/main.tsp @@ -20,6 +20,7 @@ using TypeSpec.Versioning; * The azure integration spaces resource provider. */ @armProviderNamespace +@useAuth(AadOauth2Auth<["user_impersonation"]>) @service({ title: "Azure Integration Spaces resource management API.", }) diff --git a/packages/extensions/openapi-to-typespec/test/arm-compute/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/arm-compute/tsp-output/main.tsp index d13258ca92..9f6c5d46d5 100644 --- a/packages/extensions/openapi-to-typespec/test/arm-compute/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/arm-compute/tsp-output/main.tsp @@ -57,6 +57,7 @@ using TypeSpec.Versioning; * Compute Client */ @armProviderNamespace +@useAuth(AadOauth2Auth<["user_impersonation"]>) @service({ title: "Azure Compute resource management API.", }) diff --git a/packages/extensions/openapi-to-typespec/test/arm-machinelearningservices/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/arm-machinelearningservices/tsp-output/main.tsp index 1e51b080d5..c7da7ea6de 100644 --- a/packages/extensions/openapi-to-typespec/test/arm-machinelearningservices/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/arm-machinelearningservices/tsp-output/main.tsp @@ -54,6 +54,7 @@ using TypeSpec.Versioning; * These APIs allow end users to operate on Azure Machine Learning Workspace resources. */ @armProviderNamespace +@useAuth(AadOauth2Auth<["user_impersonation"]>) @service({ title: "Azure Machine Learning Services", }) diff --git a/packages/extensions/openapi-to-typespec/test/arm-networkanalytics/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/arm-networkanalytics/tsp-output/main.tsp index 0a606533f5..e7dd49393a 100644 --- a/packages/extensions/openapi-to-typespec/test/arm-networkanalytics/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/arm-networkanalytics/tsp-output/main.tsp @@ -17,6 +17,7 @@ using TypeSpec.Versioning; * // FIXME: (missing-service-description) Add service description */ @armProviderNamespace +@useAuth(AadOauth2Auth<["user_impersonation"]>) @service({ title: "Azure Network Analytics resource management API.", }) diff --git a/packages/extensions/openapi-to-typespec/test/arm-playwrighttesting/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/arm-playwrighttesting/tsp-output/main.tsp index d252d4f616..6f7f5efd87 100644 --- a/packages/extensions/openapi-to-typespec/test/arm-playwrighttesting/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/arm-playwrighttesting/tsp-output/main.tsp @@ -16,6 +16,7 @@ using TypeSpec.Versioning; * Azure Playwright testing management service */ @armProviderNamespace +@useAuth(AadOauth2Auth<["user_impersonation"]>) @service({ title: "Microsoft AzurePlaywrightService Management API", }) diff --git a/packages/extensions/openapi-to-typespec/test/arm-servicenetworking/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/arm-servicenetworking/tsp-output/main.tsp index b3c2adf3ed..e3195e5791 100644 --- a/packages/extensions/openapi-to-typespec/test/arm-servicenetworking/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/arm-servicenetworking/tsp-output/main.tsp @@ -17,6 +17,7 @@ using TypeSpec.Versioning; * Traffic Controller Provider management API. */ @armProviderNamespace +@useAuth(AadOauth2Auth<["user_impersonation"]>) @service({ title: "Traffic Controller Provider management API.", }) diff --git a/packages/extensions/openapi-to-typespec/test/arm-sphere/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/arm-sphere/tsp-output/main.tsp index d78e8077ba..313504cb6c 100644 --- a/packages/extensions/openapi-to-typespec/test/arm-sphere/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/arm-sphere/tsp-output/main.tsp @@ -21,6 +21,7 @@ using TypeSpec.Versioning; * Azure Sphere resource management API. */ @armProviderNamespace +@useAuth(AadOauth2Auth<["user_impersonation"]>) @service({ title: "Azure Sphere resource management API.", }) diff --git a/packages/extensions/openapi-to-typespec/test/arm-storage/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/arm-storage/tsp-output/main.tsp index 7d9bc17e82..111ebb568a 100644 --- a/packages/extensions/openapi-to-typespec/test/arm-storage/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/arm-storage/tsp-output/main.tsp @@ -32,6 +32,7 @@ using TypeSpec.Versioning; * The Azure Storage Management API. */ @armProviderNamespace +@useAuth(AadOauth2Auth<["user_impersonation"]>) @service({ title: "Azure Storage resource management API.", }) diff --git a/packages/extensions/openapi-to-typespec/test/arm-test/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/arm-test/tsp-output/main.tsp index 903c1d05ca..f16ff051d8 100644 --- a/packages/extensions/openapi-to-typespec/test/arm-test/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/arm-test/tsp-output/main.tsp @@ -17,6 +17,7 @@ using TypeSpec.Versioning; * For test. */ @armProviderNamespace +@useAuth(AadOauth2Auth<["user_impersonation"]>) @service({ title: "Azure Test resource management API.", }) diff --git a/packages/extensions/openapi-to-typespec/test/batch/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/batch/tsp-output/main.tsp index f85f69d014..c7a2dc94fd 100644 --- a/packages/extensions/openapi-to-typespec/test/batch/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/batch/tsp-output/main.tsp @@ -4,6 +4,7 @@ import "./routes.tsp"; using TypeSpec.Rest; using TypeSpec.Http; +@useAuth(AadOauth2Auth<["user_impersonation"]> | ApiKeyAuth) @service({ title: "Azure Batch Service" }) diff --git a/packages/extensions/openapi-to-typespec/test/loadTest/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/loadTest/tsp-output/main.tsp index 770c7bdfac..1d395c6a5e 100644 --- a/packages/extensions/openapi-to-typespec/test/loadTest/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/loadTest/tsp-output/main.tsp @@ -8,6 +8,7 @@ using TypeSpec.Http; * These APIs allow end users to create, view and run load tests using Azure Load * Test Service. */ +@useAuth(AadOauth2Auth<["https://cnt-prod.loadtesting.azure.com/.default"]>) @service({ title: "Load Testing Service", }) diff --git a/packages/extensions/openapi-to-typespec/test/openAI/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/openAI/tsp-output/main.tsp index 5377d86ee3..55f529b7d9 100644 --- a/packages/extensions/openapi-to-typespec/test/openAI/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/openAI/tsp-output/main.tsp @@ -7,6 +7,9 @@ using TypeSpec.Http; /** * Azure OpenAI APIs for completions and search */ +@useAuth( + AadOauth2Auth<["api.read"]> | ApiKeyAuth +) @service({ title: "OpenAI", }) diff --git a/packages/extensions/openapi-to-typespec/test/qna/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/qna/tsp-output/main.tsp index aa1817fe39..33c7cc3973 100644 --- a/packages/extensions/openapi-to-typespec/test/qna/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/qna/tsp-output/main.tsp @@ -12,6 +12,12 @@ using TypeSpec.Http; * documentation can be found in https://docs.microsoft.com/en-us/azure/cognitive-services/text-analytics/overview. */ +@useAuth( + AadOauth2Auth<["https://cognitiveservices.azure.com/.default"]> | ApiKeyAuth< + ApiKeyLocation.header, + "Ocp-Apim-Subscription-Key" + > +) @service({ title: "QnA Maker", }) diff --git a/packages/extensions/openapi-to-typespec/test/qnaAuthoring/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/qnaAuthoring/tsp-output/main.tsp index d9ee4d0c6d..b0f8901363 100644 --- a/packages/extensions/openapi-to-typespec/test/qnaAuthoring/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/qnaAuthoring/tsp-output/main.tsp @@ -12,6 +12,12 @@ using TypeSpec.Http; * documentation can be found in https://docs.microsoft.com/en-us/azure/cognitive-services/text-analytics/overview. */ +@useAuth( + AadOauth2Auth<["https://cognitiveservices.azure.com/.default"]> | ApiKeyAuth< + ApiKeyLocation.header, + "Ocp-Apim-Subscription-Key" + > +) @service({ title: "Microsoft Cognitive Language Service - Question Answering - Authoring", }) diff --git a/packages/extensions/openapi-to-typespec/test/qnaRuntime/tsp-output/main.tsp b/packages/extensions/openapi-to-typespec/test/qnaRuntime/tsp-output/main.tsp index 617ac840ce..7dd3e6822d 100644 --- a/packages/extensions/openapi-to-typespec/test/qnaRuntime/tsp-output/main.tsp +++ b/packages/extensions/openapi-to-typespec/test/qnaRuntime/tsp-output/main.tsp @@ -7,6 +7,7 @@ using TypeSpec.Http; /** * An API for QnAMaker runtime */ +@useAuth(ApiKeyAuth) @service({ title: "QnAMaker Runtime Client", })