Пример #1
0
def test_workflow_transform_skillet():
    """

    Load and execute the workflow skillet and ensure all child skillets are executed properly

    :return: None
    """
    skillet_path = '../example_skillets/workflow_transform/'
    skillet_loader = SkilletLoader(path=skillet_path)
    skillet: Skillet = skillet_loader.get_skillet_with_name(
        'workflow_transform')
    # verify we can find and load the correct skillet
    assert skillet.name == 'workflow_transform'

    out = skillet.execute(context)

    assert 'pan_validation' in out

    assert 'outputs' in out

    assert 'snippets' in out

    for k, v in out.get('pan_validation', {}).items():
        r = str(v.get('results', 'False'))
        print(f'{k:60}{r}')
        assert r == 'True'

    assert 'zones' in skillet.context
Пример #2
0
def debug_snippets_in_repo(directory: Path, err_list: list) -> list:
    sl = SkilletLoader()

    all_skillets = sl.load_all_skillets_from_dir(directory)

    for e in sl.skillet_errors:
        err_detail = dict()
        err_detail['severity'] = 'error'

        if type(e) is dict:
            err_detail['path'] = e.get('path', str(directory.absolute()))
            err_detail['err_list'] = [
                e.get('error', 'Could not load Skillet YAML')
            ]
        else:
            err_detail['path'] = str(directory.absolute())
            err_detail['err_list'] = [e]

        err_list.append(err_detail)

    for skillet in all_skillets:
        debug_errors = sl.debug_skillet_structure(skillet.skillet_dict)
        if debug_errors:
            err_detail = dict()
            err_detail['path'] = skillet.path
            err_detail['severity'] = 'error'
            err_detail['err_list'] = debug_errors

            err_list.append(err_detail)

    return err_list
Пример #3
0
def test_workflow_skillet():
    """

    Load and execute the workflow skillet and ensure all child skillets are executed properly

    :return: None
    """
    skillet_path = '../example_skillets/workflow_example/'
    skillet_loader = SkilletLoader(path=skillet_path)
    skillet: Skillet = skillet_loader.get_skillet_with_name(
        'example_workflow_with_filtering')
    # verify we can find and load the correct skillet
    assert skillet.name == 'example_workflow_with_filtering'

    out = skillet.execute(context)
    assert 'pan_validation' in out

    assert 'outputs' in out

    assert 'snippets' in out

    # ensure the correct number of tests are included and executed and reported in the output
    assert len(out['pan_validation']) == 6

    # ensure all three snippets were found and executed
    assert len(skillet.snippet_outputs) == 3
Пример #4
0
    def load_skillet_by_name(self, skillet_name) -> (dict, None):
        """
        Loads application specific skillet

        :param skillet_name:
        :return:
        """

        all_skillets = cnc_utils.get_long_term_cached_value(
            self.app_dir, 'all_snippets')
        if not all_skillets:
            all_skillets = list()
            application_skillets_dir = Path(
                os.path.join(settings.SRC_PATH, self.app_dir, 'snippets'))
            skillet_loader = SkilletLoader()
            app_skillets = skillet_loader.load_all_skillets_from_dir(
                application_skillets_dir)
            for s in app_skillets:
                all_skillets.append(s.skillet_dict)

            cnc_utils.set_long_term_cached_value(self.app_dir, 'all_snippets',
                                                 all_skillets, -1)

        for skillet in all_skillets:
            if skillet['name'] == skillet_name:
                return skillet

        return None
Пример #5
0
def refresh_skillets_from_repo(repo_name: str) -> list:
    all_skillets = list()

    user_dir = os.path.expanduser('~/.pan_cnc')

    app_name = get_default_app_name()
    snippets_dir = os.path.join(user_dir, app_name, 'repositories')
    repo_dir = os.path.join(snippets_dir, repo_name)

    if not os.path.exists(repo_dir):
        print(f'Repository {repo_dir} does not exist!')
        return all_skillets

    try:
        repo_object = RepositoryDetails.objects.get(name=repo_name)

        sl = SkilletLoader()

        found_skillets = sl.load_all_skillets_from_dir(repo_dir)

        for skillet_object in found_skillets:
            skillet_name = skillet_object.name
            (skillet_record, created) = Skillet.objects.get_or_create(
                name=skillet_name,
                defaults={
                    'skillet_json': json.dumps(skillet_object.skillet_dict),
                    'repository_id': repo_object.id,
                }
            )

            if not created:
                if skillet_record.repository_id == repo_object.id:
                    # check if skillet contents have been updated
                    found_skillet_json = json.dumps(skillet_object.skillet_dict)
                    if skillet_record.skillet_json != found_skillet_json:
                        skillet_record.skillet_json = found_skillet_json
                        skillet_record.save()
                else:
                    print(f'Found existing skillet from another repository: {skillet_name}!!')
                    raise DuplicateSkilletException(
                        f'Refusing to import duplicate Skillet: {skillet_name}'
                    )

        for db_skillet in repo_object.skillet_set.all():
            found = False
            for found_skillet in found_skillets:
                if db_skillet.name == found_skillet.name:
                    found = True
                    continue

            if not found:
                db_skillet.delete()

        update_skillet_cache()

        return load_skillets_from_repo(repo_name)

    except ObjectDoesNotExist:
        return all_skillets
