コード例 #1
0
def generate_playbook_doc(input, output, examples, id_set, verbose=False):
    try:
        playbook = get_yaml(input)
        errors = []

        description = playbook.get('description', '')

        if not description:
            errors.append('Error! You are missing description for the playbook')

        doc = [description, '', '## Dependencies',
               'This playbook uses the following sub-playbooks, integrations, and scripts.', '']

        playbooks, integrations, scripts, commands = get_playbook_dependencies(playbook)
        inputs, inputs_errors = get_inputs(playbook)
        outputs, outputs_errors = get_outputs(playbook)

        errors.extend(inputs_errors)
        errors.extend(outputs_errors)

        doc.extend(generate_list_section('Sub-playbooks', playbooks, header_type=HEADER_TYPE.H3,
                                         empty_message='This playbook does not use any sub-playbooks.'))

        doc.extend(generate_list_section('Integrations', integrations, header_type=HEADER_TYPE.H3,
                                         empty_message='This playbook does not use any integrations.'))

        doc.extend(generate_list_section('Scripts', scripts, header_type=HEADER_TYPE.H3,
                                         empty_message='This playbook does not use any scripts.'))

        doc.extend(generate_list_section('Commands', commands, header_type=HEADER_TYPE.H3,
                                         empty_message='This playbook does not use any commands.'))

        doc.extend(generate_table_section(inputs, 'Playbook Inputs', 'There are no inputs for this playbook.'))

        doc.extend(generate_table_section(outputs, 'Playbook Outputs', 'There are no outputs for this playbook.'))

        doc.append('<!-- Playbook PNG image comes here -->')

        doc_text = '\n'.join(doc)

        save_output(output, 'README.md', doc_text)

        if errors:
            print_warning('Possible Errors:')
            for error in errors:
                print_warning(error)

    except Exception as ex:
        if verbose:
            raise
        else:
            print_error(f'Error: {str(ex)}')
            return
コード例 #2
0
def generate_setup_section(yaml_data: dict):
    section = [
        '1. Navigate to **Settings** > **Integrations** > **Servers & Services**.',
        '2. Search for {}.'.format(yaml_data['name']),
        '3. Click **Add instance** to create and configure a new integration instance.'
    ]
    access_data = []

    for conf in yaml_data['configuration']:
        access_data.append({
            'Parameter':
            conf.get('display'),
            'Description':
            string_escape_md(conf.get('additionalinfo', '')),
            'Required':
            conf.get('required', '')
        })

    # Check if at least one parameter has additional info field.
    # If not, remove the description column from the access data table section.
    access_data_with_description = list(
        filter(lambda x: x.get('Description', '') != '', access_data))
    if len(access_data_with_description) == 0:
        list(map(lambda x: x.pop('Description'), access_data))

    section.extend(
        generate_table_section(access_data,
                               '',
                               horizontal_rule=False,
                               numbered_section=True))
    section.append(
        '4. Click **Test** to validate the URLs, token, and connection.')

    return section
