synapse 2.170.0__py311-none-any.whl → 2.172.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 (58) hide show
  1. synapse/common.py +20 -0
  2. synapse/cortex.py +98 -6
  3. synapse/lib/agenda.py +13 -7
  4. synapse/lib/ast.py +9 -8
  5. synapse/lib/cache.py +2 -2
  6. synapse/lib/cell.py +7 -3
  7. synapse/lib/coro.py +12 -0
  8. synapse/lib/layer.py +124 -84
  9. synapse/lib/lmdbslab.py +34 -10
  10. synapse/lib/node.py +1 -1
  11. synapse/lib/slabseqn.py +11 -5
  12. synapse/lib/storm.py +7 -71
  13. synapse/lib/stormhttp.py +1 -1
  14. synapse/lib/stormlib/auth.py +19 -0
  15. synapse/lib/stormlib/cell.py +42 -4
  16. synapse/lib/stormlib/compression.py +6 -6
  17. synapse/lib/stormlib/env.py +50 -0
  18. synapse/lib/stormlib/gen.py +1 -1
  19. synapse/lib/stormlib/model.py +1 -1
  20. synapse/lib/stormtypes.py +35 -11
  21. synapse/lib/types.py +7 -7
  22. synapse/lib/version.py +2 -2
  23. synapse/lib/view.py +13 -13
  24. synapse/models/base.py +13 -0
  25. synapse/models/biz.py +14 -0
  26. synapse/models/economic.py +3 -0
  27. synapse/models/inet.py +474 -4
  28. synapse/models/infotech.py +163 -22
  29. synapse/models/orgs.py +17 -0
  30. synapse/models/risk.py +15 -1
  31. synapse/models/transport.py +1 -1
  32. synapse/tests/test_common.py +15 -0
  33. synapse/tests/test_cortex.py +9 -0
  34. synapse/tests/test_lib_ast.py +2 -1
  35. synapse/tests/test_lib_cell.py +1 -1
  36. synapse/tests/test_lib_layer.py +168 -59
  37. synapse/tests/test_lib_lmdbslab.py +49 -0
  38. synapse/tests/test_lib_stormlib_auth.py +22 -0
  39. synapse/tests/test_lib_stormlib_cell.py +47 -0
  40. synapse/tests/test_lib_stormlib_env.py +25 -0
  41. synapse/tests/test_lib_stormtypes.py +12 -1
  42. synapse/tests/test_lib_types.py +1 -0
  43. synapse/tests/test_lib_view.py +9 -9
  44. synapse/tests/test_model_base.py +5 -3
  45. synapse/tests/test_model_economic.py +4 -0
  46. synapse/tests/test_model_files.py +1 -0
  47. synapse/tests/test_model_inet.py +405 -1
  48. synapse/tests/test_model_infotech.py +135 -3
  49. synapse/tests/test_model_orgs.py +6 -0
  50. synapse/tests/test_model_risk.py +8 -0
  51. synapse/tests/test_tools_storm.py +46 -8
  52. synapse/tests/utils.py +30 -9
  53. synapse/tools/storm.py +14 -6
  54. {synapse-2.170.0.dist-info → synapse-2.172.0.dist-info}/METADATA +1 -1
  55. {synapse-2.170.0.dist-info → synapse-2.172.0.dist-info}/RECORD +58 -56
  56. {synapse-2.170.0.dist-info → synapse-2.172.0.dist-info}/WHEEL +1 -1
  57. {synapse-2.170.0.dist-info → synapse-2.172.0.dist-info}/LICENSE +0 -0
  58. {synapse-2.170.0.dist-info → synapse-2.172.0.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,3 @@
1
- import copy
2
1
  import logging
3
2
 
4
3
  import synapse.exc as s_exc
@@ -12,10 +11,16 @@ class InetModelTest(s_t_utils.SynTest):
12
11
  async def test_model_inet_basics(self):
13
12
  async with self.getTestCore() as core:
14
13
  self.len(1, await core.nodes('[ inet:web:hashtag="#hehe" ]'))
14
+ self.len(1, await core.nodes('[ inet:web:hashtag="#foo·bar"]')) # note the interpunct
15
+ self.len(1, await core.nodes('[ inet:web:hashtag="#fo·o·······b·ar"]'))
15
16
  with self.raises(s_exc.BadTypeValu):
16
17
  await core.nodes('[ inet:web:hashtag="foo" ]')
17
18
  with self.raises(s_exc.BadTypeValu):
18
19
  await core.nodes('[ inet:web:hashtag="#foo bar" ]')
20
+ with self.raises(s_exc.BadTypeValu):
21
+ self.len(1, await core.nodes('[ inet:web:hashtag="#·bar"]'))
22
+ with self.raises(s_exc.BadTypeValu):
23
+ self.len(1, await core.nodes('[ inet:web:hashtag="#foo·"]'))
19
24
 
20
25
  nodes = await core.nodes('''
21
26
  [ inet:web:instance=(foo,)
@@ -2896,3 +2901,402 @@ class InetModelTest(s_t_utils.SynTest):
2896
2901
  self.len(1, nodes)
2897
2902
  self.eq(nodes[0].get('client'), 'tcp://5.6.7.8:5678')
2898
2903
  self.eq(nodes[0].get('cert'), client)
2904
+
2905
+ async def test_model_inet_service(self):
2906
+
2907
+ async with self.getTestCore() as core:
2908
+
2909
+ provname = 'Slack Corp'
2910
+ opts = {'vars': {'provname': provname}}
2911
+ nodes = await core.nodes(f'gen.ou.org $provname', opts=opts)
2912
+ self.len(1, nodes)
2913
+ provider = nodes[0]
2914
+
2915
+ q = '''
2916
+ [ inet:service:platform=(slack,)
2917
+ :url="https://slack.com"
2918
+ :name=Slack
2919
+ :provider={ ou:org:name=$provname }
2920
+ :provider:name=$provname
2921
+ ]
2922
+ '''
2923
+ nodes = await core.nodes(q, opts=opts)
2924
+ self.len(1, nodes)
2925
+ self.eq(nodes[0].ndef, ('inet:service:platform', s_common.guid(('slack',))))
2926
+ self.eq(nodes[0].get('url'), 'https://slack.com')
2927
+ self.eq(nodes[0].get('name'), 'slack')
2928
+ self.eq(nodes[0].get('provider'), provider.ndef[1])
2929
+ self.eq(nodes[0].get('provider:name'), provname.lower())
2930
+ platform = nodes[0]
2931
+
2932
+ q = '''
2933
+ [ inet:service:instance=(vertex, slack)
2934
+ :id='T2XK1223Y'
2935
+ :platform={ inet:service:platform=(slack,) }
2936
+ :url="https://v.vtx.lk/slack"
2937
+ :name="Synapse users slack"
2938
+ ]
2939
+ '''
2940
+ nodes = await core.nodes(q)
2941
+ self.len(1, nodes)
2942
+ self.eq(nodes[0].ndef, ('inet:service:instance', s_common.guid(('vertex', 'slack'))))
2943
+ self.eq(nodes[0].get('id'), 'T2XK1223Y')
2944
+ self.eq(nodes[0].get('platform'), platform.ndef[1])
2945
+ self.eq(nodes[0].get('url'), 'https://v.vtx.lk/slack')
2946
+ self.eq(nodes[0].get('name'), 'synapse users slack')
2947
+ platinst = nodes[0]
2948
+
2949
+ q = '''
2950
+ [
2951
+ (inet:service:account=(blackout, account, vertex, slack)
2952
+ :id=U7RN51U1J
2953
+ :user=blackout
2954
+ :email=blackout@vertex.link
2955
+ :profile={ gen.ps.contact.email vertex.employee blackout@vertex.link }
2956
+ )
2957
+
2958
+ (inet:service:account=(visi, account, vertex, slack)
2959
+ :id=U2XK7PUVB
2960
+ :user=visi
2961
+ :email=visi@vertex.link
2962
+ :profile={ gen.ps.contact.email vertex.employee visi@vertex.link }
2963
+ )
2964
+ ]
2965
+ '''
2966
+ accounts = await core.nodes(q)
2967
+ self.len(2, accounts)
2968
+
2969
+ profiles = await core.nodes('ps:contact')
2970
+ self.len(2, profiles)
2971
+ self.eq(profiles[0].get('email'), 'blackout@vertex.link')
2972
+ self.eq(profiles[1].get('email'), 'visi@vertex.link')
2973
+ blckprof, visiprof = profiles
2974
+
2975
+ self.eq(accounts[0].ndef, ('inet:service:account', s_common.guid(('blackout', 'account', 'vertex', 'slack'))))
2976
+ self.eq(accounts[0].get('id'), 'U7RN51U1J')
2977
+ self.eq(accounts[0].get('user'), 'blackout')
2978
+ self.eq(accounts[0].get('email'), 'blackout@vertex.link')
2979
+ self.eq(accounts[0].get('profile'), blckprof.ndef[1])
2980
+
2981
+ self.eq(accounts[1].ndef, ('inet:service:account', s_common.guid(('visi', 'account', 'vertex', 'slack'))))
2982
+ self.eq(accounts[1].get('id'), 'U2XK7PUVB')
2983
+ self.eq(accounts[1].get('user'), 'visi')
2984
+ self.eq(accounts[1].get('email'), 'visi@vertex.link')
2985
+ self.eq(accounts[1].get('profile'), visiprof.ndef[1])
2986
+ blckacct, visiacct = accounts
2987
+
2988
+ q = '''
2989
+ [ inet:service:group=(developers, group, vertex, slack)
2990
+ :id=X1234
2991
+ :name="developers, developers, developers"
2992
+ :profile={ gen.ps.contact.email vertex.slack.group developers@vertex.slack.com }
2993
+ ]
2994
+ '''
2995
+ nodes = await core.nodes(q)
2996
+ self.len(1, nodes)
2997
+
2998
+ profiles = await core.nodes('ps:contact:email=developers@vertex.slack.com')
2999
+ self.len(1, profiles)
3000
+ devsprof = profiles[0]
3001
+
3002
+ self.eq(nodes[0].get('id'), 'X1234')
3003
+ self.eq(nodes[0].get('name'), 'developers, developers, developers')
3004
+ self.eq(nodes[0].get('profile'), devsprof.ndef[1])
3005
+ devsgrp = nodes[0]
3006
+
3007
+ q = '''
3008
+ [
3009
+ (inet:service:group:member=(blackout, developers, group, vertex, slack)
3010
+ :account=$blckiden
3011
+ :group=$devsiden
3012
+ :period=(20230601, ?)
3013
+ :creator=$visiiden
3014
+ :remover=$visiiden
3015
+ )
3016
+
3017
+ (inet:service:group:member=(visi, developers, group, vertex, slack)
3018
+ :account=$visiiden
3019
+ :group=$devsiden
3020
+ :period=(20150101, ?)
3021
+ )
3022
+ ]
3023
+ '''
3024
+ opts = {'vars': {
3025
+ 'blckiden': blckacct.ndef[1],
3026
+ 'visiiden': visiacct.ndef[1],
3027
+ 'devsiden': devsgrp.ndef[1],
3028
+ }}
3029
+ nodes = await core.nodes(q, opts=opts)
3030
+ self.len(2, nodes)
3031
+
3032
+ self.eq(nodes[0].get('account'), blckacct.ndef[1])
3033
+ self.eq(nodes[0].get('group'), devsgrp.ndef[1])
3034
+ self.eq(nodes[0].get('period'), (1685577600000, 9223372036854775807))
3035
+ self.eq(nodes[0].get('creator'), visiacct.ndef[1])
3036
+ self.eq(nodes[0].get('remover'), visiacct.ndef[1])
3037
+
3038
+ self.eq(nodes[1].get('account'), visiacct.ndef[1])
3039
+ self.eq(nodes[1].get('group'), devsgrp.ndef[1])
3040
+ self.eq(nodes[1].get('period'), (1420070400000, 9223372036854775807))
3041
+ self.none(nodes[1].get('creator'))
3042
+ self.none(nodes[1].get('remover'))
3043
+
3044
+ q = '''
3045
+ [ inet:service:session=*
3046
+ :creator=$blckiden
3047
+ :period=(202405160900, 202405161055)
3048
+ ]
3049
+ '''
3050
+ opts = {'vars': {'blckiden': blckacct.ndef[1]}}
3051
+ nodes = await core.nodes(q, opts=opts)
3052
+ self.len(1, nodes)
3053
+ self.eq(nodes[0].get('creator'), blckacct.ndef[1])
3054
+ self.eq(nodes[0].get('period'), (1715850000000, 1715856900000))
3055
+ blcksess = nodes[0]
3056
+
3057
+ q = '''
3058
+ [ inet:service:login=*
3059
+ :method=password
3060
+ :session=$blcksess
3061
+ :server=tcp://10.10.10.4:443
3062
+ :client=tcp://192.168.0.10:12345
3063
+ ]
3064
+ '''
3065
+ opts = {'vars': {'blcksess': blcksess.ndef[1]}}
3066
+ nodes = await core.nodes(q, opts=opts)
3067
+ self.len(1, nodes)
3068
+ self.eq(nodes[0].get('method'), 'password.')
3069
+
3070
+ server = await core.nodes('inet:server=tcp://10.10.10.4:443')
3071
+ self.len(1, server)
3072
+ server = server[0]
3073
+
3074
+ client = await core.nodes('inet:client=tcp://192.168.0.10:12345')
3075
+ self.len(1, client)
3076
+ client = client[0]
3077
+
3078
+ self.eq(nodes[0].get('server'), server.ndef[1])
3079
+ self.eq(nodes[0].get('client'), client.ndef[1])
3080
+
3081
+ q = '''
3082
+ [ inet:service:message:link=(blackout, developers, 1715856900000, https://www.youtube.com/watch?v=dQw4w9WgXcQ, vertex, slack)
3083
+ :title="Deadpool & Wolverine | Official Teaser | In Theaters July 26"
3084
+ :url="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
3085
+ ]
3086
+ '''
3087
+ nodes = await core.nodes(q)
3088
+ self.len(1, nodes)
3089
+ self.eq(nodes[0].get('title'), 'Deadpool & Wolverine | Official Teaser | In Theaters July 26')
3090
+ self.eq(nodes[0].get('url'), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ')
3091
+ msglink = nodes[0]
3092
+
3093
+ q = '''
3094
+ [ inet:service:channel=(general, channel, vertex, slack)
3095
+ :id=C1234
3096
+ :name=general
3097
+ :period=(20150101, ?)
3098
+ :creator=$visiiden
3099
+ :platform=$platiden
3100
+ :instance=$instiden
3101
+ ]
3102
+ '''
3103
+ opts = {'vars': {
3104
+ 'visiiden': visiacct.ndef[1],
3105
+ 'platiden': platform.ndef[1],
3106
+ 'instiden': platinst.ndef[1],
3107
+ }}
3108
+ nodes = await core.nodes(q, opts=opts)
3109
+ self.len(1, nodes)
3110
+ self.eq(nodes[0].ndef, ('inet:service:channel', s_common.guid(('general', 'channel', 'vertex', 'slack'))))
3111
+ self.eq(nodes[0].get('name'), 'general')
3112
+ self.eq(nodes[0].get('period'), (1420070400000, 9223372036854775807))
3113
+ self.eq(nodes[0].get('creator'), visiacct.ndef[1])
3114
+ self.eq(nodes[0].get('platform'), platform.ndef[1])
3115
+ self.eq(nodes[0].get('instance'), platinst.ndef[1])
3116
+ gnrlchan = nodes[0]
3117
+
3118
+ q = '''
3119
+ [
3120
+ (inet:service:channel:member=(visi, general, channel, vertex, slack)
3121
+ :account=$visiiden
3122
+ :period=(20150101, ?)
3123
+ )
3124
+
3125
+ (inet:service:channel:member=(blackout, general, channel, vertex, slack)
3126
+ :account=$blckiden
3127
+ :period=(20230601, ?)
3128
+ )
3129
+
3130
+ :platform=$platiden
3131
+ :instance=$instiden
3132
+ :channel=$chnliden
3133
+ ]
3134
+ '''
3135
+ opts = {'vars': {
3136
+ 'blckiden': blckacct.ndef[1],
3137
+ 'visiiden': visiacct.ndef[1],
3138
+ 'chnliden': gnrlchan.ndef[1],
3139
+ 'platiden': platform.ndef[1],
3140
+ 'instiden': platinst.ndef[1],
3141
+ }}
3142
+ nodes = await core.nodes(q, opts=opts)
3143
+ self.len(2, nodes)
3144
+ self.eq(nodes[0].ndef, ('inet:service:channel:member', s_common.guid(('visi', 'general', 'channel', 'vertex', 'slack'))))
3145
+ self.eq(nodes[0].get('account'), visiacct.ndef[1])
3146
+ self.eq(nodes[0].get('period'), (1420070400000, 9223372036854775807))
3147
+ self.eq(nodes[0].get('channel'), gnrlchan.ndef[1])
3148
+
3149
+ self.eq(nodes[1].ndef, ('inet:service:channel:member', s_common.guid(('blackout', 'general', 'channel', 'vertex', 'slack'))))
3150
+ self.eq(nodes[1].get('account'), blckacct.ndef[1])
3151
+ self.eq(nodes[1].get('period'), (1685577600000, 9223372036854775807))
3152
+ self.eq(nodes[1].get('channel'), gnrlchan.ndef[1])
3153
+
3154
+ for node in nodes:
3155
+ self.eq(node.get('platform'), platform.ndef[1])
3156
+ self.eq(node.get('instance'), platinst.ndef[1])
3157
+ self.eq(node.get('channel'), gnrlchan.ndef[1])
3158
+
3159
+ q = '''
3160
+ [ inet:service:message:attachment=(pbjtime.gif, blackout, developers, 1715856900000, vertex, slack)
3161
+ :file={[ file:bytes=sha256:028241d9116a02059e99cb239c66d966e1b550926575ad7dcf0a8f076a352bcd ]}
3162
+ :name=pbjtime.gif
3163
+ :text="peanut butter jelly time"
3164
+ ]
3165
+ '''
3166
+ nodes = await core.nodes(q)
3167
+ self.len(1, nodes)
3168
+ self.eq(nodes[0].get('file'), 'sha256:028241d9116a02059e99cb239c66d966e1b550926575ad7dcf0a8f076a352bcd')
3169
+ self.eq(nodes[0].get('name'), 'pbjtime.gif')
3170
+ self.eq(nodes[0].get('text'), 'peanut butter jelly time')
3171
+ attachment = nodes[0]
3172
+
3173
+ q = '''
3174
+ [
3175
+ (inet:service:message=(blackout, developers, 1715856900000, vertex, slack)
3176
+ :group=$devsiden
3177
+ :public=$lib.false
3178
+ )
3179
+
3180
+ (inet:service:message=(blackout, visi, 1715856900000, vertex, slack)
3181
+ :to=$visiiden
3182
+ :public=$lib.false
3183
+ )
3184
+
3185
+ (inet:service:message=(blackout, general, 1715856900000, vertex, slack)
3186
+ :channel=$gnrliden
3187
+ :public=$lib.true
3188
+ )
3189
+
3190
+ :account=$blckiden
3191
+ :text="omg, can't wait for the new deadpool: https://www.youtube.com/watch?v=dQw4w9WgXcQ"
3192
+ :links+=$linkiden
3193
+ :attachments+=$atchiden
3194
+
3195
+ :place:name=nyc
3196
+ :place = { gen.geo.place nyc }
3197
+ :file=*
3198
+
3199
+ :client:software = {[ it:prod:softver=* :name=woot ]}
3200
+ :client:software:name = woot
3201
+ ]
3202
+ '''
3203
+ opts = {'vars': {
3204
+ 'blckiden': blckacct.ndef[1],
3205
+ 'visiiden': visiacct.ndef[1],
3206
+ 'devsiden': devsgrp.ndef[1],
3207
+ 'gnrliden': gnrlchan.ndef[1],
3208
+ 'linkiden': msglink.ndef[1],
3209
+ 'atchiden': attachment.ndef[1],
3210
+ }}
3211
+ nodes = await core.nodes(q, opts=opts)
3212
+ self.len(3, nodes)
3213
+ for node in nodes:
3214
+
3215
+ self.eq(node.get('account'), blckacct.ndef[1])
3216
+ self.eq(node.get('text'), "omg, can't wait for the new deadpool: https://www.youtube.com/watch?v=dQw4w9WgXcQ")
3217
+ self.eq(node.get('links'), [msglink.ndef[1]])
3218
+
3219
+ self.nn(node.get('client:software'))
3220
+ self.eq(node.get('client:software:name'), 'woot')
3221
+
3222
+ self.nn(node.get('place'))
3223
+ self.eq(node.get('place:name'), 'nyc')
3224
+
3225
+ self.eq(nodes[0].get('group'), devsgrp.ndef[1])
3226
+ self.false(nodes[0].get('public'))
3227
+
3228
+ self.eq(nodes[1].get('to'), visiacct.ndef[1])
3229
+ self.false(nodes[1].get('public'))
3230
+
3231
+ self.eq(nodes[2].get('channel'), gnrlchan.ndef[1])
3232
+ self.true(nodes[2].get('public'))
3233
+
3234
+ q = '''
3235
+ [ inet:service:resource=(web, api, vertex, slack)
3236
+ :desc="The Web API supplies a collection of HTTP methods that underpin the majority of Slack app functionality."
3237
+ :instance=$instiden
3238
+ :name="Slack Web APIs"
3239
+ :platform=$platiden
3240
+ :type=slack.web.api
3241
+ :url="https://slack.com/api"
3242
+ ]
3243
+ '''
3244
+ opts = {'vars': {
3245
+ 'platiden': platform.ndef[1],
3246
+ 'instiden': platinst.ndef[1],
3247
+ }}
3248
+ nodes = await core.nodes(q, opts=opts)
3249
+ self.len(1, nodes)
3250
+ self.eq(nodes[0].get('desc'), 'The Web API supplies a collection of HTTP methods that underpin the majority of Slack app functionality.')
3251
+ self.eq(nodes[0].get('instance'), platinst.ndef[1])
3252
+ self.eq(nodes[0].get('name'), 'slack web apis')
3253
+ self.eq(nodes[0].get('platform'), platform.ndef[1])
3254
+ self.eq(nodes[0].get('type'), 'slack.web.api.')
3255
+ self.eq(nodes[0].get('url'), 'https://slack.com/api')
3256
+ resource = nodes[0]
3257
+
3258
+ nodes = await core.nodes('''
3259
+ [ inet:service:bucket:item=*
3260
+ :creator={ inet:service:account:user=visi }
3261
+ :bucket={[ inet:service:bucket=* :name=foobar
3262
+ :creator={ inet:service:account:user=visi }
3263
+ ]}
3264
+ :file=*
3265
+ :file:name=woot.exe
3266
+ ]
3267
+ ''')
3268
+ self.len(1, nodes)
3269
+ self.nn(nodes[0].get('file'))
3270
+ self.nn(nodes[0].get('bucket'))
3271
+ self.nn(nodes[0].get('creator'))
3272
+ self.eq('woot.exe', nodes[0].get('file:name'))
3273
+ self.len(1, await core.nodes('inet:service:bucket -> inet:service:bucket:item -> file:bytes'))
3274
+ self.len(1, await core.nodes('inet:service:bucket -> inet:service:bucket:item -> inet:service:account'))
3275
+ self.len(1, await core.nodes('inet:service:bucket -> inet:service:account'))
3276
+ self.len(1, await core.nodes('inet:service:bucket:name=foobar'))
3277
+
3278
+ q = '''
3279
+ [ inet:service:access=(api, blackout, 1715856900000, vertex, slack)
3280
+ :account=$blckiden
3281
+ :instance=$instiden
3282
+ :platform=$platiden
3283
+ :resource=$rsrciden
3284
+ :success=$lib.true
3285
+ :time=(1715856900000)
3286
+ ]
3287
+ '''
3288
+ opts = {'vars': {
3289
+ 'blckiden': blckacct.ndef[1],
3290
+ 'instiden': platinst.ndef[1],
3291
+ 'visiiden': visiacct.ndef[1],
3292
+ 'platiden': platform.ndef[1],
3293
+ 'rsrciden': resource.ndef[1],
3294
+ }}
3295
+ nodes = await core.nodes(q, opts=opts)
3296
+ self.len(1, nodes)
3297
+ self.eq(nodes[0].get('account'), blckacct.ndef[1])
3298
+ self.eq(nodes[0].get('instance'), platinst.ndef[1])
3299
+ self.eq(nodes[0].get('platform'), platform.ndef[1])
3300
+ self.eq(nodes[0].get('resource'), resource.ndef[1])
3301
+ self.true(nodes[0].get('success'))
3302
+ self.eq(nodes[0].get('time'), 1715856900000)
@@ -4,6 +4,7 @@ import hashlib
4
4
  import synapse.exc as s_exc
5
5
  import synapse.common as s_common
6
6
 
7
+ import synapse.lib.const as s_const
7
8
  import synapse.lib.scrape as s_scrape
8
9
 
9
10
  import synapse.models.crypto as s_m_crypto
@@ -387,6 +388,25 @@ class InfotechModelTest(s_t_utils.SynTest):
387
388
 
388
389
  self.len(1, await core.nodes('it:av:scan:result:scanner:name="visi total" -> it:av:scan:result +:scanner:name="visi scan"'))
389
390
 
391
+ q = '''
392
+ [ it:network=(vertex, ops, lan)
393
+ :desc="Vertex Project Operations LAN"
394
+ :name="opslan.lax.vertex.link"
395
+ :net4="10.1.0.0/16"
396
+ :net6="fe80::0/64"
397
+ :org={ gen.ou.org "Vertex Project" }
398
+ :type=virtual.sdn
399
+ ]
400
+ '''
401
+ nodes = await core.nodes(q)
402
+ self.len(1, nodes)
403
+ self.eq(nodes[0].ndef, ('it:network', s_common.guid(('vertex', 'ops', 'lan'))))
404
+ self.eq(nodes[0].get('desc'), 'Vertex Project Operations LAN')
405
+ self.eq(nodes[0].get('name'), 'opslan.lax.vertex.link')
406
+ self.eq(nodes[0].get('net4'), (167837696, 167903231))
407
+ self.eq(nodes[0].get('net6'), ('fe80::', 'fe80::ffff:ffff:ffff:ffff'))
408
+ self.eq(nodes[0].get('type'), 'virtual.sdn.')
409
+
390
410
  async def test_infotech_ios(self):
391
411
 
392
412
  async with self.getTestCore() as core:
@@ -447,6 +467,24 @@ class InfotechModelTest(s_t_utils.SynTest):
447
467
  node = nodes[0]
448
468
  self.eq(node.ndef, ('it:hostname', 'bobs computer'))
449
469
 
470
+ q = '''
471
+ [ it:software:image=(ubuntu, 24.10, amd64, vhdx)
472
+ :name="ubuntu-24.10-amd64.vhdx"
473
+ :published=202405170940
474
+ :publisher={[ ps:contact=(blackout,) :name=blackout ]}
475
+ :creator={[ inet:service:account=* :user=visi ]}
476
+ :parents={[ it:software:image=* :name=zoom ]}
477
+ ]
478
+ '''
479
+ nodes = await core.nodes(q)
480
+ self.len(1, nodes)
481
+ self.len(1, nodes[0].get('parents'))
482
+ self.eq(nodes[0].ndef, ('it:software:image', s_common.guid(('ubuntu', '24.10', 'amd64', 'vhdx'))))
483
+ self.eq(nodes[0].get('name'), 'ubuntu-24.10-amd64.vhdx')
484
+ self.eq(nodes[0].get('published'), 1715938800000)
485
+ self.eq(nodes[0].get('publisher'), s_common.guid(('blackout',)))
486
+ image = nodes[0]
487
+
450
488
  org0 = s_common.guid()
451
489
  host0 = s_common.guid()
452
490
  sver0 = s_common.guid()
@@ -464,11 +502,12 @@ class InfotechModelTest(s_t_utils.SynTest):
464
502
  'loc': 'us.hehe.haha',
465
503
  'operator': cont0,
466
504
  'org': org0,
467
- 'ext:id': 'foo123'
505
+ 'ext:id': 'foo123',
506
+ 'image': image.ndef[1],
468
507
  }
469
508
  q = '''[(it:host=$valu :name=$p.name :desc=$p.desc :ipv4=$p.ipv4 :place=$p.place :latlong=$p.latlong
470
509
  :os=$p.os :manu=$p.manu :model=$p.model :serial=$p.serial :loc=$p.loc :operator=$p.operator
471
- :org=$p.org :ext:id=$p."ext:id")]'''
510
+ :org=$p.org :ext:id=$p."ext:id" :image=$p.image)]'''
472
511
  nodes = await core.nodes(q, opts={'vars': {'valu': host0, 'p': props}})
473
512
  self.len(1, nodes)
474
513
  node = nodes[0]
@@ -483,6 +522,40 @@ class InfotechModelTest(s_t_utils.SynTest):
483
522
  self.eq(node.get('org'), org0)
484
523
  self.eq(node.get('operator'), cont0)
485
524
  self.eq(node.get('ext:id'), 'foo123')
525
+ host = node
526
+
527
+ q = r'''
528
+ [ it:storage:volume=(smb, 192.168.0.10, c$, temp)
529
+ :name="\\\\192.168.0.10\\c$\\temp"
530
+ :size=(10485760)
531
+ :type=windows.smb.share
532
+ ]
533
+ '''
534
+ nodes = await core.nodes(q)
535
+ self.len(1, nodes)
536
+ self.eq(nodes[0].ndef, ('it:storage:volume', s_common.guid(('smb', '192.168.0.10', 'c$', 'temp'))))
537
+ self.eq(nodes[0].get('name'), '\\\\192.168.0.10\\c$\\temp')
538
+ self.eq(nodes[0].get('size'), s_const.mebibyte * 10)
539
+ self.eq(nodes[0].get('type'), 'windows.smb.share.')
540
+ volume = nodes[0]
541
+
542
+ q = r'''
543
+ [ it:storage:mount=($hostiden, $voluiden, z:\\)
544
+ :host=$hostiden
545
+ :path="z:\\"
546
+ :volume=$voluiden
547
+ ]
548
+ '''
549
+ opts = {'vars': {
550
+ 'voluiden': volume.ndef[1],
551
+ 'hostiden': host.ndef[1],
552
+ }}
553
+ nodes = await core.nodes(q, opts=opts)
554
+ self.len(1, nodes)
555
+ self.eq(nodes[0].ndef, ('it:storage:mount', s_common.guid((host.ndef[1], volume.ndef[1], r'z:\\'))))
556
+ self.eq(nodes[0].get('host'), host.ndef[1])
557
+ self.eq(nodes[0].get('path'), 'z:')
558
+ self.eq(nodes[0].get('volume'), volume.ndef[1])
486
559
 
487
560
  valu = (host0, 'http://vertex.ninja/cool.php')
488
561
  nodes = await core.nodes('[it:hosturl=$valu]', opts={'vars': {'valu': valu}})
@@ -1112,6 +1185,62 @@ class InfotechModelTest(s_t_utils.SynTest):
1112
1185
  self.len(1, nodes)
1113
1186
  self.eq(nodes[0].ndef, ('it:cmd', 'rar a -r yourfiles.rar *.txt'))
1114
1187
 
1188
+ q = '''
1189
+ [ it:host=(VTX001, 192.168.0.10) :name=VTX001 :ipv4=192.168.0.10 ]
1190
+ $host = $node
1191
+
1192
+ [( it:cmd:session=(202405170900, 202405171000, bash, $host)
1193
+ :host=$host
1194
+ :period=(202405170900, 202405171000)
1195
+ )]
1196
+ '''
1197
+ nodes = await core.nodes(q)
1198
+ self.len(2, nodes)
1199
+ hostguid = s_common.guid(('VTX001', '192.168.0.10'))
1200
+ self.eq(nodes[0].ndef, ('it:host', hostguid))
1201
+ self.eq(nodes[1].ndef, ('it:cmd:session', s_common.guid(('202405170900', '202405171000', 'bash', hostguid))))
1202
+ self.eq(nodes[1].get('host'), hostguid)
1203
+ self.eq(nodes[1].get('period'), (1715936400000, 1715940000000))
1204
+ cmdsess = nodes[1]
1205
+
1206
+ q = '''
1207
+ [
1208
+ (it:cmd:history=(1715936400001, $sessiden)
1209
+ :cmd="ls -la"
1210
+ :time=(1715936400001)
1211
+ )
1212
+
1213
+ (it:cmd:history=(1715936400002, $sessiden)
1214
+ :cmd="cd /"
1215
+ :time=(1715936400002)
1216
+ )
1217
+
1218
+ (it:cmd:history=(1715936400003, $sessiden)
1219
+ :cmd="ls -laR"
1220
+ :time=(1715936400003)
1221
+ )
1222
+
1223
+ :session=$sessiden
1224
+ ]
1225
+ '''
1226
+ opts = {'vars': {'sessiden': cmdsess.ndef[1]}}
1227
+ nodes = await core.nodes(q, opts=opts)
1228
+ self.len(3, nodes)
1229
+ self.eq(nodes[0].ndef, ('it:cmd:history', s_common.guid(('1715936400001', cmdsess.ndef[1]))))
1230
+ self.eq(nodes[0].get('cmd'), 'ls -la')
1231
+ self.eq(nodes[0].get('time'), 1715936400001)
1232
+ self.eq(nodes[0].get('session'), cmdsess.ndef[1])
1233
+
1234
+ self.eq(nodes[1].ndef, ('it:cmd:history', s_common.guid(('1715936400002', cmdsess.ndef[1]))))
1235
+ self.eq(nodes[1].get('cmd'), 'cd /')
1236
+ self.eq(nodes[1].get('time'), 1715936400002)
1237
+ self.eq(nodes[1].get('session'), cmdsess.ndef[1])
1238
+
1239
+ self.eq(nodes[2].ndef, ('it:cmd:history', s_common.guid(('1715936400003', cmdsess.ndef[1]))))
1240
+ self.eq(nodes[2].get('cmd'), 'ls -laR')
1241
+ self.eq(nodes[2].get('time'), 1715936400003)
1242
+ self.eq(nodes[2].get('session'), cmdsess.ndef[1])
1243
+
1115
1244
  m0 = s_common.guid()
1116
1245
  mprops = {
1117
1246
  'exe': exe,
@@ -1747,6 +1876,7 @@ class InfotechModelTest(s_t_utils.SynTest):
1747
1876
 
1748
1877
  async with self.getTestCore() as core:
1749
1878
 
1879
+ opts = {'vars': {'root': core.auth.rootuser.iden}}
1750
1880
  nodes = await core.nodes('''
1751
1881
  [ it:exec:query=*
1752
1882
  :text="SELECT * FROM threats"
@@ -1755,14 +1885,16 @@ class InfotechModelTest(s_t_utils.SynTest):
1755
1885
  :api:url=https://vertex.link/api/v1.
1756
1886
  :time=20220720
1757
1887
  :offset=99
1888
+ :synuser=$root
1758
1889
  // we can assume the rest of the interface props work
1759
1890
  ]
1760
- ''')
1891
+ ''', opts=opts)
1761
1892
  self.eq(1658275200000, nodes[0].get('time'))
1762
1893
  self.eq(99, nodes[0].get('offset'))
1763
1894
  self.eq('sql', nodes[0].get('language'))
1764
1895
  self.eq({"foo": "bar"}, nodes[0].get('opts'))
1765
1896
  self.eq('SELECT * FROM threats', nodes[0].get('text'))
1897
+ self.eq(core.auth.rootuser.iden, nodes[0].get('synuser'))
1766
1898
  self.len(1, await core.nodes('it:exec:query -> it:query +it:query="SELECT * FROM threats"'))
1767
1899
 
1768
1900
  async def test_infotech_softid(self):
@@ -24,6 +24,7 @@ class OuModelTest(s_t_utils.SynTest):
24
24
  :sophistication=high
25
25
  :reporter=$lib.gen.orgByName(vertex)
26
26
  :reporter:name=vertex
27
+ :ext:id=Foo
27
28
  ]
28
29
  ''')
29
30
  self.len(1, nodes)
@@ -32,6 +33,7 @@ class OuModelTest(s_t_utils.SynTest):
32
33
  self.eq('Hehe', nodes[0].get('desc'))
33
34
  self.eq('lol.woot.', nodes[0].get('type'))
34
35
  self.eq('woot.woot', nodes[0].get('tag'))
36
+ self.eq('Foo', nodes[0].get('ext:id'))
35
37
  self.eq('T0001', nodes[0].get('mitre:attack:technique'))
36
38
  self.eq(40, nodes[0].get('sophistication'))
37
39
  self.eq('vertex', nodes[0].get('reporter:name'))
@@ -93,6 +95,7 @@ class OuModelTest(s_t_utils.SynTest):
93
95
  :techniques=$p.techniques :sophistication=$p.sophistication :tag=$p.tag
94
96
  :reporter=$p.reporter :reporter:name=$p."reporter:name" :timeline=$p.timeline
95
97
  :mitre:attack:campaign=$p."mitre:attack:campaign"
98
+ :ext:id=Foo
96
99
  )]'''
97
100
  nodes = await core.nodes(q, opts={'vars': {'valu': camp, 'p': props}})
98
101
  self.len(1, nodes)
@@ -106,6 +109,7 @@ class OuModelTest(s_t_utils.SynTest):
106
109
  self.eq(node.get('names'), ('bar', 'foo'))
107
110
  self.eq(node.get('type'), 'MyType')
108
111
  self.eq(node.get('desc'), 'MyDesc')
112
+ self.eq(node.get('ext:id'), 'Foo')
109
113
  self.eq(node.get('success'), 1)
110
114
  self.eq(node.get('sophistication'), 40)
111
115
  self.eq(node.get('camptype'), 'get.pizza.')
@@ -234,6 +238,7 @@ class OuModelTest(s_t_utils.SynTest):
234
238
  :logo=$p.logo :alias=$p.alias :phone=$p.phone :sic=$p.sic :naics=$p.naics :url=$p.url
235
239
  :us:cage=$p."us:cage" :founded=$p.founded :dissolved=$p.dissolved
236
240
  :techniques=$p.techniques :goals=$p.goals
241
+ :ext:id=Foo
237
242
  )]'''
238
243
  nodes = await core.nodes(q, opts={'vars': {'valu': guid0, 'p': props}})
239
244
  self.len(1, nodes)
@@ -254,6 +259,7 @@ class OuModelTest(s_t_utils.SynTest):
254
259
  self.eq(node.get('dissolved'), 1546300800000)
255
260
  self.eq(node.get('techniques'), tuple(sorted(teqs)))
256
261
  self.eq(node.get('goals'), (goal,))
262
+ self.eq(node.get('ext:id'), 'Foo')
257
263
  self.nn(node.get('logo'))
258
264
 
259
265
  await core.nodes('ou:org:us:cage=7qe71 [ :country={ gen.pol.country ua } :country:code=ua ]')