def cli(target_ip, target_port, target_username, target_password, include_svc_setup, infra_subnet, infra_bgp_as,
        portal_hostname, deployment_region, deployment_locations_americas, deployment_locations_europe,
        deployment_locations_apac, ip_pool_cidr, user1_password, user2_password, conf_filename):
    """
    Import a full configuration. Defaults values in parenthesis.
    """

    # creating the jinja context from the skillet vars
    print('Reading in skillet variables')
    context = dict()
    context['include_svc_setup'] = include_svc_setup
    context['infra_subnet'] = infra_subnet
    context['infra_bgp_as'] = infra_bgp_as
    context['portal_hostname'] = portal_hostname
    context['deployment_region'] = deployment_region
    context['deployment_locations_americas'] = deployment_locations_americas.split(',')
    context['deployment_locations_europe'] = deployment_locations_europe.split(',')
    context['deployment_locations_apac'] = deployment_locations_apac.split(',')
    context['ip_pool_cidr'] = ip_pool_cidr
    context['user1_password'] = user1_password
    context['user2_password'] = user2_password
    context['conf_filename'] = conf_filename


    try:
        # render the template config file and create file_contents to use with import_file
        print('Creating the configuration file')
        sl = SkilletLoader()
        skillet = sl.load_skillet_from_path('../mobile_full_config')
        output = skillet.execute(context)
        file_contents = output.get('template', '')

        # create device object and use panoply import_file to send a config file to the device
        print('Import the config file to Panorama')
        device = Panos(api_username=target_username,
                       api_password=target_password,
                       hostname=target_ip,
                       api_port=target_port
                       )

        if not device.import_file(conf_filename, file_contents, 'configuration'):
            exit(1)

        exit(0)

    except LoginException as lxe:
        print(lxe)
        exit(1)
    except SkilletLoaderException as pe:
        print(pe)
        exit(1)

    # failsafe
    exit(1)

    print('File import complete')
Пример #7
0
def load_and_dump_skillet(skillet_path: str) -> str:
    skillet_loader = SkilletLoader()
    skillet = skillet_loader.load_skillet_from_path(skillet_path)

    print('=' * 80)
    print(f'Checking {skillet.label}\n'.center(80))

    output: str = skillet.dump_yaml()

    return output
Пример #8
0
def load_and_execute_skillet(skillet_path: str) -> dict:
    skillet_loader = SkilletLoader()
    skillet = skillet_loader.load_skillet_from_path(skillet_path)

    print('=' * 80)
    print(f'Executing {skillet.label}\n'.center(80))

    output: dict = skillet.execute(context)

    return output
Пример #9
0
def test_get_skillet_by_name():
    """
    Test to verify skilletLoader can successfully load all skillets found in the 'skillet_incluedes'
    directory and return the one with the 'include_other_skillets' name

    :return: None
    """
    skillet_path = '../example_skillets/skillet_includes/'
    skillet_loader = SkilletLoader(path=skillet_path)
    skillet = skillet_loader.get_skillet_with_name('include_other_skillets')
    assert skillet is not None
Пример #10
0
def test_load_skillet():
    """
    Test to verify skilletLoader can successfully load all skillets found in the 'workflow_example'
    directory and return the one with the 'example_workflow_with_filtering' name

    :return: None
    """
    skillet_path = '../example_skillets/workflow_example/'
    skillet_loader = SkilletLoader(path=skillet_path)
    skillet = skillet_loader.get_skillet_with_name(
        'example_workflow_with_filtering')
    assert skillet is not None
