From 223bb7062e79ec0651921d7db04aeb4e4262d41b Mon Sep 17 00:00:00 2001 From: Tejaswi Salaigari Date: Thu, 13 Jun 2024 17:20:18 -0500 Subject: [PATCH 01/10] Add TagsAreTopLevelPropertiesOnly new rule --- ...pLevelPropertiesOnly_2024-06-13-22-19.json | 10 + docs/rules.md | 6 + docs/tags-are-top-level-properties-only.md | 57 +++++ .../rulesets/generated/spectral/az-arm.js | 44 +++- .../generated/spectral/az-dataplane.js | 8 +- packages/rulesets/src/spectral/az-arm.ts | 16 ++ .../tags-are-top-level-properties-only.ts | 22 ++ ...tags-are-top-level-properties-only.test.ts | 204 ++++++++++++++++++ 8 files changed, 356 insertions(+), 11 deletions(-) create mode 100644 common/changes/@microsoft.azure/openapi-validator-rulesets/tejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json create mode 100644 docs/tags-are-top-level-properties-only.md create mode 100644 packages/rulesets/src/spectral/functions/tags-are-top-level-properties-only.ts create mode 100644 packages/rulesets/src/spectral/test/tags-are-top-level-properties-only.test.ts diff --git a/common/changes/@microsoft.azure/openapi-validator-rulesets/tejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json b/common/changes/@microsoft.azure/openapi-validator-rulesets/tejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json new file mode 100644 index 000000000..d2242657d --- /dev/null +++ b/common/changes/@microsoft.azure/openapi-validator-rulesets/tejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@microsoft.azure/openapi-validator-rulesets", + "comment": "Add TagsAreTopLevelPropertiesOnly rule to check if tags are defined as top-level property, not in the properties bag", + "type": "patch" + } + ], + "packageName": "@microsoft.azure/openapi-validator-rulesets" +} \ No newline at end of file diff --git a/docs/rules.md b/docs/rules.md index cee0d8635..c3b743b5e 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -1213,6 +1213,12 @@ Validates that system data is not defined in the properties bag, but rather as a Please refer to [system-data-in-properties-bag.md](./system-data-in-properties-bag.md) for details. +### TagsAreTopLevelPropertiesOnly + +Validates that `tags` is not defined in the properties bag, but rather as a top-level property. + +Please refer to [tags-are-top-level-properties-only.md](./tags-are-top-level-properties-only.md) for details. + ### TenantLevelAPIsNotAllowed Tenant level APIs are strongly discouraged and subscription or resource group level APIs are preferred instead. diff --git a/docs/tags-are-top-level-properties-only.md b/docs/tags-are-top-level-properties-only.md new file mode 100644 index 000000000..6a299261b --- /dev/null +++ b/docs/tags-are-top-level-properties-only.md @@ -0,0 +1,57 @@ +# TagsAreTopLevelPropertiesOnly + +## Category + +ARM Error + +## Applies to + +ARM OpenAPI(swagger) specs + +## Related ARM Guideline Code + +- RPC-Put-V1-30 + +## Description + +Validates that `tags` is not defined in the properties bag, but rather as a top-level property. + +## How to fix the violation + +Ensure that any `tags` definitions are as top-level properties, not in the properties bag. + +### Valid/Good Example + +```json +"definitions": { + "tags": { + "type": "object", + "additionalProperties": { + "type": "object", + "params": { + "type": "boolean", + }, + } + }, + "properties": { + "type": "object", + "name": { + "type": "string" + } + } +} +``` + +### Invalid/Bad Example + +```json +"Resource": { + "properties": { + "properties": { + "systemData": { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/systemData", + } + } + } +} +``` diff --git a/packages/rulesets/generated/spectral/az-arm.js b/packages/rulesets/generated/spectral/az-arm.js index 5110f42f4..59af6fdb3 100644 --- a/packages/rulesets/generated/spectral/az-arm.js +++ b/packages/rulesets/generated/spectral/az-arm.js @@ -2075,7 +2075,7 @@ const patchBodyParameters = (parameters, _opts, paths) => { return errors; }; -const ERROR_MESSAGE$1 = "A patch request body must only contain properties present in the corresponding put request body, and must contain at least one of the properties."; +const ERROR_MESSAGE$2 = "A patch request body must only contain properties present in the corresponding put request body, and must contain at least one of the properties."; const PARAM_IN_BODY = (paramObject) => paramObject.in === "body"; const PATCH = "patch"; const PUT = "put"; @@ -2110,7 +2110,7 @@ const patchPropertiesCorrespondToPutProperties = (pathItem, _opts, ctx) => { const patchBodyPropertiesNotInPutBody = _.differenceWith(patchBodyProperties[0], putBodyProperties[0], _.isEqual); if (patchBodyPropertiesNotInPutBody.length > 0) { patchBodyPropertiesNotInPutBody.forEach((missingProperty) => errors.push({ - message: `${Object.keys(missingProperty)[0]} property in patch body is not present in the corresponding put body. ` + ERROR_MESSAGE$1, + message: `${Object.keys(missingProperty)[0]} property in patch body is not present in the corresponding put body. ` + ERROR_MESSAGE$2, path: path, })); return errors; @@ -2691,25 +2691,42 @@ const skuValidation = (skuSchema, opts, paths) => { const SYSTEM_DATA_CAMEL = "systemData"; const SYSTEM_DATA_UPPER_CAMEL = "SystemData"; -const PROPERTIES = "properties"; -const ERROR_MESSAGE = "System data must be defined as a top-level property, not in the properties bag."; +const PROPERTIES$1 = "properties"; +const ERROR_MESSAGE$1 = "System data must be defined as a top-level property, not in the properties bag."; const systemDataInPropertiesBag = (definition, _opts, ctx) => { const properties = getProperties(definition); const path = deepFindObjectKeyPath(properties, SYSTEM_DATA_CAMEL); if (path.length > 0) { return [ { - message: ERROR_MESSAGE, - path: _.concat(ctx.path, PROPERTIES, path[0]), + message: ERROR_MESSAGE$1, + path: _.concat(ctx.path, PROPERTIES$1, path[0]), }, ]; } const pathForUpperCamelCase = deepFindObjectKeyPath(properties, SYSTEM_DATA_UPPER_CAMEL); if (pathForUpperCamelCase.length > 0) { + return [ + { + message: ERROR_MESSAGE$1, + path: _.concat(ctx.path, PROPERTIES$1, pathForUpperCamelCase[0]), + }, + ]; + } + return []; +}; + +const TAGS = "tags"; +const PROPERTIES = "properties"; +const ERROR_MESSAGE = "Tags must be defined as a top-level property, not in the properties bag."; +const tagsAreTopLevelPropertiesOnly = (definition, _opts, ctx) => { + const properties = getProperties(definition); + const path = deepFindObjectKeyPath(properties, TAGS); + if (path.length > 0) { return [ { message: ERROR_MESSAGE, - path: _.concat(ctx.path, PROPERTIES, pathForUpperCamelCase[0]), + path: _.concat(ctx.path, PROPERTIES, path[0]), }, ]; } @@ -3512,6 +3529,19 @@ const ruleset = { function: consistentResponseSchemaForPut, }, }, + TagsAreTopLevelPropertiesOnly: { + rpcGuidelineCode: "RPC-Put-V1-30", + description: "Tags must be defined as a top-level property, not in the properties bag.", + severity: "error", + stagingOnly: true, + message: "{{error}}", + resolved: true, + formats: [oas2], + given: ["$.definitions.*.properties^"], + then: { + function: tagsAreTopLevelPropertiesOnly, + }, + }, ParametersInPost: { rpcGuidelineCode: "RPC-POST-V1-05", description: "For a POST action parameters MUST be in the payload and not in the URI.", diff --git a/packages/rulesets/generated/spectral/az-dataplane.js b/packages/rulesets/generated/spectral/az-dataplane.js index 3c54c1f54..fe46b680e 100644 --- a/packages/rulesets/generated/spectral/az-dataplane.js +++ b/packages/rulesets/generated/spectral/az-dataplane.js @@ -643,7 +643,7 @@ const ruleset$1 = { description: "Operation should have a summary or description.", message: "Operation should have a summary or description.", severity: "warn", - disableForTypeSpec: true, + disableForTypeSpec: false, disableForTypeSpecReason: "Covered by TSP's '@azure-tools/typespec-azure-core/documentation-required' rule.", given: [ "$.paths[*][?( @property === 'get' && !@.summary && !@.description )]", @@ -663,7 +663,7 @@ const ruleset$1 = { description: "All schemas should have a description or title.", message: "Schema should have a description or title.", severity: "warn", - disableForTypeSpec: true, + disableForTypeSpec: false, disableForTypeSpecReason: "Covered by TSP's '@azure-tools/typespec-azure-core/documentation-required' rule.", formats: [oas2, oas3], given: ["$.definitions[?(!@.description && !@.title)]", "$.components.schemas[?(!@.description && !@.title)]"], @@ -675,7 +675,7 @@ const ruleset$1 = { description: "All parameters should have a description.", message: "Parameter should have a description.", severity: "warn", - disableForTypeSpec: true, + disableForTypeSpec: false, disableForTypeSpecReason: "Covered by TSP's '@azure-tools/typespec-azure-core/documentation-required' rule.", given: ["$.paths[*].parameters.*", "$.paths.*[get,put,post,patch,delete,options,head].parameters.*"], then: { @@ -991,7 +991,7 @@ const ruleset$1 = { description: "The value of the 'description' property must be descriptive. It cannot be spaces or empty description.", message: "'{{property}}' parameter lacks 'description' property. Consider adding a 'description' element. Accurate description is essential for maintaining reference documentation.", severity: "error", - disableForTypeSpec: true, + disableForTypeSpec: false, disableForTypeSpecReason: "Covered by TSP's '@azure-tools/typespec-azure-core/documentation-required' rule.", resolved: false, formats: [oas2], diff --git a/packages/rulesets/src/spectral/az-arm.ts b/packages/rulesets/src/spectral/az-arm.ts index d135ee31b..48f22059d 100644 --- a/packages/rulesets/src/spectral/az-arm.ts +++ b/packages/rulesets/src/spectral/az-arm.ts @@ -47,6 +47,7 @@ import responseSchemaSpecifiedForSuccessStatusCode from "./functions/response-sc import { securityDefinitionsStructure } from "./functions/security-definitions-structure" import skuValidation from "./functions/sku-validation" import { systemDataInPropertiesBag } from "./functions/system-data-in-properties-bag" +import { tagsAreTopLevelPropertiesOnly } from "./functions/tags-are-top-level-properties-only" import { tenantLevelAPIsNotAllowed } from "./functions/tenant-level-apis-not-allowed" import { trackedExtensionResourcesAreNotAllowed } from "./functions/tracked-extension-resources-are-not-allowed" import trackedResourceTagsPropertyInRequest from "./functions/trackedresource-tags-property-in-request" @@ -731,6 +732,21 @@ const ruleset: any = { }, }, + // RPC Code: RPC-Put-V1-30 + TagsAreTopLevelPropertiesOnly: { + rpcGuidelineCode: "RPC-Put-V1-30", + description: "Tags must be defined as a top-level property, not in the properties bag.", + severity: "error", + stagingOnly: true, + message: "{{error}}", + resolved: true, + formats: [oas2], + given: ["$.definitions.*.properties^"], + then: { + function: tagsAreTopLevelPropertiesOnly, + }, + }, + /// /// ARM RPC rules for Post patterns /// diff --git a/packages/rulesets/src/spectral/functions/tags-are-top-level-properties-only.ts b/packages/rulesets/src/spectral/functions/tags-are-top-level-properties-only.ts new file mode 100644 index 000000000..f9127c791 --- /dev/null +++ b/packages/rulesets/src/spectral/functions/tags-are-top-level-properties-only.ts @@ -0,0 +1,22 @@ +import _ from "lodash" +import { deepFindObjectKeyPath, getProperties } from "./utils" + +const TAGS = "tags" +const PROPERTIES = "properties" +const ERROR_MESSAGE = "Tags must be defined as a top-level property, not in the properties bag." + +export const tagsAreTopLevelPropertiesOnly = (definition: any, _opts: any, ctx: any) => { + const properties = getProperties(definition) + const path = deepFindObjectKeyPath(properties, TAGS) + + if (path.length > 0) { + return [ + { + message: ERROR_MESSAGE, + path: _.concat(ctx.path, PROPERTIES, path[0]), + }, + ] + } + + return [] +} diff --git a/packages/rulesets/src/spectral/test/tags-are-top-level-properties-only.test.ts b/packages/rulesets/src/spectral/test/tags-are-top-level-properties-only.test.ts new file mode 100644 index 000000000..92da76f10 --- /dev/null +++ b/packages/rulesets/src/spectral/test/tags-are-top-level-properties-only.test.ts @@ -0,0 +1,204 @@ +import { Spectral } from "@stoplight/spectral-core" +import linterForRule from "./utils" + +let linter: Spectral +const errorMessage = "Tags must be defined as a top-level property, not in the properties bag." +beforeAll(async () => { + linter = await linterForRule("TagsAreTopLevelPropertiesOnly") + return linter +}) + +test("TagsAreTopLevelPropertiesOnly should find errors", () => { + const oasDoc = { + swagger: "2.0", + definitions: { + tags: { + description: "This", + type: "object", + properties: { + type: "object", + tags: { + type: "object", + additionalProperties: { + type: "object", + params: { + type: "boolean", + }, + }, + }, + }, + }, + That: { + description: "That", + type: "object", + properties: { + nonTags: { + type: "object", + additionalProperties: { + type: "object", + params: { + type: "boolean", + }, + }, + }, + }, + }, + ThaOther: { + description: "ThaOther", + type: "object", + properties: { + tags: { + type: "object", + info: { + type: "String", + }, + }, + additionalProperties: { + type: "object", + params: { + type: "boolean", + }, + }, + }, + }, + Other: { + description: "Other object", + type: "object", + properties: { + type: "object", + additionalProperties: { + type: "string", + }, + }, + }, + ThisOther: { + description: "This", + type: "object", + properties: { + type: "object", + tags: { + type: "object", + nonTags: { + type: "object", + additionalProperties: { + type: "object", + params: { + type: "boolean", + }, + }, + }, + }, + }, + }, + ActionGroupPatchBody: { + description: "A tenant action group object for the body of patch operations.", + type: "object", + properties: { + tags: { + type: "object", + additionalProperties: { + type: "string", + }, + description: "Resource tags", + }, + identity: { + $ref: "#/definitions/ManagedServiceIdentity", + }, + }, + }, + UserAssignedIdentitiy: { + title: "User-Assigned Identities", + description: + "The set of user assigned identities associated with the resource. The userAssignedIdentities dictionary keys will be ARM resource ids in the form: '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identityName}. The dictionary values can be empty objects ({}) in requests.", + type: "object", + additionalProperties: { + "x-nullable": true, + }, + }, + ManagedServiceIdentity: { + description: "Managed service identity (system assigned and/or user assigned identities)", + type: "object", + properties: { + principalId: { + readOnly: true, + format: "uuid", + type: "string", + description: + "The service principal ID of the system assigned identity. This property will only be provided for a system assigned identity.", + }, + tenantId: { + readOnly: true, + format: "uuid", + type: "string", + description: + "The tenant ID of the system assigned identity. This property will only be provided for a system assigned identity.", + }, + type: { + $ref: "src/spectral/test/resources/lro-provisioning-state-specified.json#/definitions/PrivateEndpointConnection", + }, + }, + required: ["type"], + }, + }, + } + return linter.run(oasDoc).then((results) => { + expect(results.length).toBe(4) + expect(results[0].path.join(".")).toBe("definitions.tags.properties.tags") + expect(results[1].path.join(".")).toBe("definitions.ThaOther.properties.tags") + expect(results[2].path.join(".")).toBe("definitions.ThisOther.properties.tags") + expect(results[3].path.join(".")).toBe("definitions.ActionGroupPatchBody.properties.tags") + expect(results[0].message).toBe(errorMessage) + expect(results[1].message).toBe(errorMessage) + expect(results[2].message).toBe(errorMessage) + expect(results[3].message).toBe(errorMessage) + }) +}) + +test("TagsAreTopLevelPropertiesOnly should find no errors", () => { + const oasDoc1 = { + swagger: "2.0", + definitions: { + type: "object", + source: { + type: "string", + }, + // top level property + tags: { + type: "object", + additionalProperties: { + type: "object", + params: { + type: "boolean", + }, + }, + }, + ManagedServiceIdentity: { + description: "Managed service identity (system assigned and/or user assigned identities)", + type: "object", + properties: { + principalId: { + readOnly: true, + format: "uuid", + type: "string", + description: + "The service principal ID of the system assigned identity. This property will only be provided for a system assigned identity.", + }, + tenantId: { + readOnly: true, + format: "uuid", + type: "string", + description: + "The tenant ID of the system assigned identity. This property will only be provided for a system assigned identity.", + }, + type: { + $ref: "src/spectral/test/resources/lro-provisioning-state-specified.json#/definitions/ManagedServiceIdentityWithDelegation", + }, + }, + required: ["type"], + }, + }, + } + return linter.run(oasDoc1).then((results) => { + expect(results.length).toBe(0) + }) +}) From e43457d916666f456ccd55699004addc5492fd4c Mon Sep 17 00:00:00 2001 From: Tejaswi Salaigari Date: Tue, 18 Jun 2024 11:12:41 -0500 Subject: [PATCH 02/10] addressed comments --- ...pLevelPropertiesOnly_2024-06-13-22-19.json | 2 +- docs/rules.md | 4 +- ...ags-are-not-allowed-for-proxy-resources.md | 74 ++++++++++++ docs/tags-are-top-level-properties-only.md | 57 --------- .../rulesets/generated/spectral/az-arm.js | 34 +++--- packages/rulesets/src/spectral/az-arm.ts | 8 +- ...ags-are-not-allowed-for-proxy-resources.ts | 29 +++++ .../tags-are-top-level-properties-only.ts | 22 ---- ...e-not-allowed-for-proxy-resources.test.ts} | 110 +++++------------- 9 files changed, 162 insertions(+), 178 deletions(-) create mode 100644 docs/tags-are-not-allowed-for-proxy-resources.md delete mode 100644 docs/tags-are-top-level-properties-only.md create mode 100644 packages/rulesets/src/spectral/functions/tags-are-not-allowed-for-proxy-resources.ts delete mode 100644 packages/rulesets/src/spectral/functions/tags-are-top-level-properties-only.ts rename packages/rulesets/src/spectral/test/{tags-are-top-level-properties-only.test.ts => tags-are-not-allowed-for-proxy-resources.test.ts} (58%) diff --git a/common/changes/@microsoft.azure/openapi-validator-rulesets/tejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json b/common/changes/@microsoft.azure/openapi-validator-rulesets/tejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json index d2242657d..939b13e08 100644 --- a/common/changes/@microsoft.azure/openapi-validator-rulesets/tejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json +++ b/common/changes/@microsoft.azure/openapi-validator-rulesets/tejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@microsoft.azure/openapi-validator-rulesets", - "comment": "Add TagsAreTopLevelPropertiesOnly rule to check if tags are defined as top-level property, not in the properties bag", + "comment": "Add TagsAreNotAllowedForProxyResources rule to check if tags are defined as top-level property, not in the properties bag", "type": "patch" } ], diff --git a/docs/rules.md b/docs/rules.md index c3b743b5e..d0480387c 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -1213,11 +1213,11 @@ Validates that system data is not defined in the properties bag, but rather as a Please refer to [system-data-in-properties-bag.md](./system-data-in-properties-bag.md) for details. -### TagsAreTopLevelPropertiesOnly +### TagsAreNotAllowedForProxyResources Validates that `tags` is not defined in the properties bag, but rather as a top-level property. -Please refer to [tags-are-top-level-properties-only.md](./tags-are-top-level-properties-only.md) for details. +Please refer to [tags-are-not-allowed-for-proxy-resources.md](./tags-are-not-allowed-for-proxy-resources.md) for details. ### TenantLevelAPIsNotAllowed diff --git a/docs/tags-are-not-allowed-for-proxy-resources.md b/docs/tags-are-not-allowed-for-proxy-resources.md new file mode 100644 index 000000000..bba8797da --- /dev/null +++ b/docs/tags-are-not-allowed-for-proxy-resources.md @@ -0,0 +1,74 @@ +# TagsAreNotAllowedForProxyResources + +## Category + +ARM Error + +## Applies to + +ARM OpenAPI(swagger) specs + +## Related ARM Guideline Code + +- RPC-Put-V1-30 + +## Description + +Validates that `tags` is not defined in the properties bag, but rather as a top-level property, +`tags` should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead. + +## How to fix the violation + +Ensure that any `tags` definitions are as top-level properties, not in the properties bag. + +### Valid/Good Example + +```json +"definitions": { + "Resource": { + "type": "object", + "properties": { + "type": "object", + // tope level properties + "tags": { + "type": "object", + "additionalProperties": { + "type": "object", + "params": { + "type": "boolean", + }, + } + }, + "location": { + "type": "string" + } + } + }, +} +``` + +### Invalid/Bad Example + +```json +"definitions": { + "Resource": { + "type": "string", + "properties": { + "type": "object", + "properties": { + "type": "object", + // Nested Properties + "tags": { + "type": "object", + "additionalProperties": { + "type": "object", + "params": { + "type": "boolean", + }, + } + }, + }, + } + } +} +``` \ No newline at end of file diff --git a/docs/tags-are-top-level-properties-only.md b/docs/tags-are-top-level-properties-only.md deleted file mode 100644 index 6a299261b..000000000 --- a/docs/tags-are-top-level-properties-only.md +++ /dev/null @@ -1,57 +0,0 @@ -# TagsAreTopLevelPropertiesOnly - -## Category - -ARM Error - -## Applies to - -ARM OpenAPI(swagger) specs - -## Related ARM Guideline Code - -- RPC-Put-V1-30 - -## Description - -Validates that `tags` is not defined in the properties bag, but rather as a top-level property. - -## How to fix the violation - -Ensure that any `tags` definitions are as top-level properties, not in the properties bag. - -### Valid/Good Example - -```json -"definitions": { - "tags": { - "type": "object", - "additionalProperties": { - "type": "object", - "params": { - "type": "boolean", - }, - } - }, - "properties": { - "type": "object", - "name": { - "type": "string" - } - } -} -``` - -### Invalid/Bad Example - -```json -"Resource": { - "properties": { - "properties": { - "systemData": { - "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/systemData", - } - } - } -} -``` diff --git a/packages/rulesets/generated/spectral/az-arm.js b/packages/rulesets/generated/spectral/az-arm.js index 59af6fdb3..6fcea7ef5 100644 --- a/packages/rulesets/generated/spectral/az-arm.js +++ b/packages/rulesets/generated/spectral/az-arm.js @@ -2718,19 +2718,25 @@ const systemDataInPropertiesBag = (definition, _opts, ctx) => { const TAGS = "tags"; const PROPERTIES = "properties"; -const ERROR_MESSAGE = "Tags must be defined as a top-level property, not in the properties bag."; -const tagsAreTopLevelPropertiesOnly = (definition, _opts, ctx) => { +const NestedPROPERTIES = "properties"; +const ERROR_MESSAGE = "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead."; +const tagsAreNotAllowedForProxyResources = (definition, _opts, ctx) => { const properties = getProperties(definition); - const path = deepFindObjectKeyPath(properties, TAGS); - if (path.length > 0) { - return [ - { - message: ERROR_MESSAGE, - path: _.concat(ctx.path, PROPERTIES, path[0]), - }, - ]; + const errors = []; + if ("tags" in properties && !("location" in properties)) { + errors.push({ + message: ERROR_MESSAGE, + path: _.concat(ctx.path, PROPERTIES, TAGS), + }); } - return []; + const deepProperties = deepFindObjectKeyPath(definition.properties.properties, TAGS); + if (deepProperties.length > 0) { + errors.push({ + message: ERROR_MESSAGE, + path: _.concat(ctx.path, PROPERTIES, NestedPROPERTIES, deepProperties[0]), + }); + } + return errors; }; const tenantLevelAPIsNotAllowed = (pathItems, _opts, ctx) => { @@ -3529,9 +3535,9 @@ const ruleset = { function: consistentResponseSchemaForPut, }, }, - TagsAreTopLevelPropertiesOnly: { + TagsAreNotAllowedForProxyResources: { rpcGuidelineCode: "RPC-Put-V1-30", - description: "Tags must be defined as a top-level property, not in the properties bag.", + description: "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead.", severity: "error", stagingOnly: true, message: "{{error}}", @@ -3539,7 +3545,7 @@ const ruleset = { formats: [oas2], given: ["$.definitions.*.properties^"], then: { - function: tagsAreTopLevelPropertiesOnly, + function: tagsAreNotAllowedForProxyResources, }, }, ParametersInPost: { diff --git a/packages/rulesets/src/spectral/az-arm.ts b/packages/rulesets/src/spectral/az-arm.ts index 48f22059d..d50350e79 100644 --- a/packages/rulesets/src/spectral/az-arm.ts +++ b/packages/rulesets/src/spectral/az-arm.ts @@ -47,7 +47,7 @@ import responseSchemaSpecifiedForSuccessStatusCode from "./functions/response-sc import { securityDefinitionsStructure } from "./functions/security-definitions-structure" import skuValidation from "./functions/sku-validation" import { systemDataInPropertiesBag } from "./functions/system-data-in-properties-bag" -import { tagsAreTopLevelPropertiesOnly } from "./functions/tags-are-top-level-properties-only" +import { tagsAreNotAllowedForProxyResources } from "./functions/tags-are-not-allowed-for-proxy-resources" import { tenantLevelAPIsNotAllowed } from "./functions/tenant-level-apis-not-allowed" import { trackedExtensionResourcesAreNotAllowed } from "./functions/tracked-extension-resources-are-not-allowed" import trackedResourceTagsPropertyInRequest from "./functions/trackedresource-tags-property-in-request" @@ -733,9 +733,9 @@ const ruleset: any = { }, // RPC Code: RPC-Put-V1-30 - TagsAreTopLevelPropertiesOnly: { + TagsAreNotAllowedForProxyResources: { rpcGuidelineCode: "RPC-Put-V1-30", - description: "Tags must be defined as a top-level property, not in the properties bag.", + description: "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead.", severity: "error", stagingOnly: true, message: "{{error}}", @@ -743,7 +743,7 @@ const ruleset: any = { formats: [oas2], given: ["$.definitions.*.properties^"], then: { - function: tagsAreTopLevelPropertiesOnly, + function: tagsAreNotAllowedForProxyResources, }, }, diff --git a/packages/rulesets/src/spectral/functions/tags-are-not-allowed-for-proxy-resources.ts b/packages/rulesets/src/spectral/functions/tags-are-not-allowed-for-proxy-resources.ts new file mode 100644 index 000000000..22223bbed --- /dev/null +++ b/packages/rulesets/src/spectral/functions/tags-are-not-allowed-for-proxy-resources.ts @@ -0,0 +1,29 @@ +import _ from "lodash" +import { deepFindObjectKeyPath, getProperties } from "./utils" + +const TAGS = "tags" +const PROPERTIES = "properties" +const NestedPROPERTIES = "properties" +const ERROR_MESSAGE = "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead." + +export const tagsAreNotAllowedForProxyResources = (definition: any, _opts: any, ctx: any) => { + const properties = getProperties(definition) + const errors = [] + + if ("tags" in properties && !("location" in properties)) { + errors.push({ + message: ERROR_MESSAGE, + path: _.concat(ctx.path, PROPERTIES, TAGS), + }) + } + + const deepProperties = deepFindObjectKeyPath(definition.properties.properties, TAGS) + if (deepProperties.length > 0) { + errors.push({ + message: ERROR_MESSAGE, + path: _.concat(ctx.path, PROPERTIES, NestedPROPERTIES, deepProperties[0]), + }) + } + + return errors +} diff --git a/packages/rulesets/src/spectral/functions/tags-are-top-level-properties-only.ts b/packages/rulesets/src/spectral/functions/tags-are-top-level-properties-only.ts deleted file mode 100644 index f9127c791..000000000 --- a/packages/rulesets/src/spectral/functions/tags-are-top-level-properties-only.ts +++ /dev/null @@ -1,22 +0,0 @@ -import _ from "lodash" -import { deepFindObjectKeyPath, getProperties } from "./utils" - -const TAGS = "tags" -const PROPERTIES = "properties" -const ERROR_MESSAGE = "Tags must be defined as a top-level property, not in the properties bag." - -export const tagsAreTopLevelPropertiesOnly = (definition: any, _opts: any, ctx: any) => { - const properties = getProperties(definition) - const path = deepFindObjectKeyPath(properties, TAGS) - - if (path.length > 0) { - return [ - { - message: ERROR_MESSAGE, - path: _.concat(ctx.path, PROPERTIES, path[0]), - }, - ] - } - - return [] -} diff --git a/packages/rulesets/src/spectral/test/tags-are-top-level-properties-only.test.ts b/packages/rulesets/src/spectral/test/tags-are-not-allowed-for-proxy-resources.test.ts similarity index 58% rename from packages/rulesets/src/spectral/test/tags-are-top-level-properties-only.test.ts rename to packages/rulesets/src/spectral/test/tags-are-not-allowed-for-proxy-resources.test.ts index 92da76f10..6d4ef1866 100644 --- a/packages/rulesets/src/spectral/test/tags-are-top-level-properties-only.test.ts +++ b/packages/rulesets/src/spectral/test/tags-are-not-allowed-for-proxy-resources.test.ts @@ -2,17 +2,17 @@ import { Spectral } from "@stoplight/spectral-core" import linterForRule from "./utils" let linter: Spectral -const errorMessage = "Tags must be defined as a top-level property, not in the properties bag." +const errorMessage = "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead." beforeAll(async () => { - linter = await linterForRule("TagsAreTopLevelPropertiesOnly") + linter = await linterForRule("TagsAreNotAllowedForProxyResources") return linter }) -test("TagsAreTopLevelPropertiesOnly should find errors", () => { +test("TagsAreNotAllowedForProxyResources should find errors", () => { const oasDoc = { swagger: "2.0", definitions: { - tags: { + Resources: { description: "This", type: "object", properties: { @@ -28,49 +28,26 @@ test("TagsAreTopLevelPropertiesOnly should find errors", () => { }, }, }, - That: { + ResourceIdentity: { description: "That", type: "object", properties: { - nonTags: { + type: "object", + properties: { type: "object", - additionalProperties: { + tags: { type: "object", - params: { - type: "boolean", + additionalProperties: { + type: "string", }, + description: "Resource tags", }, - }, - }, - }, - ThaOther: { - description: "ThaOther", - type: "object", - properties: { - tags: { - type: "object", - info: { - type: "String", - }, - }, - additionalProperties: { - type: "object", - params: { - type: "boolean", + location: { + type: "string", }, }, }, }, - Other: { - description: "Other object", - type: "object", - properties: { - type: "object", - additionalProperties: { - type: "string", - }, - }, - }, ThisOther: { description: "This", type: "object", @@ -78,15 +55,10 @@ test("TagsAreTopLevelPropertiesOnly should find errors", () => { type: "object", tags: { type: "object", - nonTags: { - type: "object", - additionalProperties: { - type: "object", - params: { - type: "boolean", - }, - }, + additionalProperties: { + type: "string", }, + description: "Resource tags", }, }, }, @@ -94,32 +66,21 @@ test("TagsAreTopLevelPropertiesOnly should find errors", () => { description: "A tenant action group object for the body of patch operations.", type: "object", properties: { - tags: { + type: "object", + properties: { type: "object", - additionalProperties: { + // nested tags + tags: { type: "string", }, - description: "Resource tags", - }, - identity: { - $ref: "#/definitions/ManagedServiceIdentity", }, }, }, - UserAssignedIdentitiy: { - title: "User-Assigned Identities", - description: - "The set of user assigned identities associated with the resource. The userAssignedIdentities dictionary keys will be ARM resource ids in the form: '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identityName}. The dictionary values can be empty objects ({}) in requests.", - type: "object", - additionalProperties: { - "x-nullable": true, - }, - }, ManagedServiceIdentity: { description: "Managed service identity (system assigned and/or user assigned identities)", type: "object", properties: { - principalId: { + tags: { readOnly: true, format: "uuid", type: "string", @@ -133,28 +94,26 @@ test("TagsAreTopLevelPropertiesOnly should find errors", () => { description: "The tenant ID of the system assigned identity. This property will only be provided for a system assigned identity.", }, - type: { - $ref: "src/spectral/test/resources/lro-provisioning-state-specified.json#/definitions/PrivateEndpointConnection", - }, }, - required: ["type"], }, }, } return linter.run(oasDoc).then((results) => { - expect(results.length).toBe(4) - expect(results[0].path.join(".")).toBe("definitions.tags.properties.tags") - expect(results[1].path.join(".")).toBe("definitions.ThaOther.properties.tags") + expect(results.length).toBe(5) + expect(results[0].path.join(".")).toBe("definitions.Resources.properties.tags") + expect(results[1].path.join(".")).toBe("definitions.ResourceIdentity.properties.properties.tags") expect(results[2].path.join(".")).toBe("definitions.ThisOther.properties.tags") - expect(results[3].path.join(".")).toBe("definitions.ActionGroupPatchBody.properties.tags") + expect(results[3].path.join(".")).toBe("definitions.ActionGroupPatchBody.properties.properties.tags") + expect(results[4].path.join(".")).toBe("definitions.ManagedServiceIdentity.properties.tags") expect(results[0].message).toBe(errorMessage) expect(results[1].message).toBe(errorMessage) expect(results[2].message).toBe(errorMessage) expect(results[3].message).toBe(errorMessage) + expect(results[4].message).toBe(errorMessage) }) }) -test("TagsAreTopLevelPropertiesOnly should find no errors", () => { +test("TagsAreNotAllowedForProxyResources should find no errors", () => { const oasDoc1 = { swagger: "2.0", definitions: { @@ -162,10 +121,9 @@ test("TagsAreTopLevelPropertiesOnly should find no errors", () => { source: { type: "string", }, - // top level property - tags: { + properties: { type: "object", - additionalProperties: { + noTags: { type: "object", params: { type: "boolean", @@ -176,25 +134,21 @@ test("TagsAreTopLevelPropertiesOnly should find no errors", () => { description: "Managed service identity (system assigned and/or user assigned identities)", type: "object", properties: { - principalId: { + tags: { readOnly: true, format: "uuid", type: "string", description: "The service principal ID of the system assigned identity. This property will only be provided for a system assigned identity.", }, - tenantId: { + location: { readOnly: true, format: "uuid", type: "string", description: "The tenant ID of the system assigned identity. This property will only be provided for a system assigned identity.", }, - type: { - $ref: "src/spectral/test/resources/lro-provisioning-state-specified.json#/definitions/ManagedServiceIdentityWithDelegation", - }, }, - required: ["type"], }, }, } From 6bc9e1bb2703f499ee28a3a439c59c66da919c85 Mon Sep 17 00:00:00 2001 From: Tejaswi Salaigari Date: Wed, 19 Jun 2024 14:19:01 -0500 Subject: [PATCH 03/10] addressed comments --- ...ejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json | 2 +- docs/rules.md | 2 +- docs/tags-are-not-allowed-for-proxy-resources.md | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/common/changes/@microsoft.azure/openapi-validator-rulesets/tejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json b/common/changes/@microsoft.azure/openapi-validator-rulesets/tejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json index 939b13e08..748ccbbe9 100644 --- a/common/changes/@microsoft.azure/openapi-validator-rulesets/tejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json +++ b/common/changes/@microsoft.azure/openapi-validator-rulesets/tejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@microsoft.azure/openapi-validator-rulesets", - "comment": "Add TagsAreNotAllowedForProxyResources rule to check if tags are defined as top-level property, not in the properties bag", + "comment": "Add TagsAreNotAllowedForProxyResources rule to check if tags are defined as properties bag for proxy resources", "type": "patch" } ], diff --git a/docs/rules.md b/docs/rules.md index d0480387c..92c1bef59 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -1215,7 +1215,7 @@ Please refer to [system-data-in-properties-bag.md](./system-data-in-properties-b ### TagsAreNotAllowedForProxyResources -Validates that `tags` is not defined in the properties bag, but rather as a top-level property. +`tags` should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead. Please refer to [tags-are-not-allowed-for-proxy-resources.md](./tags-are-not-allowed-for-proxy-resources.md) for details. diff --git a/docs/tags-are-not-allowed-for-proxy-resources.md b/docs/tags-are-not-allowed-for-proxy-resources.md index bba8797da..2b91774f7 100644 --- a/docs/tags-are-not-allowed-for-proxy-resources.md +++ b/docs/tags-are-not-allowed-for-proxy-resources.md @@ -14,12 +14,11 @@ ARM OpenAPI(swagger) specs ## Description -Validates that `tags` is not defined in the properties bag, but rather as a top-level property, `tags` should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead. ## How to fix the violation -Ensure that any `tags` definitions are as top-level properties, not in the properties bag. +Either remove the 'tags' property from the properties bag or consider using a tracked resource. ### Valid/Good Example From f11e4a157c21fe8843e034c29a2aa8189d74d3fa Mon Sep 17 00:00:00 2001 From: Tejaswi Salaigari Date: Thu, 20 Jun 2024 15:35:24 -0500 Subject: [PATCH 04/10] addressed the comment by removing the change log file --- ...tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json | 10 ---------- docs/tags-are-not-allowed-for-proxy-resources.md | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 common/changes/@microsoft.azure/openapi-validator-rulesets/tejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json diff --git a/common/changes/@microsoft.azure/openapi-validator-rulesets/tejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json b/common/changes/@microsoft.azure/openapi-validator-rulesets/tejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json deleted file mode 100644 index 748ccbbe9..000000000 --- a/common/changes/@microsoft.azure/openapi-validator-rulesets/tejaswis-tagsAreTopLevelPropertiesOnly_2024-06-13-22-19.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@microsoft.azure/openapi-validator-rulesets", - "comment": "Add TagsAreNotAllowedForProxyResources rule to check if tags are defined as properties bag for proxy resources", - "type": "patch" - } - ], - "packageName": "@microsoft.azure/openapi-validator-rulesets" -} \ No newline at end of file diff --git a/docs/tags-are-not-allowed-for-proxy-resources.md b/docs/tags-are-not-allowed-for-proxy-resources.md index 2b91774f7..a17e302e8 100644 --- a/docs/tags-are-not-allowed-for-proxy-resources.md +++ b/docs/tags-are-not-allowed-for-proxy-resources.md @@ -28,7 +28,7 @@ Either remove the 'tags' property from the properties bag or consider using a tr "type": "object", "properties": { "type": "object", - // tope level properties + // top level properties "tags": { "type": "object", "additionalProperties": { From 1bf62a10dc577d0bb808fe7f234ba0a14d94e572 Mon Sep 17 00:00:00 2001 From: Tejaswi Salaigari Date: Mon, 24 Jun 2024 20:18:28 -0500 Subject: [PATCH 05/10] addressed comments --- docs/rules.md | 4 ++-- ... => tags-not-allowed-in-properties-bag.md} | 24 +++++++++---------- .../rulesets/generated/spectral/az-arm.js | 12 +++++----- packages/rulesets/src/spectral/az-arm.ts | 6 ++--- ... => tags-not-allowed-in-properties-bag.ts} | 8 +++---- ...ags-not-allowed-in-properties-bag.test.ts} | 6 ++--- 6 files changed, 30 insertions(+), 30 deletions(-) rename docs/{tags-are-not-allowed-for-proxy-resources.md => tags-not-allowed-in-properties-bag.md} (71%) rename packages/rulesets/src/spectral/functions/{tags-are-not-allowed-for-proxy-resources.ts => tags-not-allowed-in-properties-bag.ts} (74%) rename packages/rulesets/src/spectral/test/{tags-are-not-allowed-for-proxy-resources.test.ts => tags-not-allowed-in-properties-bag.test.ts} (95%) diff --git a/docs/rules.md b/docs/rules.md index 3d7e079b7..a227a74d1 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -1214,11 +1214,11 @@ Validates that system data is not defined in the properties bag, but rather as a Please refer to [system-data-in-properties-bag.md](./system-data-in-properties-bag.md) for details. -### TagsAreNotAllowedForProxyResources +### TagsNotAllowedInPropertiesBag `tags` should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead. -Please refer to [tags-are-not-allowed-for-proxy-resources.md](./tags-are-not-allowed-for-proxy-resources.md) for details. +Please refer to [tags-not-allowed-in-properties-bag.md](./tags-not-allowed-in-properties-bag.md) for details. ### TenantLevelAPIsNotAllowed diff --git a/docs/tags-are-not-allowed-for-proxy-resources.md b/docs/tags-not-allowed-in-properties-bag.md similarity index 71% rename from docs/tags-are-not-allowed-for-proxy-resources.md rename to docs/tags-not-allowed-in-properties-bag.md index a17e302e8..124a42fd7 100644 --- a/docs/tags-are-not-allowed-for-proxy-resources.md +++ b/docs/tags-not-allowed-in-properties-bag.md @@ -1,4 +1,4 @@ -# TagsAreNotAllowedForProxyResources +# TagsNotAllowedInPropertiesBag ## Category @@ -18,7 +18,7 @@ ARM OpenAPI(swagger) specs ## How to fix the violation -Either remove the 'tags' property from the properties bag or consider using a tracked resource. +Either remove the `tags` from the properties bag or consider using a Tracked resource, which supports top-level `tags`. ### Valid/Good Example @@ -27,12 +27,12 @@ Either remove the 'tags' property from the properties bag or consider using a tr "Resource": { "type": "object", "properties": { - "type": "object", - // top level properties - "tags": { "type": "object", - "additionalProperties": { + // top-level properties + "tags": { "type": "object", + "additionalProperties": { + "type": "object", "params": { "type": "boolean", }, @@ -52,17 +52,17 @@ Either remove the 'tags' property from the properties bag or consider using a tr "definitions": { "Resource": { "type": "string", - "properties": { + "properties": { "type": "object", - "properties": { + "properties": { "type": "object", - // Nested Properties - "tags": { + // Nested Properties + "tags": { "type": "object", "additionalProperties": { "type": "object", - "params": { - "type": "boolean", + "params": { + "type": "boolean", }, } }, diff --git a/packages/rulesets/generated/spectral/az-arm.js b/packages/rulesets/generated/spectral/az-arm.js index 6fcea7ef5..8eb0e5171 100644 --- a/packages/rulesets/generated/spectral/az-arm.js +++ b/packages/rulesets/generated/spectral/az-arm.js @@ -2720,7 +2720,7 @@ const TAGS = "tags"; const PROPERTIES = "properties"; const NestedPROPERTIES = "properties"; const ERROR_MESSAGE = "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead."; -const tagsAreNotAllowedForProxyResources = (definition, _opts, ctx) => { +const tagsNotAllowedInPropertiesBag = (definition, _opts, ctx) => { const properties = getProperties(definition); const errors = []; if ("tags" in properties && !("location" in properties)) { @@ -2729,11 +2729,11 @@ const tagsAreNotAllowedForProxyResources = (definition, _opts, ctx) => { path: _.concat(ctx.path, PROPERTIES, TAGS), }); } - const deepProperties = deepFindObjectKeyPath(definition.properties.properties, TAGS); - if (deepProperties.length > 0) { + const deepPropertiesTags = deepFindObjectKeyPath(definition.properties.properties, TAGS); + if (deepPropertiesTags.length > 0) { errors.push({ message: ERROR_MESSAGE, - path: _.concat(ctx.path, PROPERTIES, NestedPROPERTIES, deepProperties[0]), + path: _.concat(ctx.path, PROPERTIES, NestedPROPERTIES, deepPropertiesTags[0]), }); } return errors; @@ -3535,7 +3535,7 @@ const ruleset = { function: consistentResponseSchemaForPut, }, }, - TagsAreNotAllowedForProxyResources: { + TagsNotAllowedInPropertiesBag: { rpcGuidelineCode: "RPC-Put-V1-30", description: "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead.", severity: "error", @@ -3545,7 +3545,7 @@ const ruleset = { formats: [oas2], given: ["$.definitions.*.properties^"], then: { - function: tagsAreNotAllowedForProxyResources, + function: tagsNotAllowedInPropertiesBag, }, }, ParametersInPost: { diff --git a/packages/rulesets/src/spectral/az-arm.ts b/packages/rulesets/src/spectral/az-arm.ts index d50350e79..3ad6828af 100644 --- a/packages/rulesets/src/spectral/az-arm.ts +++ b/packages/rulesets/src/spectral/az-arm.ts @@ -47,7 +47,7 @@ import responseSchemaSpecifiedForSuccessStatusCode from "./functions/response-sc import { securityDefinitionsStructure } from "./functions/security-definitions-structure" import skuValidation from "./functions/sku-validation" import { systemDataInPropertiesBag } from "./functions/system-data-in-properties-bag" -import { tagsAreNotAllowedForProxyResources } from "./functions/tags-are-not-allowed-for-proxy-resources" +import { tagsNotAllowedInPropertiesBag } from "./functions/tags-not-allowed-in-properties-bag" import { tenantLevelAPIsNotAllowed } from "./functions/tenant-level-apis-not-allowed" import { trackedExtensionResourcesAreNotAllowed } from "./functions/tracked-extension-resources-are-not-allowed" import trackedResourceTagsPropertyInRequest from "./functions/trackedresource-tags-property-in-request" @@ -733,7 +733,7 @@ const ruleset: any = { }, // RPC Code: RPC-Put-V1-30 - TagsAreNotAllowedForProxyResources: { + TagsNotAllowedInPropertiesBag: { rpcGuidelineCode: "RPC-Put-V1-30", description: "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead.", severity: "error", @@ -743,7 +743,7 @@ const ruleset: any = { formats: [oas2], given: ["$.definitions.*.properties^"], then: { - function: tagsAreNotAllowedForProxyResources, + function: tagsNotAllowedInPropertiesBag, }, }, diff --git a/packages/rulesets/src/spectral/functions/tags-are-not-allowed-for-proxy-resources.ts b/packages/rulesets/src/spectral/functions/tags-not-allowed-in-properties-bag.ts similarity index 74% rename from packages/rulesets/src/spectral/functions/tags-are-not-allowed-for-proxy-resources.ts rename to packages/rulesets/src/spectral/functions/tags-not-allowed-in-properties-bag.ts index 22223bbed..3b0132b9a 100644 --- a/packages/rulesets/src/spectral/functions/tags-are-not-allowed-for-proxy-resources.ts +++ b/packages/rulesets/src/spectral/functions/tags-not-allowed-in-properties-bag.ts @@ -6,7 +6,7 @@ const PROPERTIES = "properties" const NestedPROPERTIES = "properties" const ERROR_MESSAGE = "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead." -export const tagsAreNotAllowedForProxyResources = (definition: any, _opts: any, ctx: any) => { +export const tagsNotAllowedInPropertiesBag = (definition: any, _opts: any, ctx: any) => { const properties = getProperties(definition) const errors = [] @@ -17,11 +17,11 @@ export const tagsAreNotAllowedForProxyResources = (definition: any, _opts: any, }) } - const deepProperties = deepFindObjectKeyPath(definition.properties.properties, TAGS) - if (deepProperties.length > 0) { + const deepPropertiesTags = deepFindObjectKeyPath(definition.properties.properties, TAGS) + if (deepPropertiesTags.length > 0) { errors.push({ message: ERROR_MESSAGE, - path: _.concat(ctx.path, PROPERTIES, NestedPROPERTIES, deepProperties[0]), + path: _.concat(ctx.path, PROPERTIES, NestedPROPERTIES, deepPropertiesTags[0]), }) } diff --git a/packages/rulesets/src/spectral/test/tags-are-not-allowed-for-proxy-resources.test.ts b/packages/rulesets/src/spectral/test/tags-not-allowed-in-properties-bag.test.ts similarity index 95% rename from packages/rulesets/src/spectral/test/tags-are-not-allowed-for-proxy-resources.test.ts rename to packages/rulesets/src/spectral/test/tags-not-allowed-in-properties-bag.test.ts index 6d4ef1866..acb4b2942 100644 --- a/packages/rulesets/src/spectral/test/tags-are-not-allowed-for-proxy-resources.test.ts +++ b/packages/rulesets/src/spectral/test/tags-not-allowed-in-properties-bag.test.ts @@ -4,11 +4,11 @@ import linterForRule from "./utils" let linter: Spectral const errorMessage = "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead." beforeAll(async () => { - linter = await linterForRule("TagsAreNotAllowedForProxyResources") + linter = await linterForRule("TagsNotAllowedInPropertiesBag") return linter }) -test("TagsAreNotAllowedForProxyResources should find errors", () => { +test("TagsNotAllowedInPropertiesBag should find errors", () => { const oasDoc = { swagger: "2.0", definitions: { @@ -113,7 +113,7 @@ test("TagsAreNotAllowedForProxyResources should find errors", () => { }) }) -test("TagsAreNotAllowedForProxyResources should find no errors", () => { +test("TagsNotAllowedInPropertiesBag should find no errors", () => { const oasDoc1 = { swagger: "2.0", definitions: { From 2df2d89b3bcaa75ab51c11f48a6b9cae71724ce3 Mon Sep 17 00:00:00 2001 From: Tejaswi Salaigari Date: Fri, 2 Aug 2024 10:19:09 -0500 Subject: [PATCH 06/10] modified rule name --- packages/rulesets/generated/spectral/az-arm.js | 6 +++--- packages/rulesets/src/spectral/az-arm.ts | 6 +++--- ...s-bag.ts => tags-are-not-allowed-for-proxy-resources.ts} | 2 +- ....ts => tags-are-not-allowed-for-proxy-resources.test.ts} | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) rename packages/rulesets/src/spectral/functions/{tags-not-allowed-in-properties-bag.ts => tags-are-not-allowed-for-proxy-resources.ts} (89%) rename packages/rulesets/src/spectral/test/{tags-not-allowed-in-properties-bag.test.ts => tags-are-not-allowed-for-proxy-resources.test.ts} (95%) diff --git a/packages/rulesets/generated/spectral/az-arm.js b/packages/rulesets/generated/spectral/az-arm.js index e510b2c5d..ca96c048b 100644 --- a/packages/rulesets/generated/spectral/az-arm.js +++ b/packages/rulesets/generated/spectral/az-arm.js @@ -2720,7 +2720,7 @@ const TAGS = "tags"; const PROPERTIES = "properties"; const NestedPROPERTIES = "properties"; const ERROR_MESSAGE = "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead."; -const tagsNotAllowedInPropertiesBag = (definition, _opts, ctx) => { +const tagsAreNotAllowedForProxyResources = (definition, _opts, ctx) => { const properties = getProperties(definition); const errors = []; if ("tags" in properties && !("location" in properties)) { @@ -3535,7 +3535,7 @@ const ruleset = { function: consistentResponseSchemaForPut, }, }, - TagsNotAllowedInPropertiesBag: { + TagsAreNotAllowedForProxyResources: { rpcGuidelineCode: "RPC-Put-V1-30", description: "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead.", severity: "error", @@ -3545,7 +3545,7 @@ const ruleset = { formats: [oas2], given: ["$.definitions.*.properties^"], then: { - function: tagsNotAllowedInPropertiesBag, + function: tagsAreNotAllowedForProxyResources, }, }, ParametersInPost: { diff --git a/packages/rulesets/src/spectral/az-arm.ts b/packages/rulesets/src/spectral/az-arm.ts index ca41574d5..9a5d30aea 100644 --- a/packages/rulesets/src/spectral/az-arm.ts +++ b/packages/rulesets/src/spectral/az-arm.ts @@ -47,7 +47,7 @@ import responseSchemaSpecifiedForSuccessStatusCode from "./functions/response-sc import { securityDefinitionsStructure } from "./functions/security-definitions-structure" import skuValidation from "./functions/sku-validation" import { systemDataInPropertiesBag } from "./functions/system-data-in-properties-bag" -import { tagsNotAllowedInPropertiesBag } from "./functions/tags-not-allowed-in-properties-bag" +import { tagsAreNotAllowedForProxyResources } from "./functions/tags-are-not-allowed-for-proxy-resources" import { tenantLevelAPIsNotAllowed } from "./functions/tenant-level-apis-not-allowed" import { trackedExtensionResourcesAreNotAllowed } from "./functions/tracked-extension-resources-are-not-allowed" import trackedResourceTagsPropertyInRequest from "./functions/trackedresource-tags-property-in-request" @@ -738,7 +738,7 @@ const ruleset: any = { }, // RPC Code: RPC-Put-V1-30 - TagsNotAllowedInPropertiesBag: { + TagsAreNotAllowedForProxyResources: { rpcGuidelineCode: "RPC-Put-V1-30", description: "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead.", severity: "error", @@ -748,7 +748,7 @@ const ruleset: any = { formats: [oas2], given: ["$.definitions.*.properties^"], then: { - function: tagsNotAllowedInPropertiesBag, + function: tagsAreNotAllowedForProxyResources, }, }, diff --git a/packages/rulesets/src/spectral/functions/tags-not-allowed-in-properties-bag.ts b/packages/rulesets/src/spectral/functions/tags-are-not-allowed-for-proxy-resources.ts similarity index 89% rename from packages/rulesets/src/spectral/functions/tags-not-allowed-in-properties-bag.ts rename to packages/rulesets/src/spectral/functions/tags-are-not-allowed-for-proxy-resources.ts index 3b0132b9a..de0b27709 100644 --- a/packages/rulesets/src/spectral/functions/tags-not-allowed-in-properties-bag.ts +++ b/packages/rulesets/src/spectral/functions/tags-are-not-allowed-for-proxy-resources.ts @@ -6,7 +6,7 @@ const PROPERTIES = "properties" const NestedPROPERTIES = "properties" const ERROR_MESSAGE = "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead." -export const tagsNotAllowedInPropertiesBag = (definition: any, _opts: any, ctx: any) => { +export const tagsAreNotAllowedForProxyResources = (definition: any, _opts: any, ctx: any) => { const properties = getProperties(definition) const errors = [] diff --git a/packages/rulesets/src/spectral/test/tags-not-allowed-in-properties-bag.test.ts b/packages/rulesets/src/spectral/test/tags-are-not-allowed-for-proxy-resources.test.ts similarity index 95% rename from packages/rulesets/src/spectral/test/tags-not-allowed-in-properties-bag.test.ts rename to packages/rulesets/src/spectral/test/tags-are-not-allowed-for-proxy-resources.test.ts index acb4b2942..6d4ef1866 100644 --- a/packages/rulesets/src/spectral/test/tags-not-allowed-in-properties-bag.test.ts +++ b/packages/rulesets/src/spectral/test/tags-are-not-allowed-for-proxy-resources.test.ts @@ -4,11 +4,11 @@ import linterForRule from "./utils" let linter: Spectral const errorMessage = "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead." beforeAll(async () => { - linter = await linterForRule("TagsNotAllowedInPropertiesBag") + linter = await linterForRule("TagsAreNotAllowedForProxyResources") return linter }) -test("TagsNotAllowedInPropertiesBag should find errors", () => { +test("TagsAreNotAllowedForProxyResources should find errors", () => { const oasDoc = { swagger: "2.0", definitions: { @@ -113,7 +113,7 @@ test("TagsNotAllowedInPropertiesBag should find errors", () => { }) }) -test("TagsNotAllowedInPropertiesBag should find no errors", () => { +test("TagsAreNotAllowedForProxyResources should find no errors", () => { const oasDoc1 = { swagger: "2.0", definitions: { From 5d8fce2f5c945d39c982495e20803e6fae77be00 Mon Sep 17 00:00:00 2001 From: Tejaswi Salaigari Date: Fri, 2 Aug 2024 10:20:11 -0500 Subject: [PATCH 07/10] modified doc file --- docs/rules.md | 4 ++-- ...ies-bag.md => tags-are-not-allowed-for-proxy-resources.md} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename docs/{tags-not-allowed-in-properties-bag.md => tags-are-not-allowed-for-proxy-resources.md} (97%) diff --git a/docs/rules.md b/docs/rules.md index 7304b0948..e19770dc7 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -1214,11 +1214,11 @@ Validates that system data is not defined in the properties bag, but rather as a Please refer to [system-data-in-properties-bag.md](./system-data-in-properties-bag.md) for details. -### TagsNotAllowedInPropertiesBag +### TagsAreNotAllowedForProxyResources `tags` should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead. -Please refer to [tags-not-allowed-in-properties-bag.md](./tags-not-allowed-in-properties-bag.md) for details. +Please refer to [tags-are-not-allowed-for-proxy-resources.md](./tags-are-not-allowed-for-proxy-resources.md) for details. ### TenantLevelAPIsNotAllowed diff --git a/docs/tags-not-allowed-in-properties-bag.md b/docs/tags-are-not-allowed-for-proxy-resources.md similarity index 97% rename from docs/tags-not-allowed-in-properties-bag.md rename to docs/tags-are-not-allowed-for-proxy-resources.md index 124a42fd7..d2c5edde0 100644 --- a/docs/tags-not-allowed-in-properties-bag.md +++ b/docs/tags-are-not-allowed-for-proxy-resources.md @@ -1,4 +1,4 @@ -# TagsNotAllowedInPropertiesBag +# TagsAreNotAllowedForProxyResources ## Category From 1972d1241def09e93ca43b4d7ed39dfb5ed1ff17 Mon Sep 17 00:00:00 2001 From: Tejaswi Salaigari Date: Mon, 12 Aug 2024 16:07:42 -0500 Subject: [PATCH 08/10] Update az-arm.ts with RPC code --- packages/rulesets/src/spectral/az-arm.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rulesets/src/spectral/az-arm.ts b/packages/rulesets/src/spectral/az-arm.ts index 9a5d30aea..d44163c69 100644 --- a/packages/rulesets/src/spectral/az-arm.ts +++ b/packages/rulesets/src/spectral/az-arm.ts @@ -737,9 +737,9 @@ const ruleset: any = { }, }, - // RPC Code: RPC-Put-V1-30 + // RPC Code: RPC-Put-V1-31 TagsAreNotAllowedForProxyResources: { - rpcGuidelineCode: "RPC-Put-V1-30", + rpcGuidelineCode: "RPC-Put-V1-31", description: "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead.", severity: "error", stagingOnly: true, From a0bbb1d765b97a576121de173758f616a8d9738a Mon Sep 17 00:00:00 2001 From: Tejaswi Salaigari Date: Mon, 12 Aug 2024 16:08:30 -0500 Subject: [PATCH 09/10] Update tags-are-not-allowed-for-proxy-resources.md --- docs/tags-are-not-allowed-for-proxy-resources.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tags-are-not-allowed-for-proxy-resources.md b/docs/tags-are-not-allowed-for-proxy-resources.md index d2c5edde0..4a1bb13c9 100644 --- a/docs/tags-are-not-allowed-for-proxy-resources.md +++ b/docs/tags-are-not-allowed-for-proxy-resources.md @@ -10,7 +10,7 @@ ARM OpenAPI(swagger) specs ## Related ARM Guideline Code -- RPC-Put-V1-30 +- RPC-Put-V1-31 ## Description @@ -70,4 +70,4 @@ Either remove the `tags` from the properties bag or consider using a Tracked res } } } -``` \ No newline at end of file +``` From 13482716ec7491128904f70568e768473d5f2c25 Mon Sep 17 00:00:00 2001 From: Tejaswi Salaigari Date: Mon, 12 Aug 2024 16:18:08 -0500 Subject: [PATCH 10/10] updated RPC rule code --- packages/rulesets/generated/spectral/az-arm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rulesets/generated/spectral/az-arm.js b/packages/rulesets/generated/spectral/az-arm.js index a465216e0..171c78d8a 100644 --- a/packages/rulesets/generated/spectral/az-arm.js +++ b/packages/rulesets/generated/spectral/az-arm.js @@ -3549,7 +3549,7 @@ const ruleset = { }, }, TagsAreNotAllowedForProxyResources: { - rpcGuidelineCode: "RPC-Put-V1-30", + rpcGuidelineCode: "RPC-Put-V1-31", description: "Tags should not be specified in the properties bag for proxy resources. Consider using a Tracked resource instead.", severity: "error", stagingOnly: true,