コード例 #3
0
def test_generate_table_section_with_newlines():
    """Unit test
    Given
    - generate_table_section command
    - inputs as a list of dicts
    When
    - running the command on an input including \n (PcapFilter)
    Then
    - Validate That the \n is escaped correctly in a markdown format.
    """
    from demisto_sdk.commands.generate_docs.common import \
        generate_table_section

    section = generate_table_section([{
        'Name': 'RsaDecryptKeyEntryID',
        'Description': 'This input specifies the file entry id for the RSA decrypt key if the user provided the key'
                       ' in the incident.', 'Default Value': 'File.EntryID', 'Required': 'Optional'},
        {'Name': 'PcapFileEntryID',
         'Description': 'This input specifies the file entry id for the PCAP file if the user provided the file in the'
                        ' incident. One PCAP file can run per incident.',
         'Default Value': 'File.EntryID', 'Required': 'Optional'},
        {'Name': 'WpaPassword',
         'Description': 'This input value is used to provide a WPA \\(Wi\\-Fi Protected Access\\) password to decrypt'
                        ' encrypted 802.11 Wi\\-FI traffic.', 'Default Value': '', 'Required': 'Optional'},
        {'Name': 'PcapFilter',
         'Description': 'This input specifies a search filter to be used on the PCAP file. Filters can be used to'
                        ' search only for a specific IP, protocols and other examples. The syntax is the same as in'
                        ' Wireshark which can be found here:'
                        ' https://www.wireshark.org/docs/man-pages/wireshark-filter.html \nFor this playbook, using'
                        ' a PCAP filter will generate a new smaller PCAP file based on the provided filter therefor'
                        ' thus reducing the extraction of non relevant files.',
         'Default Value': '', 'Required': 'Optional'},
        {'Name': 'ExtractedFilesLimit',
         'Description': 'This input limits the number of files to be extracted from the PCAP file.'
                        ' Default value is 5.', 'Default Value': '5', 'Required': 'Optional'}
    ], 'Playbook Inputs', 'There are no inputs for this playbook.')

    expected_section = [
        '## Playbook Inputs',
        '---',
        '',
        '| **Name** | **Description** | **Default Value** | **Required** |',
        '| --- | --- | --- | --- |',
        '| RsaDecryptKeyEntryID | This input specifies the file entry id for the RSA decrypt key if the user provided'
        ' the key in the incident. | File.EntryID | Optional |',
        '| PcapFileEntryID | This input specifies the file entry id for the PCAP file if the user provided the file in'
        ' the incident. One PCAP file can run per incident. | File.EntryID | Optional |',
        '| WpaPassword | This input value is used to provide a WPA \\(Wi\\-Fi Protected Access\\) password'
        ' to decrypt encrypted 802.11 Wi\\-FI traffic. |  | Optional |',
        '| PcapFilter | This input specifies a search filter to be used on the PCAP file. Filters can be used to'
        ' search only for a specific IP, protocols and other examples. The syntax is the same as in Wireshark which'
        ' can be found here: https://www.wireshark.org/docs/man-pages/wireshark-filter.html <br/>For this'
        ' playbook, using a PCAP filter will generate a new smaller PCAP file based on the provided filter therefor'
        ' thus reducing the extraction of non relevant files. |  | Optional |',
        '| ExtractedFilesLimit | This input limits the number of files to be extracted from the PCAP file. '
        'Default value is 5. | 5 | Optional |',
        ''
    ]

    assert section == expected_section
コード例 #4
0
def test_generate_table_section_numbered_section():
    """
        Given
            - A table that should be part of a numbered section (like the setup section of integration README).
        When
            - Running the generate_table_section command.
        Then
            - Validate that the generated table has \t at the beginning of each line.
    """

    from demisto_sdk.commands.generate_docs.common import generate_table_section

    expected_section = [
        '', '    | **Type** | **Docker Image** |', '    | --- | --- |',
        '    | python2 | demisto/python2 |', ''
    ]

    section = generate_table_section(data=[{
        'Type': 'python2',
        'Docker Image': 'demisto/python2'
    }],
                                     title='',
                                     horizontal_rule=False,
                                     numbered_section=True)
    assert section == expected_section
コード例 #5
0
def test_generate_table_section():
    """Unit test
    Given
    - generate_table_section command
    - script metadata as a list of dicts
    When
    - running the command on the inputs including a docker image
    Then
    - Validate That the script metadata was created correctly.
    """
    from demisto_sdk.commands.generate_docs.common import \
        generate_table_section

    section = generate_table_section([{
        'Type': 'python2',
        'Docker Image': 'demisto/python2'
    }], 'Script Data', 'No data found.', 'This is the metadata of the script.')

    expected_section = [
        '## Script Data', '---', 'This is the metadata of the script.',
        '| **Type** | **Docker Image** |', '| --- | --- |',
        '| python2 | demisto/python2 |', ''
    ]

    assert section == expected_section
コード例 #6
0
def test_generate_table_section_empty():
    from demisto_sdk.commands.generate_docs.common import generate_table_section

    section = generate_table_section([], 'Script Data', 'No data found.',
                                     'This is the metadata of the script.')

    expected_section = ['## Script Data', '---', 'No data found.', '']

    assert section == expected_section
コード例 #7
0
def test_generate_table_section():
    from demisto_sdk.commands.generate_docs.common import generate_table_section

    section = generate_table_section([{
        'Type': 'python2',
        'Docker Image': 'demisto/python2'
    }], 'Script Data', 'No data found.', 'This is the metadata of the script.')

    expected_section = [
        '## Script Data', '---', 'This is the metadata of the script.',
        '| **Type** | **Docker Image** |', '| --- | --- |',
        '| python2 | demisto/python2 |', ''
    ]

    assert section == expected_section
