Repository: mitre-attack/mitreattack-python (language: python)

Issue:
[Bug] Can't load a layer exported from ATT&CK Navigator
## Expected Behavior

No error while importing a layer from ATT&CK Navigator
The zipped layer is here for reference : [layer.zip](https://github.com/mitre-attack/mitreattack-python/files/8112109/layer.zip)
## Actual Behavior

An error is raised, and the layer is not loaded :
``` log
[Layer] - AttributeError encountered ['#ff6666ff' is not in web format. Need 3 or 6 hex digit.]. Unable to load.
[Layer] - Full Traceback - Traceback (most recent call last):
  File "C:\Python310\lib\site-packages\mitreattack\navlayers\core\layer.py", line 97, in _build
    self.__layer._linker(key, self._data[key])
  File "C:\Python310\lib\site-packages\mitreattack\navlayers\core\layerobj.py", line 446, in _linker
    self.gradient = data
  File "C:\Python310\lib\site-packages\mitreattack\navlayers\core\layerobj.py", line 221, in gradient
    self.__gradient = Gradient(gradient['colors'], gradient['minValue'], gradient['maxValue'])
  File "C:\Python310\lib\site-packages\mitreattack\navlayers\core\gradient.py", line 20, in __init__
    self.maxValue = maxValue
  File "C:\Python310\lib\site-packages\mitreattack\navlayers\core\gradient.py", line 52, in maxValue
    self._compute_curve()
  File "C:\Python310\lib\site-packages\mitreattack\navlayers\core\gradient.py", line 64, in _compute_curve
    s_c = colour.Color(self.colors[index-1])
  File "C:\Python310\lib\site-packages\colour.py", line 988, in __init__
    self.web = color if color else 'black'
  File "C:\Python310\lib\site-packages\colour.py", line 1006, in __setattr__
    fc(value)
  File "C:\Python310\lib\site-packages\colour.py", line 1084, in set_web
    self.hex = web2hex(value)
  File "C:\Python310\lib\site-packages\colour.py", line 670, in web2hex
    raise AttributeError(
AttributeError: '#ff6666ff' is not in web format. Need 3 or 6 hex digit.
```
## Steps to Reproduce the Problem

  1. Go to https://mitre-attack.github.io/attack-navigator/
  2. Create an empty enterprise layer
  3. Download the layer into `layer.json`
  4. Load the layer using Python

      ``` python
      from mitreattack.navlayers.core.layer import Layer
      
      test = Layer()
      test.from_file("layer.json")
      ```
 5. Observe the console output 



Discussion / hints:
Thanks for bringing this to our attention! It looks like the export format for navigator may have been updated slightly, which shouldn't be too hard to address.

Fix patch:
diff --git a/mitreattack/navlayers/core/gradient.py b/mitreattack/navlayers/core/gradient.py
index 05caec4f..f95b4a19 100644
--- a/mitreattack/navlayers/core/gradient.py
+++ b/mitreattack/navlayers/core/gradient.py
@@ -28,6 +28,13 @@ def colors(self, colors):
         typeCheckerArray(type(self).__name__, colors, str, "colors")
         self.__colors = []
         for entry in colors:
+            try:
+                colour.Color(entry)
+            except AttributeError:
+                if entry.startswith('#'):
+                    entry = entry[:7]
+                else:
+                    entry = entry[:6]
             self.__colors.append(entry)
         self._compute_curve()
 
diff --git a/mitreattack/navlayers/core/layerobj.py b/mitreattack/navlayers/core/layerobj.py
index 61f3e0e1..85f075a9 100644
--- a/mitreattack/navlayers/core/layerobj.py
+++ b/mitreattack/navlayers/core/layerobj.py
@@ -456,6 +456,8 @@ def _linker(self, field, data):
             self.selectSubtechniquesWithParent = data
         elif field == 'metadata':
             self.metadata = data
+        elif field == 'links':
+            self.links = data
         else:
             handler(type(self).__name__, "Unknown layer property: {}"
                     .format(field))


Test patch:
diff --git a/tests/resources/testing_data.py b/tests/resources/testing_data.py
index f73e92ac..63dd5278 100644
--- a/tests/resources/testing_data.py
+++ b/tests/resources/testing_data.py
@@ -7721,9 +7721,9 @@
   ],
   "gradient": {
    "colors": [
-    "#ff6666",
-    "#ffe766",
-    "#8ec843"
+    "#ff6666ff",
+    "#ffe766ff",
+    "#8ec843ff"
    ],
    "minValue": 0,
    "maxValue": 100
@@ -7750,7 +7750,8 @@
     "name": "layer metadata 2",
     "value": "layer metadata 2 value"
    }
-  ]
+  ],
+  "links": [],
  }
 
 example_layer_v42_dict = {