Skip to content

Commit

Permalink
Cleanup doc links in rules (#3152)
Browse files Browse the repository at this point in the history
  • Loading branch information
kddejong authored Apr 18, 2024
1 parent d7af638 commit e95304e
Show file tree
Hide file tree
Showing 36 changed files with 322 additions and 269 deletions.
75 changes: 65 additions & 10 deletions docs/cfn-schema-specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,70 @@ The core linting of `cfn-lint` is based on the [CloudFormation resource provider
Resource provider schemas are based on [JSON Schema](https://json-schema.org) and include modifications for the service to work with CloudFormation.

## Rules based on the Specifications

There are multiple rules that are based on information from the specification files. Every keyword in the [draft-07](https://json-schema.org/draft-07/json-schema-release-notes) are accounted for by cfn-lint. In a lot of scenarios we will remap those validators to cfn-lint rule IDs so the rules can be suppressed as needed.

## Changes to JSON schema validation

To improve the experience of validation we have made modifications to standard JSON schema so that it works better with CloudFormation.

### Type checking

CloudFormation allows types to work interchangeably as long as a conversion can be done (Example: "10" and 10 are equivalent). As a result we have modified type checking to validate the values are of the right type.

## Grouping functions

CloudFormation allows for a value of a property to be `{"Ref": "AWS:NoValue"}` which is equivalent to that property not being specified. JSON schema validators that work on a set of properties (object or array) are validated after the properties have been cleaned of these no values. This will allow validators like required and dependencies to work as intended.

### Intrinsic functions

When resource provider schemas are created they do not account for CloudFormation [intrinsic functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html). cfn-lint will account for these intrinsic functions by validating the structure of the function. Additionally, if possible, the value will be resolved (Example: `{"Ref": "AWS::Region"}` will resolve to "us-east-1") and that value will be validated against the schema.

## Extending JSON schema validation

### Extending the schemas with AWS types

Certain resource properties represent a type that is common across many resource types (example: availaibility zones, AMIs, VPCs, IAM identity policies, etc.). To provide common validation of these types we have extended the resource provider schemas with a type of `awsType` the value for the keyword is the type name. For a list of supported types go here.

### Extending the schemas with more JSON schemas

Resource types may have complex rules to define what a valid resource configuration is (example: for RDS the properties you need to specify can change based on the engine and if you are restoring from a snapshot). cfn-lint extends the resource provider schema with the keyworkd `cfnLint` which will validate the appropriate level against additional schema documents. This mechanism allows cfn-lint rule writers to create a new rule ID for these additional schemas which then allow users of cfn-lint to disable these validations as needed.

### Extending the schemas with new keywords

To make schema writing easier across hundereds of resources we have extend the schemas to include some additional keywords. While these keywords can be covered under the JSON schema they have to be done with a combination of `if`s, `onlyOne`s, `anyOf`s, etc. By using these keywords we can extend the schema for common scenarios when writing CloudFormation schemas.

#### pattern

_pattern_ keyword is used to validate a string against a regular expression. [JSON Schema docs](https://json-schema.org/understanding-json-schema/reference/string#regexp)

#### enum

_enum_ is used to restrict a value to a fixed set of values. [JSON Schema docs](https://json-schema.org/understanding-json-schema/reference/string#enum)

#### number range

_minimum_ and _maximum_ is used to define the inclusive range for a number or integer.
_exclusiveMinimum_ and _exclusiveMaximum_ is used to define the exlusive range for a number or integer.

#### array length

_minItems_ and _maxItems_ is used to provide the inclusive length of an array.

#### properties

_properties_ provides the key names and a value that represents the schema to validate the property for an object. [JSON Schema Docs](https://json-schema.org/understanding-json-schema/reference/object#properties)

#### required

_required_ defines a list of required properties. [JSON Schema docs](https://json-schema.org/understanding-json-schema/reference/object#required)

#### requiredXor
*requiredXor* is used to define when only one property from a set properties is required.

_requiredXor_ is used to define when only one property from a set properties is required.

On the following defined object

```json
{
"properties": {
Expand All @@ -44,13 +79,17 @@ On the following defined object
"additionalProperties": false
}
```

The cfn-lint schema

```json
{
"requiredXor": ["a", "b", "c"]
}
```

is equivalent to the JSON schema

```json
{
"oneOf": [
Expand All @@ -68,9 +107,11 @@ is equivalent to the JSON schema
```

#### propertiesNand
*propertiesNand* is used to define when none or only one property from a set properties can be defined.

_propertiesNand_ is used to define when none or only one property from a set properties can be defined.

On the following defined object

```json
{
"properties": {
Expand All @@ -83,12 +124,15 @@ On the following defined object
```

The cfn-lint schema

```json
{
"propertiesNand": ["a", "b", "c"]
}
```

is equivalent to the JSON schema

```json
{
"oneOf": [
Expand All @@ -102,23 +146,26 @@ is equivalent to the JSON schema
"required": ["c"]
},
{
"properties": {
"a": false,
"b": false,
"c": false
}
"properties": {
"a": false,
"b": false,
"c": false
}
}
]
}
```

#### dependentRequired
*dependentRequired* has been backported into cfn-lint. You can read the definition [here](https://json-schema.org/understanding-json-schema/reference/conditionals#dependentRequired)

_dependentRequired_ has been backported into cfn-lint. You can read the definition [here](https://json-schema.org/understanding-json-schema/reference/conditionals#dependentRequired)

#### dependentExcluded
*dependentExcluded* is the opposite of dependentRequired. The list of properties should not be specified when the key property is specified.

_dependentExcluded_ is the opposite of dependentRequired. The list of properties should not be specified when the key property is specified.

On the following defined object

```json
{
"properties": {
Expand All @@ -131,14 +178,17 @@ On the following defined object
```

The cfn-lint schema

```json
{
"dependentExcluded": {
"a": ["b", "c"]
}
}
```

is equivalent to the JSON schema

```json
{
"dependencies": {
Expand All @@ -153,4 +203,9 @@ is equivalent to the JSON schema
```

#### prefixItems
*prefixItems* is similar to the definition of [prefixItems](https://json-schema.org/understanding-json-schema/reference/array#tupleValidation) but doesn't actually do the prefix. The current resource schema doesn't support [items](https://json-schema.org/understanding-json-schema/reference/array#items) being an array. We use `prefixItems` to validate array items where ordering matters.

_prefixItems_ is similar to the definition of [prefixItems](https://json-schema.org/understanding-json-schema/reference/array#tupleValidation) but doesn't actually do the prefix. The current resource schema doesn't support [items](https://json-schema.org/understanding-json-schema/reference/array#items) being an array. We use `prefixItems` to validate array items where ordering matters.

#### type

_type_ specifies the data type for a schema. [JSON Schema docs](https://json-schema.org/understanding-json-schema/reference/type)
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from cfnlint.rules import CloudFormationLintRule


class AllowedValue(CloudFormationLintRule):
class Enum(CloudFormationLintRule):
"""Check if parameters have a valid value"""

id = "W2030"
Expand All @@ -16,7 +16,7 @@ class AllowedValue(CloudFormationLintRule):
"Check if parameters have a valid value in case of an enumator. The Parameter's"
" allowed values is based on the usages in property (Ref)"
)
source_url = "https://github.com/aws-cloudformation/cfn-python-lint/blob/main/docs/cfn-resource-specification.md#allowedvalue"
source_url = "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/cfn-schema-specification.md#enum"
tags = ["parameters", "resources", "property", "allowed value"]

# This rule is triggered from the equivalent rule E3030
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
from cfnlint.rules import CloudFormationLintRule


class NumberSize(CloudFormationLintRule):
class NumberRange(CloudFormationLintRule):
"""Check if a Number has a length within the limit"""

id = "W3034"
shortdesc = "Check if a number is between min and max"
description = (
"Check numbers (integers and floats) for its value being between the minimum"
"Check numbers and integers for its value being between the minimum"
" and maximum"
)
source_url = "https://github.com/awslabs/cfn-python-lint/blob/main/docs/cfn-resource-specification.md#allowedpattern"
source_url = "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/cfn-schema-specification.md#number-size"
tags = ["resources", "property", "number", "size"]

def validate(self, validator, m, instance, schema, fn):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from cfnlint.rules import CloudFormationLintRule


class AllowedPattern(CloudFormationLintRule):
class Pattern(CloudFormationLintRule):
"""Check if parameters have a valid value"""

id = "W2031"
Expand All @@ -16,8 +16,8 @@ class AllowedPattern(CloudFormationLintRule):
"Check if parameters have a valid value in a pattern. The Parameter's allowed"
" pattern is based on the usages in property (Ref)"
)
source_url = "https://github.com/aws-cloudformation/cfn-python-lint/blob/main/docs/cfn-resource-specification.md#allowedpattern"
tags = ["parameters", "resources", "property", "allowed pattern"]
source_url = "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/cfn-schema-specification.md#pattern"
tags = ["parameters", "resources", "property", "pattern"]

# This rule is triggered from the equivalent rule E3031
# the values are fed from there and we adjust the error outputs
Expand Down
19 changes: 19 additions & 0 deletions src/cfnlint/rules/resources/properties/ArrayLength.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from cfnlint.rules import CloudFormationLintRule


class ArrayLength(CloudFormationLintRule):
"""Check if List has a size within the limit"""

id = "E3032"
shortdesc = "Check if a array has between min and max number of values specified"
description = (
"Check array for the number of items in the list to validate they are between"
" the minimum and maximum"
)
source_url = "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/cfn-schema-specification.md#arraylength"
tags = ["resources", "property", "array", "length"]
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ class DependentExcluded(CloudFormationLintRule):
description = (
"When certain properties are specified other properties should not be included"
)
source_url = "https://github.com/aws-cloudformation/cfn-python-lint/blob/main/docs/cfn-resource-specification.md"
source_url = "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/cfn-schema-specification.md#dependentexcluded"
tags = ["resources"]
4 changes: 2 additions & 2 deletions src/cfnlint/rules/resources/properties/DependentRequired.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from cfnlint.rules import CloudFormationLintRule


class DependentExcluded(CloudFormationLintRule):
class DependentRequired(CloudFormationLintRule):
"""Check Required Resource Configuration"""

id = "E3021"
Expand All @@ -18,5 +18,5 @@ class DependentExcluded(CloudFormationLintRule):
"When certain properties are specified it results "
"in other properties to be required"
)
source_url = "https://github.com/aws-cloudformation/cfn-python-lint/blob/main/docs/cfn-resource-specification.md#pr"
source_url = "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/cfn-schema-specification.md#dependentrequired"
tags = ["resources"]
2 changes: 1 addition & 1 deletion src/cfnlint/rules/resources/properties/Enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Enum(CloudFormationLintRule):
id = "E3030"
shortdesc = "Check if properties have a valid value"
description = "Check if properties have a valid value in case of an enumator"
source_url = "https://github.com/aws-cloudformation/cfn-python-lint/blob/main/docs/cfn-resource-specification.md#allowedvalue"
source_url = "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/cfn-schema-specification.md#enum"
tags = ["resources", "property", "allowed value"]
child_rules = {
"W2030": None,
Expand Down
19 changes: 0 additions & 19 deletions src/cfnlint/rules/resources/properties/ListSize.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from cfnlint.rules import CloudFormationLintRule


class MinMax(CloudFormationLintRule):
class NumberRange(CloudFormationLintRule):
"""Check if a Number has a length within the limit"""

id = "E3034"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from cfnlint.rules import CloudFormationLintRule


class OnlyOne(CloudFormationLintRule):
class OneOf(CloudFormationLintRule):
"""Check Properties Resource Configuration"""

id = "E3018"
Expand Down
2 changes: 1 addition & 1 deletion src/cfnlint/rules/resources/properties/Pattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Pattern(CloudFormationLintRule):
"Check if properties have a valid value in case of a pattern (Regular"
" Expression)"
)
source_url = "https://github.com/awslabs/cfn-python-lint/blob/main/docs/cfn-resource-specification.md#allowedpattern"
source_url = "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/cfn-schema-specification.md#pattern"
tags = ["resources", "property", "allowed pattern", "regex"]
child_rules = {
"W2031": None,
Expand Down
4 changes: 2 additions & 2 deletions src/cfnlint/rules/resources/properties/PrefixItems.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ class PrefixItems(CloudFormationLintRule):
id = "E3008"
shortdesc = "Validate an array in order"
description = "Will validate arrays in order for schema validation"
source_url = "https://github.com/aws-cloudformation/cfn-python-lint/blob/main/docs/cfn-resource-specification.md#required"
tags = ["resources"]
source_url = "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/cfn-schema-specification.md#prefixitems"
tags = ["resources", "properties", "array", "prefixItems"]
2 changes: 1 addition & 1 deletion src/cfnlint/rules/resources/properties/Properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Properties(BaseJsonSchema):
id = "E3002"
shortdesc = "Resource properties are invalid"
description = "Making sure that resources properties are properly configured"
source_url = "https://github.com/aws-cloudformation/cfn-python-lint/blob/main/docs/cfn-resource-specification.md#properties"
source_url = "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/cfn-schema-specification.md#properties"
tags = ["resources"]

def __init__(self):
Expand Down
4 changes: 2 additions & 2 deletions src/cfnlint/rules/resources/properties/Required.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ class Required(CloudFormationLintRule):
id = "E3003"
shortdesc = "Required Resource properties are missing"
description = "Making sure that Resources properties that are required exist"
source_url = "https://github.com/aws-cloudformation/cfn-python-lint/blob/main/docs/cfn-resource-specification.md#required"
tags = ["resources"]
source_url = "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/cfn-schema-specification.md#required"
tags = ["resources", "properties", "required"]
2 changes: 1 addition & 1 deletion src/cfnlint/rules/resources/properties/RequiredXor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ class RequiredXor(CloudFormationLintRule):
id = "E3014"
shortdesc = "Validate only one of a set of required properties are specified"
description = "Making sure that Resources properties that are required exist"
source_url = "https://github.com/aws-cloudformation/cfn-python-lint/blob/main/docs/cfn-resource-specification.md#required"
source_url = "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/cfn-schema-specification.md#requiredxor"
tags = ["resources"]
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from cfnlint.rules import CloudFormationLintRule


class MinMaxLength(CloudFormationLintRule):
class StringLength(CloudFormationLintRule):
"""Check if a String has a length within the limit"""

id = "E3033"
Expand Down
2 changes: 1 addition & 1 deletion src/cfnlint/rules/resources/properties/Type.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Type(CloudFormationLintRule):
"Checks resource property values with Primitive Types for values that match"
" those types."
)
source_url = "https://github.com/aws-cloudformation/cfn-python-lint/blob/main/docs/cfn-resource-specification.md#valueprimitivetype"
source_url = "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/cfn-schema-specification.md#type"
tags = ["resources"]

strict_exceptions = {
Expand Down
2 changes: 1 addition & 1 deletion src/cfnlint/rules/resources/properties/UniqueItems.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class UniqueItems(CloudFormationLintRule):
"Certain lists don't support duplicate items. "
"Check when duplicates are provided but not supported."
)
source_url = "https://github.com/aws-cloudformation/cfn-python-lint/blob/main/docs/cfn-resource-specification.md#allowedvalue"
source_url = "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/cfn-schema-specification.md#uniqueitems"
tags = ["resources", "property", "list"]
child_rules = {
"I3037": None,
Expand Down
Loading

0 comments on commit e95304e

Please sign in to comment.