-
Notifications
You must be signed in to change notification settings - Fork 81
Add Foundations V4 encryption types and no-deprecated-common-types linter rule for CustomerManagedKeyEncryption #4532
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
0e14d2e
64ab89b
365320d
ace118d
80309e5
8dd404b
a938477
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| changeKind: feature | ||
| packages: | ||
| - "@azure-tools/typespec-azure-resource-manager" | ||
| --- | ||
|
|
||
| Add Foundations V4 encryption types (CustomerManagedKeyEncryptionV4, KeyEncryptionKeyIdentityV4, KeyEncryptionKeyIdentityTypeV4) to replace deprecated CustomerManagedKeyEncryption. Add new @armCommonDefinitionExcluded decorator and arm-common-definition-excluded linter rule to warn when CustomerManagedKeyEncryption is used directly in service specifications outside the Azure.ResourceManager namespace. Deprecate CustomerManagedKeyEncryption in favor of the Encryption type. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -334,6 +334,18 @@ export type GenericResourceInternalDecorator = ( | |
| target: Model, | ||
| ) => DecoratorValidatorCallbacks | void; | ||
|
|
||
| /** | ||
| * Marks an Azure Resource Manager common type as excluded from direct use in | ||
| * service specifications. Types decorated with this decorator should not be | ||
| * referenced directly in service specs; use the equivalent Foundations type instead. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we not use
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had forgotten we could do that. I think we should phase this in, with emitting the diagnostic in this version and making the type internal in next version. This makes a bit better transition if some spec is in development that uses this type. thoughts?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah yeah didn't pay attention it was added toe existing type. What about deprecation to simplify |
||
| * @param replacementTypeName The name of the replacement type to use instead | ||
| */ | ||
| export type ArmCommonDefinitionExcludedDecorator = ( | ||
| context: DecoratorContext, | ||
| target: Model, | ||
|
markcowl marked this conversation as resolved.
|
||
| replacementTypeName: string, | ||
| ) => DecoratorValidatorCallbacks | void; | ||
|
|
||
| export type AzureResourceManagerPrivateDecorators = { | ||
| resourceParameterBaseFor: ResourceParameterBaseForDecorator; | ||
| resourceBaseParametersOf: ResourceBaseParametersOfDecorator; | ||
|
|
@@ -357,4 +369,5 @@ export type AzureResourceManagerPrivateDecorators = { | |
| legacyExtensionResourceOperation: LegacyExtensionResourceOperationDecorator; | ||
| validateCommonTypesVersionForResource: ValidateCommonTypesVersionForResourceDecorator; | ||
| genericResourceInternal: GenericResourceInternalDecorator; | ||
| armCommonDefinitionExcluded: ArmCommonDefinitionExcludedDecorator; | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| using Azure.Core; | ||
|
|
||
| namespace Azure.ResourceManager.Foundations; | ||
|
|
||
| /** The type of identity to use. */ | ||
| union KeyEncryptionKeyIdentityTypeV4 { | ||
| /** System assigned identity */ | ||
| SystemAssignedIdentity: "systemAssignedIdentity", | ||
|
|
||
| /** User assigned identity */ | ||
| UserAssignedIdentity: "userAssignedIdentity", | ||
|
|
||
| /** Delegated identity */ | ||
| DelegatedResourceIdentity: "delegatedResourceIdentity", | ||
|
|
||
| string, | ||
| } | ||
|
|
||
| /** All identity configuration for Customer-managed key settings defining which identity should be used to auth to Key Vault. */ | ||
| model KeyEncryptionKeyIdentityV4 { | ||
| /** The type of identity to use. Values can be systemAssignedIdentity, userAssignedIdentity, or delegatedResourceIdentity. */ | ||
| identityType?: KeyEncryptionKeyIdentityTypeV4; | ||
|
|
||
| /** User assigned identity to use for accessing key encryption key Url. Ex: /subscriptions/fa5fc227-a624-475e-b696-cdd604c735bc/resourceGroups/<resource group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myId. Mutually exclusive with identityType systemAssignedIdentity. */ | ||
| userAssignedIdentityResourceId?: Azure.Core.armResourceIdentifier; | ||
|
|
||
| /** application client identity to use for accessing key encryption key Url in a different tenant. Ex: f83c6b1b-4d34-47e4-bb34-9d83df58b540 */ | ||
| federatedClientId?: uuid; | ||
|
|
||
| /** delegated identity to use for accessing key encryption key Url. Ex: /subscriptions/fa5fc227-a624-475e-b696-cdd604c735bc/resourceGroups/<resource group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myId. Mutually exclusive with identityType systemAssignedIdentity and userAssignedIdentity - internal use only. */ | ||
| delegatedIdentityClientId?: uuid; | ||
| } | ||
|
|
||
| /** Customer-managed key encryption properties for the resource. */ | ||
| model CustomerManagedKeyEncryptionV4 { | ||
| /** All identity configuration for Customer-managed key settings defining which identity should be used to auth to Key Vault. */ | ||
| keyEncryptionKeyIdentity?: KeyEncryptionKeyIdentityV4; | ||
|
|
||
| /** key encryption key Url, versioned or non-versioned. Ex: https://contosovault.vault.azure.net/keys/contosokek/562a4bb76b524a1493a6afe8e536ee78 or https://contosovault.vault.azure.net/keys/contosokek. */ | ||
| keyEncryptionKeyUrl?: string; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| import { Model, ModelProperty, createRule, getNamespaceFullName, paramMessage } from "@typespec/compiler"; | ||
| import { getArmCommonDefinitionExcluded } from "../private.decorators.js"; | ||
|
|
||
| /** | ||
| * Rule that prevents direct usage of deprecated ARM common types | ||
| * in service specifications outside the Azure.ResourceManager library. | ||
|
markcowl marked this conversation as resolved.
|
||
| */ | ||
| export const noDeprecatedCommonTypesRule = createRule({ | ||
| name: "no-deprecated-common-types", | ||
| severity: "warning", | ||
| description: | ||
| "Verify deprecated common types are not used directly in service specifications.", | ||
| url: "https://azure.github.io/typespec-azure/docs/libraries/azure-resource-manager/rules/no-deprecated-common-types", | ||
| messages: { | ||
| default: paramMessage`The type '${"typeName"}' is an internal Azure Resource Manager common type and should not be used directly in service specifications. Use the type '${"replacementType"}' instead.`, | ||
| }, | ||
| create(context) { | ||
| return { | ||
| modelProperty: (property: ModelProperty) => { | ||
| const type = property.type; | ||
| if (type.kind !== "Model") return; | ||
|
|
||
| // Check if the property type is a deprecated ARM common type | ||
| const replacementType = getArmCommonDefinitionExcluded(context.program, type as Model); | ||
| if (!replacementType) return; | ||
|
|
||
| // Allow usage within Azure.ResourceManager namespace | ||
| const containingNamespace = property.model?.namespace; | ||
| if ( | ||
| containingNamespace && | ||
| getNamespaceFullName(containingNamespace).startsWith("Azure.ResourceManager") | ||
| ) { | ||
| return; | ||
| } | ||
|
|
||
| context.reportDiagnostic({ | ||
| format: { typeName: (type as Model).name, replacementType }, | ||
| target: property, | ||
| }); | ||
| }, | ||
| }; | ||
| }, | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| import { Tester } from "#test/tester.js"; | ||
| import { | ||
| LinterRuleTester, | ||
| TesterInstance, | ||
| createLinterRuleTester, | ||
| } from "@typespec/compiler/testing"; | ||
| import { beforeEach, it } from "vitest"; | ||
|
|
||
| import { noDeprecatedCommonTypesRule } from "../../src/rules/no-deprecated-common-types.js"; | ||
|
|
||
| let runner: TesterInstance; | ||
| let tester: LinterRuleTester; | ||
|
|
||
| beforeEach(async () => { | ||
| runner = await Tester.createInstance(); | ||
| tester = createLinterRuleTester( | ||
| runner, | ||
| noDeprecatedCommonTypesRule, | ||
| "@azure-tools/typespec-azure-resource-manager", | ||
| ); | ||
| }); | ||
|
|
||
| it("emits diagnostic when using CustomerManagedKeyEncryption directly in a user spec", async () => { | ||
| await tester | ||
| .expect( | ||
| ` | ||
| @service(#{ title: "Test" }) | ||
| @versioned(Microsoft.Contoso.Versions) | ||
| @armProviderNamespace | ||
| namespace Microsoft.Contoso; | ||
|
|
||
| enum Versions { | ||
| @armCommonTypesVersion(Azure.ResourceManager.CommonTypes.Versions.v4) | ||
| v4; | ||
| } | ||
|
|
||
| @added(Microsoft.Contoso.Versions.v4) | ||
| model EncryptionConfig { | ||
| customerManagedKey: Azure.ResourceManager.CommonTypes.CustomerManagedKeyEncryption; | ||
| } | ||
| `, | ||
| ) | ||
| .toEmitDiagnostics({ | ||
| code: "@azure-tools/typespec-azure-resource-manager/no-deprecated-common-types", | ||
| }); | ||
| }); | ||
|
|
||
| it("does not emit diagnostic when using CustomerManagedKeyEncryption via Encryption wrapper", async () => { | ||
| await tester | ||
| .expect( | ||
| ` | ||
| @service(#{ title: "Test" }) | ||
| @versioned(Microsoft.Contoso.Versions) | ||
| @armProviderNamespace | ||
| namespace Microsoft.Contoso; | ||
|
|
||
| enum Versions { | ||
| @armCommonTypesVersion(Azure.ResourceManager.CommonTypes.Versions.v4) | ||
| v4; | ||
| } | ||
|
|
||
| @added(Microsoft.Contoso.Versions.v4) | ||
| model ResourceProperties { | ||
| encryption?: Azure.ResourceManager.CommonTypes.Encryption; | ||
| } | ||
| `, | ||
| ) | ||
| .toBeValid(); | ||
| }); | ||
|
|
||
| it("does not emit diagnostic when using Foundations.CustomerManagedKeyEncryptionV4", async () => { | ||
| await tester | ||
| .expect( | ||
| ` | ||
| @armProviderNamespace | ||
| @service | ||
| namespace Microsoft.Contoso; | ||
|
|
||
| model EncryptionConfig { | ||
| customerManagedKey: Azure.ResourceManager.Foundations.CustomerManagedKeyEncryptionV4; | ||
| } | ||
| `, | ||
| ) | ||
| .toBeValid(); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| --- | ||
| title: no-deprecated-common-types | ||
| --- | ||
|
|
||
| ```text title="Full name" | ||
| @azure-tools/typespec-azure-resource-manager/no-deprecated-common-types | ||
| ``` | ||
|
|
||
| Verify that deprecated common types are not referenced directly in user service specs. Use the replacement type suggested in the diagnostic message. | ||
|
|
||
| #### ❌ Incorrect | ||
|
|
||
| ```tsp | ||
| @armProviderNamespace | ||
| @service | ||
| namespace Microsoft.Contoso; | ||
|
|
||
| model EncryptionConfig { | ||
| customerManagedKey: Azure.ResourceManager.CommonTypes.CustomerManagedKeyEncryption; | ||
| } | ||
| ``` | ||
|
|
||
| #### ✅ Correct | ||
|
|
||
| Use the `Encryption` wrapper type which is the recommended approach: | ||
|
|
||
| ```tsp | ||
| @armProviderNamespace | ||
| @service | ||
| namespace Microsoft.Contoso; | ||
|
|
||
| model ResourceProperties { | ||
| encryption?: Azure.ResourceManager.CommonTypes.Encryption; | ||
| } | ||
| ``` | ||
|
|
||
| Or use the equivalent type from `Azure.ResourceManager.Foundations`: | ||
|
|
||
| ```tsp | ||
| @armProviderNamespace | ||
| @service | ||
| namespace Microsoft.Contoso; | ||
|
|
||
| model EncryptionConfig { | ||
| customerManagedKey: Azure.ResourceManager.Foundations.CustomerManagedKeyEncryptionV4; | ||
| } | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.