Skip to content
This repository was archived by the owner on Dec 11, 2023. It is now read-only.

First pass at a lambda-supporting combination class#15

Merged
ArtificialErmine merged 8 commits intomitre-attack:masterfrom
ArtificialErmine:layerops
May 5, 2020
Merged

First pass at a lambda-supporting combination class#15
ArtificialErmine merged 8 commits intomitre-attack:masterfrom
ArtificialErmine:layerops

Conversation

@ArtificialErmine
Copy link
Copy Markdown
Contributor

Adds support for custom combinations of attack layers.

Example usage:
from layerops import layerops

obj = layerops([layer_data])
obj.process(score=lambda t:t[0] * 2, defaults={'score':3})

@isaisabel isaisabel self-assigned this Jan 16, 2020
@isaisabel isaisabel mentioned this pull request Feb 5, 2020
@beerMT
Copy link
Copy Markdown

beerMT commented Apr 5, 2020

@isaisabel I'm trying to figure out how I can go about testing this functionality for the PR. Currently, if you load layers into /nav-app/src/assets and enable the default_layers property you can load layers. But the example usage code above appears to be python, and I'm trying to figure out what the overall workflow looks like. Really hope this feature gets implemented!

@isaisabel
Copy link
Copy Markdown
Contributor

Hi @beerMT,

This WIP code is designed to work with ATT&CK Navigator layer files independently of the ATT&CK Navigator. The objective is that you should be able to use this in lieu of "create layer from other layers" interface of the Navigator. This implementation would be slightly more powerful (and notably able to be included in automated workflows) than the Navigator interface, but their purposes are the same.

See the example usage at the top of the layerops file for a python usage example. We'll likely be writing additional documentation for how to use the interface before it gets merged.

Comment thread objects/layer.py Outdated
Comment thread scripts/layerops.py Outdated
Comment thread scripts/layerops.py Outdated
Comment thread objects/layer.py Outdated
Comment thread objects/layer.py Outdated
Comment thread objects/layer.py Outdated
Comment thread scripts/layerops.py Outdated
Comment thread scripts/layerops.py Outdated
Comment thread scripts/layerops.py Outdated
@beerMT
Copy link
Copy Markdown

beerMT commented Apr 8, 2020

Hi @beerMT,

This WIP code is designed to work with ATT&CK Navigator layer files independently of the ATT&CK Navigator. The objective is that you should be able to use this in lieu of "create layer from other layers" interface of the Navigator. This implementation would be slightly more powerful (and notably able to be included in automated workflows) than the Navigator interface, but their purposes are the same.

See the example usage at the top of the layerops file for a python usage example. We'll likely be writing additional documentation for how to use the interface before it gets merged.

Thanks for the response on that question. I've noticed in doing multiple layer joins on the Navigator GUI that you can only have 10 layers open. I'm assuming that this limitation would not exist, since that seems to be a browser/UI design decision vs. a coding limitation. Layer joins don't appear to be computationally complex since it's jsons and counting for the most part.

@isaisabel
Copy link
Copy Markdown
Contributor

@beerMT You're correct, the Navigator 10-layer limitation is due to performance issues that arise in that application when more than 10 layers are open simultaneously.

Copy link
Copy Markdown
Contributor

@isaisabel isaisabel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some documentation level feedback proposed a minor change to how the layer classes are imported. A lot of the documentation level stuff is pretty pedantic so if you feel differently about any of the proposed changes please let me know.

Comment thread layers/README.md Outdated
Comment thread layers/README.md Outdated
Comment thread layers/README.md Outdated
Comment thread layers/README.md Outdated
Comment thread layers/README.md Outdated
Comment thread layers/README.md Outdated
Comment thread layers/README.md Outdated
Comment thread layers/README.md Outdated
Comment thread layers/README.md Outdated
Comment thread layers/README.md Outdated
Comment on lines +62 to +85
#### Example Usage
```python
from layers.manipulators.layerops import LayerOps
from layers.core.layer import Layer

demo = Layer()
demo.load_file("C:\Users\attack\Downloads\layer.json")
demo2 = Layer()
demo2.load_input({"name": "example layer", ... })

lo = LayerOps(score=lambda x: x[0] * x[1],
name=lambda x: x[1],
desc=lambda x: "This is an list example")
out_layer = lo.process([demo, demo2])
out_layer.export_file("C:\demo_layer1.json")

lo2 = LayerOps(score=lambda x: x['a'],
color=lambda x: x['b'],
desc=lambda x: "This is a dict example")
out_layer2 = lo2.process({'a': demo, 'b': demo2})
dict_layer = out_layer2.get_dict()
print(dict_layer)
out_layer2.export_file("C:\demo_layer2.json")
``` No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need additional examples here and better explanations about what the existing examples do.

For the additional examples, we should have actual applications of how layerops might be used. Some possibilities:

  • average scores of any number of input layers
  • reverse the score of the input layer (100-x[0] assuming the score is on a 0-100 scale)
  • Merge comments ("; ".join(x) I think?)

Each example should have a comment explaining what that layerops instance's purpose is.

We should also demonstrate the functionality of a single layerops instance being reused. For example, show the "average layers" being used on layers A,B, and then C,D,E in two separate executions.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've got examples for each of these. Let me know what you think.

Copy link
Copy Markdown
Contributor

@isaisabel isaisabel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the neverending review. Should be one of the last passes before it's ready to be merged. Mostly just cleaning up APIs and a few bugs.

Comment thread layers/README.md Outdated
Comment thread layers/README.md
Comment thread layers/README.md
Comment thread layers/README.md
Comment on lines +74 to +75
from layers.manipulators.layerops import LayerOps
from layers.core.layer import Layer
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to work for me:

$ python3
Python 3.7.4 (default, Sep  7 2019, 18:27:02)
[Clang 10.0.1 (clang-1001.0.46.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from layers.core.layer import Layer
>>> from layers.manipulators.layerops import LayerOps
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/isabel/working/temp/attack-scripts/layers/manipulators/layerops.py", line 23, in <module>
    from layers.core import Layer
ImportError: cannot import name 'Layer' from 'layers.core' (unknown location)
>>>

Changing the import at the beginning of the layerops script to from layers.core.layer import Layer seems to fix the issue, but it assumes the working directory is the root of this repo. If I'm running from the layers folder and run from manipulators.layerops import LayerOps, the absolute import breaks.

I'm not sure what the best practice is with this — a relative import, or just tell the user to always import from the repo root folder? If the latter, please specify where this is being run from in the example as well as putting towards the top of the file "all scripts should be imported and run from the root folder of this repository."

Long term if this is going to become a pip package this probably needs to be relative. Not sure if it's worth doing now.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Speaking of importing, this conversation doesn't seem to have been addressed: #15 (comment)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was, I just failed to notice that the updated init.py wasn't included in the update for some reason. I've fixed this, and it appears to work properly from wherever now.

Comment thread layers/core/layer.py Outdated
Comment thread layers/README.md Outdated
Comment thread layers/manipulators/layerops.py Outdated
Comment thread layers/core/layer.py Outdated
Copy link
Copy Markdown
Contributor

@isaisabel isaisabel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still having trouble importing layerops from within the layers folder (see #15 (comment))

Comment thread layers/README.md Outdated
Comment thread layers/README.md Outdated
Comment thread layers/README.md Outdated
Comment thread layers/core/layer.py Outdated
Copy link
Copy Markdown
Contributor

@isaisabel isaisabel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks and works great!

@ArtificialErmine ArtificialErmine merged commit 836c7ae into mitre-attack:master May 5, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants