synapse 2.192.0__py311-none-any.whl → 2.194.0__py311-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of synapse might be problematic. Click here for more details.

Files changed (77) hide show
  1. synapse/common.py +15 -0
  2. synapse/cortex.py +19 -25
  3. synapse/datamodel.py +6 -3
  4. synapse/exc.py +6 -1
  5. synapse/lib/agenda.py +17 -6
  6. synapse/lib/ast.py +242 -97
  7. synapse/lib/auth.py +1 -0
  8. synapse/lib/cell.py +31 -85
  9. synapse/lib/cli.py +20 -11
  10. synapse/lib/parser.py +5 -1
  11. synapse/lib/snap.py +44 -15
  12. synapse/lib/storm.lark +16 -1
  13. synapse/lib/storm.py +40 -21
  14. synapse/lib/storm_format.py +1 -0
  15. synapse/lib/stormctrl.py +88 -6
  16. synapse/lib/stormlib/cache.py +6 -2
  17. synapse/lib/stormlib/json.py +5 -2
  18. synapse/lib/stormlib/scrape.py +1 -1
  19. synapse/lib/stormlib/stix.py +8 -8
  20. synapse/lib/stormtypes.py +32 -5
  21. synapse/lib/version.py +2 -2
  22. synapse/lib/view.py +20 -3
  23. synapse/models/geopol.py +1 -0
  24. synapse/models/geospace.py +1 -0
  25. synapse/models/inet.py +20 -1
  26. synapse/models/infotech.py +24 -6
  27. synapse/models/orgs.py +7 -2
  28. synapse/models/person.py +15 -4
  29. synapse/models/risk.py +19 -2
  30. synapse/models/telco.py +10 -3
  31. synapse/tests/test_axon.py +6 -6
  32. synapse/tests/test_cortex.py +133 -14
  33. synapse/tests/test_exc.py +4 -0
  34. synapse/tests/test_lib_agenda.py +282 -2
  35. synapse/tests/test_lib_aha.py +13 -6
  36. synapse/tests/test_lib_ast.py +301 -10
  37. synapse/tests/test_lib_auth.py +6 -7
  38. synapse/tests/test_lib_cell.py +71 -1
  39. synapse/tests/test_lib_grammar.py +14 -0
  40. synapse/tests/test_lib_layer.py +1 -1
  41. synapse/tests/test_lib_lmdbslab.py +3 -3
  42. synapse/tests/test_lib_storm.py +273 -55
  43. synapse/tests/test_lib_stormctrl.py +65 -0
  44. synapse/tests/test_lib_stormhttp.py +5 -5
  45. synapse/tests/test_lib_stormlib_auth.py +5 -5
  46. synapse/tests/test_lib_stormlib_cache.py +38 -6
  47. synapse/tests/test_lib_stormlib_json.py +20 -0
  48. synapse/tests/test_lib_stormlib_modelext.py +3 -3
  49. synapse/tests/test_lib_stormlib_scrape.py +6 -6
  50. synapse/tests/test_lib_stormlib_spooled.py +1 -1
  51. synapse/tests/test_lib_stormlib_xml.py +5 -5
  52. synapse/tests/test_lib_stormtypes.py +54 -57
  53. synapse/tests/test_lib_view.py +1 -1
  54. synapse/tests/test_model_base.py +1 -2
  55. synapse/tests/test_model_geopol.py +4 -0
  56. synapse/tests/test_model_geospace.py +6 -0
  57. synapse/tests/test_model_inet.py +43 -5
  58. synapse/tests/test_model_infotech.py +10 -1
  59. synapse/tests/test_model_orgs.py +17 -2
  60. synapse/tests/test_model_person.py +23 -1
  61. synapse/tests/test_model_risk.py +13 -0
  62. synapse/tests/test_tools_healthcheck.py +4 -4
  63. synapse/tests/test_tools_storm.py +95 -0
  64. synapse/tests/test_utils.py +17 -18
  65. synapse/tests/test_utils_getrefs.py +1 -1
  66. synapse/tests/utils.py +0 -35
  67. synapse/tools/changelog.py +6 -4
  68. synapse/tools/storm.py +1 -1
  69. synapse/utils/getrefs.py +14 -3
  70. synapse/vendor/cpython/lib/http/__init__.py +0 -0
  71. synapse/vendor/cpython/lib/http/cookies.py +59 -0
  72. synapse/vendor/cpython/lib/test/test_http_cookies.py +49 -0
  73. {synapse-2.192.0.dist-info → synapse-2.194.0.dist-info}/METADATA +6 -6
  74. {synapse-2.192.0.dist-info → synapse-2.194.0.dist-info}/RECORD +77 -73
  75. {synapse-2.192.0.dist-info → synapse-2.194.0.dist-info}/WHEEL +1 -1
  76. {synapse-2.192.0.dist-info → synapse-2.194.0.dist-info}/LICENSE +0 -0
  77. {synapse-2.192.0.dist-info → synapse-2.194.0.dist-info}/top_level.txt +0 -0
@@ -71,7 +71,7 @@ class LibScrape(s_stormtypes.Lib):
71
71
  $form="ps:name"