コード例 #8
0
def generate_setup_section(yaml_data: dict):
    section = [
        '1. Navigate to **Settings** > **Integrations** > **Servers & Services**.',
        '2. Search for {}.'.format(yaml_data['name']),
        '3. Click **Add instance** to create and configure a new integration instance.'
    ]
    access_data = []

    for conf in yaml_data['configuration']:
        access_data.append(
            {'Parameter': conf.get('name', ''),
             'Description': conf.get('display', ''),
             'Required': conf.get('required', '')})

    section.extend(generate_table_section(access_data, '', horizontal_rule=False))
    section.append('4. Click **Test** to validate the URLs, token, and connection.')

    return section
コード例 #9
0
def test_generate_table_section_empty():
    """Unit test
    Given
    - generate_table_section command
    - script empty metadata
    When
    - running the command on the inputs
    Then
    - Validate That the script metadata was created correctly.
    """
    from demisto_sdk.commands.generate_docs.common import \
        generate_table_section

    section = generate_table_section([], 'Script Data', 'No data found.', 'This is the metadata of the script.')

    expected_section = [
        '## Script Data', '---', 'No data found.', '']

    assert section == expected_section
コード例 #10
0
def generate_script_doc(input_path,
                        examples,
                        output: str = None,
                        permissions: str = None,
                        limitations: str = None,
                        insecure: bool = False,
                        verbose: bool = False):
    try:
        doc: list = []
        errors: list = []
        example_section: list = []

        if not output:  # default output dir will be the dir of the input file
            output = os.path.dirname(os.path.realpath(input_path))

        if examples:
            if os.path.isfile(examples):
                with open(examples, 'r') as examples_file:
                    examples = examples_file.read().splitlines()
            else:
                examples = examples.split(',')
                for i, example in enumerate(examples):
                    if not example.startswith('!'):
                        examples[i] = f'!{examples}'

            example_dict, build_errors = build_example_dict(examples, insecure)
            script_name = list(
                example_dict.keys())[0] if example_dict else None
            example_section, example_errors = generate_script_example(
                script_name, example_dict)
            errors.extend(build_errors)
            errors.extend(example_errors)
        else:
            errors.append(
                'Note: Script example was not provided. For a more complete documentation,run with the -e '
                'option with an example command. For example: -e "!ConvertFile entry_id=<entry_id>".'
            )

        script = get_yaml(input_path)

        # get script data
        script_info = get_script_info(input_path)
        script_id = script.get('commonfields')['id']

        # get script dependencies
        dependencies, _ = get_depends_on(script)

        # get the script usages by the id set
        if not os.path.isfile(DEFAULT_ID_SET_PATH):
            id_set_creator = IDSetCreator(output='', print_logs=False)
            id_set, _, _ = id_set_creator.create_id_set()
        else:
            id_set = open_id_set_file(DEFAULT_ID_SET_PATH)

        used_in = get_used_in(id_set, script_id)

        description = script.get('comment', '')
        # get inputs/outputs
        inputs, inputs_errors = get_inputs(script)
        outputs, outputs_errors = get_outputs(script)

        errors.extend(inputs_errors)
        errors.extend(outputs_errors)

        if not description:
            errors.append(
                'Error! You are missing a description for the Script')

        doc.append(description + '\n')

        doc.extend(generate_table_section(script_info, 'Script Data'))

        if dependencies:
            doc.extend(
                generate_list_section(
                    'Dependencies',
                    dependencies,
                    True,
                    text='This script uses the following commands and scripts.'
                ))

        # Script global permissions
        if permissions == 'general':
            doc.extend(generate_section('Permissions', ''))

        if used_in:
            if len(used_in) <= 10:
                doc.extend(
                    generate_list_section(
                        'Used In',
                        used_in,
                        True,
                        text=
                        'This script is used in the following playbooks and scripts.'
                    ))
            else:  # if we have more than 10 use a sample
                print_warning(
                    f'"Used In" section found too many scripts/playbooks ({len(used_in)}). Will use a sample of 10.'
                    ' Full list is available as a comment in the README file.')
                sample_used_in = random.sample(used_in, 10)
                doc.extend(
                    generate_list_section(
                        'Used In',
                        sorted(sample_used_in),
                        True,
                        text=
                        'Sample usage of this script can be found in the following playbooks and scripts.'
                    ))
                used_in_str = '\n'.join(used_in)
                doc.append(
                    f"<!--\nUsed In: list was truncated. Full list commented out for reference:\n\n{used_in_str}\n -->\n"
                )

        doc.extend(
            generate_table_section(inputs, 'Inputs',
                                   'There are no inputs for this script.'))

        doc.extend(
            generate_table_section(outputs, 'Outputs',
                                   'There are no outputs for this script.'))

        if example_section:
            doc.extend(example_section)

        # Known limitations
        if limitations:
            doc.extend(
                generate_numbered_section('Known Limitations', limitations))

        doc_text = '\n'.join(doc)

        save_output(output, 'README.md', doc_text)

        if errors:
            print_warning('Possible Errors:')
            for error in errors:
                print_warning(error)

    except Exception as ex:
        if verbose:
            raise
        else:
            print_error(f'Error: {str(ex)}')
            return
