F5Networks / f5-common-python

Python SDK for configuration and monitoring of F5® BIG-IP® devices via the iControl® REST API.
https://f5-sdk.readthedocs.org
Apache License 2.0
262 stars 135 forks source link

Why is ASM Violations collection not available? #1486

Open sonicblind opened 6 years ago

sonicblind commented 6 years ago

Hi,

I am wondering how can I get a collection of all ASM violations?

To me, the fact that I am able to fetch them via this REST call: https://<hostname>/mgmt/tm/asm/violations/ should be a proof that the F5 API does support this collection.

Why is it then not implemented in f5-common-python? And why is it also missing in ASM namespace in official user guide (page 71)?

I don't understand why is it missing in the ASM namespace, and also not implemented in f5-common-sdk when the API is able to deliver the data for violations?

What am I missing here?

Thanks in advance for any ideas.

Cheers, Martin

sonicblind commented 6 years ago

In case somebody would be interested in the same topic, I managed to fix this for myself by extending the f5-common-python.

Under ./f5/bigip/tm/asm/ I created a new file violations.py as a new module for ASM violations. I used existing module attack_types.py as a template for violations.py.

Then, I altered the existing init.py and made only two simple additions:

Works like a charm.

jasonrahm commented 6 years ago

others will still need this functionality. Feel free to post your code here and I will write tests for it so it can be merged for everyone.

sonicblind commented 6 years ago

Under f5/bigip/tm/asm/ I created a new file called violations.py with this following content. It is basically a copy of attack_types.py from the same directory, I only replaced the necessary names etc.

from f5.bigip.resource import AsmResource
from f5.bigip.resource import Collection
from f5.sdk_exception import UnsupportedOperation

class Violations_s(Collection):
    """BIG-IP ASM Violations collection."""
    def __init__(self, asm):
        super(Violations_s, self).__init__(asm)
        self._meta_data['object_has_stats'] = False
        self._meta_data['allowed_lazy_attributes'] = [Violation]
        self._meta_data['attribute_registry'] = {
            'tm:asm:violations:violationstate': Violation
        }

class Violation(AsmResource):
    """BIG-IP ASM Violation resource"""
    def __init__(self, violations_s):
        super(Violation, self).__init__(violations_s)
        self._meta_data['required_json_kind'] = 'tm:asm:violations:violationstate'

    def create(self, **kwargs):
        """Create is not supported for Violation resource
                :raises: UnsupportedOperation
        """
        raise UnsupportedOperation(
            "%s does not support the create method" % self.__class__.__name__
        )

    def delete(self, **kwargs):
        """Delete is not supported for Violation resource
                :raises: UnsupportedOperation
        """
        raise UnsupportedOperation(
            "%s does not support the delete method" % self.__class__.__name__
        )

    def modify(self, **kwargs):
        """Modify is not supported for Violation resource
                :raises: UnsupportedOperation
        """
        raise UnsupportedOperation(
            "%s does not support the modify method" % self.__class__.__name__
    )

Then I altered the code of f5/bigip/tm/asm/__init__.py. I added only two lines, the last import statement and the last item in self._meta_data['allowed_lazy_attributes']:

from f5.bigip.resource import OrganizingCollection
from f5.bigip.tm.asm.attack_types import Attack_Types_s
from f5.bigip.tm.asm.file_transfer import File_Transfer
from f5.bigip.tm.asm.policies import Policies_s
from f5.bigip.tm.asm.policy_templates import Policy_Templates_s
from f5.bigip.tm.asm.signature_sets import Signature_Sets_s
from f5.bigip.tm.asm.signature_statuses import Signature_Statuses_s
from f5.bigip.tm.asm.signature_systems import Signature_Systems_s
from f5.bigip.tm.asm.signature_update import Signature_Update
from f5.bigip.tm.asm.signatures import Signatures_s
from f5.bigip.tm.asm.tasks import Tasks
from f5.bigip.tm.asm.violations import Violations_s

class Asm(OrganizingCollection):
    """BIG-IP® Application Security Manager (ASM) organizing collection."""

    def __init__(self, tm):
        super(Asm, self).__init__(tm)
        self._meta_data['allowed_lazy_attributes'] = [
            Attack_Types_s,
            File_Transfer,
            Policies_s,
            Policy_Templates_s,
            Signature_Sets_s,
            Signature_Statuses_s,
            Signature_Systems_s,
            Signature_Update,
            Signatures_s,
            Tasks,
        Violations_s,
        ]
sonicblind commented 6 years ago

And here is a simple script which shows how to achieve the same, but without touching the official modules of f5-common-python.


from f5.bigip import ManagementRoot

from f5.sdk_exception import UnsupportedOperation
from f5.bigip.resource import AsmResource
from f5.bigip.resource import Collection

class Violations_s(Collection):
    def __init__(self, asm):
        super(Violations_s, self).__init__(asm)
        self._meta_data['object_has_stats'] = False
        self._meta_data['allowed_lazy_attributes'] = [Violation]
        self._meta_data['attribute_registry'] = {
            'tm:asm:violations:violationstate': Violation
        }

class Violation(AsmResource):
    def __init__(self, violations_s):
        super(Violation, self).__init__(violations_s)
        self._meta_data['required_json_kind'] = 'tm:asm:violations:violationstate'

    def create(self, **kwargs):
        raise UnsupportedOperation(f"{self.__class__.__name__} does not support the create method")

    def delete(self, **kwargs):
        raise UnsupportedOperation(f"{self.__class__.__name__} does not support the delete method")

    def modify(self, **kwargs):
        raise UnsupportedOperation(f"{self.__class__.__name__} does not support the modify method")

mgmt = ManagementRoot(hostname, username, password)

# Get collection of attack types - this is available in f5-common-python
attacks = mgmt.tm.asm.attack_types_s.get_collection(requests_params={'params': '$top=5&$select=id,name'})
for attack in attacks:
    print(attack.id, attack.name)

# Now add violations to available API calls
mgmt.tm.asm._meta_data['allowed_lazy_attributes'].append(Violations_s)

# Get collection of violations - this isn't available in f5-common-python
# But is now since we manually added the functionality
violations = mgmt.tm.asm.violations_s.get_collection(requests_params={'params': '$top=5&$select=id,name'})
for violation in violations:
    print(violation.id, violation.name)
wojtek0806 commented 6 years ago

@sonicblind I would suggest opening a pull request and tests for this, so you can author it? If you are external to F5 we would need you to sign a document (last I check we did that anyway) but it would be great if you coded this and submitted PR.

sonicblind commented 6 years ago

@wojtek0806

I already wrote additional code to enable me to retrieve 'tm:asm:events:requests:requeststate'. This was also not part of the existing distribution.

But I have never done a contribution to GitHub. Don't know how this all works. If you are willing to guide me through, I'll be happy to help.