72
72
 
73
73
  function scrape(text, form) {
74
- $ret = $lib.list()
74
+ $ret = ()
75
75
  for ($valu, $info) in $lib.scrape.genMatches($text, $re) {
76
76
  $ret.append(($form, $valu, $info))
77
77
  }
@@ -74,7 +74,7 @@ _DefaultConfig = {
74
74
  'created': 'return($lib.stix.export.timestamp(.created))',
75
75
  'modified': 'return($lib.stix.export.timestamp(.created))',
76
76
  'sectors': '''
77
- init { $list = $lib.list() }
77
+ init { $list = () }
78
78
  -> ou:industry +:name $list.append(:name)
79
79
  fini { if $list { return($list) } }
80
80
  ''',
@@ -88,7 +88,7 @@ _DefaultConfig = {
88
88
  'first_seen': '+.seen $seen=.seen return($lib.stix.export.timestamp($seen.0))',
89
89
  'last_seen': '+.seen $seen=.seen return($lib.stix.export.timestamp($seen.1))',
90
90
  'goals': '''
91
- init { $goals = $lib.list() }
91
+ init { $goals = () }
92
92
  -> ou:campaign:org -> ou:goal | uniq | +:name $goals.append(:name)
93
93
  fini { if $goals { return($goals) } }
94
94
  ''',
@@ -183,7 +183,7 @@ _DefaultConfig = {
183
183
  'props': {
184
184
  'value': 'return($node.repr())',
185
185
  'resolves_to_refs': '''
186
- init { $refs = $lib.list() }
186
+ init { $refs = () }
187
187
  { -> inet:dns:a -> inet:ipv4 $refs.append($bundle.add($node)) }
188
188
  { -> inet:dns:aaaa -> inet:ipv6 $refs.append($bundle.add($node)) }
189
189
  { -> inet:dns:cname:fqdn :cname -> inet:fqdn $refs.append($bundle.add($node)) }
@@ -257,7 +257,7 @@ _DefaultConfig = {
257
257
  ''',
258
258
  'mime_type': '+:mime return(:mime)',
259
259
  'contains_refs': '''
260
- init { $refs = $lib.list() }
260
+ init { $refs = () }
261
261
  -(refs)> *
262
262
  $stixid = $bundle.add($node)
263
263
  if $stixid { $refs.append($stixid) }
@@ -279,7 +279,7 @@ _DefaultConfig = {
279
279
  'is_multipart': 'return($lib.false)',
280
280
  'from_ref': ':from -> inet:email return($bundle.add($node))',
281
281
  'to_refs': '''
282
- init { $refs = $lib.list() }
282
+ init { $refs = () }
283
283
  { :to -> inet:email $refs.append($bundle.add($node)) }
284
284
  fini { if $refs { return($refs) } }
285
285
  ''',
@@ -311,7 +311,7 @@ _DefaultConfig = {
311
311
  'created': 'return($lib.stix.export.timestamp(.created))',
312
312
  'modified': 'return($lib.stix.export.timestamp(.created))',
313
313
  'sample_refs': '''
314
- init { $refs = $lib.list() }
314
+ init { $refs = () }
315
315
  -> file:bytes $refs.append($bundle.add($node))
316
316
  fini { if $refs { return($refs) } }
317
317
  ''',
@@ -393,7 +393,7 @@ _DefaultConfig = {
393
393
  'description': 'if (:desc) { return (:desc) }',
394
394
  'created': 'return($lib.stix.export.timestamp(.created))',
395
395
  'modified': 'return($lib.stix.export.timestamp(.created))',
396
- 'external_references': 'if :cve { $cve=:cve $cve=$cve.upper() $list=$lib.list(({"source_name": "cve", "external_id": $cve})) return($list) }'
396
+ 'external_references': 'if :cve { $cve=:cve $cve=$cve.upper() return(([{"source_name": "cve", "external_id": $cve}])) }'
397
397
  },
398
398
  'rels': (
399
399
 
@@ -439,7 +439,7 @@ _DefaultConfig = {
439
439
  'modified': 'return($lib.stix.export.timestamp(.created))',
440
440
  'published': 'return($lib.stix.export.timestamp(:published))',
441
441
  'object_refs': '''
442
- init { $refs = $lib.list() }
442
+ init { $refs = () }
443
443
  -(refs)> *
444
444
  $stixid = $bundle.add($node)
445
445
  if $stixid { $refs.append($stixid) }
synapse/lib/stormtypes.py CHANGED
@@ -201,11 +201,29 @@ class StormTypesRegistry:
201
201
  raise Exception('no key!')
202
202
  self.addStormLib(path, ctor)
203
203
 
204
+ for info in ctor._storm_locals:
205
+ rtype = info.get('type')
206
+ if isinstance(rtype, dict) and rtype.get('type') == 'function':
207
+ if (fname := rtype.get('_funcname')) == '_storm_query':
208
+ continue
209
+
210
+ if (func := getattr(ctor, fname, None)) is not None:
211
+ funcpath = '.'.join(('lib',) + ctor._storm_lib_path + (info['name'],))
212
+ func._storm_funcpath = f"${funcpath}"
213
+
204
214
  return ctor
205
215
 
206
216
  def registerType(self, ctor):
207
217
  '''Decorator to register a StormPrim'''
208
218
  self.addStormType(ctor.__name__, ctor)
219
+
220
+ for info in ctor._storm_locals:
221
+ rtype = info.get('type')
222
+ if isinstance(rtype, dict) and rtype.get('type') == 'function':
223
+ fname = rtype.get('_funcname')
224
+ if (func := getattr(ctor, fname, None)) is not None:
225
+ func._storm_funcpath = f"{ctor._storm_typename}.{info['name']}"
226
+
209
227
  return ctor
210
228
 
211
229
  def iterLibs(self):
@@ -557,7 +575,7 @@ class StormType:
557
575
  raise s_exc.NoSuchName(name=name, mesg=mesg)
558
576
 
559
577
  if s_scope.get('runt').readonly and not getattr(stor, '_storm_readonly', False):
560
- mesg = f'Function ({stor.__name__}) is not marked readonly safe.'
578
+ mesg = f'Setting {name} on {self._storm_typename} is not marked readonly safe.'
561
579
  raise s_exc.IsReadOnly(mesg=mesg, name=name, valu=valu)
562
580
 
563
581
  await s_coro.ornot(stor, valu)
@@ -628,6 +646,7 @@ class Lib(StormType):
628
646
  if callable(v) and v.__name__ == 'realfunc':
629
647
  v._storm_runtime_lib = self
630
648
  v._storm_runtime_lib_func = k
649
+ v._storm_funcpath = f'${".".join(("lib",) + self.name + (k,))}'
631
650
 
632
651
  self.locls[k] = v
633
652
 
@@ -1228,7 +1247,8 @@ class LibBase(Lib):
1228
1247
  'desc': 'Additional keyword arguments containing data to add to the event.', },
1229
1248
  ),
1230
1249
  'returns': {'type': 'null', }}},
1231
- {'name': 'list', 'desc': 'Get a Storm List object.',
1250
+ {'name': 'list', 'desc': 'Get a Storm List object. This is deprecated, use ([]) to declare a list instead.',
1251
+ 'deprecated': {'eolvers': 'v3.0.0'},
1232
1252
  'type': {'type': 'function', '_funcname': '_list',
1233
1253
  'args': (
1234
1254
  {'name': '*vals', 'type': 'any', 'desc': 'Initial values to place in the list.', },
@@ -1288,7 +1308,8 @@ class LibBase(Lib):
1288
1308
  cli> storm if $lib.false { $lib.print('Is True') } else { $lib.print('Is False') }
1289
1309
  Is False''',
1290
1310
  'type': 'boolean', },
1291
- {'name': 'text', 'desc': 'Get a Storm Text object.',
1311
+ {'name': 'text', 'desc': 'Get a Storm Text object. This is deprecated; please use a list to append strings to, and then use ``$lib.str.join()`` to join them on demand.',
1312
+ 'deprecated': {'eolvers': '3.0.0'},
1292
1313
  'type': {'type': 'function', '_funcname': '_text',
1293
1314
  'args': (
1294
1315
  {'name': '*args', 'type': 'str',
@@ -1644,7 +1665,7 @@ class LibBase(Lib):
1644
1665
  if mesg:
1645
1666
  mesg = await self._get_mesg(mesg, **kwargs)
1646
1667
  await self.runt.warn(mesg, log=False)
1647
- raise s_stormctrl.StormExit(mesg)
1668
+ raise s_stormctrl.StormExit(mesg=mesg)
1648
1669
  raise s_stormctrl.StormExit()
1649
1670
 
1650
1671
  @stormfunc(readonly=True)
@@ -1661,10 +1682,16 @@ class LibBase(Lib):
1661
1682
 
1662
1683
  @stormfunc(readonly=True)
1663
1684
  async def _list(self, *vals):
1685
+ s_common.deprecated('$lib.list()', curv='2.194.0')
1686
+ await self.runt.snap.warnonce('$lib.list() is deprecated. Use ([]) instead.')
1664
1687
  return List(list(vals))
1665
1688
 
1666
1689
  @stormfunc(readonly=True)
1667
1690
  async def _text(self, *args):
1691
+ s_common.deprecated('$lib.text()', curv='2.194.0')
1692
+ runt = s_scope.get('runt')
1693
+ if runt:
1694
+ await runt.snap.warnonce('$lib.text() is deprecated. Please use a list to append strings to, and then use ``$lib.str.join()`` to join them on demand.')
1668
1695
  valu = ''.join(args)
1669
1696
  return Text(valu)
1670
1697
 
@@ -5158,7 +5185,7 @@ class List(Prim):
5158
5185
  Examples:
5159
5186
  Populate a list by extending it with to other lists::
5160
5187
 
5161
- $list = $lib.list()
5188
+ $list = ()
5162
5189
 
5163
5190
  $foo = (f, o, o)
5164
5191
  $bar = (b, a, r)
synapse/lib/version.py CHANGED
@@ -223,6 +223,6 @@ def reqVersion(valu, reqver,
223
223
  ##############################################################################
224
224
  # The following are touched during the release process by bumpversion.
225
225
  # Do not modify these directly.
226
- version = (2, 192, 0)
226
+ version = (2, 194, 0)
227
227
  verstring = '.'.join([str(x) for x in version])
228
- commit = '8a442a534d27fff4c6189922c4b0ea85d332f18e'
228
+ commit = 'fb479d376805f963f11c5029310325c13ef2c883'
synapse/lib/view.py CHANGED
@@ -635,7 +635,6 @@ class View(s_nexus.Pusher): # type: ignore
635
635
  async def _calcForkLayers(self):
636
636
  # recompute the proper set of layers for a forked view
637
637
  # (this may only be called from within a nexus handler)
638
-
639
638
  '''
640
639
  We spent a lot of time thinking/talking about this so some hefty
641
640
  comments are in order:
@@ -953,6 +952,15 @@ class View(s_nexus.Pusher): # type: ignore
953
952
  extra={'synapse': {'text': text, 'username': user.name, 'user': user.iden}})
954
953
  raise
955
954
 
955
+ except (s_stormctrl.StormLoopCtrl, s_stormctrl.StormGenrCtrl) as e:
956
+ if isinstance(e, s_stormctrl.StormLoopCtrl):
957
+ mesg = f'Loop control statement "{e.statement}" used outside of a loop.'
958
+ else:
959
+ mesg = f'Generator control statement "{e.statement}" used outside of a generator function.'
960
+ logmesg = f'Error during storm execution for {{ {text} }} - {mesg}'
961
+ logger.exception(logmesg, extra={'synapse': {'text': text, 'username': user.name, 'user': user.iden}})
962
+ raise s_exc.StormRuntimeError(mesg=mesg, statement=e.statement, highlight=e.get('highlight')) from e
963
+
956
964
  except Exception:
957
965
  logger.exception(f'Error during callStorm execution for {{ {text} }}',
958
966
  extra={'synapse': {'text': text, 'username': user.name, 'user': user.iden}})
@@ -1055,8 +1063,17 @@ class View(s_nexus.Pusher): # type: ignore
1055
1063
  raise
1056
1064
 
1057
1065
  except Exception as e:
1058
- logger.exception(f'Error during storm execution for {{ {text} }}',
1059
- extra={'synapse': {'text': text, 'username': user.name, 'user': user.iden}})
1066
+ mesg = ''
1067
+ if isinstance(e, s_stormctrl.StormLoopCtrl):
1068
+ mesg = f'Loop control statement "{e.statement}" used outside of a loop.'
1069
+ e = s_exc.StormRuntimeError(mesg=mesg, statement=e.statement, highlight=e.get('highlight'))
1070
+ elif isinstance(e, s_stormctrl.StormGenrCtrl):
1071
+ mesg = f'Generator control statement "{e.statement}" used outside of a generator function.'
1072
+ e = s_exc.StormRuntimeError(mesg=mesg, statement=e.statement, highlight=e.get('highlight'))
1073
+ logmesg = f'Error during storm execution for {{ {text} }}'
1074
+ if mesg:
1075
+ logmesg = f'{logmesg} - {mesg}'
1076
+ logger.exception(logmesg, extra={'synapse': {'text': text, 'username': user.name, 'user': user.iden}})
1060
1077
  enfo = s_common.err(e)
1061
1078
  enfo[1].pop('esrc', None)
1062
1079
  enfo[1].pop('ename', None)
synapse/models/geopol.py CHANGED
@@ -69,6 +69,7 @@ class PolModule(s_module.CoreModule):
69
69
  ('tld', ('inet:fqdn', {}), {}),
70
70
 
71
71
  ('name', ('geo:name', {}), {
72
+ 'alts': ('names',),
72
73
  'doc': 'The name of the country.'}),
73
74
 
74
75
  ('names', ('array', {'type': 'geo:name', 'uniq': True, 'sorted': True}), {
@@ -495,6 +495,7 @@ class GeoModule(s_module.CoreModule):
495
495
  ('geo:place', {}, (
496
496
 
497
497
  ('name', ('geo:name', {}), {
498
+ 'alts': ('names',),
498
499
  'doc': 'The name of the place.'}),
499
500
 
500
501
  ('type', ('geo:place:taxonomy', {}), {
synapse/models/inet.py CHANGED
@@ -1442,7 +1442,11 @@ class InetModule(s_module.CoreModule):
1442
1442
  'doc': 'A channel within a web service or instance such as slack or discord.'
1443
1443
  }),
1444
1444
 
1445
- ('inet:web:hashtag', ('str', {'lower': True, 'regex': r'^#\w[\w·]*(?<!·)$'}), {
1445
+ ('inet:web:hashtag', ('str', {'lower': True, 'strip': True, 'regex': r'^#[^\p{Z}#]+$'}), {
1446
+ # regex explanation:
1447
+ # - starts with pound
1448
+ # - one or more non-whitespace/non-pound character
1449
+ # The minimum hashtag is a pound with a single non-whitespace character
1446
1450
  'doc': 'A hashtag used in a web post.',
1447
1451
  }),
1448
1452
 
@@ -1728,6 +1732,9 @@ class InetModule(s_module.CoreModule):
1728
1732
  'template': {'service:base': 'object'},
1729
1733
  'props': (
1730
1734
 
1735
+ ('url', ('inet:url', {}), {
1736
+ 'doc': 'The primary URL associated with the {service:base}.'}),
1737
+
1731
1738
  ('status', ('inet:service:object:status', {}), {
1732
1739
  'doc': 'The status of the {service:base}.'}),
1733
1740
 
@@ -1811,6 +1818,9 @@ class InetModule(s_module.CoreModule):
1811
1818
 
1812
1819
  ('inet:email:message', {}, (
1813
1820
 
1821
+ ('id', ('str', {'strip': True}), {
1822
+ 'doc': 'The ID parsed from the "message-id" header.'}),
1823
+
1814
1824
  ('to', ('inet:email', {}), {
1815
1825
  'doc': 'The email address of the recipient.'}),
1816
1826
 
@@ -2171,6 +2181,9 @@ class InetModule(s_module.CoreModule):
2171
2181
  ('dst:ssh:key', ('crypto:key', {}), {
2172
2182
  'doc': 'The key sent by the server as part of an SSH session setup.'}),
2173
2183
 
2184
+ ('capture:host', ('it:host', {}), {
2185
+ 'doc': 'The host which captured the flow.'}),
2186
+
2174
2187
  ('raw', ('data', {}), {
2175
2188
  'doc': 'A raw record used to create the flow which may contain additional protocol details.'}),
2176
2189
  )),
@@ -2194,6 +2207,9 @@ class InetModule(s_module.CoreModule):
2194
2207
  ('host', ('it:host', {}), {
2195
2208
  'doc': 'The host that used the network egress.'}),
2196
2209
 
2210
+ ('host:iface', ('inet:iface', {}), {
2211
+ 'doc': 'The interface which the host used to connect out via the egress.'}),
2212
+
2197
2213
  ('account', ('inet:service:account', {}), {
2198
2214
  'doc': 'The service account which used the client address to egress.'}),
2199
2215
 
@@ -3769,6 +3785,9 @@ class InetModule(s_module.CoreModule):
3769
3785
  ('replyto', ('inet:service:message', {}), {
3770
3786
  'doc': 'The message that this message was sent in reply to. Used for message threading.'}),
3771
3787
 
3788
+ ('repost', ('inet:service:message', {}), {
3789
+ 'doc': 'The original message reposted by this message.'}),
3790
+
3772
3791
  ('links', ('array', {'type': 'inet:service:message:link', 'uniq': True, 'sorted': True}), {
3773
3792
  'doc': 'An array of links contained within the message.'}),
3774
3793
 
@@ -655,6 +655,7 @@ class ItModule(s_module.CoreModule):
655
655
 
656
656
  ('it:host', ('guid', {}), {
657
657
  'interfaces': ('inet:service:object',),
658
+ 'template': {'service:base': 'host'},
658
659
  'doc': 'A GUID that represents a host or system.'}),
659
660
 
660
661
  ('it:log:event:type:taxonomy', ('taxonomy', {}), {
@@ -784,6 +785,7 @@ class ItModule(s_module.CoreModule):
784
785
  }),
785
786
  ('it:dev:repo', ('guid', {}), {
786
787
  'interfaces': ('inet:service:object',),
788
+ 'template': {'service:base': 'repository'},
787
789
  'doc': 'A version control system instance.',
788
790
  }),
789
791
  ('it:dev:repo:remote', ('guid', {}), {
@@ -791,10 +793,12 @@ class ItModule(s_module.CoreModule):
791
793
  }),
792
794
  ('it:dev:repo:branch', ('guid', {}), {
793
795
  'interfaces': ('inet:service:object',),
796
+ 'template': {'service:base': 'repository branch'},
794
797
  'doc': 'A branch in a version control system instance.',
795
798
  }),
796
799
  ('it:dev:repo:commit', ('guid', {}), {
797
800
  'interfaces': ('inet:service:object',),
801
+ 'template': {'service:base': 'repository commit'},
798
802
  'doc': 'A commit to a repository.',
799
803
  }),
800
804
  ('it:dev:repo:diff', ('guid', {}), {
@@ -802,18 +806,22 @@ class ItModule(s_module.CoreModule):
802
806
  }),
803
807
  ('it:dev:repo:issue:label', ('guid', {}), {
804
808
  'interfaces': ('inet:service:object',),
809
+ 'template': {'service:base': 'repository issue label'},
805
810
  'doc': 'A label applied to a repository issue.',
806
811
  }),
807
812
  ('it:dev:repo:issue', ('guid', {}), {
808
813
  'interfaces': ('inet:service:object',),
814
+ 'template': {'service:base': 'repository issue'},
809
815
  'doc': 'An issue raised in a repository.',
810
816
  }),
811
817
  ('it:dev:repo:issue:comment', ('guid', {}), {
812
818
  'interfaces': ('inet:service:object',),
819
+ 'template': {'service:base': 'repository issue comment'},
813
820
  'doc': 'A comment on an issue in a repository.',
814
821
  }),
815
822
  ('it:dev:repo:diff:comment', ('guid', {}), {
816
823
  'interfaces': ('inet:service:object',),
824
+ 'template': {'service:base': 'repository diff comment'},
817
825
  'doc': 'A comment on a diff in a repository.',
818
826
  }),
819
827
  ('it:prod:soft', ('guid', {}), {
@@ -849,10 +857,12 @@ class ItModule(s_module.CoreModule):
849
857
  }),
850
858
 
851
859
  ('it:os:ios:idfa', ('it:adid', {}), {
852
- 'doc': 'An iOS advertising identification string.'}),
860
+ 'deprecated': True,
861
+ 'doc': 'Deprecated. Please use it:adid.'}),
853
862
 
854
863
  ('it:os:android:aaid', ('it:adid', {}), {
855
- 'doc': 'An android advertising identification string.'}),
864
+ 'deprecated': True,
865
+ 'doc': 'Deprecated. Please use it:adid.'}),
856
866
 
857
867
  ('it:os:android:perm', ('str', {}), {
858
868
  'doc': 'An android permission string.'}),
@@ -963,12 +973,12 @@ class ItModule(s_module.CoreModule):
963
973
  }),
964
974
  ('it:exec:pipe', ('guid', {}), {
965
975
  'interfaces': ('it:host:activity',),
966
- 'doc': 'A named pipe created by a process at runtime.',
967
- }),
976
+ 'doc': 'A named pipe created by a process at runtime.'}),
977
+
968
978
  ('it:exec:url', ('guid', {}), {
969
979
  'interfaces': ('it:host:activity',),
970
- 'doc': 'An instance of a host requesting a URL.',
971
- }),
980
+ 'doc': 'An instance of a host requesting a URL using any protocol scheme.'}),
981
+
972
982
  ('it:exec:bind', ('guid', {}), {
973
983
  'interfaces': ('it:host:activity',),
974
984
  'doc': 'An instance of a host binding a listening port.',
@@ -1046,6 +1056,7 @@ class ItModule(s_module.CoreModule):
1046
1056
 
1047
1057
  ('it:host:tenancy', ('guid', {}), {
1048
1058
  'interfaces': ('inet:service:object',),
1059
+ 'template': {'service:base': 'host tenancy'},
1049
1060
  'doc': 'A time window where a host was a tenant run by another host.'}),
1050
1061
 
1051
1062
  ('it:software:image:type:taxonomy', ('taxonomy', {}), {
@@ -1054,6 +1065,7 @@ class ItModule(s_module.CoreModule):
1054
1065
 
1055
1066
  ('it:software:image', ('guid', {}), {
1056
1067
  'interfaces': ('inet:service:object',),
1068
+ 'template': {'service:base': 'software image'},
1057
1069
  'doc': 'The base image used to create a container or OS.'}),
1058
1070
 
1059
1071
  ('it:storage:mount', ('guid', {}), {
@@ -2084,7 +2096,12 @@ class ItModule(s_module.CoreModule):
2084
2096
  )),
2085
2097
  ('it:prod:soft:taxonomy', {}, ()),
2086
2098
  ('it:prod:soft', {}, (
2099
+
2100
+ ('id', ('str', {'strip': True}), {
2101
+ 'doc': 'An ID for the software.'}),
2102
+
2087
2103
  ('name', ('it:prod:softname', {}), {
2104
+ 'alts': ('names',),
2088
2105
  'doc': 'Name of the software.',
2089
2106
  }),
2090
2107
  ('type', ('it:prod:soft:taxonomy', {}), {
@@ -2206,6 +2223,7 @@ class ItModule(s_module.CoreModule):
2206
2223
  'doc': 'Deprecated. Please use it:prod:softver:name.',
2207
2224
  }),
2208
2225
  ('name', ('it:prod:softname', {}), {
2226
+ 'alts': ('names',),
2209
2227
  'doc': 'Name of the software version.',
2210
2228
  }),
2211
2229
  ('names', ('array', {'type': 'it:prod:softname', 'uniq': True, 'sorted': True}), {
synapse/models/orgs.py CHANGED
@@ -493,10 +493,10 @@ class OuModule(s_module.CoreModule):
493
493
  ('ou:id:number', {}, (
494
494
 
495
495
  ('type', ('ou:id:type', {}), {
496
- 'doc': 'The type of org id', 'ro': True}),
496
+ 'doc': 'The type of org ID.', 'ro': True}),
497
497
 
498
498
  ('value', ('ou:id:value', {}), {
499
- 'doc': 'The value of org id', 'ro': True}),
499
+ 'doc': 'The value of the org ID.', 'ro': True}),
500
500
 
501
501
  ('status', ('str', {'lower': True, 'strip': True}), {
502
502
  'doc': 'A freeform status such as valid, suspended, expired.'}),
@@ -526,6 +526,7 @@ class OuModule(s_module.CoreModule):
526
526
  ('ou:goal', {}, (
527
527
 
528
528
  ('name', ('ou:goalname', {}), {
529
+ 'alts': ('names',),
529
530
  'doc': 'A terse name for the goal.'}),
530
531
 
531
532
  ('names', ('array', {'type': 'ou:goalname', 'sorted': True, 'uniq': True}), {
@@ -570,6 +571,7 @@ class OuModule(s_module.CoreModule):
570
571
  'doc': 'The FQDN of the org responsible for the campaign. Used for entity resolution.'}),
571
572
 
572
573
  ('goal', ('ou:goal', {}), {
574
+ 'alts': ('goals',),
573
575
  'doc': 'The assessed primary goal of the campaign.'}),
574
576
 
575
577
  ('slogan', ('lang:phrase', {}), {
@@ -585,6 +587,7 @@ class OuModule(s_module.CoreModule):
585
587
  'doc': 'Records the success/failure status of the campaign if known.'}),
586
588
 
587
589
  ('name', ('ou:campname', {}), {
590
+ 'alts': ('names',),
588
591
  'ex': 'operation overlord',
589
592
  'doc': 'A terse name of the campaign.'}),
590
593
 
@@ -924,6 +927,7 @@ class OuModule(s_module.CoreModule):
924
927
  ('ou:industry', {}, (
925
928
 
926
929
  ('name', ('ou:industryname', {}), {
930
+ 'alts': ('names',),
927
931
  'doc': 'The name of the industry.'}),
928
932
 
929
933
  ('type', ('ou:industry:type:taxonomy', {}), {
@@ -1176,6 +1180,7 @@ class OuModule(s_module.CoreModule):
1176
1180
  'doc': 'An array of contacts which sponsored the conference.',
1177
1181
  }),
1178
1182
  ('name', ('entity:name', {}), {
1183
+ 'alts': ('names',),
1179
1184
  'doc': 'The full name of the conference.',
1180
1185
  'ex': 'defcon 2017'}),
1181
1186
 
synapse/models/person.py CHANGED
@@ -254,6 +254,7 @@ class PsModule(s_module.CoreModule):
254
254
  'doc': 'The most recent known vitals for the person.',
255
255
  }),
256
256
  ('name', ('ps:name', {}), {
257
+ 'alts': ('names',),
257
258
  'doc': 'The localized name for the person.',
258
259
  }),
259
260
  ('name:sur', ('ps:tokn', {}), {
@@ -350,12 +351,17 @@ class PsModule(s_module.CoreModule):
350
351
  'doc': 'The most recent known vitals for the contact.',
351
352
  }),
352
353
  ('name', ('ps:name', {}), {
353
- 'doc': 'The person name listed for the contact.',
354
- }),
354
+ 'alts': ('names',),
355
+ 'doc': 'The person name listed for the contact.'}),
356
+
357
+ ('bio', ('str', {}), {
358
+ 'doc': 'A brief bio provided for the contact.'}),
359
+
355
360
  ('desc', ('str', {}), {
356
- 'doc': 'A description of this contact.',
357
- }),
361
+ 'doc': 'A description of this contact.'}),
362
+
358
363
  ('title', ('ou:jobtitle', {}), {
364
+ 'alts': ('titles',),
359
365
  'doc': 'The job/org title listed for this contact.'}),
360
366
 
361
367
  ('titles', ('array', {'type': 'ou:jobtitle', 'sorted': True, 'uniq': True}), {
@@ -365,12 +371,14 @@ class PsModule(s_module.CoreModule):
365
371
  'doc': 'The photo listed for this contact.',
366
372
  }),
367
373
  ('orgname', ('ou:name', {}), {
374
+ 'alts': ('orgnames',),
368
375
  'doc': 'The listed org/company name for this contact.',
369
376
  }),
370
377
  ('orgfqdn', ('inet:fqdn', {}), {
371
378
  'doc': 'The listed org/company FQDN for this contact.',
372
379
  }),
373
380
  ('user', ('inet:user', {}), {
381
+ 'alts': ('users',),
374
382
  'doc': 'The username or handle for this contact.'}),
375
383
 
376
384
  ('service:accounts', ('array', {'type': 'inet:service:account', 'sorted': True, 'uniq': True}), {
@@ -412,6 +420,7 @@ class PsModule(s_module.CoreModule):
412
420
  'doc': 'The home or main site for this contact.',
413
421
  }),
414
422
  ('email', ('inet:email', {}), {
423
+ 'alts': ('emails',),
415
424
  'doc': 'The main email address for this contact.',
416
425
  }),
417
426
  ('email:work', ('inet:email', {}), {
@@ -440,6 +449,7 @@ class PsModule(s_module.CoreModule):
440
449
  'doc': 'The work phone number for this contact.',
441
450
  }),
442
451
  ('id:number', ('ou:id:number', {}), {
452
+ 'alts': ('id:numbers',),
443
453
  'doc': 'An ID number issued by an org and associated with this contact.',
444
454
  }),
445
455
  ('adid', ('it:adid', {}), {
@@ -479,6 +489,7 @@ class PsModule(s_module.CoreModule):
479
489
  }),
480
490
 
481
491
  ('lang', ('lang:language', {}), {
492
+ 'alts': ('langs',),
482
493
  'doc': 'The language specified for the contact.'}),
483
494
 
484
495
  ('langs', ('array', {'type': 'lang:language'}), {
synapse/models/risk.py CHANGED
@@ -242,9 +242,18 @@ class RiskModule(s_module.CoreModule):
242
242
  (('risk:mitigation', 'uses', 'inet:service:rule'), {
243
243
  'doc': 'The mitigation uses the service rule.'}),
244
244
 
245
+ (('risk:mitigation', 'uses', 'it:prod:softver'), {
246
+ 'doc': 'The mitigation uses the software version.'}),
247
+
248
+ (('risk:mitigation', 'uses', 'it:prod:hardware'), {
249
+ 'doc': 'The mitigation uses the hardware.'}),
250
+
245
251
  (('risk:leak', 'leaked', None), {
246
252
  'doc': 'The leak included the disclosure of the target node.'}),
247
253
 
254
+ (('risk:leak', 'enabled', 'risk:leak'), {
255
+ 'doc': 'The source leak enabled the target leak to occur.'}),
256
+
248
257
  (('risk:extortion', 'leveraged', None), {
249
258
  'doc': 'The extortion event was based on attacker access to the target node.'}),
250
259
 
@@ -301,6 +310,7 @@ class RiskModule(s_module.CoreModule):
301
310
  'doc': "The reporting organization's assessed location of the threat cluster."}),
302
311
 
303
312
  ('org:name', ('ou:name', {}), {
313
+ 'alts': ('org:names',),
304
314
  'ex': 'apt1',
305
315
  'doc': "The reporting organization's name for the threat cluster."}),
306
316
 
@@ -374,6 +384,7 @@ class RiskModule(s_module.CoreModule):
374
384
  'doc': 'The authoritative software family for the tool.'}),
375
385
 
376
386
  ('soft:name', ('it:prod:softname', {}), {
387
+ 'alts': ('soft:names',),
377
388
  'doc': 'The reporting organization\'s name for the tool.'}),
378
389
 
379
390
  ('soft:names', ('array', {'type': 'it:prod:softname', 'uniq': True, 'sorted': True}), {
@@ -407,10 +418,12 @@ class RiskModule(s_module.CoreModule):
407
418
  'doc': 'A description of the mitigation approach for the vulnerability.'}),
408
419
 
409
420
  ('software', ('it:prod:softver', {}), {
410
- 'doc': 'A software version which implements a fix for the vulnerability.'}),
421
+ 'deprecated': True,
422
+ 'doc': 'Deprecated. Please use risk:mitigation -(uses)> it:prod:softver.'}),
411
423
 
412
424
  ('hardware', ('it:prod:hardware', {}), {
413
- 'doc': 'A hardware version which implements a fix for the vulnerability.'}),
425
+ 'deprecated': True,
426
+ 'doc': 'Deprecated. Please use risk:mitigation -(uses)> it:prod:hardware.'}),
414
427
 