コード例 #11
0
def generate_playbook_doc(input,
                          output: str = None,
                          permissions: str = None,
                          limitations: str = None,
                          verbose: bool = False):
    try:
        playbook = get_yaml(input)
        if not output:  # default output dir will be the dir of the input file
            output = os.path.dirname(os.path.realpath(input))
        errors = []

        description = playbook.get('description', '')
        _name = playbook.get('name', 'Unknown')
        if not description:
            errors.append(
                'Error! You are missing description for the playbook')

        doc = [
            description, '', '## Dependencies',
            'This playbook uses the following sub-playbooks, integrations, and scripts.',
            ''
        ]

        playbooks, integrations, scripts, commands = get_playbook_dependencies(
            playbook, input)
        inputs, inputs_errors = get_inputs(playbook)
        outputs, outputs_errors = get_outputs(playbook)
        playbook_filename = os.path.basename(input).replace('.yml', '')

        errors.extend(inputs_errors)
        errors.extend(outputs_errors)

        # Playbooks general permissions
        if permissions == 'general':
            doc.extend(generate_section('Permissions', ''))

        doc.extend(
            generate_list_section(
                'Sub-playbooks',
                playbooks,
                header_type=HEADER_TYPE.H3,
                empty_message='This playbook does not use any sub-playbooks.'))

        doc.extend(
            generate_list_section(
                'Integrations',
                integrations,
                header_type=HEADER_TYPE.H3,
                empty_message='This playbook does not use any integrations.'))

        doc.extend(
            generate_list_section(
                'Scripts',
                scripts,
                header_type=HEADER_TYPE.H3,
                empty_message='This playbook does not use any scripts.'))

        doc.extend(
            generate_list_section(
                'Commands',
                commands,
                header_type=HEADER_TYPE.H3,
                empty_message='This playbook does not use any commands.'))

        doc.extend(
            generate_table_section(inputs, 'Playbook Inputs',
                                   'There are no inputs for this playbook.'))

        doc.extend(
            generate_table_section(outputs, 'Playbook Outputs',
                                   'There are no outputs for this playbook.'))

        # Known limitations
        if limitations:
            doc.extend(
                generate_numbered_section('Known Limitations', limitations))

        doc.append('## Playbook Image\n---')
        doc.append(f'![{_name}](Insert the link to your image here)')

        doc_text = '\n'.join(doc)

        save_output(output, f'{playbook_filename}_README.md', doc_text)

        if errors:
            print_warning('Possible Errors:')
            for error in errors:
                print_warning(error)

    except Exception as ex:
        if verbose:
            raise
        else:
            print_error(f'Error: {str(ex)}')
            return