Пример #11
0
def test_skillet_includes():
    """
    Tests to verify the Skillet object is successfully compiled from all included skillets.
    The 'include_other_skillets' skillet includes snippets and variables from two other skillets
    in the same directory

    :return: None
    """
    skillet_path = '../example_skillets/skillet_includes/'
    skillet_loader = SkilletLoader(path=skillet_path)
    skillet: Skillet = skillet_loader.get_skillet_with_name(
        'include_other_skillets')
    # verify we can find and load the correct skillet
    assert skillet.name == 'include_other_skillets'

    # verify the correct number of snippets.
    assert len(skillet.snippets) == 9

    included_snippet: Snippet = skillet.get_snippet_by_name(
        'network_profiles.check_network_profiles')

    # verify we can get an included snippet from the skillet object
    assert included_snippet is not None

    # verify the 'label' metadata attribute has been overridden correctly
    assert included_snippet.metadata.get(
        'label', '') == 'Check Network Profiles Override'

    included_variable: dict = skillet.get_variable_by_name('another_variable')

    # verify the included variable is present in the compiled skillet
    assert included_variable is not None

    # verify the default value is correctly overridden from the included variable
    assert included_variable.get('default', '') == 'test123456'

    second_included_variable: dict = skillet.get_variable_by_name(
        'some_update_variable')
    assert second_included_variable is not None

    another_included_variable: dict = skillet.get_variable_by_name(
        'zone_to_test')
    assert another_included_variable["default"] == "untrust"

    # Ensure using includes / overrides leaves our original skillet definition intact
    # added for issue #163
    child_skillet: Skillet = skillet_loader.get_skillet_with_name(
        'network_profiles')
    child_snippet: Snippet = child_skillet.get_snippet_by_name(
        'check_network_profiles')

    assert child_snippet.metadata.get('label',
                                      '') == 'Ensure Named profile exists'
Пример #12
0
def cli(skillet_path, target_ip, target_port, target_username, target_password, env_file):
    """
    Load the Skillet from the command line.  Defaults values in parenthesis.
    """

    try:
        sl = SkilletLoader()
        skillet = sl.load_skillet_from_path(skillet_path)

        if env_file is not None:
            try:
                with open(env_file, 'r') as ef:
                    context = yaml.safe_load(ef.read())
            except yaml.YAMLError:
                context = os.environ.copy()
        else:
            context = skillet.update_context(os.environ.copy())

        if skillet.type == 'panos':
            device = Panos(api_username=target_username,
                           api_password=target_password,
                           hostname=target_ip,
                           api_port=target_port
                           )

            skillet.panoply = device
            output = skillet.execute(context)
            # FIXME - context should always include a key indicating success / failure of the given skillet
            # we may need situations where a failure doesn't necessarily raise an exception and we should handle
            # this here. Possibly for things likes like - skillet already applied, no action taken, or some
            # check failed...
            if output.get('result', 'failure') == 'success':
                msg = device.commit()
                # msg = 'no commit for testing, commit commented out for now'
                print(f'Successfully executed Skillet {skillet.name} for host: {target_ip}')
                print(f'commit message was: {msg}')
                print(f'output was: {context}')
                exit(0)
            else:
                exit(1)

    except LoginException as lxe:
        print(lxe)
        exit(1)
    except SkilletLoaderException as lde:
        print(lde)
        exit(1)

    # failsafe
    exit(1)
Пример #13
0
def refresh_skillets_from_repo(repo_name: str) -> list:
    all_skillets = list()

    user_dir = os.path.expanduser('~/.pan_cnc')

    app_name = get_default_app_name()
    snippets_dir = os.path.join(user_dir, app_name, 'repositories')
    repo_dir = os.path.join(snippets_dir, repo_name)

    try:
        repo_object = RepositoryDetails.objects.get(name=repo_name)

        sl = SkilletLoader()

        found_skillets = sl.load_all_skillets_from_dir(repo_dir)

        for skillet_object in found_skillets:
            skillet_name = skillet_object.name
            (skillet_record, created) = Skillet.objects.get_or_create(
                name=skillet_name,
                defaults={
                    'skillet_json': json.dumps(skillet_object.skillet_dict),
                    'repository_id': repo_object.id,
                })

            if not created:
                # check if skillet contents have been updated
                found_skillet_json = json.dumps(skillet_object.skillet_dict)
                if skillet_record.skillet_json != found_skillet_json:
                    skillet_record.skillet_json = found_skillet_json
                    skillet_record.save()

        for db_skillet in repo_object.skillet_set.all():
            found = False
            for found_skillet in found_skillets:
                if db_skillet.name == found_skillet.name:
                    found = True
                    continue

            if not found:
                db_skillet.delete()

        update_skillet_cache()

        return load_skillets_from_repo(repo_name)

    except ObjectDoesNotExist:
        return all_skillets