415
428
  ('reporter', ('ou:org', {}), {
416
429
  'doc': 'The organization reporting on the mitigation.'}),
@@ -430,6 +443,7 @@ class RiskModule(s_module.CoreModule):
430
443
  ('risk:vuln', {}, (
431
444
 
432
445
  ('name', ('risk:vulnname', {}), {
446
+ 'alts': ('names',),
433
447
  'doc': 'A user specified name for the vulnerability.'}),
434
448
 
435
449
  ('names', ('array', {'type': 'risk:vulnname', 'sorted': True, 'uniq': True}), {
@@ -1034,6 +1048,9 @@ class RiskModule(s_module.CoreModule):
1034
1048
  ('leaker', ('ps:contact', {}), {
1035
1049
  'doc': 'The identity which leaked the information.'}),
1036
1050
 
1051
+ ('recipient', ('ps:contact', {}), {
1052
+ 'doc': 'The identity which received the leaked information.'}),
1053
+
1037
1054
  ('type', ('risk:leak:type:taxonomy', {}), {
1038
1055
  'doc': 'A type taxonomy for the leak.'}),
1039
1056
 
synapse/models/telco.py CHANGED
@@ -369,9 +369,16 @@ class TelcoModule(s_module.CoreModule):
369
369
  ('wifi:bssid', ('inet:mac', {}), {}),
370
370
 
371
371
  # host specific data
372
- ('adid', ('it:adid', {}), {}),
373
- ('aaid', ('it:os:android:aaid', {}), {}),
374
- ('idfa', ('it:os:ios:idfa', {}), {}),
372
+ ('adid', ('it:adid', {}), {
373
+ 'doc': 'The advertising ID of the mobile telemetry sample.'}),
374
+
375
+ ('aaid', ('it:os:android:aaid', {}), {
376
+ 'deprecated': True,
377
+ 'doc': 'Deprecated. Please use :adid.'}),
378
+
379
+ ('idfa', ('it:os:ios:idfa', {}), {
380
+ 'deprecated': True,
381
+ 'doc': 'Deprecated. Please use :adid.'}),
375
382
 
376
383
  # User related data
377
384
  ('name', ('ps:name', {}), {}),