assets/MaesterTestSchema.psd1
|
# Schema of the [MaesterTest] attribute (docs/proposals/maester-3.0-test-attributes.md, section 2, and # the Maester 3.0 design, sections 3.1 and 4). # # The engine reads [MaesterTest(...)] from a test file's AST and validates it against this table; # a test file is never executed to read its metadata. The property list must match # MaesterTestAttribute in src/Maester.Engine (a unit test compares them). # # Property keys: # Type string | string[] | bool # Required Always | BuiltIn (required for tests shipped with Maester) | No # NotRequiredWhen the property is not required when another property has this value, for example # @{ Severity = 'Info' } # AllowedValues closed list, compared case-insensitively and stored in this spelling # ValuesFrom the values are validated against an engine registry instead of a fixed list: # ServiceRegistry, or Taxonomy.Products, Taxonomy.Features, Taxonomy.Areas and # Taxonomy.ResourceTypes (assets/MaesterTaxonomy.psd1). A test shipped with Maester must # use a registry value; a custom test may use any value that fits Pattern and MaxLength # Pattern regular expression each value must match # MaxLength maximum length of each value # Default value used when the property is omitted (documentation; the engine applies it) # Description one line, used by generated docs @{ SchemaVersion = '1.0' # Segments of letters and digits (and '_' after the first segment) separated by '.' or '-', # starting with a letter and containing at least one digit or separator. IdPattern = '^(?=.*[0-9.\-])[A-Za-z][A-Za-z0-9]*([.\-][A-Za-z0-9_]+)*$' IdMaxLength = 64 # ID prefixes that belong to tests shipped with Maester, and MP. for Maester Packs. ReservedPrefixes = @('MT.', 'CISA.', 'CIS.', 'EIDSCA.', 'ORCA.', 'AD-', 'AZDO.', 'MT1060.', 'MP.') # Names reserved for future properties. Adding one later does not break existing tests. ReservedNames = @('OptionalService', 'TimeoutSeconds') # Properties removed in Maester 3.0, with the message the reader gives for each. RemovedProperties = @{ Category = '`Category` was removed in Maester 3.0. Use `Product` and `Feature`; the result''s `Block` is derived from them.' Preview = '`Preview` was removed in Maester 3.0. Use `Lifecycle = ''Preview''`.' } # Parameter names a test cannot declare for configuration: the engine supplies them. ReservedParameterNames = @('Instance') ReservedParameterPrefixes = @('Mt') # Types a test parameter may have (section 3.4). ParameterTypes = @('int', 'bool', 'switch', 'string', 'string[]') Properties = @{ Id = @{ Type = 'string' Required = 'Always' Pattern = '^(?=.*[0-9.\-])[A-Za-z][A-Za-z0-9]*([.\-][A-Za-z0-9_]+)*$' MaxLength = 64 Description = 'Stable identifier. The file is Test.<Id>.ps1.' } Title = @{ Type = 'string' Required = 'Always' Pattern = '^[^\r\n]+$' Description = 'One-line title shown in the report.' } Product = @{ Type = 'string' Required = 'BuiltIn' ValuesFrom = 'Taxonomy.Products' Pattern = '^[^\r\n]+$' MaxLength = 40 Description = 'Key of the product where the fix is made, for example entra. An alias such as Entra ID is stored as the key. Groups console progress and the run summary; written to the result as Product.' } RelatedProduct = @{ Type = 'string[]' Required = 'No' ValuesFrom = 'Taxonomy.Products' Pattern = '^[^\r\n]+$' MaxLength = 40 Description = 'Keys of other products the test also checks or depends on. Never the same key as Product.' } Feature = @{ Type = 'string' Required = 'BuiltIn' ValuesFrom = 'Taxonomy.Features' Pattern = '^[^\r\n]+$' MaxLength = 60 Description = 'Key of the part of the product the test is about, for example conditional-access. One of the features of the test''s product.' } Area = @{ Type = 'string' Required = 'BuiltIn' ValuesFrom = 'Taxonomy.Areas' Pattern = '^[^\r\n]+$' MaxLength = 60 Description = 'Key of the security theme, whatever the product, for example authentication.' } ResourceType = @{ Type = 'string' Required = 'BuiltIn' ValuesFrom = 'Taxonomy.ResourceTypes' Pattern = '^[A-Za-z][A-Za-z0-9]*$' Description = 'What a failing result points at, for example Tenant or User.' } Severity = @{ Type = 'string' Required = 'BuiltIn' AllowedValues = @('Critical', 'High', 'Medium', 'Low', 'Info') Description = 'Default severity. The run config may override it.' } UserImpact = @{ Type = 'string' Required = 'BuiltIn' NotRequiredWhen = @{ Severity = 'Info' } AllowedValues = @('Low', 'Medium', 'High') Description = 'How much the recommended fix disrupts end users. Omitted when Severity is Info.' } ImplementationCost = @{ Type = 'string' Required = 'BuiltIn' NotRequiredWhen = @{ Severity = 'Info' } AllowedValues = @('Low', 'Medium', 'High') Description = 'How much administrator work the recommended fix takes. Omitted when Severity is Info.' } Mitre = @{ Type = 'string[]' Required = 'BuiltIn' Pattern = '^(T[0-9]{4}(\.[0-9]{3})?|None)$' Description = 'MITRE ATT&CK technique IDs the checked control prevents or detects (T1110, T1110.003), or the single value None.' } Control = @{ Type = 'string[]' Required = 'No' Pattern = '^[a-z0-9][a-z0-9.\-]*:[^\s,]+$' Description = 'Requirements of frameworks the test supports, written <framework-key>:<requirement-id>, beside the benchmark it is named after.' } Service = @{ Type = 'string[]' Required = 'BuiltIn' ValuesFrom = 'ServiceRegistry' Description = 'Services that must all be connected, or None.' } License = @{ Type = 'string[]' Required = 'No' Pattern = '^[A-Za-z0-9_\-]+(&[A-Za-z0-9_\-]+)*$' Description = 'Service plan names. The tenant needs any one element; A&B inside an element means all of them.' } Permission = @{ Type = 'string[]' Required = 'No' Pattern = '^[^,\r\n]*[^,\s][^,\r\n]*$' Description = 'Permissions the test needs, one per element, no commas. Recorded; not enforced.' } TenantType = @{ Type = 'string[]' Required = 'No' AllowedValues = @('Workforce', 'External') Default = @('Workforce') Description = 'Tenant types the test applies to.' } Cloud = @{ Type = 'string[]' Required = 'No' AllowedValues = @('Commercial', 'GCC', 'GCCHigh', 'DoD', 'China', 'Bleu', 'Delos', 'GovSG') Description = 'Clouds the test is valid in. Omitted means all clouds.' } Platform = @{ Type = 'string[]' Required = 'No' AllowedValues = @('Windows', 'Linux', 'MacOS') Description = 'Operating systems the test can run on. Omitted means all platforms.' } Lifecycle = @{ Type = 'string' Required = 'No' AllowedValues = @('Preview', 'Stable', 'Deprecated') Default = 'Stable' Description = 'Preview, Stable or Deprecated. A Preview test is not run unless -IncludePreview or any -Tag is given, or its exact ID is in -TestId.' } ReplacedBy = @{ Type = 'string' Required = 'No' Pattern = '^(?=.*[0-9.\-])[A-Za-z][A-Za-z0-9]*([.\-][A-Za-z0-9_]+)*$' MaxLength = 64 Description = 'ID of the test that took the place of a Deprecated test.' } LongRunning = @{ Type = 'bool' Required = 'No' Default = $false Description = 'Not run unless long-running tests are included.' } Exclusive = @{ Type = 'bool' Required = 'No' Default = $false Description = 'The test must not run concurrently with another test.' } InstanceSource = @{ Type = 'string' Required = 'No' Pattern = '^[A-Za-z][A-Za-z0-9\-_]*$' Description = 'Name of a function in the same file that returns the instances of a family.' } Tag = @{ Type = 'string[]' Required = 'No' Pattern = '^[^,]*\S[^,]*$' Description = 'Free labels of the owner of the test folder, for -Tag and -ExcludeTag. Non-empty, no commas.' } Author = @{ Type = 'string[]' Required = 'BuiltIn' Pattern = '^[A-Za-z0-9](?:[A-Za-z0-9]|-(?=[A-Za-z0-9])){0,38}$' Description = 'GitHub handles of the initial author(s).' } Contributor = @{ Type = 'string[]' Required = 'No' Pattern = '^[A-Za-z0-9](?:[A-Za-z0-9]|-(?=[A-Za-z0-9])){0,38}$' Description = 'GitHub handles of secondary contributors, in order of first contribution.' } HelpUrl = @{ Type = 'string' Required = 'No' Pattern = '^https://\S+$' Default = 'The suite template' Description = '"Learn more" link.' } } # [MaesterParameter] on a test parameter. ParameterAttribute = @{ Kind = @{ Type = 'string' Required = 'Always' ValuesFrom = 'ParameterKindRegistry' Pattern = '^[A-Za-z][A-Za-z0-9]*(\.[A-Za-z][A-Za-z0-9]*)+$' Description = 'Name of an entry in the parameter-kind registry, for example Entra.Group.' } } } |