Пример #14
0
def test_load_skillet_from_path():
    skillet_path = '../example_skillets/skillet_includes/include_other_skillets.skillet.yaml'
    skillet_loader = SkilletLoader()
    skillet = skillet_loader.load_skillet_from_path(skillet_path)

    # verify we can find and load the correct skillet
    assert skillet.name == 'include_other_skillets'

    # verify the correct number of snippets.
    assert len(skillet.snippets) == 9

    included_snippet: Snippet = skillet.get_snippet_by_name(
        'network_profiles.check_network_profiles')

    # verify we can get an included snippet from the skillet object
    assert included_snippet is not None
Пример #15
0
def main():
    # define available arguments/parameters a user can pass to the module
    module_args = dict(skillet=dict(type='str', required=True),
                       skillet_path=dict(type='str', required=True),
                       vars=dict(type='dict'),
                       provider=dict(type='dict', required=True))

    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=False,
    )

    # create our context dict. Every skillet requires a context that contains connection information
    # as well as any vars required for that particular skillet

    skillet_context = dict()
    skillet_context.update(module.params['vars'])
    skillet_context.update(module.params['provider'])

    skillet_loader = SkilletLoader(module.params['skillet_path'])

    skillet = skillet_loader.get_skillet_with_name(module.params['skillet'])

    if skillet is None:
        module.fail_json(msg='Could not find Skillet with name {0}'.format(
            module.params['name']))

    # refuse to run any non panos / panorama skillet types
    if not skillet.type == 'pan_validation':
        module.fail_json(msg='Invalid Skillet Type')

    try:
        output = skillet.execute(skillet_context)
        output_str = json.dumps(output)

        for snippet in output['pan_validation']:
            if not output['pan_validation'][snippet]['results']:
                module.fail_json(msg=output_str)

        module.exit_json(changed=False, stdout=output_str)

    except PanoplyException as p:
        module.fail_json(msg='{0}'.format(p))
Пример #16
0
def load_and_execute_skillet(skillet_path: str) -> None:
    skillet_loader = SkilletLoader(path=skillet_path)
    skillet = skillet_loader.skillets[0]
    print('=' * 80)
    print(f'Executing {skillet.label}\n'.center(80))

    output = skillet.execute(context)

    if 'pan_validation' in output:
        for k, v in output.get('pan_validation', {}).items():
            r = str(v.get('results', 'False'))
            print(f'{k:60}{r}')
            assert r == 'True'
Пример #17
0
def cli(skillet_path, target_ip, target_port, target_username,
        target_password):
    """
    Load the Skillet from the command line.  Defaults values in parenthesis.
    """

    try:
        sl = SkilletLoader()
        skillet = sl.load_skillet_from_path(skillet_path)
        context = skillet.update_context(os.environ.copy())

        if skillet.type == 'panos':
            device = Panoply(api_username=target_username,
                             api_password=target_password,
                             hostname=target_ip,
                             api_port=target_port)

            # set the device object on the skillet object
            skillet.panoply = device
            skillet.execute(context)
            print('Performing Commit')
            device.commit()
            print(
                f'Successfully pushed Skillet {skillet.name} to host: {target_ip}'
            )
            exit(0)

    except LoginException as lxe:
        print(lxe)
        exit(1)
    except SkilletLoaderException as lde:
        print(lde)
        exit(1)

    # failsafe
    exit(1)
Пример #18
0
def cli(skillet_path, target_ip, target_port, target_username,
        target_password):
    """
    Render a full configuration template, import it into the device and load it
    """

    try:
        # ensure skillet_path contains the skillet you want as this will just load them all
        sl = SkilletLoader(skillet_path)
        # grab first skillet from list
        skillet = sl.skillets[0]

        # this allows any variables needed for the template skillet too be passed in
        # via env vars. Especially useful for Jenkins and docker type deployments
        context = skillet.update_context(os.environ.copy())

        if skillet.type == 'template':
            device = Panoply(api_username=target_username,
                             api_password=target_password,
                             hostname=target_ip,
                             api_port=target_port)
            output = skillet.execute(context)
            template = output.get('template', None)
            if template is None:
                print('Could not render template')
                exit(1)

            snippet = skillet.snippet_stack[0]
            device.import_file(snippet.get('name', 'loaded_config'), template,
                               'configuration')
            device.load_config(snippet.get('name', 'loaded_config'))
            print('Performing commit...')
            device.commit()
            print(
                f'Successfully imported and loaded Skillet {skillet.name} to host: {target_ip}'
            )
            exit(0)

    except LoginException as lxe:
        print(lxe)
        exit(1)
    except SkilletLoaderException as lde:
        print(lde)
        exit(1)

    # failsafe
    exit(1)
Пример #19
0
    print('Appetizer Configuration file already found!')
    exit(0)

print('Building Appetizer Configuration ...')

repo = os.environ.get(
    'REPO', 'https://github.com/PaloAltoNetworks/SkilletBuilder.git')
repo_branch = os.environ.get('BRANCH', 'master')
repo_name = os.environ.get('NAME', 'appetizer')

local_dir = os.path.expanduser('~/.pan_cnc/appetizer/repositories')

if not os.path.exists(local_dir):
    os.makedirs(local_dir)

sl = SkilletLoader()

repo_full_dir = os.path.join(local_dir, repo_name)
if os.path.exists(repo_full_dir):
    print('Using local dir')
    all_skillets = sl.load_all_skillets_from_dir(repo_full_dir)
else:
    print(f'Pulling anew into {local_dir}')
    # do not check for self signed certs here
    os.environ['GIT_SSL_NO_VERIFY'] = "1"
    all_skillets = sl.load_from_git(repo,
                                    repo_name,
                                    repo_branch,
                                    local_dir=local_dir)

src_dir = os.path.join(repo_full_dir, 'src')
Пример #20
0
#!/usr/bin/env python3

from skilletlib import SkilletLoader

sl = SkilletLoader('.')

skillet = sl.get_skillet_with_name('panos_cli_example')

context = dict()
context['cli_command'] = 'show system info'
context['username'] = '******'
context['password'] = '******'
context['ip_address'] = 'NOPE'

output = skillet.execute(context)

print(output.get('output_template', 'n/a'))

