From 113961ce1598fcd23fe1ea3bd7bb606066146ecf Mon Sep 17 00:00:00 2001 From: DC3-DCCI Date: Fri, 16 Feb 2024 13:00:56 -0500 Subject: [PATCH] Expanding adoc validation python script, adding GitHub job to automatically run it, fixing errors found within adoc files. --- .../extensions-asciidocs-validation.yml | 18 ++++++++ .../STIX-2.1-CUI-marking.adoc | 5 +-- .../Identity-Contact-Information.adoc | 19 +++++---- .../Incident Extension Suite.adoc | 41 ++++++++++--------- .../observed-string-8b1/Observed String.adoc | 5 ++- .../STIX-2.1-PAP-marking-definition.adoc | 2 +- scripts/validate_adoc.py | 9 ++-- 7 files changed, 60 insertions(+), 39 deletions(-) create mode 100644 .github/workflows/extensions-asciidocs-validation.yml diff --git a/.github/workflows/extensions-asciidocs-validation.yml b/.github/workflows/extensions-asciidocs-validation.yml new file mode 100644 index 00000000000..5207593c0db --- /dev/null +++ b/.github/workflows/extensions-asciidocs-validation.yml @@ -0,0 +1,18 @@ +name: AsciiDoc Validation +on: [push, pull_request] + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set Up Python + uses: actions/setup-python@v2 + with: + python-version: '3.10' + - name: Validate adoc + working-directory: extension-definition-specifications + run: | + for file in */*.adoc; do + python ../scripts/validate_adoc.py -i "$file" + done diff --git a/extension-definition-specifications/cui-marking-definition-dff/STIX-2.1-CUI-marking.adoc b/extension-definition-specifications/cui-marking-definition-dff/STIX-2.1-CUI-marking.adoc index b4ab4cab181..fd046837075 100644 --- a/extension-definition-specifications/cui-marking-definition-dff/STIX-2.1-CUI-marking.adoc +++ b/extension-definition-specifications/cui-marking-definition-dff/STIX-2.1-CUI-marking.adoc @@ -1,6 +1,3 @@ -cui - - :stylesheet: stix.css :stylesdir: ../../asciidoc-shared :toc: macro @@ -72,7 +69,7 @@ The tables below describe the properties of a STIX 2.1 CUI marking definition ex |[stixtype]#{string_url}[string]# |The extension_type property indicates the type of extension is being used. -The value of this property *MUST* be [stixtype]#<># +The value of this property *MUST* be [stixliteral]#property-extension# |*control* (required) |[stixtype]#{string_url}[string]# diff --git a/extension-definition-specifications/identity-66e/Identity-Contact-Information.adoc b/extension-definition-specifications/identity-66e/Identity-Contact-Information.adoc index a498bc811ef..3efac81e279 100644 --- a/extension-definition-specifications/identity-66e/Identity-Contact-Information.adoc +++ b/extension-definition-specifications/identity-66e/Identity-Contact-Information.adoc @@ -10,6 +10,8 @@ :list_url: https://docs.oasis-open.org/cti/stix/v2.1/os/stix-v2.1-os.html#_9w329aiwpu1y :open_vocab_url: https://docs.oasis-open.org/cti/stix/v2.1/os/stix-v2.1-os.html#_bnnxah80y7by :string_url: https://docs.oasis-open.org/cti/stix/v2.1/os/stix-v2.1-os.html#_uxyhzmv0vpyc +:user_account_url: https://docs.oasis-open.org/cti/stix/v2.1/os/stix-v2.1-os.html#_azo70vgj1vm2 +:email_address_url: https://docs.oasis-open.org/cti/stix/v2.1/os/stix-v2.1-os.html#_wmenahkvqmgj = [stixtitle]*Identity Contact Information Extension Version 1.0 for STIX™ Version 2.1* @@ -96,7 +98,7 @@ The properties and additional types within the Identity Contact Information Exte == 2. Additional Sub-Object Types [[contact-number]] -=== 2.1 Contact Number Object Type +=== 2.1. Contact Number Object Type *Type Name:* [stixtype]#contact-number# [width="100%",cols="37%,23%,40%",options="header",] @@ -123,7 +125,7 @@ The properties and additional types within the Identity Contact Information Exte |=== [[email-contact]] -=== 2.2 Email Contact Object Type +=== 2.2. Email Contact Object Type *Type Name:* [stixtype]#email-contact# [width="100%",cols="37%,23%,40%",options="header",] @@ -145,12 +147,12 @@ The properties and additional types within the Identity Contact Information Exte |The type of email that address is used for. This *SHOULD* be drawn from [stixtype]#<>#. |*email_address_ref* (required) -|[stixtype]#{identifier_url}[identifer]# of type [stixtype]#<># +|[stixtype]#{identifier_url}[identifer]# of type [stixtype]#{email_address_url}[email-addr]# |A reference to the email address itself. |=== [[social-media-contact]] -=== 2.3 Social Media Contact Object Type +=== 2.3. Social Media Contact Object Type *Type Name:* [stixtype]#social-media-contact# [width="100%",cols="37%,23%,40%",options="header",] @@ -174,7 +176,7 @@ The properties and additional types within the Identity Contact Information Exte This *SHOULD NOT* be used to capture the social media service used. That *SHOULD* be encoded into the User Account Object that is linked to by the user_account_ref property. |*user_account_ref* (required) -|[stixtype]#{identifier_url}[identifer]# of type [stixtype]#<># +|[stixtype]#{identifier_url}[identifer]# of type [stixtype]#{user_account_url}[user-account]# |A reference to the social media account itself. |=== @@ -206,7 +208,7 @@ This *SHOULD NOT* be used to capture the social media service used. That *SHOUL |=== [[digital-contact-ov]] -=== 3.2 Digital Contact Type Vocabulary +=== 3.2. Digital Contact Type Vocabulary *Type Name:* [stixtype]#digital-contact-ov# [width="100%",cols="37%,63%",options="header",] @@ -226,19 +228,18 @@ This *SHOULD NOT* be used to capture the social media service used. That *SHOUL == 4. Identity Contact Information Examples -=== 4.1 Identitiy Contact Details Example +=== 4.1. Identitiy Contact Details Example [source,json] ---- include::examples/individual_contact_example.json[] ---- -=== 4.2 Organization Contact Details Example +=== 4.2. Organization Contact Details Example [source,json] ---- include::examples/organization_contact_example.json[] ---- -[[appendix-a]] == Appendix A. Acknowledgements *Primary Editor* diff --git a/extension-definition-specifications/incident-ef7/Incident Extension Suite.adoc b/extension-definition-specifications/incident-ef7/Incident Extension Suite.adoc index 8948913df82..c7656b186c6 100644 --- a/extension-definition-specifications/incident-ef7/Incident Extension Suite.adoc +++ b/extension-definition-specifications/incident-ef7/Incident Extension Suite.adoc @@ -39,6 +39,7 @@ :sighting_url: https://docs.oasis-open.org/cti/stix/v2.1/os/stix-v2.1-os.html#_a795guqsap3r :threat_actor_url: https://docs.oasis-open.org/cti/stix/v2.1/os/stix-v2.1-os.html#_k017w16zutw :tool_url: https://docs.oasis-open.org/cti/stix/v2.1/os/stix-v2.1-os.html#_z4voa9ndw8v +:sco_url: https://docs.oasis-open.org/cti/stix/v2.1/os/stix-v2.1-os.html#_mlbmudhl16lr = [stixtitle]*Incident Core Extension Version 2.1 for STIX^TM^ Version 2.1* @@ -78,7 +79,7 @@ The current STIX 2.1 Incident object was defined as a stub with the expectation In the 1.0 version of the core incident extension, information on impact, events, and tasks were embedded within the Incident object itself, however this was found to have limitations. Therefore, the 2.0 version of this extension has been created in which these components have been separated into independent SDOs for more complex incidents to be accurately modeled. -These extensions allow incidents to be tracked across their life cycle where [stixtype]#<># are first flagged for investigation resulting in [stixtype]#incidents# with [stixtype]#<># being worked to resolve them. +These extensions allow incidents to be tracked across their life cycle where [stixtype]#<># are first flagged for investigation resulting in [stixtype]#{incident_url}incidents# with [stixtype]#<># being worked to resolve them. Incidents have [stixtype]#<># that change over time. [stixtype]#<># can cause or influence these [stixtype]#<># which are in turn mitigated and potentially resolved by [stixtype]#<># performed as part of the incident response process. Both [stixtype]#<># and [stixtype]#<># can exist independently of [stixtype]#{incident_url}[incidents]# and in most workflows will occur prior to an incident being declared. @@ -259,7 +260,7 @@ Additionally, this can be used to supplement the *created_by_ref* property in ca |=== // end::incident-relationships[] -==== 2.1.2 Example +==== 2.1.2. Example [source,json] ---- @@ -432,7 +433,7 @@ For example, a dropper running led to a ransomware tool to be downloaded and run |[stixtype]#<># |[stixrelationship]#impacts# |[stixtype]#{infrastructure_url}[infrastructure]#, + -[stixtype]#[]# +[stixtype]#{sco_url}[]# |An event has an impact on specific infrastructure. While not all SCO types will make sense in this relationship, allowing any type of SCO prevents artificially restricting what could be used. |[stixtype]#<># @@ -470,7 +471,7 @@ For example, a dropper running led to a ransomware tool to be downloaded and run // end::event-relationships[] -==== 2.2.2 Example +==== 2.2.2. Example [source,json] ---- @@ -646,7 +647,7 @@ This value *MUST* be an integer between 0 to 100. This can be translated into qu |=== -===== 2.3.2.1.1 Availability Impact Example +====== 2.3.2.1.1. Availability Impact Example [source,json] ---- @@ -692,7 +693,7 @@ The value of this property *MUST NOT* be negative. The value of this property *MUST NOT* be negative. |=== -===== 2.3.2.2.1 Confidentiality Impact Example +====== 2.3.2.2.1. Confidentiality Impact Example [source,json] ---- @@ -718,7 +719,7 @@ The value of this property *SHOULD* come from the [stixtype]#<># |[stixrelationship]#impacts# |[stixtype]#{infrastructure_url}[infrastructure]#, + -[stixtype]#[]# +[stixtype]#{sco_url}[]# |A task has an impact on specific infrastructure. |[stixtype]#<># @@ -1155,7 +1156,7 @@ Using these embedded relationships ensures that an incomplete sequence cannot be // end::task-relationships[] -==== 2.4.2 Example +==== 2.4.2. Example [source,json] ---- @@ -1246,7 +1247,7 @@ The values of this property *MUST* come from the [stixtype]#<># +The value of this property *MUST* be [stixliteral]#property-extension# |*pap* (required) |[stixtype]#{string_url}[string]# diff --git a/scripts/validate_adoc.py b/scripts/validate_adoc.py index c08e2ea08c8..34d59cd1da3 100644 --- a/scripts/validate_adoc.py +++ b/scripts/validate_adoc.py @@ -7,7 +7,7 @@ class Validator(): def __init__(self, file_path): self._errors = [] - with open(file_path, "rt") as input_file: + with open(file_path, "rt", encoding="utf-8") as input_file: self._content = input_file.read() def run_jobs(self) -> list: @@ -96,7 +96,9 @@ def section_ids(self, content) -> None: self._errors.append(f"Line {line_number}: {item} should be 1 as the first item") continue - if len(parts) == len(last_parts): + if item[-1] != ".": + self._errors.append(f"Line {line_number}: {item} has no . at the end") + elif len(parts) == len(last_parts): if int(last_parts[-1]) != int(parts[-1]) - 1: self._errors.append(f"Line {line_number}: {item} should be {'.'.join(last_parts[:-1])}.{int(last_parts[-1]) + 1}") elif len(parts) > len(last_parts): @@ -128,9 +130,10 @@ def section_ids(self, content) -> None: errors = validator.run_jobs() if len(errors) > 0: + print(f"Error Validating: {args.input_path}", file=sys.stderr) print("\n".join(errors), file=sys.stderr) exit(1) else: - print("No errors found") + print(f"No errors found: {args.input_path}") exit(0) \ No newline at end of file