mirror of
https://github.com/vxcontrol/soldr-modules.git
synced 2026-07-18 18:44:30 -04:00
Compare commits
117 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 74831c4c97 | |||
| f1c1e49db1 | |||
| 0a3f02bc5f | |||
| a8be3ba0af | |||
| af941e1c71 | |||
| be3651d827 | |||
| a1df667c98 | |||
| dfbdbbc495 | |||
| c18af383fd | |||
| 599b5180e9 | |||
| 1e827cf5a0 | |||
| d19f506558 | |||
| 8e032785d7 | |||
| d28ff67b4f | |||
| 094fd0d190 | |||
| ad90fa13b3 | |||
| 34a0c99813 | |||
| ce42366da7 | |||
| f3b4b61be3 | |||
| fdcd94b4d9 | |||
| 4baa30e8c7 | |||
| bf545f1a7a | |||
| b3ce04b5c6 | |||
| 39c72a5577 | |||
| faa553a310 | |||
| afda35651c | |||
| 03856d1336 | |||
| 7ec96dd84c | |||
| 75dd83eecf | |||
| 19514048aa | |||
| b10cc7bfc0 | |||
| a0ca8fd1dc | |||
| 2445f9bb0c | |||
| 69886543bb | |||
| ffb0b15cca | |||
| 5a04c3a8a5 | |||
| 77048d99ce | |||
| cd842fce75 | |||
| e168a06f78 | |||
| 6687c3e552 | |||
| 08d0876321 | |||
| 10cc0f34ae | |||
| 29ab89ff01 | |||
| 977496eb24 | |||
| 298e80e243 | |||
| e715eaaf41 | |||
| 1141e4f8fd | |||
| fb768ad945 | |||
| 2b13bef44b | |||
| 0a521c7b0a | |||
| 0edb31670c | |||
| 665fc773ec | |||
| 4ea8a4bb93 | |||
| 8df2641f71 | |||
| ab2ae0e487 | |||
| c0fd490a93 | |||
| 862659a747 | |||
| 0eafc0cfb5 | |||
| f9ef7b0dcc | |||
| a2c586c809 | |||
| e017a46a59 | |||
| 281f6d71f8 | |||
| 9640b655ff | |||
| 06b2fab216 | |||
| 5aab1e119f | |||
| fd8b19d458 | |||
| a943faf956 | |||
| d5324301ed | |||
| 89c123afa7 | |||
| e26ea21191 | |||
| 0e3500583e | |||
| 127a97795c | |||
| 909306160c | |||
| 89005d4e34 | |||
| 43df33625b | |||
| 989cc8a0dd | |||
| c5bfb2bc8a | |||
| 16202c0b3c | |||
| 2e09f2fb59 | |||
| 8c0cdb92df | |||
| 40647f6cde | |||
| 357bb09836 | |||
| ba8311d7e6 | |||
| 5469e06baa | |||
| 7cf37a9683 | |||
| 94c1543b1e | |||
| 938e000ba3 | |||
| 8ed3604ea2 | |||
| a5030cf001 | |||
| fdd581324c | |||
| 793f835932 | |||
| e0f94fda6f | |||
| 67a94ae3b3 | |||
| 701cf72ea1 | |||
| 616faaa8d5 | |||
| c6b6df1ce6 | |||
| 8d829e8c88 | |||
| d962eb358d | |||
| 7fc9e94903 | |||
| 90c1c37c64 | |||
| e1bb789913 | |||
| 65d769a8c1 | |||
| 397de6cbc7 | |||
| 2550dfa54d | |||
| a9efaacefb | |||
| f00abef04a | |||
| 36d3b30079 | |||
| cec71fe343 | |||
| a9ed215b2c | |||
| b6f5fa510c | |||
| 19b6424398 | |||
| 701fbfc4e7 | |||
| b4e61a30bc | |||
| 4135277bd8 | |||
| 053dc5c142 | |||
| 4d8c670161 | |||
| a6d05ce4ed |
@@ -0,0 +1,64 @@
|
||||
name: "\U0001F41B Bug report"
|
||||
description: "Report a bug with this project."
|
||||
title: "[Bug]: "
|
||||
labels: ["bug"]
|
||||
assignees:
|
||||
- asdek
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report! Please fill in as much of the template below as you can.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: Please write a clear and concise description of the bug, including what you expect to happen and what is currently happening.
|
||||
placeholder: |
|
||||
Feature '...' is not working properly. I expect '...' to happen, but '...' happens instead
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: Please write the steps needed to reproduce the bug.
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. Scroll down to '...'
|
||||
4. See error
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Screenshots, screen recording, code snippet
|
||||
description: |
|
||||
If possible, please upload a screenshot or screen recording which demonstrates the bug. You can use [LICEcap](https://www.cockos.com/licecap/) to create a GIF screen recording.
|
||||
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||
For small snippets paste it directly here, or you can use [GitHub Gist](https://gist.github.com) to share multiple code files.
|
||||
Please ensure the shared code can be used by a developer to reproduce the issue—ideally it can be copied into a local development environment or executed in a browser console to help debug the issue
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Environment information
|
||||
placeholder: |
|
||||
- UI server version: <!-- [e.g. 3.2.0] -->
|
||||
- Agent server version: <!-- [e.g. 3.2.0] -->
|
||||
- Agent version: <!-- [e.g. 3.2.0] -->
|
||||
- Module version: <!-- [e.g. 1.0.1] -->
|
||||
- Link Module code: <!-- [link-to-zip-archive-with-helpful-code] -->
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: operating-systems
|
||||
attributes:
|
||||
label: Which agent binary used?
|
||||
description: We have several different builds, choose which ones have the problem.
|
||||
options:
|
||||
- label: darwin-amd64
|
||||
- label: linux-386
|
||||
- label: linux-amd64
|
||||
- label: windows-386
|
||||
- label: windows-amd64
|
||||
validations:
|
||||
required: true
|
||||
@@ -0,0 +1,36 @@
|
||||
name: "\U0001F680 Enhancement"
|
||||
description: "Suggest an idea for this project."
|
||||
title: "[Enhancement]: "
|
||||
labels: ["enhancement"]
|
||||
assignees:
|
||||
- asdek
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for suggesting an idea to make things better. Please fill in as much of the template below as you can.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Is your enhancement related to a problem? Please describe.
|
||||
description: Please describe the problem you are trying to solve.
|
||||
placeholder: |
|
||||
I use this project as a `...` and I would like `...` so that `...describe benefit...`.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Designs
|
||||
description: |
|
||||
If applicable, add mockups/screenshots/etc. to help explain your idea.
|
||||
Tip: You can attach images or videos by clicking this area to highlight it and then dragging files in.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe alternatives you've considered
|
||||
description: |
|
||||
Please describe alternative solutions or features you have considered.
|
||||
placeholder: |
|
||||
I have also considered `...describe alternative...`, however I feel that my solution described above is better because of `...reason...`.
|
||||
validations:
|
||||
required: false
|
||||
@@ -0,0 +1,37 @@
|
||||
<!--
|
||||
Filling out this template is required. Any PR that does not include enough information to be reviewed may be closed at a maintainers' discretion.
|
||||
-->
|
||||
|
||||
### Description of the Change
|
||||
<!--
|
||||
We must be able to understand the design of your change from this description. The maintainer reviewing this PR may not have worked with this code recently, so please provide as much detail as possible.
|
||||
|
||||
Where possible, please also include:
|
||||
- verification steps to ensure your change has the desired effects and has not introduced any regressions
|
||||
- any benefits that will be realized
|
||||
- any alternative implementations or possible drawbacks that you considered
|
||||
- screenshots or screencasts
|
||||
-->
|
||||
|
||||
<!-- Enter any applicable Issue number(s) here that will be closed/resolved by this PR. -->
|
||||
Closes #
|
||||
|
||||
### How to test the Change
|
||||
<!-- Please provide steps on how to test or validate that the change in this PR works as described. -->
|
||||
|
||||
### Changelog Entry
|
||||
<!--
|
||||
Please include a summary for this PR, noting whether this is something being Added / Changed / Deprecated / Removed / Fixed / or Security related. You can replace the sample entries after this comment block with the single changelog entry line for this PR. -->
|
||||
> Added - New feature
|
||||
> Changed - Existing functionality
|
||||
> Deprecated - Soon-to-be removed feature
|
||||
> Removed - Feature
|
||||
> Fixed - Bug fix
|
||||
> Security - Vulnerability
|
||||
|
||||
### Checklist:
|
||||
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
|
||||
<!--- If you are unsure about any of these, please ask for clarification. We are here to help! -->
|
||||
- [ ] I have updated the documentation accordingly.
|
||||
- [ ] I have added tests to cover my change.
|
||||
- [ ] All new and existing tests pass.
|
||||
@@ -0,0 +1,75 @@
|
||||
# Saved Replies
|
||||
|
||||
In order to help reduce the time it takes to respond to open Issues and Pull Requests, we should leverage [GitHub’s Saved Replies](https://help.github.com/en/articles/about-saved-replies) to help when we are continually responding in the same manner. The following are various Saved Replies that the soldr team should use to respond to Issues and Pull Requests to ensure our community responses are similar and to minimize the amount of time crafting the same response to different requests.
|
||||
|
||||
Since GitHub currently does not allow us to have a repository-wide or organization-wide list of [saved replies](https://help.github.com/articles/working-with-saved-replies/), these replies need to be maintained by individual team members. Since the replies can be modified in the future, all responses are versioned to simplify the process of keeping the replies up to date.
|
||||
|
||||
While these Saved Replies attempt to give you the ability to quickly reply to Issues and Pull Requests, they are not meant to be the _exact_ response you should use every time. Consider customizing them to fit the context of the Issue or Pull Request contribution you are replying to. You will be best served by welcoming the contributor to the project (if its their first issue/PR), thanking them for their contribution, giving them context to your response (especially if you're closing their issue/PR), and noting next steps (e.g., issue milestoned for a specific release, open to them submitting a PR to resolve an issue, sending a PR to someone else to review).
|
||||
|
||||
You can add these saved replies to [your personal GitHub account here](https://github.com/settings/replies).
|
||||
|
||||
_Sources: [1](https://github.com/angular/angular/blob/master/docs/SAVED_REPLIES.md), [2](https://github.com/angular/angular-cli/blob/master/.github/SAVED_REPLIES.md), [3](https://github.com/prometheus/docs/blob/master/snippets/saved_replies.md), & [4](https://gist.github.com/jywarren/c9a80e0e53f42208974683aa01c623c8)._
|
||||
|
||||
## Issue: already fixed (v1)
|
||||
```
|
||||
Thanks for filing this Issue! Fortunately it is now obsolete due to changes in a recent release. Please update to the most recent version to resolve the problem.
|
||||
|
||||
If you are still having problems after updating, then please provide additional details for us to try and replicate your issue.
|
||||
```
|
||||
|
||||
## Issue: don't understand (v1)
|
||||
```
|
||||
I'm sorry but I don't understand the problem you are reporting. Would you please rephrase your issue so I can attempt to better understand it?
|
||||
```
|
||||
|
||||
## Issue: can't reproduce (v1)
|
||||
```
|
||||
Thanks for filing this Issue! Unfortunately I cannot reproduce the problem following the instructions you provided. We require that reported issues have reproduction steps that highlights the problem.
|
||||
|
||||
If the problem still exists for you, then please include any additional information on how to reproduce it.
|
||||
```
|
||||
|
||||
## Issue: behaving as expected (v1)
|
||||
```
|
||||
It appears this behaves as expected. If you still feel there is an issue, please provide further details on your problem.
|
||||
```
|
||||
|
||||
## Issue: template missing (v1)
|
||||
```
|
||||
Thanks for filing this Issue! Please note that we have Issue templates for [bug](https://github.com/vxcontrol/soldr/blob/master/.github/ISSUE_TEMPLATE/1-bug-report.md), [enhancement](https://github.com/vxcontrol/soldr/blob/master/.github/ISSUE_TEMPLATE/2-enhancement.md). I would appreciate it if you could edit your Issue and add in the missing details.
|
||||
```
|
||||
|
||||
## Issue: PR please? (v1)
|
||||
```
|
||||
I would love your help on this Issue, would be happy to review a PR for it, and will attempt to provide any assistance you might need.
|
||||
```
|
||||
|
||||
## Issue or PR: duplicate (v1)
|
||||
```
|
||||
Thanks for filing this (issue, PR). However this is a duplicate of an existing (issue, PR) #NUMBER, so I'm closing this but if you think this was in error then don't hesitate to comment. Otherwise please subscribe to #NUMBER for future updates.
|
||||
```
|
||||
|
||||
## Issue or PR: close as inactive (v1)
|
||||
```
|
||||
I'm closing this issue due to inactivity, but please let me know if you're still having problems so I can try to help... thanks!
|
||||
```
|
||||
|
||||
## Issue or PR: send for help! (v1)
|
||||
```
|
||||
Thanks for filing this! Unfortunately I’m uncertain on how to proceed here, so I’m pinging (@maintainer, @10up/open-source-practice) for their input.
|
||||
```
|
||||
|
||||
## PR: merging and more (v1)
|
||||
```
|
||||
This looks perfect, so I'll merge it. If you are looking for another challenge, then please take a look at our `help-wanted` list: https://github.com/vxcontrol/soldr/labels/help-wanted. Thanks!
|
||||
```
|
||||
|
||||
## PR: template missing (v1)
|
||||
```
|
||||
Thanks for filing this PR! Please note that we have a [PR template](https://github.com/vxcontrol/soldr/blob/master/.github/PULL_REQUEST_TEMPLATE.md) that is required. I would appreciate it if you could edit your PR and add in the missing details.
|
||||
```
|
||||
|
||||
## PR: missing related Issue (v1)
|
||||
```
|
||||
Thanks for filing this PR! Please note that we require an Issue for each PR so that approach and other details can be discussed in the Issue while code review can happen in the PR. I would appreciate it if you could [open an Issue](https://github.com/vxcontrol/soldr/issues/new/choose) and link it to this PR for further discussion.
|
||||
```
|
||||
@@ -0,0 +1,52 @@
|
||||
name: 'Docker build'
|
||||
description: 'Build docker in workdir'
|
||||
inputs:
|
||||
docker_name:
|
||||
description: 'Name of creation docker image'
|
||||
required: true
|
||||
default: ''
|
||||
builddir:
|
||||
description: 'Name of creation docker image'
|
||||
required: false
|
||||
default: '.'
|
||||
docker_login:
|
||||
description: 'Login to docker hub'
|
||||
required: true
|
||||
default: ''
|
||||
docker_password:
|
||||
description: 'Password to docker hub'
|
||||
required: true
|
||||
default: ''
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Generate Docker tags
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: |
|
||||
docker.io/vxcontrol/${{ inputs.docker_name }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'master') }}
|
||||
type=semver,pattern={{version}}
|
||||
flavor: |
|
||||
latest=false
|
||||
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ inputs.docker_login }}
|
||||
password: ${{ inputs.docker_password }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3
|
||||
env:
|
||||
DOCKER_BUILDKIT: 1
|
||||
with:
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
context: ${{ inputs.builddir }}
|
||||
@@ -0,0 +1,23 @@
|
||||
name: VXModules build and push
|
||||
|
||||
on: workflow_call
|
||||
|
||||
jobs:
|
||||
build_and_push_docker:
|
||||
name: Docker Build and Publish
|
||||
environment:
|
||||
name: production
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Docker build dbmigrate
|
||||
uses: ./.github/actions/docker_build
|
||||
with:
|
||||
workdir: "build/package/dbmigrate"
|
||||
docker_name: "soldr-modules"
|
||||
docker_login: ${{ secrets.DOCKER_LOGIN }}
|
||||
docker_password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
@@ -0,0 +1,16 @@
|
||||
name: Docker build and push
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- v[0-9]+.[0-9]+.[0-9]+
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
# BUILD DOCKER
|
||||
build_docker_vxmodules:
|
||||
uses: vxcontrol/soldr-modules/.github/workflows/build-docker-modules.yml@master
|
||||
if: github.ref_name == 'master' || startsWith(github.ref, 'refs/tags')
|
||||
secrets: inherit
|
||||
+4
-2
@@ -10,7 +10,8 @@ tools/sysmon.xml
|
||||
|
||||
.idea/
|
||||
.venv/
|
||||
.vscode/
|
||||
.vscode/launch.json
|
||||
.vscode/settings.json
|
||||
|
||||
tmpcwd/*
|
||||
tmpdir/*
|
||||
@@ -18,5 +19,6 @@ tmpdir/*
|
||||
|
||||
luacov-html
|
||||
luacov.*
|
||||
!luacov.lua
|
||||
coverage-report
|
||||
junit.xml
|
||||
junit.xml
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
[submodule "luapower"]
|
||||
path = luapower
|
||||
url = git@github.com:capr/multigit.git
|
||||
url = git@github.com:vxcontrol/multigit.git
|
||||
|
||||
+12
-4
@@ -6,11 +6,11 @@ self = false
|
||||
files["**/*_spec.lua"].std = "+busted"
|
||||
files["**/tests/*_spec.lua"].std = "+busted"
|
||||
|
||||
max_line_length=160
|
||||
max_string_line_length=250
|
||||
max_comment_line_length=320
|
||||
max_line_length = 160
|
||||
max_string_line_length = 250
|
||||
max_comment_line_length = 320
|
||||
|
||||
exclude_files = {"tests_framework/*"}
|
||||
exclude_files = { "tests_framework/*" }
|
||||
|
||||
read_globals = {
|
||||
-- table
|
||||
@@ -22,6 +22,9 @@ read_globals = {
|
||||
-- assert
|
||||
"assert.is_true",
|
||||
"assert.is_false",
|
||||
"assert.equal",
|
||||
"assert.not_nil",
|
||||
"assert.is_nil",
|
||||
|
||||
-- yaci API
|
||||
"newclass",
|
||||
@@ -74,12 +77,14 @@ globals = {
|
||||
"__mock",
|
||||
|
||||
-- utils classes
|
||||
"CSystemInfo",
|
||||
"CFileReader",
|
||||
"CReader",
|
||||
|
||||
-- correlator classes
|
||||
"CEventEngine",
|
||||
"CActionEngine",
|
||||
"CActionsValidator",
|
||||
"CCorrEngine",
|
||||
"CBaseEngine",
|
||||
|
||||
@@ -103,9 +108,12 @@ globals = {
|
||||
"setfenv",
|
||||
|
||||
-- busted API
|
||||
"context",
|
||||
"describe",
|
||||
"teardown",
|
||||
"setup",
|
||||
"it",
|
||||
"test",
|
||||
"before_each"
|
||||
}
|
||||
|
||||
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"eriklynd.json-tools",
|
||||
"nickdemayo.vscode-json-editor",
|
||||
"bubuabu.busted-test-explorer",
|
||||
"keyring.Lua",
|
||||
"yinfei.luahelper",
|
||||
"actboy168.lua-debug",
|
||||
"satoren.lualint",
|
||||
"octref.vetur",
|
||||
"Vue.volar",
|
||||
"sdras.vue-vscode-snippets",
|
||||
"hollowtree.vue-snippets",
|
||||
"ElemeFE.vscode-element-helper",
|
||||
"infosec-intern.yara"
|
||||
]
|
||||
}
|
||||
+13
-21
@@ -1,8 +1,8 @@
|
||||
FROM minio/mc
|
||||
FROM minio/mc as minio_client
|
||||
|
||||
FROM mysql:5.7-debian
|
||||
FROM python:3.10-alpine
|
||||
|
||||
COPY --from=0 /usr/bin/mc /usr/bin/mc
|
||||
COPY --from=minio_client /usr/bin/mc /usr/bin/mc
|
||||
|
||||
ARG VXVERSION=unknown
|
||||
|
||||
@@ -17,6 +17,7 @@ COPY startup.sh /opt/vxmodules/
|
||||
# SQL file generator script
|
||||
COPY gen_sql.py /opt/vxmodules/
|
||||
# Content for test loading modules from S3
|
||||
COPY auditd /opt/vxmodules/mon/auditd
|
||||
COPY syslog /opt/vxmodules/mon/syslog
|
||||
COPY sysmon /opt/vxmodules/mon/sysmon
|
||||
COPY file_remover /opt/vxmodules/mon/file_remover
|
||||
@@ -28,31 +29,22 @@ COPY correlator /opt/vxmodules/mon/correlator
|
||||
COPY correlator_linux /opt/vxmodules/mon/correlator_linux
|
||||
COPY yara_scanner /opt/vxmodules/mon/yara_scanner
|
||||
COPY lua_interpreter /opt/vxmodules/mon/lua_interpreter
|
||||
COPY osquery /opt/vxmodules/mon/osquery
|
||||
COPY osquery_linux /opt/vxmodules/mon/osquery_linux
|
||||
COPY shell /opt/vxmodules/mon/shell
|
||||
COPY utils /opt/vxmodules/mon/utils
|
||||
COPY config.json /opt/vxmodules/mon/
|
||||
|
||||
RUN chmod +x /opt/vxmodules/startup.sh
|
||||
RUN chmod +x /opt/vxmodules/gen_sql.py
|
||||
|
||||
RUN \
|
||||
apt update && \
|
||||
apt install -y ca-certificates && \
|
||||
apt install -y jq && \
|
||||
apt install -y --no-install-recommends python3 python3-pip && \
|
||||
apt clean -y && \
|
||||
apt autoremove -y && \
|
||||
rm -rf /tmp/* /var/tmp/* && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf
|
||||
|
||||
RUN pip3 install pypika
|
||||
RUN chmod +x /opt/vxmodules/startup.sh && \
|
||||
chmod +x /opt/vxmodules/gen_sql.py && \
|
||||
apk add --no-cache mysql-client bash jq && \
|
||||
echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf && \
|
||||
pip3 install pypika && \
|
||||
echo ${VXVERSION} > /opt/vxmodules/version
|
||||
|
||||
WORKDIR /opt/vxmodules/mon/
|
||||
|
||||
# Generate new dump sql files
|
||||
RUN python3 /opt/vxmodules/gen_sql.py /opt/vxmodules/
|
||||
|
||||
# Write version file
|
||||
RUN echo ${VXVERSION} > /opt/vxmodules/version
|
||||
|
||||
ENTRYPOINT ["/opt/vxmodules/startup.sh"]
|
||||
|
||||
@@ -3,7 +3,7 @@ END USER LICENSE AGREEMENT FOR SOLDR MODULES
|
||||
|
||||
1. General provisions
|
||||
|
||||
1.1. This License License (hereinafter the License) represents an agreement between A-Lab FZE (hereinafter the Rightholder) and the end user (hereinafter the User) with regard to SOLDR modules (hereinafter the Software) made publicly available by the Rightholder at the repository address https://github.com/vxcontrol/soldr-modules (hereinafter referred to as the Software) and/or the Software Modifications as defined herebelow made available as SOLDR modules forks at other github repositories.
|
||||
1.1. This License (hereinafter the License) represents an agreement between A-Lab FZE (hereinafter the Rightholder) and the end user (hereinafter the User) with regard to SOLDR modules (hereinafter the Software) made publicly available by the Rightholder at the repository address https://github.com/vxcontrol/soldr-modules (hereinafter referred to as the Software) and/or the Software Modifications as defined herebelow made available as SOLDR modules forks at other github repositories.
|
||||
|
||||
1.2. Whenever the Rigtholder provide any updates, fixes and/or patches to the Software (hereinafter Software update installation package) such Software update installation packages are considered a part of the Software and provided strictly under the License as well.
|
||||
|
||||
@@ -33,7 +33,7 @@ END USER LICENSE AGREEMENT FOR SOLDR MODULES
|
||||
|
||||
3. Copyright
|
||||
|
||||
3.1. The Rightholder of the Software is JSC Positive Technologies.
|
||||
3.1. The Rightholder of the Software is A-Lab FZE.
|
||||
|
||||
3.2. All rights (including the right for the content that can become available as a result of the Software use) are the property of the Rightholder.
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
return {
|
||||
_all = { lpath = "cmodule/?.lua" }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
test:
|
||||
$(SOLDR_MODULES)/bin/busted $(BUSTED_FLAGS) .
|
||||
|
||||
OS_LIST := $(subst docker/Dockerfile.,,$(wildcard docker/Dockerfile.*))
|
||||
test-inside-docker: $(OS_LIST:%=test-inside-%)
|
||||
|
||||
test-inside-%: docker/Dockerfile.%
|
||||
@echo === $* ===
|
||||
@docker build -t test/$* -f docker/Dockerfile.$* . >&-
|
||||
@docker run --rm \
|
||||
-e SOLDR_MODULES=/src \
|
||||
-v $(SOLDR_MODULES):/src:ro \
|
||||
-w /src/auditd/1.0.0 \
|
||||
test/$* /src/bin/busted --exclude-tags=systemd $(BUSTED_FLAGS) .
|
||||
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const name = "empty";
|
||||
|
||||
module.exports = {
|
||||
name,
|
||||
props: ["protoAPI", "hash", "module", "api", "components", "viewMode"],
|
||||
data: () => ({
|
||||
})
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1,80 @@
|
||||
local exec = require "exec"
|
||||
local managed = require "managed"
|
||||
local try = require "try"
|
||||
|
||||
-- Checks if systemd is available on current OS.
|
||||
--:: () -> ok?, err::string?
|
||||
local function check_systemd()
|
||||
return exec("type systemctl"),
|
||||
string.format("unsupported linux distro: systemd not found")
|
||||
end
|
||||
|
||||
-- Ensures that audit is installed and available to use.
|
||||
--:: pkg.Manager -> ok::boolean, err::string?
|
||||
local function ensure_audit(pm)
|
||||
if exec("type auditctl") then
|
||||
return true end
|
||||
local ok, err = try(function()
|
||||
-- TODO: sync packages?
|
||||
-- assert(pm:sync())
|
||||
assert(pm:install("audit", "auditd"))
|
||||
assert(exec("type auditctl"))
|
||||
return true
|
||||
end)
|
||||
return ok, string.format("audit not available: %s", err)
|
||||
end
|
||||
|
||||
-- Abstraction over a managed state of Linux Auditing System.
|
||||
local State = {}; State.__index = State
|
||||
|
||||
function State.new()
|
||||
return setmetatable({}, State)
|
||||
end
|
||||
|
||||
-- Performs installation and configuration of Linux Auditing System.
|
||||
-- It's idempotent and can be kept calling repeatedly, without any significant
|
||||
-- performance cost, to ensure the system meets the required configuration.
|
||||
--:: pkg.Manager, [managed.File] -> ok?, err::string?
|
||||
function State:setup(pm, files)
|
||||
return try(function()
|
||||
assert(ensure_audit(pm))
|
||||
|
||||
local rules = assert(exec("auditctl -l"))
|
||||
local status = assert(managed.ensure_all(files))
|
||||
if self._rules ~= rules or status == managed.MODIFIED then
|
||||
assert(exec("systemctl daemon-reload"))
|
||||
assert(exec("systemctl try-reload-or-restart auditd.service"))
|
||||
end
|
||||
|
||||
assert(exec("systemctl start auditd.service"))
|
||||
self._rules = assert(exec("auditctl -l"))
|
||||
return status
|
||||
end)
|
||||
end
|
||||
|
||||
local file_auditd_conf = managed.file("/etc/audit/auditd.conf", "644")
|
||||
local file_audit_rules = managed.file("/etc/audit/audit.rules", "400")
|
||||
|
||||
-- Overrides configuration of auditd service to always read audit rules
|
||||
-- from `/etc/audit/audit.rules` with `auditctl`.
|
||||
-- (By default most linux distros are configured to use `augenrules` and
|
||||
-- read audit rules from `/etc/audit/rules.d`)
|
||||
local file_auditd_service_override =
|
||||
managed.file("/etc/systemd/system/auditd.service.d/override.conf", "644")
|
||||
file_auditd_service_override:set[[
|
||||
# Managed by SOLDR(auditd)
|
||||
[Service]
|
||||
ExecStartPost=
|
||||
ExecStartPost=-/sbin/auditctl -R /etc/audit/audit.rules
|
||||
ExecReload=
|
||||
ExecReload=kill -HUP $MAINPID
|
||||
ExecReload=-/sbin/auditctl -R /etc/audit/audit.rules
|
||||
]]
|
||||
|
||||
return {
|
||||
State = State,
|
||||
check_systemd = check_systemd,
|
||||
file_auditd_conf = file_auditd_conf,
|
||||
file_audit_rules = file_audit_rules,
|
||||
file_auditd_service_override = file_auditd_service_override,
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
local audit = require "audit"
|
||||
local exec = require "exec"
|
||||
local pkg = require "pkg"
|
||||
local glue = require "glue"
|
||||
|
||||
local pm, state
|
||||
local os = glue.gsplit(tostring(glue.readfile("/etc/issue", "r")) or "unknown", "\n")()
|
||||
|
||||
local function has_prefix(str, prefix)
|
||||
return string.find(str, prefix, 1, true) == 1,
|
||||
string.format("expected %q has prefix %q", str, prefix)
|
||||
end
|
||||
|
||||
context(os .. " | audit", function()
|
||||
test("check_systemd() #systemd", function()
|
||||
assert(audit.check_systemd())
|
||||
end)
|
||||
end)
|
||||
|
||||
context(os .. " | audit setup() #root #systemd #network #write", function()
|
||||
setup(function()
|
||||
pm = assert(pkg.find_manager())
|
||||
state = audit.State.new()
|
||||
end)
|
||||
|
||||
local function setup_and_assert()
|
||||
local files = {
|
||||
audit.file_auditd_service_override,
|
||||
audit.file_auditd_conf,
|
||||
audit.file_audit_rules,
|
||||
}
|
||||
audit.file_auditd_conf:set("#TEST\nspace_left = 1\n")
|
||||
audit.file_audit_rules:set("-D\n-w /TEST\n")
|
||||
|
||||
assert(state:setup(pm, files))
|
||||
|
||||
assert.equals("active", assert(exec("systemctl is-active auditd.service")))
|
||||
local conf = assert(exec("cat /etc/audit/auditd.conf"))
|
||||
assert(has_prefix(conf, "#TEST\n"))
|
||||
assert.equals("-w /TEST -p rwxa", assert(exec("auditctl -l")))
|
||||
end
|
||||
|
||||
local function reset()
|
||||
assert(exec("systemctl disable --now auditd.service; true"))
|
||||
assert(exec("rm -rf /etc/systemd/system/auditd.service.d"))
|
||||
assert(exec("systemctl daemon-reload"))
|
||||
|
||||
assert(exec("auditctl --signal TERM; true"))
|
||||
assert(exec("auditctl -D; true"))
|
||||
assert(exec("rm -rf /etc/audit"))
|
||||
end
|
||||
teardown(reset)
|
||||
|
||||
test("case: audit is not installed", function()
|
||||
-- TODO: actually remove package audit
|
||||
reset()
|
||||
setup_and_assert()
|
||||
end)
|
||||
|
||||
test("case: auditd is running with some rules in rules.d", function()
|
||||
reset()
|
||||
assert(pm:install("audit", "auditd"))
|
||||
assert(exec("mkdir -p /etc/audit/rules.d"))
|
||||
assert(exec("echo -w /UNWANTED > /etc/audit/rules.d/unwanted.rules"))
|
||||
assert(exec("systemctl start auditd.service"))
|
||||
setup_and_assert()
|
||||
end)
|
||||
|
||||
test("case: someone's changed audit rules", function()
|
||||
setup_and_assert()
|
||||
assert(exec("auditctl -D"))
|
||||
setup_and_assert()
|
||||
end)
|
||||
end)
|
||||
@@ -0,0 +1,31 @@
|
||||
require("engine")
|
||||
local M = {}
|
||||
|
||||
local event_engine
|
||||
local action_engine
|
||||
|
||||
function M.update_config()
|
||||
local prefix_db = __gid .. "."
|
||||
local fields_schema = __config.get_fields_schema()
|
||||
local event_config = __config.get_current_event_config()
|
||||
local module_info = __config.get_module_info()
|
||||
|
||||
event_engine = CEventEngine(fields_schema, event_config, module_info, prefix_db, false)
|
||||
action_engine = CActionEngine({}, false)
|
||||
end
|
||||
M.update_config()
|
||||
|
||||
local function send_event(name, data)
|
||||
local result, list = event_engine:push_event{
|
||||
name = name,
|
||||
data = data or {},
|
||||
}
|
||||
if result then action_engine:exec(__aid, list) end
|
||||
end
|
||||
|
||||
function M.error(err)
|
||||
__log.error(err)
|
||||
send_event("auditd_error", {message=tostring(err)})
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -0,0 +1,30 @@
|
||||
local try = require "try"
|
||||
|
||||
local function show_output(s)
|
||||
local MAX_LENGTH = 1024
|
||||
s = string.gsub(s, "\n", "\\n")
|
||||
s = string.sub(s, 1, MAX_LENGTH)
|
||||
return s
|
||||
end
|
||||
|
||||
local function trim_end(s)
|
||||
return string.gsub(s, "%s+$", "")
|
||||
end
|
||||
|
||||
-- Executes the given command in a shell.
|
||||
-- NOTE: stderr is redirecting to stdout.
|
||||
--:: string -> output::string?, err::string?
|
||||
local function exec(cmd)
|
||||
local result, err = try(function()
|
||||
local stdout = assert(
|
||||
io.popen("exec <&- 2>&1;"..cmd), "io.popen failed")
|
||||
local output = stdout:read("a") or ""
|
||||
local ok, status, code = stdout:close()
|
||||
assert(ok,
|
||||
string.format("%s=%d: %s", status, code, show_output(output)))
|
||||
return trim_end(output)
|
||||
end)
|
||||
return result, string.format("exec(%s): %s", cmd, err)
|
||||
end
|
||||
|
||||
return exec
|
||||
@@ -0,0 +1,36 @@
|
||||
local exec = require "exec"
|
||||
|
||||
local function string_contains(str, sub)
|
||||
return string.find(str, sub, 1, true) ~= nil
|
||||
end
|
||||
|
||||
describe("exec", function()
|
||||
it("runs a given command", function()
|
||||
assert(exec("true"))
|
||||
end)
|
||||
|
||||
it("should return stdout+stderr", function()
|
||||
local output = assert(exec("echo OUTPUT"))
|
||||
assert.equals("OUTPUT", output)
|
||||
end)
|
||||
|
||||
it("must fail if exit code != 0", function()
|
||||
local ok, err = exec("echo ERROR; false")
|
||||
assert(not ok)
|
||||
assert(string_contains(err, 'exit=1: ERROR'),
|
||||
string.format("unexpected error message: %s", err))
|
||||
end)
|
||||
|
||||
it("stdin should be closed to avoid blocking", function()
|
||||
assert.has_error(function()
|
||||
assert(exec("cat"))
|
||||
end)
|
||||
end)
|
||||
|
||||
test("a bad command", function()
|
||||
local ok, err = exec("unknown-command")
|
||||
assert(not ok)
|
||||
assert(string_contains(err, "not found"),
|
||||
string.format("unexpected error message: %s", err))
|
||||
end)
|
||||
end)
|
||||
@@ -0,0 +1,45 @@
|
||||
local audit = require "audit"
|
||||
local pkg = require "pkg"
|
||||
local cjson = require "cjson"
|
||||
local event = require "event"
|
||||
|
||||
local ok, err = audit.check_systemd()
|
||||
if not ok then
|
||||
event.error(err)
|
||||
__api.await(-1); return "success"
|
||||
end
|
||||
|
||||
local pm, err = pkg.find_manager()
|
||||
if not pm then
|
||||
event.error(err)
|
||||
__api.await(-1); return "success"
|
||||
end
|
||||
|
||||
local austate = audit.State.new()
|
||||
local watcher = require("watcher").new()
|
||||
|
||||
local function update_config()
|
||||
event.update_config()
|
||||
local c = cjson.decode(__config.get_current_config())
|
||||
audit.file_auditd_conf:set(c.auditd_conf)
|
||||
audit.file_audit_rules:set(c.audit_rules)
|
||||
watcher:reset(c.check_interval)
|
||||
end
|
||||
update_config()
|
||||
|
||||
__api.add_cbs{
|
||||
control = function(cmtype, data)
|
||||
if cmtype == "update_config" then update_config() end
|
||||
return true
|
||||
end,
|
||||
}
|
||||
|
||||
watcher:run(function()
|
||||
local ok, err = austate:setup(pm, {
|
||||
audit.file_auditd_service_override,
|
||||
audit.file_auditd_conf,
|
||||
audit.file_audit_rules,
|
||||
})
|
||||
if not ok then event.error(err) end
|
||||
end)
|
||||
return "success"
|
||||
@@ -0,0 +1,93 @@
|
||||
local exec = require "exec"
|
||||
local try = require "try"
|
||||
|
||||
local MODIFIED = {}
|
||||
|
||||
local File = {}; File.__index = File
|
||||
|
||||
-- Introduces a "managed" file.
|
||||
-- 1. Set the required access `mode` to the file.
|
||||
-- 2. Set the required content of the file with `set`.
|
||||
-- 3. Then use `ensure` to adjust the file on disk to required state.
|
||||
-- NOTE: `mode` is a string in `chmod` format, see: chmod(1).
|
||||
--:: string, string -> File
|
||||
local function file(path, mode)
|
||||
return setmetatable({
|
||||
_path = path,
|
||||
_mode = mode,
|
||||
_data = "",
|
||||
}, File)
|
||||
end
|
||||
|
||||
function File:path()
|
||||
return self._path
|
||||
end
|
||||
|
||||
-- Sets target content of the file.
|
||||
--:: string -> ()
|
||||
function File:set(data)
|
||||
self._data = data
|
||||
end
|
||||
|
||||
-- Adjust the file on disk to required state.
|
||||
-- Does nothing if the file on disk matches the required state.
|
||||
--:: () -> boolean|MODIFIED, err::string?
|
||||
function File:ensure()
|
||||
if self:compare() == MODIFIED then
|
||||
local ok, err = self:write()
|
||||
return ok and MODIFIED,
|
||||
string.format("%s: %s", self._path, err)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Entirely overwrites the file on disk with the required content.
|
||||
--:: () -> ok::boolean, err::string?
|
||||
function File:write()
|
||||
return try(function()
|
||||
assert(exec(
|
||||
string.format("mkdir -p $(dirname %q)", self._path)))
|
||||
|
||||
local f = assert(io.open(self._path, "wb"), "failed to open")
|
||||
local w, err = f:write(self._data);
|
||||
f:close()
|
||||
assert(w, err)
|
||||
|
||||
assert(exec(
|
||||
string.format("chmod %q %q", self._mode, self._path)))
|
||||
return true
|
||||
end)
|
||||
end
|
||||
|
||||
-- Compares the required content with the file's content on disk.
|
||||
--:: () -> true|MODIFIED
|
||||
function File:compare()
|
||||
local data
|
||||
local f = io.open(self._path, "rb")
|
||||
if f then
|
||||
data = f:read("a")
|
||||
f:close()
|
||||
end
|
||||
return self._data == data or MODIFIED
|
||||
end
|
||||
|
||||
-- Calls `ensure` for every item of `list`.
|
||||
-- Returns MODIFIED if any of list returns MODIFIED.
|
||||
-- Immediately returns false if any of list failed.
|
||||
--:: [File] -> boolean|MODIFIED, err::string?
|
||||
local function ensure_all(list)
|
||||
return try(function()
|
||||
local status = true
|
||||
for _, item in ipairs(list) do
|
||||
if assert(item:ensure()) == MODIFIED then
|
||||
status = MODIFIED end
|
||||
end
|
||||
return status
|
||||
end)
|
||||
end
|
||||
|
||||
return {
|
||||
MODIFIED = MODIFIED,
|
||||
file = file,
|
||||
ensure_all = ensure_all,
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
local managed = require "managed"
|
||||
local exec = require "exec"
|
||||
|
||||
local function rm(path)
|
||||
local cmd = string.format("rm -rf %q", path)
|
||||
assert(exec(cmd))
|
||||
end
|
||||
|
||||
local function read_file(filename)
|
||||
local f = assert(io.open(filename, "rb"),
|
||||
string.format("failed to open: %s", filename))
|
||||
return assert(f:read("a")), f:close()
|
||||
end
|
||||
|
||||
local function read_mode(filename)
|
||||
local cmd = string.format("ls -l %q | cut -c-10", filename)
|
||||
return assert(exec(cmd))
|
||||
end
|
||||
|
||||
describe("managed File #write", function()
|
||||
setup(function()
|
||||
tmp = assert(exec("mktemp -d"))
|
||||
f_name = tmp .. "/sub/file"
|
||||
end)
|
||||
teardown(function() rm(tmp) end)
|
||||
|
||||
describe("ensure()", function()
|
||||
it("should create a file unless it exists", function()
|
||||
local f = managed.file(f_name, "ug=rw,o=r")
|
||||
f:set("CREATE")
|
||||
|
||||
local status = assert(f:ensure())
|
||||
assert.equals(managed.MODIFIED, status)
|
||||
assert.equals("CREATE", read_file(f_name))
|
||||
assert.equals("-rw-rw-r--", read_mode(f_name))
|
||||
end)
|
||||
|
||||
it("should return `true` while file's content == required content", function()
|
||||
local f = managed.file(f_name, "INVALID")
|
||||
f:set("CREATE")
|
||||
|
||||
local status = assert(f:ensure())
|
||||
assert.is_true(status)
|
||||
end)
|
||||
|
||||
it("should overwrite if file's content != required content", function()
|
||||
local f = managed.file(f_name, "0400")
|
||||
f:set("UPDATE")
|
||||
|
||||
local status = assert(f:ensure())
|
||||
assert.equals(managed.MODIFIED, status)
|
||||
assert.equals("UPDATE", read_file(f_name))
|
||||
assert.equals("-r--------", read_mode(f_name))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("ensure_all() #write", function()
|
||||
setup(function()
|
||||
tmp = assert(exec("mktemp -d"))
|
||||
file_a = managed.file(tmp.."/a", "a=rw")
|
||||
file_b = managed.file(tmp.."/b", "a=rw")
|
||||
end)
|
||||
teardown(function() rm(tmp) end)
|
||||
|
||||
it("should call ensure() for every item", function()
|
||||
file_a:set("CREATE")
|
||||
file_b:set("CREATE")
|
||||
|
||||
local status = managed.ensure_all{file_a, file_b}
|
||||
assert.equals(managed.MODIFIED, status)
|
||||
assert.equals("CREATE", read_file(file_a:path()))
|
||||
assert.equals("CREATE", read_file(file_b:path()))
|
||||
end)
|
||||
|
||||
it("should return MODIFIED if any of item is modified", function()
|
||||
file_a:set("UPDATE")
|
||||
assert.equals(managed.MODIFIED, managed.ensure_all{file_a, file_b})
|
||||
|
||||
file_b:set("UPDATE")
|
||||
assert.equals(managed.MODIFIED, managed.ensure_all{file_a, file_b})
|
||||
end)
|
||||
|
||||
it("otherwise returns `true`", function()
|
||||
assert.is_true(managed.ensure_all{file_a, file_b})
|
||||
end)
|
||||
end)
|
||||
@@ -0,0 +1,94 @@
|
||||
local exec = require "exec"
|
||||
|
||||
-- Replaces each occurrence of `{name}` in cmd with the corresponding
|
||||
-- value of key `name` from table vars.
|
||||
--:: string, {string => string} -> string
|
||||
local function format_cmd(cmd, vars)
|
||||
for name, var in pairs(vars) do
|
||||
cmd = string.gsub(cmd, "{"..name.."}", var)
|
||||
end
|
||||
return cmd
|
||||
end
|
||||
|
||||
-- Manager is an abstraction over system package managers.
|
||||
-- See the list of supported package managers below.
|
||||
local Manager = {}; Manager.__index = Manager
|
||||
|
||||
local backend_commands = {
|
||||
test = "type {bin}",
|
||||
sync = "true",
|
||||
install = "false",
|
||||
}
|
||||
|
||||
function Manager.new(name, bin, commands)
|
||||
commands = commands or {}
|
||||
for type, cmd in pairs(backend_commands) do
|
||||
commands[type] = commands[type] or cmd
|
||||
end
|
||||
return setmetatable({
|
||||
name = name,
|
||||
bin = bin,
|
||||
_cmd = commands,
|
||||
}, Manager)
|
||||
end
|
||||
|
||||
-- Tests if the manager is available on current OS.
|
||||
--:: () -> ok?, err::string?
|
||||
function Manager:test()
|
||||
local cmd = format_cmd(self._cmd.test, {name=self.name, bin=self.bin})
|
||||
return exec(cmd)
|
||||
end
|
||||
|
||||
-- Used to synchronize the package index files from their sources.
|
||||
--:: () -> ok?, err::string?
|
||||
function Manager:sync()
|
||||
local cmd = format_cmd(self._cmd.sync, {name=self.name, bin=self.bin})
|
||||
return exec(cmd)
|
||||
end
|
||||
|
||||
-- Performs installation procedure for the given package.
|
||||
-- Additional args are used as alternative names of the package.
|
||||
--:: string... -> ok::boolean, err::string?
|
||||
function Manager:install(package, ...)
|
||||
local ok, err
|
||||
for _, package in ipairs{package, ...} do
|
||||
local cmd = format_cmd(self._cmd.install,
|
||||
{name=self.name, bin=self.bin, package=package})
|
||||
ok, err = exec(cmd)
|
||||
if ok then return true end
|
||||
end
|
||||
return false, err
|
||||
end
|
||||
|
||||
-- List of supported package managers.
|
||||
local managers = {
|
||||
Manager.new("APT", "apt-get", {
|
||||
sync = "{bin} update --quiet",
|
||||
install = "{bin} install --quiet --yes {package}",
|
||||
}),
|
||||
Manager.new("DNF", "dnf", {
|
||||
install = "{bin} --quiet -y install {package}",
|
||||
}),
|
||||
Manager.new("YUM", "yum", {
|
||||
install = "{bin} --quiet -y install {package}",
|
||||
}),
|
||||
Manager.new("Pacman", "pacman", {
|
||||
sync = "{bin} -Sy --noconfirm",
|
||||
install = "{bin} -S --asdeps --noconfirm {package}",
|
||||
}),
|
||||
}
|
||||
|
||||
-- Tries to guess a package manager available on current OS.
|
||||
--:: () -> Manager?, err::string?
|
||||
local function find_manager()
|
||||
for _, manager in ipairs(managers) do
|
||||
if manager:test() then return manager end
|
||||
end
|
||||
return nil, "unsupported linux distro: package manager not found"
|
||||
end
|
||||
|
||||
return {
|
||||
find_manager = find_manager,
|
||||
testing = {
|
||||
format_cmd = format_cmd },
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
local pkg = require "pkg"
|
||||
local exec = require "exec"
|
||||
|
||||
local function is_installed(name)
|
||||
return exec("type "..name)
|
||||
end
|
||||
|
||||
describe("format_cmd()", function()
|
||||
local format_cmd = pkg.testing.format_cmd
|
||||
|
||||
it("replaces {name} placeholders", function()
|
||||
local cmd = format_cmd("one={one} two={two}", {
|
||||
one = "ONE",
|
||||
two = "TWO",
|
||||
})
|
||||
assert.equals("one=ONE two=TWO", cmd)
|
||||
end)
|
||||
|
||||
it("replaces ALL {name} occurrences", function()
|
||||
assert.equals("a=VAR b=VAR",
|
||||
format_cmd("a={var} b={var}", {var="VAR"}))
|
||||
end)
|
||||
|
||||
it("ignores {unknown} variables", function()
|
||||
assert.equals("{unknown}", format_cmd("{unknown}", {}))
|
||||
end)
|
||||
|
||||
it("skips unused variables", function()
|
||||
assert.equals("", format_cmd("", {unused="UNUSED"}))
|
||||
end)
|
||||
end)
|
||||
|
||||
context("package manager #root", function()
|
||||
setup(function()
|
||||
pm = assert(pkg.find_manager())
|
||||
end)
|
||||
|
||||
test("sync() #network", function()
|
||||
assert(pm:sync())
|
||||
end)
|
||||
|
||||
test("install() #network", function()
|
||||
local package = "lsof"
|
||||
-- Uncomment to assert clean installation:
|
||||
-- assert(not is_installed(package),
|
||||
-- string.format("expected %q to be not installed", package))
|
||||
assert(pm:install("alternative", package))
|
||||
assert(is_installed(package))
|
||||
end)
|
||||
end)
|
||||
@@ -0,0 +1,17 @@
|
||||
-- Strips "FILE:LINE:" prefix from an error message.
|
||||
--:: string -> string
|
||||
local function strip_place(err)
|
||||
return string.gsub(err, "^.-:.-: ", "")
|
||||
end
|
||||
|
||||
-- Customized protected call around assert/error.
|
||||
-- In contrast to pcall/xpcall returns unchanged list of the result arguments
|
||||
-- of `f` on success.
|
||||
local function try(f, ...)
|
||||
local args = table.pack(xpcall(f, strip_place, ...))
|
||||
if args[1] == true then
|
||||
return table.unpack(args, 2) end
|
||||
return table.unpack(args)
|
||||
end
|
||||
|
||||
return try
|
||||
@@ -0,0 +1,28 @@
|
||||
local Watcher = {}; Watcher.__index = Watcher
|
||||
|
||||
--:: seconds? -> Watcher
|
||||
function Watcher.new(interval)
|
||||
return setmetatable({
|
||||
_interval = interval or 0,
|
||||
}, Watcher)
|
||||
end
|
||||
|
||||
--:: seconds? -> ()
|
||||
function Watcher:reset(interval)
|
||||
self._last_run = 0
|
||||
self._interval = interval or self._interval
|
||||
end
|
||||
|
||||
function Watcher:run(f)
|
||||
self._last_run = 0
|
||||
while not __api.is_close() do
|
||||
local now = os.time()
|
||||
if now - self._last_run >= self._interval then
|
||||
self._last_run = now
|
||||
f()
|
||||
end
|
||||
__api.await(1000)
|
||||
end
|
||||
end
|
||||
|
||||
return Watcher
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {},
|
||||
"required": [],
|
||||
"type": "object"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"1.0.0": {
|
||||
"en": {
|
||||
"date": "05-25-2023",
|
||||
"title": "Base functionality",
|
||||
"description": "Added the possibility to install and configure the auditd component"
|
||||
},
|
||||
"ru": {
|
||||
"date": "25.05.2023",
|
||||
"title": "Базовая функциональность",
|
||||
"description": "Добавлена возможность устанавливать и конфигурировать компонент auditd"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"audit_rules": {
|
||||
"rules": {},
|
||||
"type": "string",
|
||||
"ui": {
|
||||
"columns": 6,
|
||||
"widget": "textarea",
|
||||
"widgetConfig": {
|
||||
"rows": 8
|
||||
}
|
||||
}
|
||||
},
|
||||
"auditd_conf": {
|
||||
"rules": {},
|
||||
"type": "string",
|
||||
"ui": {
|
||||
"columns": 6,
|
||||
"widget": "textarea",
|
||||
"widgetConfig": {
|
||||
"rows": 8
|
||||
}
|
||||
}
|
||||
},
|
||||
"check_interval": {
|
||||
"rules": {},
|
||||
"type": "integer",
|
||||
"ui": {
|
||||
"columns": 4,
|
||||
"widgetConfig": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"audit_rules",
|
||||
"auditd_conf",
|
||||
"check_interval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"audit_rules": "# Managed by SOLDR(auditd)\n-D\n",
|
||||
"auditd_conf": "# Managed by SOLDR(auditd)\nwrite_logs = yes\nlog_file = /var/log/audit/audit.log\nlog_format = ENRICHED\nmax_log_file = 50\nmax_log_file_action = ROTATE\nnum_logs = 2\nspace_left = 100\nspace_left_action = SUSPEND\n",
|
||||
"check_interval": 600
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"auditd_error": {
|
||||
"actions": [
|
||||
{
|
||||
"fields": [],
|
||||
"module_name": "this",
|
||||
"name": "log_to_db",
|
||||
"priority": 10
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
"message"
|
||||
],
|
||||
"type": "atomic"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"audit_rules": "# Managed by SOLDR(auditd)\n-D\n",
|
||||
"auditd_conf": "# Managed by SOLDR(auditd)\nwrite_logs = yes\nlog_file = /var/log/audit/audit.log\nlog_format = ENRICHED\nmax_log_file = 50\nmax_log_file_action = ROTATE\nnum_logs = 2\nspace_left = 100\nspace_left_action = SUSPEND\n",
|
||||
"check_interval": 600
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"auditd_error": {
|
||||
"actions": [
|
||||
{
|
||||
"fields": [],
|
||||
"module_name": "this",
|
||||
"name": "log_to_db",
|
||||
"priority": 10
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
"message"
|
||||
],
|
||||
"type": "atomic"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
[]
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"auditd_error": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/events.atomic"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"fields": {
|
||||
"default": [
|
||||
"message"
|
||||
],
|
||||
"items": {
|
||||
"enum": [
|
||||
"message"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"maxItems": 1,
|
||||
"minItems": 1,
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"fields"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"auditd_error"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"message": {
|
||||
"rules": {},
|
||||
"type": "string",
|
||||
"ui": {
|
||||
"widgetConfig": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [],
|
||||
"type": "object"
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "auditd",
|
||||
"template": "empty",
|
||||
"version": {
|
||||
"major": 1,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"os": {
|
||||
"linux": [
|
||||
"386",
|
||||
"amd64"
|
||||
]
|
||||
},
|
||||
"system": false,
|
||||
"actions": [],
|
||||
"events": [
|
||||
"auditd_error"
|
||||
],
|
||||
"fields": [
|
||||
"message"
|
||||
],
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"module": {
|
||||
"en": {
|
||||
"title": "Auditd installer (cyberok)",
|
||||
"description": "Installs and configures the auditd component"
|
||||
},
|
||||
"ru": {
|
||||
"title": "Установщик auditd (cyberok)",
|
||||
"description": "Устанавливает и конфигурирует компонент auditd"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"audit_rules": {
|
||||
"en": {
|
||||
"title": "Rules",
|
||||
"description": "The /etc/audit/audit.rules file contents"
|
||||
},
|
||||
"ru": {
|
||||
"title": "Правила",
|
||||
"description": "Содержимое файла /etc/audit/audit.rules"
|
||||
}
|
||||
},
|
||||
"auditd_conf": {
|
||||
"en": {
|
||||
"title": "Auditd configuration",
|
||||
"description": "The /etc/audit/auditd.conf file contents"
|
||||
},
|
||||
"ru": {
|
||||
"title": "Конфигурация auditd",
|
||||
"description": "Содержимое файла /etc/audit/auditd.conf"
|
||||
}
|
||||
},
|
||||
"check_interval": {
|
||||
"en": {
|
||||
"title": "Configuration check interval on an agent (in seconds)",
|
||||
"description": ""
|
||||
},
|
||||
"ru": {
|
||||
"title": "Интервал проверки конфигурации на агенте, сек",
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"secure_config": {},
|
||||
"fields": {
|
||||
"message": {
|
||||
"en": {
|
||||
"title": "message",
|
||||
"description": "message"
|
||||
},
|
||||
"ru": {
|
||||
"title": "message",
|
||||
"description": "message"
|
||||
}
|
||||
}
|
||||
},
|
||||
"actions": {},
|
||||
"events": {
|
||||
"auditd_error": {
|
||||
"en": {
|
||||
"title": "The module failed to install auditd on the agent",
|
||||
"description": "An error occurred during auditd installation"
|
||||
},
|
||||
"ru": {
|
||||
"title": "Модуль не смог установить auditd на агенте",
|
||||
"description": "Ошибка при установке auditd"
|
||||
}
|
||||
}
|
||||
},
|
||||
"action_config": {},
|
||||
"event_config": {
|
||||
"auditd_error": {}
|
||||
},
|
||||
"tags": {}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {},
|
||||
"required": [],
|
||||
"type": "object"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
[]
|
||||
@@ -0,0 +1,3 @@
|
||||
FROM debian:10
|
||||
RUN apt-get update;
|
||||
RUN apt-get install --yes --download-only auditd;
|
||||
@@ -0,0 +1,3 @@
|
||||
FROM debian:11
|
||||
RUN apt-get update;
|
||||
RUN apt-get install --yes --download-only auditd;
|
||||
@@ -0,0 +1,2 @@
|
||||
FROM oraclelinux:8
|
||||
RUN dnf install -y --downloadonly audit;
|
||||
@@ -0,0 +1,3 @@
|
||||
FROM ubuntu:20.04
|
||||
RUN apt-get update;
|
||||
RUN apt-get install --yes --download-only auditd;
|
||||
@@ -0,0 +1,3 @@
|
||||
FROM ubuntu:22.04
|
||||
RUN apt-get update;
|
||||
RUN apt-get install --yes --download-only auditd;
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1,5 @@
|
||||
__api.add_cbs{
|
||||
control = function() return true end
|
||||
}
|
||||
__api.await(-1)
|
||||
return "success"
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Configurable by user:
|
||||
SOLDR_MODULES="${SOLDR_MODULES:-$PWD}"
|
||||
|
||||
exec "$SOLDR_MODULES/bin/luajit" "$SOLDR_MODULES/tests_framework/lua/bin/busted" "$@"
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Configurable by user:
|
||||
SOLDR_MODULES="${SOLDR_MODULES:-$PWD}"
|
||||
LUAPOWER_PLATFORM="${LUAPOWER_PLATFORM:-linux64}"
|
||||
|
||||
LUA_BIN="$SOLDR_MODULES/luapower/bin/$LUAPOWER_PLATFORM/luajit-bin"
|
||||
|
||||
export LUA_PATH="\
|
||||
$SOLDR_MODULES/tests_framework/lua/?.lua;\
|
||||
$SOLDR_MODULES/tests_framework/lua/?/init.lua;\
|
||||
$SOLDR_MODULES/luapower/?.lua;\
|
||||
$SOLDR_MODULES/luapower/?/init.lua;\
|
||||
$SOLDR_MODULES/utils/?.lua;\
|
||||
$SOLDR_MODULES/utils/?/init.lua;\
|
||||
$LUA_PATH"
|
||||
|
||||
export LUA_CPATH="\
|
||||
$SOLDR_MODULES/luapower/bin/$LUAPOWER_PLATFORM/lib?.dylib;\
|
||||
$SOLDR_MODULES/luapower/bin/$LUAPOWER_PLATFORM/clib/?.so;\
|
||||
$LUA_CPATH"
|
||||
|
||||
exec "$LUA_BIN" "$@"
|
||||
+181
-430
@@ -37,8 +37,8 @@
|
||||
"reason",
|
||||
"version"
|
||||
],
|
||||
"last_module_update": "2022-10-26 00:00:00",
|
||||
"last_update": "2022-10-26 00:00:00"
|
||||
"last_module_update": "2023-05-25 00:00:00",
|
||||
"last_update": "2023-05-25 00:00:00"
|
||||
},
|
||||
{
|
||||
"group_id": "",
|
||||
@@ -66,8 +66,8 @@
|
||||
"fields": [
|
||||
"reason"
|
||||
],
|
||||
"last_module_update": "2022-10-26 00:00:00",
|
||||
"last_update": "2022-10-26 00:00:00"
|
||||
"last_module_update": "2023-05-25 00:00:00",
|
||||
"last_update": "2023-05-25 00:00:00"
|
||||
},
|
||||
{
|
||||
"group_id": "",
|
||||
@@ -96,8 +96,8 @@
|
||||
"actions": [],
|
||||
"events": [],
|
||||
"fields": [],
|
||||
"last_module_update": "2022-04-29 00:00:00",
|
||||
"last_update": "2022-04-29 00:00:00"
|
||||
"last_module_update": "2022-12-08 00:00:00",
|
||||
"last_update": "2022-12-08 00:00:00"
|
||||
},
|
||||
{
|
||||
"group_id": "",
|
||||
@@ -131,8 +131,8 @@
|
||||
"syslog_module_stopped"
|
||||
],
|
||||
"fields": [],
|
||||
"last_module_update": "2022-04-29 00:00:00",
|
||||
"last_update": "2022-04-29 00:00:00"
|
||||
"last_module_update": "2022-12-08 00:00:00",
|
||||
"last_update": "2022-12-08 00:00:00"
|
||||
},
|
||||
{
|
||||
"group_id": "",
|
||||
@@ -181,8 +181,8 @@
|
||||
"subject.fullpath",
|
||||
"subject.process.fullpath"
|
||||
],
|
||||
"last_module_update": "2022-04-29 00:00:00",
|
||||
"last_update": "2022-04-29 00:00:00"
|
||||
"last_module_update": "2022-12-23 00:00:00",
|
||||
"last_update": "2022-12-23 00:00:00"
|
||||
},
|
||||
{
|
||||
"group_id": "",
|
||||
@@ -249,8 +249,8 @@
|
||||
"subject.process.id",
|
||||
"subject.process.name"
|
||||
],
|
||||
"last_module_update": "2022-08-26 00:00:00",
|
||||
"last_update": "2022-06-26 00:00:00"
|
||||
"last_module_update": "2022-12-20 00:00:00",
|
||||
"last_update": "2022-12-20 00:00:00"
|
||||
},
|
||||
{
|
||||
"group_id": "",
|
||||
@@ -275,9 +275,11 @@
|
||||
},
|
||||
"actions": [
|
||||
"yr_object_scan_proc",
|
||||
"yr_object_scan_proc_non_cached",
|
||||
"yr_object_task_scan_proc",
|
||||
"yr_scan_fs",
|
||||
"yr_subject_scan_proc",
|
||||
"yr_subject_scan_proc_non_cached",
|
||||
"yr_subject_task_scan_proc",
|
||||
"yr_task_fastscan_fs",
|
||||
"yr_task_fastscan_proc",
|
||||
@@ -293,12 +295,18 @@
|
||||
"yr_module_started",
|
||||
"yr_module_stopped",
|
||||
"yr_object_process_matched_high",
|
||||
"yr_object_process_matched_high_cached",
|
||||
"yr_object_process_matched_low",
|
||||
"yr_object_process_matched_low_cached",
|
||||
"yr_object_process_matched_medium",
|
||||
"yr_object_process_matched_medium_cached",
|
||||
"yr_process_matched_custom",
|
||||
"yr_subject_process_matched_high",
|
||||
"yr_subject_process_matched_high_cached",
|
||||
"yr_subject_process_matched_low",
|
||||
"yr_subject_process_matched_medium"
|
||||
"yr_subject_process_matched_low_cached",
|
||||
"yr_subject_process_matched_medium",
|
||||
"yr_subject_process_matched_medium_cached"
|
||||
],
|
||||
"fields": [
|
||||
"malware_class",
|
||||
@@ -314,8 +322,8 @@
|
||||
"subject.process.fullpath",
|
||||
"subject.process.id"
|
||||
],
|
||||
"last_module_update": "2022-11-07 09:11:39",
|
||||
"last_update": "2022-11-07 09:11:39"
|
||||
"last_module_update": "2023-01-26 00:00:00",
|
||||
"last_update": "2023-01-26 00:00:00"
|
||||
},
|
||||
{
|
||||
"group_id": "",
|
||||
@@ -364,8 +372,8 @@
|
||||
"subject.fullpath",
|
||||
"subject.process.fullpath"
|
||||
],
|
||||
"last_module_update": "2022-09-30 00:00:00",
|
||||
"last_update": "2022-09-30 00:00:00"
|
||||
"last_module_update": "2022-12-20 00:00:00",
|
||||
"last_update": "2022-12-20 00:00:00"
|
||||
},
|
||||
{
|
||||
"group_id": "",
|
||||
@@ -385,113 +393,42 @@
|
||||
},
|
||||
"actions": [],
|
||||
"events": [
|
||||
"Auxiliary_SuspiciousWeightsTrojan_Linux_subject_a",
|
||||
"Local_Recon_by_Web_User",
|
||||
"Malware_Exploit_Elf_CVE_2019_14287_a",
|
||||
"Malware_Exploit_Elf_CVE_2021_4034_a",
|
||||
"Malware_Trojan_Linux_Generic_a",
|
||||
"Malware_Trojan_Spy_Linux_Generic_a",
|
||||
"Raw_Socket",
|
||||
"Reverse_Tunneling_via_SSH",
|
||||
"Suspicious_Create_File_Attribute_Hidden",
|
||||
"Suspicious_Create_File_Boot_Modification",
|
||||
"Suspicious_Create_File_Boot_RCScripts",
|
||||
"Suspicious_Create_File_Ldd_PreloadDynamicLibrary",
|
||||
"Suspicious_Create_File_Scheduler_At",
|
||||
"Suspicious_Create_File_Scheduler_Cron",
|
||||
"Suspicious_Create_File_Scheduler_SystemdTimer",
|
||||
"Suspicious_Create_File_Shell_Config",
|
||||
"Suspicious_Create_File_Ssh_AuthorizedKeys",
|
||||
"Suspicious_Create_File_Systemd_Service",
|
||||
"Suspicious_Create_File_Xdg_Autostart",
|
||||
"Suspicious_Create_Process_Chkconfig_DisableRCScripts",
|
||||
"Suspicious_Create_Process_Iptables_ModifyFirewall",
|
||||
"Suspicious_Create_Process_Service_Disable",
|
||||
"Suspicious_Create_Process_Setenforce_ModifySELinux",
|
||||
"Suspicious_Create_Process_Sudo_Bruteforce",
|
||||
"Suspicious_Create_Process_WipeData_Destruction",
|
||||
"Suspicious_Read_File_Email_Local",
|
||||
"Suspicious_Read_File_Fstab_Configuration",
|
||||
"Suspicious_Read_File_Passwd_CredentialsEnumeration",
|
||||
"Suspicious_Read_File_Polkit_Policy",
|
||||
"Suspicious_Read_File_Shadow_CredentialsDumping",
|
||||
"Suspicious_Read_System_BIOS_Reconnaissance",
|
||||
"Suspicious_Read_System_DMI_CheckVM",
|
||||
"Suspicious_Read_System_Kernel_ASLR",
|
||||
"Suspicious_Read_System_Kernel_PtraceScope",
|
||||
"Suspicious_Read_System_KeyState_Keylogger",
|
||||
"Suspicious_Read_System_PCI_GPU",
|
||||
"Suspicious_Read_System_PCI_USB",
|
||||
"Suspicious_Read_System_Proc_ARPSessions",
|
||||
"Suspicious_Read_System_Proc_BootCmdline",
|
||||
"Suspicious_Read_System_Proc_Modules",
|
||||
"Suspicious_Read_System_Proc_Route",
|
||||
"Suspicious_Read_System_Proc_SCSI",
|
||||
"Suspicious_Read_System_Proc_TCPSessions",
|
||||
"Suspicious_Write_Disk_Data_DirectAccess",
|
||||
"Suspicious_Write_File_PAM_Persistence",
|
||||
"Suspicious_Write_Process_Inject_Ptrace",
|
||||
"Tunneling_via_SSH",
|
||||
"Tunneling_via_SSHuttle_Client",
|
||||
"Tunneling_via_SSHuttle_Server"
|
||||
"Suspicious_Write_Process_Inject_Ptrace"
|
||||
],
|
||||
"fields": [
|
||||
"action",
|
||||
"alert.key",
|
||||
"category.generic",
|
||||
"category.high",
|
||||
"category.low",
|
||||
"correlation_name",
|
||||
"correlation_type",
|
||||
"event_src.asset",
|
||||
"event_src.host",
|
||||
"event_src.hostname",
|
||||
"event_src.id",
|
||||
"event_src.ip",
|
||||
"event_src.subsys",
|
||||
"event_src.title",
|
||||
"event_src.vendor",
|
||||
"importance",
|
||||
"incident.aggregation.key",
|
||||
"incident.aggregation.timeout",
|
||||
"incident.category",
|
||||
"incident.severity",
|
||||
"labels",
|
||||
"numfield1",
|
||||
"numfield2",
|
||||
"object",
|
||||
"object.account.group",
|
||||
"object.account.id",
|
||||
"object.account.name",
|
||||
"object.fullpath",
|
||||
"object.name",
|
||||
"object.path",
|
||||
"object.process.cmdline",
|
||||
"object.process.cwd",
|
||||
"object.process.fullpath",
|
||||
"object.process.id",
|
||||
"object.process.meta",
|
||||
"object.process.name",
|
||||
"object.process.parent.id",
|
||||
"object.process.path",
|
||||
"object.state",
|
||||
"object.value",
|
||||
"status",
|
||||
"subject",
|
||||
"subject.account.id",
|
||||
"subject.account.name",
|
||||
"subject.account.privileges",
|
||||
"subject.account.session_id",
|
||||
"subject.process.fullpath",
|
||||
"subject.process.id",
|
||||
"subject.process.meta",
|
||||
"subject.process.name",
|
||||
"subject.process.parent.id",
|
||||
"subject.process.path",
|
||||
"subject.type"
|
||||
"subject.process.path"
|
||||
],
|
||||
"last_module_update": "2022-11-07 12:52:12",
|
||||
"last_update": "2022-11-07 12:52:12"
|
||||
"last_module_update": "2023-05-25 12:00:00",
|
||||
"last_update": "2023-05-25 12:00:00"
|
||||
},
|
||||
{
|
||||
"group_id": "",
|
||||
@@ -511,379 +448,48 @@
|
||||
},
|
||||
"actions": [],
|
||||
"events": [
|
||||
"Abnormal_Directory_for_Process",
|
||||
"Abusing_CredSSP",
|
||||
"Access_System_Credential_files_via_cmdline",
|
||||
"Access_into_Sensitive_Files_via_Network_Share",
|
||||
"Accessibility_Feature_Tool_Abuse",
|
||||
"Account_Created_on_Local_System",
|
||||
"Account_Discovery",
|
||||
"Account_or_Group_discovery_via_SAM_R",
|
||||
"Add_new_user_in_commandline",
|
||||
"Alternate_Data_Stream",
|
||||
"Audit_XP_params_change",
|
||||
"Auxiliary_SuspiciousWeightsTrojan_Windows_subject_a",
|
||||
"Auxiliary_SuspiciousWeightsTrojan_Windows_subject_b",
|
||||
"BitsJob_Download_and_Run",
|
||||
"COM_object_persistence",
|
||||
"CVE_2021_41379_Subrule_Elevation_service_chain",
|
||||
"CVE_2021_41379_Subrule_Start_elevation",
|
||||
"CVE_2021_41379_exploitation",
|
||||
"CVE_2022_26500_26501_exploitation",
|
||||
"CVE_2022_26503_Subrule_1",
|
||||
"CVE_2022_26503_Subrule_2",
|
||||
"CVE_2022_26503_exploitation",
|
||||
"Client_Side_Execution_via_DCOM",
|
||||
"Clipboard_Access",
|
||||
"Clipboard_Access_Powershell",
|
||||
"Cmstp_AWL_Bypass",
|
||||
"Cobalt_Strike_Assembly",
|
||||
"Cobalt_Strike_Payload_Delivery_Check",
|
||||
"Cobalt_Strike_Pipe_from_AdminShare",
|
||||
"Cobalt_Strike_Process_Injection",
|
||||
"Cobalt_Strike_Psexec_Jump",
|
||||
"Cobalt_Strike_SMB_Beacon",
|
||||
"Cobalt_Strike_Service_Move",
|
||||
"Code_Execution_Via_JDK_Tools",
|
||||
"Command_Processor_Autorun_Modify",
|
||||
"Computer_object_ldap_request",
|
||||
"ControlPanel_AWL_Bypass",
|
||||
"Copy_Mimikatz_To_Share",
|
||||
"Credential_Access_to_Passwords_Storage",
|
||||
"Credential_Dump_in_Local_Registry",
|
||||
"Csc_AWL_Bypass",
|
||||
"DRSUAPI_User_Enumeration",
|
||||
"DSInternals_Usage",
|
||||
"Disable_Credential_Guard",
|
||||
"Disable_LSA_Protection",
|
||||
"Disable_Restricted_Admin_Mode",
|
||||
"Dnscmd_AWL_Bypass",
|
||||
"Domain_Controllers_Discovery",
|
||||
"Domain_Trust_Discovery",
|
||||
"Download_File_Through_Curl",
|
||||
"Download_File_Through_Windows_Defender",
|
||||
"Downloading_Remote_File_Via_Lolbas",
|
||||
"Empire_Stager",
|
||||
"Esentutil_Copy_File",
|
||||
"Execute_Encoded_Powershell",
|
||||
"Execute_Malicious_Command",
|
||||
"Execute_Malicious_Powershell_Cmdlet",
|
||||
"Execute_PSEXEC",
|
||||
"Execute_Suspicious_Command_via_cmd",
|
||||
"Failed_LSASS_Injection",
|
||||
"Fast_Create_and_Delete_Account",
|
||||
"Finger_AWL_Bypass",
|
||||
"Groups_And_Users_Enumeration",
|
||||
"Hidden_Scheduled_Task",
|
||||
"Hidden_Service_Create",
|
||||
"Hide_Account_from_Logon_Screen",
|
||||
"IEExec_AWL_Bypass",
|
||||
"Impacket_SMBEXEC",
|
||||
"Impacket_Secretsdump",
|
||||
"InstallUtil_AWL_Bypass",
|
||||
"Intercept_Creds_from_MSTSC",
|
||||
"Internal_Monologue_Attack",
|
||||
"KeePass_Keys_Extraction",
|
||||
"KeePass_Persistence",
|
||||
"Koadic_MSHTA_Stager",
|
||||
"Koadic_REGSVR32_Stager",
|
||||
"Koadic_Rundll32_Stager",
|
||||
"Koadic_WMIC_Stager",
|
||||
"LAPS_Enumeration",
|
||||
"LOLBin_Copying",
|
||||
"LSA_SSP_Change",
|
||||
"Lazagne_Usage",
|
||||
"Local_Pass_the_Hash",
|
||||
"Lsass_Dump_via_SilentProcessExit",
|
||||
"Lsass_SilentProcessExit_Keys",
|
||||
"MSBuild_AWL_Bypass",
|
||||
"MSHTA_AWL_Bypass",
|
||||
"MSXSL_AWL_Bypass",
|
||||
"Malicious_CHM_File",
|
||||
"Malicious_Office_Document",
|
||||
"Malware_Backdoor_Win32_Evilnum_a",
|
||||
"Malware_Backdoor_Win32_Havex_a",
|
||||
"Malware_Backdoor_Win32_NetWire_b",
|
||||
"Malware_Backdoor_Win32_Pteredo_a",
|
||||
"Malware_Backdoor_Win64_Throwback_b",
|
||||
"Malware_Exploit_Win32_CVE_2022_30190_a",
|
||||
"Malware_Exploit_Win32_PrintSpooler_a",
|
||||
"Malware_Hacktool_Win32_CrackMapExec_a",
|
||||
"Malware_Trojan_Dropper_MSOffice_Launcher_a",
|
||||
"Malware_Trojan_Dropper_Script_Generic_a",
|
||||
"Malware_Trojan_Dropper_Win32_Generic_k",
|
||||
"Malware_Trojan_Ransom_Win32_Generic_a",
|
||||
"Malware_Trojan_Ransom_Win32_Generic_b",
|
||||
"Malware_Trojan_Win32_Generic_a",
|
||||
"Malware_Trojan_Win32_Generic_o",
|
||||
"Malware_Trojan_Win32_Generic_s",
|
||||
"Malware_Trojan_Win32_Generic_t",
|
||||
"Mavinject_AWL_Bypass",
|
||||
"Metasploit_Payload",
|
||||
"Microsoft_Teams_AWL_Bypass",
|
||||
"Mimikatz_Command",
|
||||
"Msiexec_AWL_Bypass",
|
||||
"NetCat_Usage",
|
||||
"Network_Share_Discovery",
|
||||
"Odbcconf_AWL_Bypass",
|
||||
"Office_File_with_Macros",
|
||||
"Office_Normal_dotm_modification",
|
||||
"Office_XLL_modification",
|
||||
"Password_Policy_Discovery",
|
||||
"Pcalua_AWL_Bypass",
|
||||
"Permission_Groups_Discovery",
|
||||
"Persistence_Netsh_DLL",
|
||||
"Port_Forwarding_or_Tunneling",
|
||||
"Potential_Users_Or_Groups_Enumeration_Process",
|
||||
"Potential_domain_groups_and_users_enumeration_handle",
|
||||
"Potential_localgroups_and_administrators_enumeration_handle",
|
||||
"Powershell_Remoting",
|
||||
"Process_Discovery",
|
||||
"Proxy_Tools_Usage",
|
||||
"RDP_Session_Hijacking",
|
||||
"Reading_Registry_Objects",
|
||||
"RegAsm_or_RegSvcs_AWL_Bypass",
|
||||
"Registry_Winlogon_Helper",
|
||||
"Regsvr32_AWL_Bypass",
|
||||
"Remote_Admin_Share_Access",
|
||||
"Remote_Code_Execution_Via_AtSvc",
|
||||
"Remote_Connection_through_SMBEXEC_WinXP",
|
||||
"Remote_Copy_Credential_Dump_Artifact",
|
||||
"Remote_Copying_Malicious_File",
|
||||
"Remote_File_Download_Via_Certutil",
|
||||
"Remote_Password_Dump",
|
||||
"Remoting_Impacket_PsExec",
|
||||
"Remoting_SysInternals_PsExec",
|
||||
"Remoting_WMI",
|
||||
"Remoting_WinExec",
|
||||
"Remoting_Windows_Shell",
|
||||
"Remove_Access_To_Sensitive_Account",
|
||||
"Remove_Account_From_Sensitive_Group",
|
||||
"Rubeus_Usage",
|
||||
"RunAs_Subrule_Login",
|
||||
"RunAs_System_or_External_tools",
|
||||
"Run_Malicious_Msbuild_Project",
|
||||
"Run_whoami_as_System",
|
||||
"Rundll32_AWL_Bypass",
|
||||
"SPN_LDAP_requests",
|
||||
"Scheduled_Task_Was_Created_Or_Updated_Via_Schtasks",
|
||||
"Search_Stored_Credentials",
|
||||
"Service_Created_or_Modified",
|
||||
"Shadow_Copies_Deletion_with_Builtin_Tools",
|
||||
"Shadow_Key_Creation",
|
||||
"Shadow_Screen_save",
|
||||
"Shadow_Screen_saves_PowerShell",
|
||||
"SharpSploit_Usage",
|
||||
"SharpWMI_Usage",
|
||||
"Sharphound_Client_Side",
|
||||
"Sharphound_Server_Side",
|
||||
"SilentTrinity_Stager",
|
||||
"Sliver_Shell_Usage",
|
||||
"Software_Discovery",
|
||||
"Spoolsv_Priv_Escalation",
|
||||
"Stop_Important_Service",
|
||||
"Stop_Important_Service_registry",
|
||||
"Subrule_Sharphound_Client_Side",
|
||||
"Subrule_Sharphound_Server_Side",
|
||||
"Suspicious_Access_To_Users_Folder",
|
||||
"Suspicious_Child_from_Messenger_Process",
|
||||
"Suspicious_Create_File_FromBrowser_SuspiciousExtension",
|
||||
"Suspicious_Create_File_FromMessenger_SuspiciousExtension",
|
||||
"Suspicious_Create_File_PartitionMaster_DirectAccess",
|
||||
"Suspicious_Create_File_RawDisk_DirectAccess",
|
||||
"Suspicious_Create_Object_Account_Persistence",
|
||||
"Suspicious_Create_Process_At_Persistence",
|
||||
"Suspicious_Create_Process_BitsAdmin_RestrictionBypass",
|
||||
"Suspicious_Create_Process_Debugger_Inject",
|
||||
"Suspicious_Create_Process_DirectoryMock_UACBypass",
|
||||
"Suspicious_Create_Process_NetSh_NetShell",
|
||||
"Suspicious_Create_Process_Ping_SelfDelete",
|
||||
"Suspicious_Create_Process_RunScript_WScript",
|
||||
"Suspicious_Create_Process_Schtasks_Persistence",
|
||||
"Suspicious_Create_Process_TaskKill_TerminateProcess",
|
||||
"Suspicious_Create_Process_VSTOInstaller_OfficeAddIns",
|
||||
"Suspicious_Create_Process_VirtualInstance_Evasion",
|
||||
"Suspicious_Create_Process_WinDef_AddExclusion",
|
||||
"Suspicious_Create_Process_WinDef_ChangeSettings",
|
||||
"Suspicious_Create_Process_WithDebugger_Execution_Predetect_2_1",
|
||||
"Suspicious_Create_Process_WusaExtract_UACBypass",
|
||||
"Suspicious_Create_Registry_Key_SafeBoot",
|
||||
"Suspicious_Delete_Registry_Key_ETWProvider",
|
||||
"Suspicious_Delete_Registry_Key_RunAsPPL",
|
||||
"Suspicious_Delete_Registry_Key_SafeBoot",
|
||||
"Suspicious_Delete_Registry_Key_Service",
|
||||
"Suspicious_Delete_Registry_Key_TaskSD",
|
||||
"Suspicious_File_Created_by_Legal_Process",
|
||||
"Suspicious_Windows_Kernel_creating",
|
||||
"Suspicious_Wmic_Command",
|
||||
"Suspicious_Write_File_EfiSystemPartition_Persistence",
|
||||
"Suspicious_Write_File_USB_AirSpread",
|
||||
"Suspicious_Write_Process_Inject_CreateRemoteThread",
|
||||
"Suspicious_Write_Registry_Key_CPL",
|
||||
"Suspicious_Write_Registry_Key_ChangeDefaultFileAssociation",
|
||||
"Suspicious_Write_Registry_Key_ChangeFirewallPolicy",
|
||||
"Suspicious_Write_Registry_Key_ChangeRdpPort",
|
||||
"Suspicious_Write_Registry_Key_CredentialsDelegation",
|
||||
"Suspicious_Write_Registry_Key_DisableAppLaunch",
|
||||
"Suspicious_Write_Registry_Key_DisableTaskManager",
|
||||
"Suspicious_Write_Registry_Key_DisableUAC",
|
||||
"Suspicious_Write_Registry_Key_FlashConfigEnrollee",
|
||||
"Suspicious_Write_Registry_Key_ImagePath",
|
||||
"Suspicious_Write_Registry_Key_InjectAppCertDlls",
|
||||
"Suspicious_Write_Registry_Key_InjectAppInitDLLs",
|
||||
"Suspicious_Write_Registry_Key_InjectImageFileExecutionOptions",
|
||||
"Suspicious_Write_Registry_Key_InjectLoadAppInitDLLs",
|
||||
"Suspicious_Write_Registry_Key_InjectSilentProcessExit",
|
||||
"Suspicious_Write_Registry_Key_KillAntivirus",
|
||||
"Suspicious_Write_Process_Inject_ProcessTampering",
|
||||
"Suspicious_Write_Registry_Key_LsaComponents",
|
||||
"Suspicious_Write_Registry_Key_ModifyRdpSettings",
|
||||
"Suspicious_Write_Registry_Key_OfficeTemplate",
|
||||
"Suspicious_Write_Registry_Key_ProxyHijack",
|
||||
"Suspicious_Write_Registry_Key_SafeBoot",
|
||||
"Suspicious_Write_Registry_Key_ScreenSaver",
|
||||
"Suspicious_Write_Registry_Key_SvchostContextService",
|
||||
"Suspicious_Write_Registry_Key_TerminalContextService",
|
||||
"Suspicious_Write_Registry_Key_TimeProviders",
|
||||
"Suspicious_process_execution_sequence",
|
||||
"Sysmon_Driver_Unload",
|
||||
"System_Information_Discovery",
|
||||
"System_Network_Configuration_Discovery",
|
||||
"System_Network_Connections_Discovery",
|
||||
"System_Service_Discovery",
|
||||
"TikiTorch_Process_Injection",
|
||||
"Universal_Windows_Platform_Apps_Modify",
|
||||
"User_object_ldap_request",
|
||||
"Userinitmprlogonscript_Modify",
|
||||
"WDAC_Bypass_via_Dbgsrv",
|
||||
"WDigest_Enable",
|
||||
"WMI_Subscriptions",
|
||||
"WinAPI_Access_from_Powershell",
|
||||
"Windows_Accessibility_StickyKey_modification",
|
||||
"Windows_Autorun_Modification",
|
||||
"Windows_Defender_Disable",
|
||||
"Windows_Eventlog_cleaning",
|
||||
"Windows_Hacktool_Usage",
|
||||
"Windows_Malicious_service_registration",
|
||||
"Windows_Registry_sensitive_keys_modification",
|
||||
"Windows_Service_Installed",
|
||||
"Windows_Shadow_copy_removal",
|
||||
"Windows_WMI_event_consumer_registration",
|
||||
"Windows_WMI_event_subscription_removal",
|
||||
"Windows_firewall_enable_local_RDP",
|
||||
"XSL_Script_WMIC_Execution"
|
||||
"Suspicious_Write_Registry_Key_ScreenSaver"
|
||||
],
|
||||
"fields": [
|
||||
"action",
|
||||
"alert.context",
|
||||
"alert.key",
|
||||
"category.generic",
|
||||
"category.high",
|
||||
"category.low",
|
||||
"chain_id",
|
||||
"correlation_name",
|
||||
"correlation_type",
|
||||
"dst.asset",
|
||||
"dst.fqdn",
|
||||
"dst.host",
|
||||
"dst.hostname",
|
||||
"dst.ip",
|
||||
"dst.mac",
|
||||
"dst.port",
|
||||
"event_src.asset",
|
||||
"event_src.category",
|
||||
"event_src.fqdn",
|
||||
"event_src.host",
|
||||
"event_src.hostname",
|
||||
"event_src.ip",
|
||||
"event_src.rule",
|
||||
"event_src.subsys",
|
||||
"event_src.title",
|
||||
"event_src.vendor",
|
||||
"importance",
|
||||
"incident.aggregation.key",
|
||||
"incident.aggregation.time_window",
|
||||
"incident.aggregation.timeout",
|
||||
"incident.attacking_addresses",
|
||||
"incident.category",
|
||||
"incident.severity",
|
||||
"labels",
|
||||
"numfield1",
|
||||
"object",
|
||||
"object.account.domain",
|
||||
"object.account.fullname",
|
||||
"object.account.id",
|
||||
"object.account.name",
|
||||
"object.account.privileges",
|
||||
"object.account.session_id",
|
||||
"object.domain",
|
||||
"object.fullpath",
|
||||
"object.hash",
|
||||
"object.id",
|
||||
"object.name",
|
||||
"object.new_value",
|
||||
"object.path",
|
||||
"object.process.cmdline",
|
||||
"object.process.cwd",
|
||||
"object.process.fullpath",
|
||||
"object.process.guid",
|
||||
"object.process.hash",
|
||||
"object.process.id",
|
||||
"object.process.meta",
|
||||
"object.process.name",
|
||||
"object.process.original_name",
|
||||
"object.process.parent.cmdline",
|
||||
"object.process.parent.fullpath",
|
||||
"object.process.parent.guid",
|
||||
"object.process.parent.id",
|
||||
"object.process.parent.name",
|
||||
"object.process.parent.path",
|
||||
"object.process.path",
|
||||
"object.process.version",
|
||||
"object.property",
|
||||
"object.query",
|
||||
"object.state",
|
||||
"object.storage.fullpath",
|
||||
"object.storage.id",
|
||||
"object.storage.name",
|
||||
"object.storage.path",
|
||||
"object.type",
|
||||
"object.value",
|
||||
"object.vendor",
|
||||
"object.version",
|
||||
"reason",
|
||||
"src.asset",
|
||||
"src.fqdn",
|
||||
"src.host",
|
||||
"src.hostname",
|
||||
"src.ip",
|
||||
"src.mac",
|
||||
"src.port",
|
||||
"status",
|
||||
"subject",
|
||||
"subject.account.domain",
|
||||
"subject.account.fullname",
|
||||
"subject.account.id",
|
||||
"subject.account.name",
|
||||
"subject.account.privileges",
|
||||
"subject.account.session_id",
|
||||
"subject.name",
|
||||
"subject.process.cmdline",
|
||||
"subject.process.cwd",
|
||||
"subject.process.fullpath",
|
||||
"subject.process.guid",
|
||||
"subject.process.hash",
|
||||
"subject.process.id",
|
||||
"subject.process.meta",
|
||||
"subject.process.name",
|
||||
"subject.process.original_name",
|
||||
"subject.process.parent.id",
|
||||
"subject.process.path",
|
||||
"subject.process.version",
|
||||
"subject.type",
|
||||
"subject.version"
|
||||
"subject.process.path"
|
||||
],
|
||||
"last_module_update": "2022-10-26 00:00:00",
|
||||
"last_update": "2022-10-26 00:00:00"
|
||||
"last_module_update": "2023-05-25 00:00:00",
|
||||
"last_update": "2023-05-25 00:00:00"
|
||||
},
|
||||
{
|
||||
"group_id": "",
|
||||
@@ -913,7 +519,152 @@
|
||||
"fields": [
|
||||
"reason"
|
||||
],
|
||||
"last_module_update": "2022-11-02 00:00:00",
|
||||
"last_update": "2022-11-02 00:00:00"
|
||||
"last_module_update": "2023-05-25 12:00:00",
|
||||
"last_update": "2023-05-25 12:00:00"
|
||||
},
|
||||
{
|
||||
"group_id": "",
|
||||
"policy_id": "",
|
||||
"state": "release",
|
||||
"template": "generic",
|
||||
"os": {
|
||||
"darwin": [
|
||||
"amd64"
|
||||
],
|
||||
"linux": [
|
||||
"386",
|
||||
"amd64"
|
||||
],
|
||||
"windows": [
|
||||
"386",
|
||||
"amd64"
|
||||
]
|
||||
},
|
||||
"name": "shell",
|
||||
"version": {
|
||||
"major": 1,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"actions": [
|
||||
"shell_start",
|
||||
"shell_stop"
|
||||
],
|
||||
"events": [
|
||||
"shell_action_exec_failed",
|
||||
"shell_action_exec_success"
|
||||
],
|
||||
"fields": [
|
||||
],
|
||||
"last_module_update": "2023-06-06 00:00:00",
|
||||
"last_update": "2023-06-06 00:00:00"
|
||||
},
|
||||
{
|
||||
"group_id": "",
|
||||
"policy_id": "",
|
||||
"state": "release",
|
||||
"template": "empty",
|
||||
"os": {
|
||||
"linux": [
|
||||
"386",
|
||||
"amd64"
|
||||
]
|
||||
},
|
||||
"name": "auditd",
|
||||
"version": {
|
||||
"major": 1,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"actions": [],
|
||||
"events": [
|
||||
"auditd_error"
|
||||
],
|
||||
"fields": [
|
||||
"message"
|
||||
],
|
||||
"tags": [],
|
||||
"last_module_update": "2023-06-06 00:00:00",
|
||||
"last_update": "2023-06-06 00:00:00"
|
||||
},
|
||||
{
|
||||
"group_id": "",
|
||||
"policy_id": "",
|
||||
"state": "release",
|
||||
"template": "empty",
|
||||
"os": {
|
||||
"windows": [
|
||||
"386",
|
||||
"amd64"
|
||||
]
|
||||
},
|
||||
"name": "osquery",
|
||||
"version": {
|
||||
"major": 1,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"actions": [],
|
||||
"events": [
|
||||
"osquery_already_installed",
|
||||
"osquery_already_started",
|
||||
"osquery_config_updated_error",
|
||||
"osquery_config_updated_success",
|
||||
"osquery_flagfile_updated_error",
|
||||
"osquery_flagfile_updated_success",
|
||||
"osquery_installed_error",
|
||||
"osquery_installed_success",
|
||||
"osquery_started_error",
|
||||
"osquery_started_success",
|
||||
"osquery_unexpected_stopped",
|
||||
"osquery_unexpected_uninstalled",
|
||||
"osquery_uninstalled_error",
|
||||
"osquery_uninstalled_success"
|
||||
],
|
||||
"fields": [
|
||||
"reason",
|
||||
"version"
|
||||
],
|
||||
"last_module_update": "2023-06-06 00:00:00",
|
||||
"last_update": "2023-06-06 00:00:00"
|
||||
},
|
||||
{
|
||||
"group_id": "",
|
||||
"policy_id": "",
|
||||
"state": "release",
|
||||
"template": "empty",
|
||||
"os": {
|
||||
"linux": [
|
||||
"386",
|
||||
"amd64"
|
||||
]
|
||||
},
|
||||
"name": "osquery_linux",
|
||||
"version": {
|
||||
"major": 1,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"actions": [],
|
||||
"events": [
|
||||
"osquery_linux_already_installed",
|
||||
"osquery_linux_already_started",
|
||||
"osquery_linux_config_updated_error",
|
||||
"osquery_linux_config_updated_success",
|
||||
"osquery_linux_installed_error",
|
||||
"osquery_linux_installed_success",
|
||||
"osquery_linux_started_error",
|
||||
"osquery_linux_started_success",
|
||||
"osquery_linux_unexpected_stopped",
|
||||
"osquery_linux_unexpected_uninstalled",
|
||||
"osquery_linux_uninstalled_error",
|
||||
"osquery_linux_uninstalled_success"
|
||||
],
|
||||
"fields": [
|
||||
"reason",
|
||||
"version"
|
||||
],
|
||||
"last_module_update": "2023-06-06 00:00:00",
|
||||
"last_update": "2023-06-06 00:00:00"
|
||||
}
|
||||
]
|
||||
@@ -8,7 +8,7 @@ const name = "empty";
|
||||
|
||||
module.exports = {
|
||||
name,
|
||||
props: ["protoAPI", "hash", "module", "eventsAPI", "modulesAPI", "components", "viewMode"],
|
||||
props: ["protoAPI", "hash", "module", "api", "components", "viewMode"],
|
||||
data: () => ({
|
||||
})
|
||||
};
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -3,6 +3,7 @@ require("strict")
|
||||
require("engines.base_engine")
|
||||
require("engines.corr_engine")
|
||||
|
||||
local rex = require("rex_pcre2")
|
||||
local json = require("cjson.safe")
|
||||
|
||||
CActsEngine = newclass("CActsEngine", CBaseEngine)
|
||||
@@ -19,7 +20,7 @@ function CActsEngine:init(cfg)
|
||||
self.super:init(cfg)
|
||||
|
||||
self.correlator = CCorrEngine(
|
||||
function(event)
|
||||
function (event)
|
||||
self:push_result(event)
|
||||
end
|
||||
)
|
||||
@@ -27,13 +28,14 @@ function CActsEngine:init(cfg)
|
||||
if not self.correlator.valid then
|
||||
__log.info("try to restore correlator instance")
|
||||
self.correlator = CCorrEngine(
|
||||
function(event)
|
||||
function (event)
|
||||
self:push_result(event)
|
||||
end,
|
||||
true
|
||||
)
|
||||
end
|
||||
|
||||
self.excludes = {}
|
||||
self.proc_id_fields = {
|
||||
"object.process.id",
|
||||
"object.process.parent.id",
|
||||
@@ -41,6 +43,13 @@ function CActsEngine:init(cfg)
|
||||
"subject.process.parent.id",
|
||||
}
|
||||
|
||||
self.topic_name = "raw_events"
|
||||
if __imc.subscribe_to_topic then
|
||||
assert(__imc.subscribe_to_topic(self.topic_name, __gid), "can't subscribe to topic")
|
||||
else
|
||||
__log.debug("topics mechanism unsupported on agent side")
|
||||
end
|
||||
|
||||
-- initialization of object after base class constructing
|
||||
self:update_config_cb()
|
||||
end
|
||||
@@ -60,7 +69,7 @@ function CActsEngine:timer_cb()
|
||||
-- __log.debug("timer_cb CActsEngine")
|
||||
local acts_engine = CActsEngine:cast(self)
|
||||
acts_engine.correlator:pullEvents()
|
||||
__metric.add_int_gauge_counter("corr_agent_mem_usage", collectgarbage("count")*1024)
|
||||
__metric.add_int_gauge_counter("corr_agent_mem_usage", collectgarbage("count") * 1024)
|
||||
return 500
|
||||
end
|
||||
|
||||
@@ -70,6 +79,9 @@ function CActsEngine:quit_cb()
|
||||
__log.debug("quit_cb CActsEngine")
|
||||
|
||||
-- here will be triggered before closing vxproto object and destroying the state
|
||||
if __imc.unsubscribe_from_topic then
|
||||
assert(__imc.unsubscribe_from_topic(self.topic_name, __gid), "can't unsubscribe from topic")
|
||||
end
|
||||
end
|
||||
|
||||
-- in: string
|
||||
@@ -90,6 +102,10 @@ end
|
||||
-- out: nil
|
||||
function CActsEngine:update_config_cb()
|
||||
__log.debug("update_config_cb CActsEngine")
|
||||
|
||||
local acts_engine = CActsEngine:cast(self)
|
||||
acts_engine:load_excludes()
|
||||
|
||||
-- actual current configuration contains into next fields
|
||||
-- self.config.actions
|
||||
-- self.config.events
|
||||
@@ -115,8 +131,10 @@ function CActsEngine:recv_data_cb(src, data)
|
||||
__metric.add_int_counter("corr_agent_events_recv_count", #odata)
|
||||
__metric.add_int_counter("corr_agent_events_recv_size", #data)
|
||||
|
||||
for _,v in ipairs(odata) do
|
||||
v.body = json.encode(v.body)
|
||||
for _, v in ipairs(odata) do
|
||||
if v.mime == "application/x-pt-eventlog" or v.mime == "application/json" then
|
||||
v.body = json.encode(v.body)
|
||||
end
|
||||
while acts_engine.correlator:sendEvent(json.encode(v)) == false do
|
||||
__api.await(50)
|
||||
end
|
||||
@@ -157,6 +175,108 @@ function CActsEngine:recv_action_cb(src, data, name)
|
||||
return false
|
||||
end
|
||||
|
||||
-- in: nil
|
||||
-- out: nil
|
||||
function CActsEngine:load_excludes()
|
||||
self.excludes = {}
|
||||
for _, exclude in ipairs(self.config.module.excludes) do
|
||||
local compiled = {}
|
||||
for _, cond in ipairs(exclude) do
|
||||
if type(cond) ~= "table" then
|
||||
__log.errorf("condition isn't a table (array) value: '%s'", json.encode(cond))
|
||||
goto continue
|
||||
end
|
||||
if type(cond.fields) ~= "table" then
|
||||
__log.errorf("fields isn't a table (array) value: '%s'", json.encode(cond.fields))
|
||||
goto continue
|
||||
end
|
||||
if #cond.fields == 0 then
|
||||
__log.errorf("fields is empty array")
|
||||
goto continue
|
||||
end
|
||||
for _, field in ipairs(cond.fields) do
|
||||
if type(field) ~= "string" then
|
||||
__log.errorf("field isn't a string value: '%s'", json.encode(field))
|
||||
goto continue
|
||||
end
|
||||
end
|
||||
if type(cond.regex) ~= "string" then
|
||||
__log.errorf("regex isn't a string value: '%s'", json.encode(cond.regex))
|
||||
goto continue
|
||||
end
|
||||
local status, regex = pcall(rex.new, cond.regex)
|
||||
if not status then
|
||||
__log.errorf("can't compile regexp: '%s' with error '%s'", cond.regex, regex)
|
||||
goto continue
|
||||
end
|
||||
table.insert(compiled, {
|
||||
fields = cond.fields,
|
||||
sregex = cond.regex,
|
||||
cregex = regex,
|
||||
})
|
||||
::continue::
|
||||
end
|
||||
if #compiled ~= 0 then
|
||||
table.insert(self.excludes, compiled)
|
||||
end
|
||||
end
|
||||
__log.infof("loaded %d excludes from '%s'", #self.excludes, json.encode(self.config.module.excludes))
|
||||
end
|
||||
|
||||
-- in: table
|
||||
-- out: bool, table
|
||||
function CActsEngine:match_excludes(event)
|
||||
local body = {}
|
||||
for fname, fvalue in pairs(event) do
|
||||
if type(fname) ~= "string" then
|
||||
fname = tostring(fname) or ""
|
||||
end
|
||||
if type(fvalue) ~= "string" then
|
||||
fvalue = json.encode(fvalue) or ""
|
||||
end
|
||||
body[fname] = fvalue
|
||||
end
|
||||
|
||||
for _, exclude in ipairs(self.excludes) do
|
||||
local matches = {}
|
||||
for _, cond in ipairs(exclude) do
|
||||
for _, fname in ipairs(cond.fields) do
|
||||
local fvalue = body[fname]
|
||||
if not fvalue then
|
||||
-- field '{fname}' isn't exist in body
|
||||
goto next_field
|
||||
end
|
||||
local match = cond.cregex:match(fvalue)
|
||||
if match then
|
||||
table.insert(matches, {
|
||||
field = fname,
|
||||
match = match,
|
||||
regex = cond.sregex,
|
||||
value = fvalue,
|
||||
})
|
||||
-- field '{fname}' with value '{fvalue}' matches '{match}' by regex '{cond.sregex}'
|
||||
__log.debugf("field '%s' with value '%s' matches '%s' by regex '%s'", fname, fvalue, match, cond.sregex)
|
||||
goto next_condition
|
||||
end
|
||||
-- field '{fname}' with value '{fvalue}' doesn't match by regex '{cond.sregex}'
|
||||
__log.debugf("field '%s' with value '%s' doesn't match by regex '%s'", fname, fvalue, cond.sregex)
|
||||
::next_field::
|
||||
end
|
||||
-- fields '{cond.fields}' don't match by regex '{cond.sregex}'
|
||||
__log.debugf("fields '%s' don't match by regex '%s'", json.encode(cond.fields), cond.sregex)
|
||||
goto next_exclude
|
||||
::next_condition::
|
||||
end
|
||||
if #matches == #exclude then
|
||||
__log.debugf("all exclude conditions matched with event body '%s'", json.encode(matches))
|
||||
return true, matches
|
||||
end
|
||||
::next_exclude::
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- in: table
|
||||
-- out: nil
|
||||
function CActsEngine:push_result(event)
|
||||
@@ -170,11 +290,11 @@ function CActsEngine:push_result(event)
|
||||
|
||||
if event_name == nil or event_name == "" then return end
|
||||
|
||||
local config_events = self.config["events"] or {events={}}
|
||||
local config_event = config_events[event_name] or {fields={}}
|
||||
local config_fields = self.config["fields"] or {properties={}}
|
||||
local config_events = self.config["events"] or { events = {} }
|
||||
local config_event = config_events[event_name] or { fields = {} }
|
||||
local config_fields = self.config["fields"] or { properties = {} }
|
||||
local _fields = config_event["fields"] or {}
|
||||
local defaults = {string = "", number = 0, integer = 0, object = {}, array = {}, boolean = false, null = nil}
|
||||
local defaults = { string = "", number = 0, integer = 0, object = {}, array = {}, boolean = false, null = nil }
|
||||
|
||||
for _, v in ipairs(self.proc_id_fields) do
|
||||
result[v] = tonumber(result[v])
|
||||
@@ -184,5 +304,7 @@ function CActsEngine:push_result(event)
|
||||
end
|
||||
|
||||
__log.debugf("perform logic to push result: '%s'", json.encode(result))
|
||||
self:push_event(event_name,result)
|
||||
if not self:match_excludes(result) then
|
||||
self:push_event(event_name, result)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -156,7 +156,7 @@ function CBaseEngine:commit_success(src, action_name, action_data)
|
||||
|
||||
-- case to notify other side about action execution result
|
||||
if type(action_data.retaddr) == "string" and action_data.retaddr ~= "" then
|
||||
local data = cjson.encode(glue.merge({status = "success"}, action_data))
|
||||
local data = cjson.encode(glue.merge({ status = "success" }, action_data))
|
||||
__api.send_data_to(src, data)
|
||||
end
|
||||
end
|
||||
@@ -174,7 +174,7 @@ function CBaseEngine:commit_failed(src, action_name, action_data)
|
||||
|
||||
-- case to notify other side about action execution result
|
||||
if type(action_data.retaddr) == "string" and action_data.retaddr ~= "" then
|
||||
local data = cjson.encode(glue.merge({status = "error"}, action_data))
|
||||
local data = cjson.encode(glue.merge({ status = "error" }, action_data))
|
||||
__api.send_data_to(src, data)
|
||||
end
|
||||
end
|
||||
@@ -200,7 +200,7 @@ end
|
||||
-- out: string
|
||||
-- destination token (string) it'll be empty if agent disconnected
|
||||
function CBaseEngine:get_server_token()
|
||||
local tablelength = function(t)
|
||||
local tablelength = function (t)
|
||||
local count = 0
|
||||
for _ in pairs(t) do count = count + 1 end
|
||||
return count
|
||||
|
||||
@@ -85,17 +85,17 @@ end
|
||||
function CCorrEngine:init(receiveEvents, restore)
|
||||
zip.unzip(__tmpdir .. "\\data\\graphs.zip", "-d", __tmpdir .. "\\data\\")
|
||||
self.callbacks = {
|
||||
receive = function(type, data, size)
|
||||
receive = function (type, data, size)
|
||||
if type == 1 and receiveEvents then
|
||||
receiveEvents(ffi.string(data,size))
|
||||
receiveEvents(ffi.string(data, size))
|
||||
elseif type == 2 then
|
||||
self.statistics = json.decode(ffi.string(data,size))
|
||||
self.statistics = json.decode(ffi.string(data, size))
|
||||
elseif type == 3 then
|
||||
__log.errorf("caught error from corr lib: '%s'", ffi.string(data,size))
|
||||
__log.errorf("caught error from corr lib: '%s'", ffi.string(data, size))
|
||||
end
|
||||
|
||||
return size
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
self.statistics = {}
|
||||
@@ -179,12 +179,12 @@ function CCorrEngine.get_file_hash_md5(filepath)
|
||||
end
|
||||
|
||||
function CCorrEngine.copyFile(src, dst, force)
|
||||
local f, err = io.open(src, 'rb')
|
||||
local f, err = io.open(src, "rb")
|
||||
if not f then return nil, err end
|
||||
|
||||
local t, ok
|
||||
if not force then
|
||||
t = io.open(dst, 'rb')
|
||||
t = io.open(dst, "rb")
|
||||
if t then
|
||||
f:close()
|
||||
t:close()
|
||||
@@ -192,7 +192,7 @@ function CCorrEngine.copyFile(src, dst, force)
|
||||
end
|
||||
end
|
||||
|
||||
t, err = io.open(dst, 'w+b')
|
||||
t, err = io.open(dst, "w+b")
|
||||
if not t then
|
||||
f:close()
|
||||
return nil, err
|
||||
|
||||
@@ -2,7 +2,7 @@ require("engines.acts_engine")
|
||||
|
||||
-- base config to actions engine
|
||||
local cfg = {
|
||||
config = {}
|
||||
config = {},
|
||||
}
|
||||
|
||||
-- actions engine initialize
|
||||
@@ -12,24 +12,22 @@ local acts_engine = CActsEngine(cfg)
|
||||
__api.set_recv_timeout(5000) -- 5s
|
||||
|
||||
__api.add_cbs({
|
||||
data = function(src, data)
|
||||
data = function (src, data)
|
||||
__log.debugf("receive data from '%s' with data", src)
|
||||
assert(acts_engine ~= nil, "actions engine instance is not initialized")
|
||||
|
||||
return acts_engine:recv_data(src, data)
|
||||
end,
|
||||
|
||||
file = function(src, path, name)
|
||||
file = function (src, path, name)
|
||||
__log.infof("receive file from '%s' with name '%s' path '%s'", src, name, path)
|
||||
assert(acts_engine ~= nil, "actions engine instance is not initialized")
|
||||
|
||||
return acts_engine:recv_file(src, path, name)
|
||||
end,
|
||||
|
||||
-- text = function(src, text, name)
|
||||
-- msg = function(src, msg, mtype)
|
||||
|
||||
action = function(src, data, name)
|
||||
action = function (src, data, name)
|
||||
__log.infof("receive action '%s' from '%s' with data %s", name, src, data)
|
||||
assert(acts_engine ~= nil, "actions engine instance is not initialized")
|
||||
|
||||
@@ -37,8 +35,7 @@ __api.add_cbs({
|
||||
__log.infof("requested action '%s' was executed: %s", name, action_result)
|
||||
return action_result
|
||||
end,
|
||||
|
||||
control = function(cmtype, data)
|
||||
control = function (cmtype, data)
|
||||
__log.debugf("receive control msg '%s' with data %s", cmtype, data)
|
||||
assert(acts_engine ~= nil, "actions engine instance is not initialized")
|
||||
|
||||
@@ -61,6 +58,7 @@ __api.add_cbs({
|
||||
|
||||
__log.infof("module '%s' was started", __config.ctx.name)
|
||||
acts_engine:run()
|
||||
__api.del_cbs({ "data", "file", "action", "control" })
|
||||
__log.infof("module '%s' was stopped", __config.ctx.name)
|
||||
|
||||
-- explicit destroy engine
|
||||
|
||||
@@ -50,9 +50,8 @@ function CModule:init(moduleName)
|
||||
self.api = {
|
||||
create = self.module.module_create,
|
||||
destroy = self.module.module_destroy,
|
||||
version = nil,--self.module.Module__Version,
|
||||
|
||||
is_inited = false
|
||||
version = nil, --self.module.Module__Version,
|
||||
is_inited = false,
|
||||
}
|
||||
self.transport = ffi.new("api_module_transport[1]", {})
|
||||
end
|
||||
@@ -101,7 +100,7 @@ function CModule:register(profile, callbacks)
|
||||
|
||||
self.functions = {}
|
||||
|
||||
self.functions["receive"] = function(transport, type, data, size)
|
||||
self.functions["receive"] = function (transport, type, data, size)
|
||||
if callbacks and transport == self.transport and callbacks["receive"] then
|
||||
return callbacks["receive"](type, data, size)
|
||||
end
|
||||
@@ -116,7 +115,7 @@ function CModule:register(profile, callbacks)
|
||||
local ctmpdir = ffi.new("char[?]", 256)
|
||||
lk32.GetDllDirectoryA(256, ctmpdir)
|
||||
lk32.SetDllDirectoryA(__tmpdir)
|
||||
self.api.is_inited = self.module_i.init(self.transport,self.profile, #profile)
|
||||
self.api.is_inited = self.module_i.init(self.transport, self.profile, #profile)
|
||||
lk32.SetDllDirectoryA(ctmpdir)
|
||||
|
||||
return self.api.is_inited, ""
|
||||
@@ -131,7 +130,7 @@ function CModule:start()
|
||||
self.module_i.start(self.transport)
|
||||
end
|
||||
|
||||
function CModule:send(type,data)
|
||||
function CModule:send(type, data)
|
||||
if self.transport[0].to_module == nil then
|
||||
return
|
||||
end
|
||||
|
||||
@@ -1,6 +1,95 @@
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {},
|
||||
"properties": {
|
||||
"excludes": {
|
||||
"items": {
|
||||
"items": {
|
||||
"properties": {
|
||||
"fields": {
|
||||
"rules": {
|
||||
"required": true
|
||||
},
|
||||
"type": "array",
|
||||
"ui": {
|
||||
"columns": 6,
|
||||
"label": "dx: window.__$ncform.lang === 'en' ? 'Variables' : 'Переменные'",
|
||||
"widget": "select",
|
||||
"widgetConfig": {
|
||||
"allowCreate": true,
|
||||
"clearable": true,
|
||||
"defaultFirstOption": false,
|
||||
"enumSourceRemote": {
|
||||
"otherParams": {
|
||||
"filters[]": "{\"field\": \"module_name\", \"value\": [\"correlator\"]}",
|
||||
"group": "name",
|
||||
"lang": "en",
|
||||
"page": 1,
|
||||
"pageSize": -1,
|
||||
"type": "init"
|
||||
},
|
||||
"remoteUrl": "/api/v1/options/fields",
|
||||
"resField": "data.fields"
|
||||
},
|
||||
"filterLocal": true,
|
||||
"filterable": true,
|
||||
"itemDataKey": "item",
|
||||
"itemLabelField": "name",
|
||||
"itemValueField": "name",
|
||||
"multiple": true
|
||||
}
|
||||
},
|
||||
"value": []
|
||||
},
|
||||
"regex": {
|
||||
"rules": {
|
||||
"customRule": [
|
||||
{
|
||||
"errMsg": "regexp format required",
|
||||
"script": "dx: ((val) =\u003e { try { const v = new RegExp(val); return typeof(v) !== undefined } catch(e) { return false } })(__get({{$root}}, {{$path}}))"
|
||||
}
|
||||
],
|
||||
"required": true
|
||||
},
|
||||
"type": "string",
|
||||
"ui": {
|
||||
"columns": 6,
|
||||
"label": "dx: window.__$ncform.lang === 'en' ? 'Regular expression' : 'Регулярное выражение'"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [],
|
||||
"type": "object",
|
||||
"ui": {
|
||||
"label": "dx: ((fields) =\u003e { const or = (window.__$ncform.lang === 'en' ? ' OR ' : ' ИЛИ '); const retIsArray = ((val, def) =\u003e (typeof val === 'object' \u0026\u0026 Array.isArray(val) ? val : def)); fields = retIsArray(fields, []); switch(fields.length) { case 0: return (window.__$ncform.lang === 'en' ? 'empty' : 'пустой список'); case 1: return fields[0]; default: return '(' + [...new Set(fields.map(f =\u003e '...' + f.split('.').slice(-1)[0]))].join(or) + ')'; } })(__get({{$root}}, {{$path}} + '.fields'))"
|
||||
}
|
||||
},
|
||||
"type": "array",
|
||||
"ui": {
|
||||
"label": "dx: (() =\u003e { const and = (window.__$ncform.lang === 'en' ? ' AND ' : ' И '); const or = (window.__$ncform.lang === 'en' ? ' OR ' : ' ИЛИ '); const retIsArray = ((val, def) =\u003e (typeof val === 'object' \u0026\u0026 Array.isArray(val) ? val : def)); const getLabel = ((fields) =\u003e { fields = retIsArray(fields, []); switch(fields.length) { case 0: return (window.__$ncform.lang === 'en' ? 'empty' : 'пустой список'); case 1: return JSON.stringify(fields[0]); default: return '(' + [...new Set(fields.map(f =\u003e JSON.stringify('...' + f.split('.').slice(-1)[0])))].join(or) + ')'; } }); return retIsArray(__get({{$root}}, {{$path}}), []).map(e =\u003e getLabel(e.fields)).join(and);})()",
|
||||
"noLabelSpace": true,
|
||||
"showIdxLabel": false,
|
||||
"showLegend": false,
|
||||
"widget": "array-tabs",
|
||||
"widgetConfig": {
|
||||
"showOneIfEmpty": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"rules": {},
|
||||
"type": "array",
|
||||
"ui": {
|
||||
"noLabelSpace": true,
|
||||
"showIdxLabel": false,
|
||||
"showLabel": false,
|
||||
"showLegend": true,
|
||||
"widgetConfig": {
|
||||
"collapsed": true,
|
||||
"disableReorder": true,
|
||||
"itemCollapse": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [],
|
||||
"type": "object"
|
||||
}
|
||||
@@ -1 +1,3 @@
|
||||
{}
|
||||
{
|
||||
"excludes": []
|
||||
}
|
||||
@@ -1 +1,3 @@
|
||||
{}
|
||||
{
|
||||
"excludes": []
|
||||
}
|
||||
@@ -1,7 +1,18 @@
|
||||
{
|
||||
"action_config": {},
|
||||
"actions": {},
|
||||
"config": {},
|
||||
"config": {
|
||||
"excludes": {
|
||||
"en": {
|
||||
"description": "Exclusion list",
|
||||
"title": "Exclusions"
|
||||
},
|
||||
"ru": {
|
||||
"description": "Список исключений",
|
||||
"title": "Исключения"
|
||||
}
|
||||
}
|
||||
},
|
||||
"event_config": {
|
||||
"Suspicious_Create_Process_BitsAdmin_RestrictionBypass": {},
|
||||
"Suspicious_Create_Process_NetSh_NetShell": {},
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
|
||||
__api.add_cbs({
|
||||
|
||||
-- data = function(src, data)
|
||||
-- file = function(src, path, name)
|
||||
-- text = function(src, text, name)
|
||||
-- msg = function(src, msg, mtype)
|
||||
-- action = function(src, data, name)
|
||||
|
||||
control = function(cmtype, data)
|
||||
control = function (cmtype, data)
|
||||
__log.debugf("receive control msg '%s' with payload: %s", cmtype, data)
|
||||
|
||||
-- cmtype: "quit"
|
||||
@@ -25,4 +23,4 @@ __api.await(-1)
|
||||
|
||||
__log.infof("module '%s' was stopped", __config.ctx.name)
|
||||
|
||||
return 'success'
|
||||
return "success"
|
||||
|
||||
@@ -8,7 +8,7 @@ const name = "empty";
|
||||
|
||||
module.exports = {
|
||||
name,
|
||||
props: ["protoAPI", "hash", "module", "eventsAPI", "modulesAPI", "components", "viewMode"],
|
||||
props: ["protoAPI", "hash", "module", "api", "components", "viewMode"],
|
||||
data: () => ({
|
||||
})
|
||||
};
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -3,6 +3,7 @@ require("strict")
|
||||
require("engines.base_engine")
|
||||
require("engines.corr_engine")
|
||||
|
||||
local rex = require("rex_pcre2")
|
||||
local json = require("cjson.safe")
|
||||
|
||||
CActsEngine = newclass("CActsEngine", CBaseEngine)
|
||||
@@ -19,7 +20,7 @@ function CActsEngine:init(cfg)
|
||||
self.super:init(cfg)
|
||||
|
||||
self.correlator = CCorrEngine(
|
||||
function(event)
|
||||
function (event)
|
||||
self:push_result(event)
|
||||
end
|
||||
)
|
||||
@@ -27,7 +28,7 @@ function CActsEngine:init(cfg)
|
||||
if not self.correlator.valid then
|
||||
__log.info("try to restore correlator instance")
|
||||
self.correlator = CCorrEngine(
|
||||
function(event)
|
||||
function (event)
|
||||
self:push_result(event)
|
||||
end,
|
||||
true
|
||||
@@ -36,6 +37,7 @@ function CActsEngine:init(cfg)
|
||||
|
||||
assert(self.correlator.valid == true, "failed to initilize correlator")
|
||||
|
||||
self.excludes = {}
|
||||
self.proc_id_fields = {
|
||||
"object.process.id",
|
||||
"object.process.parent.id",
|
||||
@@ -43,6 +45,13 @@ function CActsEngine:init(cfg)
|
||||
"subject.process.parent.id",
|
||||
}
|
||||
|
||||
self.topic_name = "raw_events"
|
||||
if __imc.subscribe_to_topic then
|
||||
assert(__imc.subscribe_to_topic(self.topic_name, __gid), "can't subscribe to topic")
|
||||
else
|
||||
__log.debug("topics mechanism unsupported on agent side")
|
||||
end
|
||||
|
||||
-- initialization of object after base class constructing
|
||||
self:update_config_cb()
|
||||
end
|
||||
@@ -62,7 +71,7 @@ function CActsEngine:timer_cb()
|
||||
-- __log.debug("timer_cb CActsEngine")
|
||||
local acts_engine = CActsEngine:cast(self)
|
||||
acts_engine.correlator:pullEvents()
|
||||
__metric.add_int_gauge_counter("corr_agent_mem_usage", collectgarbage("count")*1024)
|
||||
__metric.add_int_gauge_counter("corr_agent_mem_usage", collectgarbage("count") * 1024)
|
||||
return 500
|
||||
end
|
||||
|
||||
@@ -72,6 +81,9 @@ function CActsEngine:quit_cb()
|
||||
__log.debug("quit_cb CActsEngine")
|
||||
|
||||
-- here will be triggered before closing vxproto object and destroying the state
|
||||
if __imc.unsubscribe_from_topic then
|
||||
assert(__imc.unsubscribe_from_topic(self.topic_name, __gid), "can't unsubscribe from topic")
|
||||
end
|
||||
end
|
||||
|
||||
-- in: string
|
||||
@@ -92,6 +104,10 @@ end
|
||||
-- out: nil
|
||||
function CActsEngine:update_config_cb()
|
||||
__log.debug("update_config_cb CActsEngine")
|
||||
|
||||
local acts_engine = CActsEngine:cast(self)
|
||||
acts_engine:load_excludes()
|
||||
|
||||
-- actual current configuration contains into next fields
|
||||
-- self.config.actions
|
||||
-- self.config.events
|
||||
@@ -117,8 +133,10 @@ function CActsEngine:recv_data_cb(src, data)
|
||||
__metric.add_int_counter("corr_agent_events_recv_count", #odata)
|
||||
__metric.add_int_counter("corr_agent_events_recv_size", #data)
|
||||
|
||||
for _,v in ipairs(odata) do
|
||||
v.body = json.encode(v.body)
|
||||
for _, v in ipairs(odata) do
|
||||
if v.mime == "application/x-pt-eventlog" or v.mime == "application/json" then
|
||||
v.body = json.encode(v.body)
|
||||
end
|
||||
while acts_engine.correlator:sendEvent(json.encode(v)) == false do
|
||||
__api.await(50)
|
||||
end
|
||||
@@ -159,6 +177,108 @@ function CActsEngine:recv_action_cb(src, data, name)
|
||||
return false
|
||||
end
|
||||
|
||||
-- in: nil
|
||||
-- out: nil
|
||||
function CActsEngine:load_excludes()
|
||||
self.excludes = {}
|
||||
for _, exclude in ipairs(self.config.module.excludes) do
|
||||
local compiled = {}
|
||||
for _, cond in ipairs(exclude) do
|
||||
if type(cond) ~= "table" then
|
||||
__log.errorf("condition isn't a table (array) value: '%s'", json.encode(cond))
|
||||
goto continue
|
||||
end
|
||||
if type(cond.fields) ~= "table" then
|
||||
__log.errorf("fields isn't a table (array) value: '%s'", json.encode(cond.fields))
|
||||
goto continue
|
||||
end
|
||||
if #cond.fields == 0 then
|
||||
__log.errorf("fields is empty array")
|
||||
goto continue
|
||||
end
|
||||
for _, field in ipairs(cond.fields) do
|
||||
if type(field) ~= "string" then
|
||||
__log.errorf("field isn't a string value: '%s'", json.encode(field))
|
||||
goto continue
|
||||
end
|
||||
end
|
||||
if type(cond.regex) ~= "string" then
|
||||
__log.errorf("regex isn't a string value: '%s'", json.encode(cond.regex))
|
||||
goto continue
|
||||
end
|
||||
local status, regex = pcall(rex.new, cond.regex)
|
||||
if not status then
|
||||
__log.errorf("can't compile regexp: '%s' with error '%s'", cond.regex, regex)
|
||||
goto continue
|
||||
end
|
||||
table.insert(compiled, {
|
||||
fields = cond.fields,
|
||||
sregex = cond.regex,
|
||||
cregex = regex,
|
||||
})
|
||||
::continue::
|
||||
end
|
||||
if #compiled ~= 0 then
|
||||
table.insert(self.excludes, compiled)
|
||||
end
|
||||
end
|
||||
__log.infof("loaded %d excludes from '%s'", #self.excludes, json.encode(self.config.module.excludes))
|
||||
end
|
||||
|
||||
-- in: table
|
||||
-- out: bool, table
|
||||
function CActsEngine:match_excludes(event)
|
||||
local body = {}
|
||||
for fname, fvalue in pairs(event) do
|
||||
if type(fname) ~= "string" then
|
||||
fname = tostring(fname) or ""
|
||||
end
|
||||
if type(fvalue) ~= "string" then
|
||||
fvalue = json.encode(fvalue) or ""
|
||||
end
|
||||
body[fname] = fvalue
|
||||
end
|
||||
|
||||
for _, exclude in ipairs(self.excludes) do
|
||||
local matches = {}
|
||||
for _, cond in ipairs(exclude) do
|
||||
for _, fname in ipairs(cond.fields) do
|
||||
local fvalue = body[fname]
|
||||
if not fvalue then
|
||||
-- field '{fname}' isn't exist in body
|
||||
goto next_field
|
||||
end
|
||||
local match = cond.cregex:match(fvalue)
|
||||
if match then
|
||||
table.insert(matches, {
|
||||
field = fname,
|
||||
match = match,
|
||||
regex = cond.sregex,
|
||||
value = fvalue,
|
||||
})
|
||||
-- field '{fname}' with value '{fvalue}' matches '{match}' by regex '{cond.sregex}'
|
||||
__log.debugf("field '%s' with value '%s' matches '%s' by regex '%s'", fname, fvalue, match, cond.sregex)
|
||||
goto next_condition
|
||||
end
|
||||
-- field '{fname}' with value '{fvalue}' doesn't match by regex '{cond.sregex}'
|
||||
__log.debugf("field '%s' with value '%s' doesn't match by regex '%s'", fname, fvalue, cond.sregex)
|
||||
::next_field::
|
||||
end
|
||||
-- fields '{cond.fields}' don't match by regex '{cond.sregex}'
|
||||
__log.debugf("fields '%s' don't match by regex '%s'", json.encode(cond.fields), cond.sregex)
|
||||
goto next_exclude
|
||||
::next_condition::
|
||||
end
|
||||
if #matches == #exclude then
|
||||
__log.debugf("all exclude conditions matched with event body '%s'", json.encode(matches))
|
||||
return true, matches
|
||||
end
|
||||
::next_exclude::
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- in: table
|
||||
-- out: nil
|
||||
function CActsEngine:push_result(event)
|
||||
@@ -172,11 +292,11 @@ function CActsEngine:push_result(event)
|
||||
|
||||
if event_name == nil or event_name == "" then return end
|
||||
|
||||
local config_events = self.config["events"] or {events={}}
|
||||
local config_event = config_events[event_name] or {fields={}}
|
||||
local config_fields = self.config["fields"] or {properties={}}
|
||||
local config_events = self.config["events"] or { events = {} }
|
||||
local config_event = config_events[event_name] or { fields = {} }
|
||||
local config_fields = self.config["fields"] or { properties = {} }
|
||||
local _fields = config_event["fields"] or {}
|
||||
local defaults = {string = "", number = 0, integer = 0, object = {}, array = {}, boolean = false, null = nil}
|
||||
local defaults = { string = "", number = 0, integer = 0, object = {}, array = {}, boolean = false, null = nil }
|
||||
|
||||
for _, v in ipairs(self.proc_id_fields) do
|
||||
result[v] = tonumber(result[v])
|
||||
@@ -186,5 +306,7 @@ function CActsEngine:push_result(event)
|
||||
end
|
||||
|
||||
__log.debugf("perform logic to push result: '%s'", json.encode(result))
|
||||
self:push_event(event_name,result)
|
||||
if not self:match_excludes(result) then
|
||||
self:push_event(event_name, result)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -156,7 +156,7 @@ function CBaseEngine:commit_success(src, action_name, action_data)
|
||||
|
||||
-- case to notify other side about action execution result
|
||||
if type(action_data.retaddr) == "string" and action_data.retaddr ~= "" then
|
||||
local data = cjson.encode(glue.merge({status = "success"}, action_data))
|
||||
local data = cjson.encode(glue.merge({ status = "success" }, action_data))
|
||||
__api.send_data_to(src, data)
|
||||
end
|
||||
end
|
||||
@@ -174,7 +174,7 @@ function CBaseEngine:commit_failed(src, action_name, action_data)
|
||||
|
||||
-- case to notify other side about action execution result
|
||||
if type(action_data.retaddr) == "string" and action_data.retaddr ~= "" then
|
||||
local data = cjson.encode(glue.merge({status = "error"}, action_data))
|
||||
local data = cjson.encode(glue.merge({ status = "error" }, action_data))
|
||||
__api.send_data_to(src, data)
|
||||
end
|
||||
end
|
||||
@@ -200,7 +200,7 @@ end
|
||||
-- out: string
|
||||
-- destination token (string) it'll be empty if agent disconnected
|
||||
function CBaseEngine:get_server_token()
|
||||
local tablelength = function(t)
|
||||
local tablelength = function (t)
|
||||
local count = 0
|
||||
for _ in pairs(t) do count = count + 1 end
|
||||
return count
|
||||
|
||||
@@ -87,17 +87,17 @@ function CCorrEngine:init(receiveEvents, restore)
|
||||
local tmpdir_data = luapath.combine(__tmpdir, "data")
|
||||
zip.unzip(luapath.combine(tmpdir_data, "graphs.zip"), "-d", tmpdir_data)
|
||||
self.callbacks = {
|
||||
receive = function(type, data, size)
|
||||
receive = function (type, data, size)
|
||||
if type == 1 and receiveEvents then
|
||||
receiveEvents(ffi.string(data,size))
|
||||
receiveEvents(ffi.string(data, size))
|
||||
elseif type == 2 then
|
||||
self.statistics = json.decode(ffi.string(data,size))
|
||||
self.statistics = json.decode(ffi.string(data, size))
|
||||
elseif type == 3 then
|
||||
__log.errorf("caught error from corr lib: '%s'", ffi.string(data,size))
|
||||
__log.errorf("caught error from corr lib: '%s'", ffi.string(data, size))
|
||||
end
|
||||
|
||||
return size
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
self.statistics = {}
|
||||
@@ -189,12 +189,12 @@ function CCorrEngine.get_file_hash_md5(filepath)
|
||||
end
|
||||
|
||||
function CCorrEngine.copyFile(src, dst, force)
|
||||
local f, err = io.open(src, 'rb')
|
||||
local f, err = io.open(src, "rb")
|
||||
if not f then return nil, err end
|
||||
|
||||
local t, ok
|
||||
if not force then
|
||||
t = io.open(dst, 'rb')
|
||||
t = io.open(dst, "rb")
|
||||
if t then
|
||||
f:close()
|
||||
t:close()
|
||||
@@ -202,7 +202,7 @@ function CCorrEngine.copyFile(src, dst, force)
|
||||
end
|
||||
end
|
||||
|
||||
t, err = io.open(dst, 'w+b')
|
||||
t, err = io.open(dst, "w+b")
|
||||
if not t then
|
||||
f:close()
|
||||
return nil, err
|
||||
@@ -229,7 +229,7 @@ end
|
||||
function CCorrEngine:copyDir(dir_from, dir_to, force)
|
||||
for file in lfs.dir(dir_from) do
|
||||
if file ~= "." and file ~= ".." then
|
||||
local f = dir_from .. '/' .. file
|
||||
local f = dir_from .. "/" .. file
|
||||
local attr = lfs.attributes(f)
|
||||
|
||||
if attr.mode == "directory" then
|
||||
|
||||
@@ -2,7 +2,7 @@ require("engines.acts_engine")
|
||||
|
||||
-- base config to actions engine
|
||||
local cfg = {
|
||||
config = {}
|
||||
config = {},
|
||||
}
|
||||
|
||||
-- actions engine initialize
|
||||
@@ -12,24 +12,22 @@ local acts_engine = CActsEngine(cfg)
|
||||
__api.set_recv_timeout(5000) -- 5s
|
||||
|
||||
__api.add_cbs({
|
||||
data = function(src, data)
|
||||
data = function (src, data)
|
||||
__log.debugf("receive data from '%s' with data", src)
|
||||
assert(acts_engine ~= nil, "actions engine instance is not initialized")
|
||||
|
||||
return acts_engine:recv_data(src, data)
|
||||
end,
|
||||
|
||||
file = function(src, path, name)
|
||||
file = function (src, path, name)
|
||||
__log.infof("receive file from '%s' with name '%s' path '%s'", src, name, path)
|
||||
assert(acts_engine ~= nil, "actions engine instance is not initialized")
|
||||
|
||||
return acts_engine:recv_file(src, path, name)
|
||||
end,
|
||||
|
||||
-- text = function(src, text, name)
|
||||
-- msg = function(src, msg, mtype)
|
||||
|
||||
action = function(src, data, name)
|
||||
action = function (src, data, name)
|
||||
__log.infof("receive action '%s' from '%s' with data %s", name, src, data)
|
||||
assert(acts_engine ~= nil, "actions engine instance is not initialized")
|
||||
|
||||
@@ -37,8 +35,7 @@ __api.add_cbs({
|
||||
__log.infof("requested action '%s' was executed: %s", name, action_result)
|
||||
return action_result
|
||||
end,
|
||||
|
||||
control = function(cmtype, data)
|
||||
control = function (cmtype, data)
|
||||
__log.debugf("receive control msg '%s' with data %s", cmtype, data)
|
||||
assert(acts_engine ~= nil, "actions engine instance is not initialized")
|
||||
|
||||
@@ -61,6 +58,7 @@ __api.add_cbs({
|
||||
|
||||
__log.infof("module '%s' was started", __config.ctx.name)
|
||||
acts_engine:run()
|
||||
__api.del_cbs({ "data", "file", "action", "control" })
|
||||
__log.infof("module '%s' was stopped", __config.ctx.name)
|
||||
|
||||
-- explicit destroy engine
|
||||
|
||||
@@ -52,16 +52,15 @@ function CModule:init(moduleName)
|
||||
end
|
||||
end
|
||||
|
||||
self.wrap_load(function()
|
||||
self.wrap_load(function ()
|
||||
self.module = ffi.load(moduleName)
|
||||
end)
|
||||
|
||||
self.api = {
|
||||
create = self.module.module_create,
|
||||
destroy = self.module.module_destroy,
|
||||
version = nil,--self.module.Module__Version,
|
||||
|
||||
is_inited = false
|
||||
version = nil, --self.module.Module__Version,
|
||||
is_inited = false,
|
||||
}
|
||||
self.transport = ffi.new("api_module_transport[1]", {})
|
||||
end
|
||||
@@ -112,7 +111,7 @@ function CModule:register(profile, callbacks)
|
||||
|
||||
self.functions = {}
|
||||
|
||||
self.functions["receive"] = function(transport, type, data, size)
|
||||
self.functions["receive"] = function (transport, type, data, size)
|
||||
if callbacks and transport == self.transport and callbacks["receive"] then
|
||||
return callbacks["receive"](type, data, size)
|
||||
end
|
||||
@@ -124,7 +123,7 @@ function CModule:register(profile, callbacks)
|
||||
self.module_i = self.api.create(self.transport, 0, nil)
|
||||
self.profile = ffi.new("const char[?]", #profile + 1, profile)
|
||||
|
||||
self.wrap_load(function()
|
||||
self.wrap_load(function ()
|
||||
self.api.is_inited = self.module_i.init(self.transport, self.profile, #profile)
|
||||
end)
|
||||
|
||||
@@ -140,7 +139,7 @@ function CModule:start()
|
||||
self.module_i.start(self.transport)
|
||||
end
|
||||
|
||||
function CModule:send(type,data)
|
||||
function CModule:send(type, data)
|
||||
if self.transport[0].to_module == nil then
|
||||
return
|
||||
end
|
||||
|
||||
@@ -1,6 +1,95 @@
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {},
|
||||
"properties": {
|
||||
"excludes": {
|
||||
"items": {
|
||||
"items": {
|
||||
"properties": {
|
||||
"fields": {
|
||||
"rules": {
|
||||
"required": true
|
||||
},
|
||||
"type": "array",
|
||||
"ui": {
|
||||
"columns": 6,
|
||||
"label": "dx: window.__$ncform.lang === 'en' ? 'Fields' : 'Переменные'",
|
||||
"widget": "select",
|
||||
"widgetConfig": {
|
||||
"allowCreate": true,
|
||||
"clearable": true,
|
||||
"defaultFirstOption": false,
|
||||
"enumSourceRemote": {
|
||||
"otherParams": {
|
||||
"filters[]": "{\"field\": \"module_name\", \"value\": [\"correlator\"]}",
|
||||
"group": "name",
|
||||
"lang": "en",
|
||||
"page": 1,
|
||||
"pageSize": -1,
|
||||
"type": "init"
|
||||
},
|
||||
"remoteUrl": "/api/v1/options/fields",
|
||||
"resField": "data.fields"
|
||||
},
|
||||
"filterLocal": true,
|
||||
"filterable": true,
|
||||
"itemDataKey": "item",
|
||||
"itemLabelField": "name",
|
||||
"itemValueField": "name",
|
||||
"multiple": true
|
||||
}
|
||||
},
|
||||
"value": []
|
||||
},
|
||||
"regex": {
|
||||
"rules": {
|
||||
"customRule": [
|
||||
{
|
||||
"errMsg": "regexp format required",
|
||||
"script": "dx: ((val) =\u003e { try { const v = new RegExp(val); return typeof(v) !== undefined } catch(e) { return false } })(__get({{$root}}, {{$path}}))"
|
||||
}
|
||||
],
|
||||
"required": true
|
||||
},
|
||||
"type": "string",
|
||||
"ui": {
|
||||
"columns": 6,
|
||||
"label": "dx: window.__$ncform.lang === 'en' ? 'Regular expression' : 'Регулярное выражение'"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [],
|
||||
"type": "object",
|
||||
"ui": {
|
||||
"label": "dx: ((fields) =\u003e { const or = (window.__$ncform.lang === 'en' ? ' OR ' : ' ИЛИ '); const retIsArray = ((val, def) =\u003e (typeof val === 'object' \u0026\u0026 Array.isArray(val) ? val : def)); fields = retIsArray(fields, []); switch(fields.length) { case 0: return (window.__$ncform.lang === 'en' ? 'empty' : 'пустой список'); case 1: return fields[0]; default: return '(' + [...new Set(fields.map(f =\u003e '...' + f.split('.').slice(-1)[0]))].join(or) + ')'; } })(__get({{$root}}, {{$path}} + '.fields'))"
|
||||
}
|
||||
},
|
||||
"type": "array",
|
||||
"ui": {
|
||||
"label": "dx: (() =\u003e { const and = (window.__$ncform.lang === 'en' ? ' AND ' : ' И '); const or = (window.__$ncform.lang === 'en' ? ' OR ' : ' ИЛИ '); const retIsArray = ((val, def) =\u003e (typeof val === 'object' \u0026\u0026 Array.isArray(val) ? val : def)); const getLabel = ((fields) =\u003e { fields = retIsArray(fields, []); switch(fields.length) { case 0: return (window.__$ncform.lang === 'en' ? 'empty' : 'пустой список'); case 1: return JSON.stringify(fields[0]); default: return '(' + [...new Set(fields.map(f =\u003e JSON.stringify('...' + f.split('.').slice(-1)[0])))].join(or) + ')'; } }); return retIsArray(__get({{$root}}, {{$path}}), []).map(e =\u003e getLabel(e.fields)).join(and);})()",
|
||||
"noLabelSpace": true,
|
||||
"showIdxLabel": false,
|
||||
"showLegend": false,
|
||||
"widget": "array-tabs",
|
||||
"widgetConfig": {
|
||||
"showOneIfEmpty": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"rules": {},
|
||||
"type": "array",
|
||||
"ui": {
|
||||
"noLabelSpace": true,
|
||||
"showIdxLabel": false,
|
||||
"showLabel": false,
|
||||
"showLegend": true,
|
||||
"widgetConfig": {
|
||||
"collapsed": true,
|
||||
"disableReorder": true,
|
||||
"itemCollapse": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [],
|
||||
"type": "object"
|
||||
}
|
||||
@@ -1 +1,3 @@
|
||||
{}
|
||||
{
|
||||
"excludes": []
|
||||
}
|
||||
@@ -1 +1,3 @@
|
||||
{}
|
||||
{
|
||||
"excludes": []
|
||||
}
|
||||
@@ -1,7 +1,18 @@
|
||||
{
|
||||
"action_config": {},
|
||||
"actions": {},
|
||||
"config": {},
|
||||
"config": {
|
||||
"excludes": {
|
||||
"en": {
|
||||
"description": "Exclusions list",
|
||||
"title": "Exclusions"
|
||||
},
|
||||
"ru": {
|
||||
"description": "Список исключений",
|
||||
"title": "Исключения"
|
||||
}
|
||||
}
|
||||
},
|
||||
"event_config": {
|
||||
"Malware_Exploit_Elf_CVE_2021_4034_a": {},
|
||||
"Suspicious_Create_File_Boot_Modification": {},
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
|
||||
__api.add_cbs({
|
||||
|
||||
-- data = function(src, data)
|
||||
-- file = function(src, path, name)
|
||||
-- text = function(src, text, name)
|
||||
-- msg = function(src, msg, mtype)
|
||||
-- action = function(src, data, name)
|
||||
|
||||
control = function(cmtype, data)
|
||||
control = function (cmtype, data)
|
||||
__log.debugf("receive control msg '%s' with payload: %s", cmtype, data)
|
||||
|
||||
-- cmtype: "quit"
|
||||
@@ -25,4 +23,4 @@ __api.await(-1)
|
||||
|
||||
__log.infof("module '%s' was stopped", __config.ctx.name)
|
||||
|
||||
return 'success'
|
||||
return "success"
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
version: "3"
|
||||
services:
|
||||
tests:
|
||||
tty: true
|
||||
entrypoint:
|
||||
bash -c "cd soldr-modules && ./tests_framework/lua/bin/busted.linux64.cmd tests/."
|
||||
build:
|
||||
context: .
|
||||
dockerfile: tests/Dockerfile
|
||||
volumes:
|
||||
- .:/soldr-modules
|
||||
# command: tail -f /dev/null
|
||||
@@ -8,7 +8,7 @@ const name = "empty";
|
||||
|
||||
module.exports = {
|
||||
name,
|
||||
props: ["protoAPI", "hash", "module", "eventsAPI", "modulesAPI", "components", "viewMode"],
|
||||
props: ["protoAPI", "hash", "module", "api", "components", "viewMode"],
|
||||
data: () => ({
|
||||
})
|
||||
};
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user