def test_skillet_includes():
    """
    Tests to verify the Skillet object is successfully compiled from all included skillets.
    The 'include_other_skillets' skillet includes snippets and variables from two other skillets
    in the same directory

    :return: None
    """
    skillet_path = '../example_skillets/skillet_includes/'
    skillet_loader = SkilletLoader(path=skillet_path)
    skillet: Skillet = skillet_loader.get_skillet_with_name(
        'include_other_skillets')
    # verify we can find and load the correct skillet
    assert skillet.name == 'include_other_skillets'
    # verify the correct number of snippets.
    assert len(skillet.snippets) == 14

    # Check that parent snippets and variables are brought in correctly
    not_included_snippet: Snippet = skillet.get_snippet_by_name('parse_config')
    # verify that non-included snippets are appended to the skillet, from include_other_skillets
    assert not_included_snippet is not None

    parent_preserve_variable: dict = skillet.get_variable_by_name(
        'shared_base_variable')
    # verify that the override variables brought up to the parent are preserved
    assert "toggle_hint" not in parent_preserve_variable

    # Check that a snippet of this format is brought in correctly
    #       - name: something
    #         include: child_skillet
    simple_include_snippet: Snippet = skillet.get_snippet_by_name(
        'update_schedule.get_update_schedule')
    # verify that snippet with just include: keyword is brought in properly, from update_schedule
    assert simple_include_snippet is not None

    simple_include_variable: dict = skillet.get_variable_by_name(
        'some_update_variable')
    # verify that variable with just include: keyword is brought in properly, from update_schedule
    assert simple_include_variable is not None

    # Check that a snippet of this format is brought in correctly
    #       - name: something
    #         include: child_skillet
    #         include_snippets:
    #           - name: snippet_1
    #             attribute:
    included_snip_only_snippet: Snippet = skillet.get_snippet_by_name(
        'network_profiles.check_network_profiles')
    # verify we can get an included snippet from the skillet object
    assert included_snip_only_snippet is not None
    # verify the 'label' metadata attribute has been overridden correctly
    assert included_snip_only_snippet.metadata.get(
        'label', '') == 'Check Network Profiles Override'

    included_snip_only_variable: dict = skillet.get_variable_by_name(
        'another_variable')
    # verify the child variable is present in compiled skillet
    assert included_snip_only_variable is not None

    # Check that a snippet of this format is brought in correctly
    #       - name: something
    #         include: child_skillet
    #         include_variables:
    #           - name: variable_1
    #             attribute:
    included_var_only_snippet: Snippet = skillet.get_snippet_by_name(
        'check_zones.ensure_desired_zone')
    # verify we can get an included snippet from the skillet object
    assert included_var_only_snippet is not None

    included_var_only_variable: dict = skillet.get_variable_by_name(
        'zone_to_test')
    # verify the child's default gets overridden because of the parent's attribute definition
    assert included_var_only_variable["default"] == "untrust"

    # Check that a snippet of this format is brought in correctly
    #       - name: something
    #         include: child_skillet
    #         include_variables:
    #           - name: all
    #             attribute:
    merge_snip_snippet: Snippet = skillet.get_snippet_by_name(
        "qos_class.qos_parse")
    # verify that the snippets get added to compiled snippet
    assert merge_snip_snippet is not None

    merged_override_from_all_variable: dict = skillet.get_variable_by_name(
        'qos_class')
    # verify that shared children variables merge attributes
    assert merged_override_from_all_variable["toggle_hint"] is not None
    assert "internet" in merged_override_from_all_variable["toggle_hint"][
        "value"]
    assert "untrust" in merged_override_from_all_variable["toggle_hint"][
        "value"]

    child_override_1_variable: dict = skillet.get_variable_by_name(
        'child_1_unique_variable')
    # verify that child override works
    assert child_override_1_variable["toggle_hint"] is not None

    child_override_2_variable: dict = skillet.get_variable_by_name(
        'child_2_unique_variable')
    # verify that child override works
    assert child_override_2_variable["toggle_hint"] is not None

    # Added for issue #163
    child_skillet: Skillet = skillet_loader.get_skillet_with_name(
        'network_profiles')
    child_snippet: Snippet = child_skillet.get_snippet_by_name(
        'check_network_profiles')
    # ensure using includes / overrides leaves our original skillet definition intact
    assert child_snippet.metadata.get('label',
                                      '') == 'Ensure Named profile exists'
    print('Error Executing Skillet')
    print(se)
    sys.exit(1)
except LoginException as le:
    print('Error Logging into device')
    print(le)
    sys.exit(1)

# check we actually have some diffs
if len(snippets) == 0:
    print('No Diffs found between these two configs')

    sys.exit(2)

# SkilletLoader is used to... Load Skillets
skillet_loader = SkilletLoader()

# create_skillet will return a Skillet Object from the metadata dictionary passed in.
# in this case, we create a minimal metadata dict and pass it in to create a simple 'template' skillet
# a template skillet is a nice wrapper around the jinja engine
template_skillet = skillet_loader.create_skillet(
    {'type': 'template',
     'snippets': [
         {'name': 'template', 'file': './ansible_pb_template.j2'}
     ]
     }
)

# to execute this skillet, create the context object which includes any variables found in the template file
context = dict()
context['snippets'] = snippets
Пример #23
0
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

# Authors: Nathan Embery

from skilletlib import SkilletLoader

# use skilletLoader from skilletlib to load and execute the skillet
sl = SkilletLoader()

# our skillet is located in the same directory
skillet = sl.load_skillet_from_path('.')

# each skillet can specify what items are customizable.
# Create a context dictionary to hold our customized variables for this execution.
context = dict()
context['username'] = '******'
context['password'] = '******'
context['ip_address'] = '10.10.10.10'

# This Ansible playbook may take a very long time. Use the 'execute_async' method to poll for the output as it happens
# As with the execute method, we pass in our context object
# The primary different is 'execute_async' returns a generator that we can iterate over to get the output as it happens
# from the docker container
Пример #24
0
    except LoginException as le:
        print('Error Logging into device')
        print(le)
        exit(1)

else:
    config = os.environ.get('config', '')

skillet_content_raw = os.environ.get('SKILLET_CONTENT', '')
debug = os.environ.get('DEBUG', False)

# because we are passing this value around, we may need to unescape it here
skillet_content = html.unescape(skillet_content_raw)