コード例 #12
0
def generate_script_doc(input, output, examples, id_set='', verbose=False):
    try:
        doc = []
        errors = []
        used_in = []
        example_section = []

        if examples:
            if not examples.startswith('!'):
                examples = f'!{examples}'

            example_dict, build_errors = build_example_dict([examples])
            script_name = examples.split(' ')[0][1:]
            example_section, example_errors = generate_script_example(
                script_name, example_dict)
            errors.extend(build_errors)
            errors.extend(example_errors)
        else:
            errors.append(
                f'Note: Script example was not provided. For a more complete documentation,run with the -e '
                f'option with an example command. For example: -e "!ConvertFile entry_id=<entry_id>".'
            )

        script = get_yaml(input)

        # get script data
        secript_info = get_script_info(input)
        script_id = script.get('commonfields')['id']

        # get script dependencies
        dependencies, _ = get_depends_on(script)

        if not id_set:
            errors.append(f'id_set.json file is missing')
        elif not os.path.isfile(id_set):
            errors.append(f'id_set.json file {id_set} was not found')
        else:
            used_in = get_used_in(id_set, script_id)

        description = script.get('comment', '')
        deprecated = script.get('deprecated', False)
        # get inputs/outputs
        inputs, inputs_errors = get_inputs(script)
        outputs, outputs_errors = get_outputs(script)

        errors.extend(inputs_errors)
        errors.extend(outputs_errors)

        if not description:
            errors.append(
                'Error! You are missing description for the playbook')

        if deprecated:
            doc.append('`Deprecated`')

        doc.append(description)

        doc.extend(generate_table_section(secript_info, 'Script Data'))

        if dependencies:
            doc.extend(
                generate_list_section(
                    'Dependencies',
                    dependencies,
                    True,
                    text='This script uses the following commands and scripts.'
                ))

        if used_in:
            doc.extend(
                generate_list_section(
                    'Used In',
                    used_in,
                    True,
                    text=
                    'This script is used in the following playbooks and scripts.'
                ))

        doc.extend(
            generate_table_section(inputs, 'Inputs',
                                   'There are no inputs for this script.'))

        doc.extend(
            generate_table_section(outputs, 'Outputs',
                                   'There are no outputs for this script.'))

        if example_section:
            doc.extend(example_section)

        doc_text = '\n'.join(doc)

        save_output(output, 'README.md', doc_text)

        if errors:
            print_warning('Possible Errors:')
            for error in errors:
                print_warning(error)

    except Exception as ex:
        if verbose:
            raise
        else:
            print_error(f'Error: {str(ex)}')
            return
コード例 #13
0
def generate_script_doc(input,
                        examples,
                        output: str = None,
                        permissions: str = None,
                        limitations: str = None,
                        insecure: bool = False,
                        verbose: bool = False):
    try:
        doc = []
        errors = []
        used_in = []
        example_section = []

        if not output:  # default output dir will be the dir of the input file
            output = os.path.dirname(os.path.realpath(input))

        if examples:
            if not examples.startswith('!'):
                examples = f'!{examples}'

            example_dict, build_errors = build_example_dict([examples],
                                                            insecure)
            script_name = examples.split(' ')[0][1:]
            example_section, example_errors = generate_script_example(
                script_name, example_dict)
            errors.extend(build_errors)
            errors.extend(example_errors)
        else:
            errors.append(
                f'Note: Script example was not provided. For a more complete documentation,run with the -e '
                f'option with an example command. For example: -e "!ConvertFile entry_id=<entry_id>".'
            )

        script = get_yaml(input)

        # get script data
        secript_info = get_script_info(input)
        script_id = script.get('commonfields')['id']

        # get script dependencies
        dependencies, _ = get_depends_on(script)

        # get the script usages by the id set
        id_set_creator = IDSetCreator()
        id_set = id_set_creator.create_id_set()
        used_in = get_used_in(id_set, script_id)

        description = script.get('comment', '')
        deprecated = script.get('deprecated', False)
        # get inputs/outputs
        inputs, inputs_errors = get_inputs(script)
        outputs, outputs_errors = get_outputs(script)

        errors.extend(inputs_errors)
        errors.extend(outputs_errors)

        if not description:
            errors.append(
                'Error! You are missing description for the playbook')

        if deprecated:
            doc.append('`Deprecated`')

        doc.append(description)

        doc.extend(generate_table_section(secript_info, 'Script Data'))

        if dependencies:
            doc.extend(
                generate_list_section(
                    'Dependencies',
                    dependencies,
                    True,
                    text='This script uses the following commands and scripts.'
                ))

        # Script global permissions
        if permissions == 'general':
            doc.extend(generate_section('Permissions', ''))

        if used_in:
            doc.extend(
                generate_list_section(
                    'Used In',
                    used_in,
                    True,
                    text=
                    'This script is used in the following playbooks and scripts.'
                ))

        doc.extend(
            generate_table_section(inputs, 'Inputs',
                                   'There are no inputs for this script.'))

        doc.extend(
            generate_table_section(outputs, 'Outputs',
                                   'There are no outputs for this script.'))

        if example_section:
            doc.extend(example_section)

        # Known limitations
        if limitations:
            doc.extend(
                generate_numbered_section('Known Limitations', limitations))

        doc_text = '\n'.join(doc)

        save_output(output, 'README.md', doc_text)

        if errors:
            print_warning('Possible Errors:')
            for error in errors:
                print_warning(error)

    except Exception as ex:
        if verbose:
            raise
        else:
            print_error(f'Error: {str(ex)}')
            return