sl = SkilletLoader()
# get the full contents of the environment to initialize the skillet context
try:

    context = dict()
    context['config'] = config

    # create the skillet definition from the 'skillet_content' dict we got from the environ
    skillet_dict_raw = oyaml.safe_load(skillet_content)

    # use skilletLoader to normalize the skillet definition and fix common config file errors
    skillet_dict = sl.normalize_skillet_dict(skillet_dict_raw)
    skillet_dict['snippet_path'] = '.'

    # create the skillet object from the skillet dict
    if 'pan_validation' in skillet_dict.get('type'):
Пример #25
0
def execute_docker_skillet(skillet_def: dict, args: dict) -> str:
    """
    Execute a skillet of type 'docker'. This requires the calling application have access to the
    docker socket

    :param skillet_def: the skillet as loaded from the YAML file (dict)
    :param args: context arguments required for the given skillets. These will overwrite the 'variables' in the
    skillet
    :return: JSON encoded string with dict containing the following keys: {'returncode', 'out', 'err'}
    """
    state = dict()
    full_output = ''
    err = ''
    rc = 0

    docker_helper = DockerHelper()

    if skillet_def['type'] != 'docker' and skillet_def['type'] != 'terraform':
        rc = 255
        err = f'Not a valid skillet type: {skillet_def["type"]}!'

    elif not docker_helper.check_docker_server():
        rc = 240
        err = 'Could not connect to Docker daemon, verify permissions on the docker socket! \n\n' \
              'See the documentation for details: https://panhandler.readthedocs.io/en/master/debugging.html'

    else:
        try:
            persistent_volumes = docker_helper.get_cnc_volumes()

            if 'app_data' not in skillet_def:
                skillet_def['app_data'] = dict()

            # always overwrite any volumes that may have snuck in here
            if persistent_volumes:
                skillet_def['app_data']['volumes'] = persistent_volumes

            else:
                # only this app should be setting app_data/volumes here, remove anything else
                if 'volumes' in skillet_def['app_data']:
                    skillet_def['app_data'].pop('volumes')

            sl = SkilletLoader()
            skillet = sl.create_skillet(skillet_def)

            # FIX for #181
            sanitized_args = __santize_args(args)

            output_generator = skillet.execute_async(sanitized_args)

            for out in output_generator:
                full_output += out
                current_task.update_state(state='PROGRESS', meta=full_output)

            r = skillet.get_results()

            # FIXME - docker skillets can run multiple snippets / cmds inside the container
            # should check for the output of each and determine if a single failure is considered a failure
            # for the entire skillet or only a failure for one step ?
            if isinstance(r, dict) and 'snippets' in r:
                for k, v in r['snippets'].items():
                    result = v.get('results', 'failure')

                    if result == 'success':
                        full_output = v.get('raw', '')
                    elif result == 'error' or 'fail' in result:
                        err = v.get('raw', 'error')
                        rc = 2
                    else:
                        full_output = v.get('raw', '')
                        err = f'Unknown return value type {result}'
                        rc = 3
            else:
                full_output = r
                err = 'unknown output from skillet'

        except DockerHelperException as dee:
            logger.error(dee)
            rc = 1
            err = str(dee)

        except SkilletLoaderException as sle:
            logger.error(sle)
            rc = 1
            err = str(sle)

    state['returncode'] = rc
    state['out'] = full_output
    state['err'] = err

    return json.dumps(state)
    print("Error Executing Skillet")
    print(se)
    sys.exit(1)
except LoginException as le:
    print("Error Logging into device")
    print(le)
    sys.exit(1)

# check we actually have some diffs
if len(snippets) == 0:
    print("No Diffs found between these two configs")

    sys.exit(2)

# SkilletLoader is used to... Load Skillets
skillet_loader = SkilletLoader()

# create_skillet will return a Skillet Object from the metadata dictionary passed in.
# in this case, we create a minimal metadata dict and pass it in to create a simple 'template' skillet
# a template skillet is a nice wrapper around the jinja engine
template_skillet = skillet_loader.create_skillet(
    {"type": "template", "snippets": [{"name": "template", "file": "./ansible_pb_template.j2"}]}
)

# to execute this skillet, create the context object which includes any variables found in the template file
context = dict()
context["snippets"] = snippets
context["playbook_name"] = "Auto Generated PAN-OS Playbook"
# execute the template skillet and get the returned output
output = template_skillet.execute(context)