This commit is contained in:
2
shuffle/functions/extensions/aws-s3-lambda/README.md
Normal file
2
shuffle/functions/extensions/aws-s3-lambda/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# AWS Lambda forwarder to Shuffle
|
||||
This function is made to forward S3 notifications to Shuffle to run a workflow when an object is made or updated.
|
22
shuffle/functions/extensions/aws-s3-lambda/s3_function.py
Normal file
22
shuffle/functions/extensions/aws-s3-lambda/s3_function.py
Normal file
@ -0,0 +1,22 @@
|
||||
import json
|
||||
import urllib.parse
|
||||
import urllib3
|
||||
import os
|
||||
|
||||
print('Loading function')
|
||||
|
||||
def lambda_handler(event, context):
|
||||
# Get the object from the event and show its content type
|
||||
bucket = event['Records'][0]['s3']['bucket']['name']
|
||||
|
||||
webhook = os.environ.get("SHUFFLE_WEBHOOK")
|
||||
if not webhook:
|
||||
return "No webhook environment defined: SHUFFLE_WEBHOOK"
|
||||
|
||||
http = urllib3.PoolManager()
|
||||
ret = http.request('POST', webhook, body=json.dumps(event["Records"][0]).encode("utf-8"))
|
||||
if ret.status != 200:
|
||||
return "Bad status code for webhook: %d" % ret.status
|
||||
|
||||
print("Status code: %d\nData: %s" % (ret.status, ret.data))
|
||||
return "Successfully started with data %s" % ret.data
|
@ -0,0 +1,2 @@
|
||||
cortexutils
|
||||
requests
|
@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "Shuffle",
|
||||
"version": "1.0",
|
||||
"author": "@frikkylikeme",
|
||||
"url": "https://github.com/frikky/shuffle",
|
||||
"license": "AGPL-V3",
|
||||
"description": "Execute a workflow in Shuffle",
|
||||
"dataTypeList": ["thehive:case", "thehive:alert", "thehive:case_artifact"],
|
||||
"command": "Shuffle/shuffle.py",
|
||||
"baseConfig": "Shuffle",
|
||||
"configurationItems": [
|
||||
{
|
||||
"name": "url",
|
||||
"description": "The URL to your shuffle instance",
|
||||
"type": "string",
|
||||
"multi": false,
|
||||
"required": true,
|
||||
"defaultValue": "https://shuffler.io"
|
||||
},
|
||||
{
|
||||
"name": "api_key",
|
||||
"description": "The API key to your Shuffle user",
|
||||
"type": "string",
|
||||
"multi": false,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "verifyssl",
|
||||
"description": "Verify SSL certificate",
|
||||
"type": "boolean",
|
||||
"multi": false,
|
||||
"required": true,
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "workflow_id",
|
||||
"description": "The ID of the workflow to execute",
|
||||
"type": "string",
|
||||
"multi": false,
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
#encoding: utf-8
|
||||
|
||||
from cortexutils.responder import Responder
|
||||
import requests
|
||||
|
||||
class Shuffle(Responder):
|
||||
def __init__(self):
|
||||
Responder.__init__(self)
|
||||
self.api_key = self.get_param("config.api_key", "")
|
||||
self.url = self.get_param("config.url", "")
|
||||
self.workflow_id = self.get_param("config.workflow_id", "")
|
||||
self.verify = self.get_param('config.verifyssl', True, None)
|
||||
|
||||
def run(self):
|
||||
Responder.run(self)
|
||||
parsed_url = "%s/api/v1/workflows/%s/execute" % (self.url, self.workflow_id)
|
||||
headers = {
|
||||
"Authorization": "Bearer %s" % self.api_key,
|
||||
"User-Agent": "Cortex-Analyzer"
|
||||
}
|
||||
requests.post(parsed_url, headers=headers,verify=self.verify)
|
||||
|
||||
self.report({'message': 'message sent'})
|
||||
|
||||
if __name__ == '__main__':
|
||||
Shuffle().run()
|
@ -0,0 +1,2 @@
|
||||
cortexutils
|
||||
requests
|
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "Shuffle_webhook",
|
||||
"version": "1.0",
|
||||
"author": "@azgaviperr",
|
||||
"url": "https://github.com/frikky/shuffle",
|
||||
"license": "AGPL-V3",
|
||||
"description": "Execute a webhook in Shuffle",
|
||||
"dataTypeList": ["thehive:case", "thehive:alert", "thehive:case_artifact"],
|
||||
"command": "Shuffle_Webhook/shuffle_webhook.py",
|
||||
"baseConfig": "Shuffle_Webhook",
|
||||
"configurationItems": [
|
||||
{
|
||||
"name": "webhook_url",
|
||||
"description": "The URL to your shuffle instance",
|
||||
"type": "string",
|
||||
"multi": false,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "verifyssl",
|
||||
"description": "Verify SSL certificate",
|
||||
"type": "boolean",
|
||||
"multi": false,
|
||||
"required": true,
|
||||
"defaultValue": true
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python3
|
||||
#encoding: utf-8
|
||||
|
||||
from cortexutils.responder import Responder
|
||||
import requests
|
||||
|
||||
class Shuffle(Responder):
|
||||
def __init__(self):
|
||||
Responder.__init__(self)
|
||||
self.api_key = self.get_param("config.api_key", "")
|
||||
self.webhook_url = self.get_param("config.webhook_url", "")
|
||||
self.webhook_id = self.get_param("config.webhook_id", "")
|
||||
self.verify = self.get_param('config.verifyssl', True, None)
|
||||
self.data = self.get_param('data')
|
||||
|
||||
def run(self):
|
||||
Responder.run(self)
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
"User-Agent": "Cortex-Analyzer"
|
||||
}
|
||||
requests.post(self.webhook_url, headers=headers,verify=self.verify, json=self.data)
|
||||
|
||||
self.report({'message': 'message sent'})
|
||||
|
||||
if __name__ == '__main__':
|
||||
Shuffle().run()
|
19
shuffle/functions/extensions/elasticsearch/run.sh
Normal file
19
shuffle/functions/extensions/elasticsearch/run.sh
Normal file
@ -0,0 +1,19 @@
|
||||
#docker run -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ELASTICSEARCH_USERNAME=frikky -e ELASTICSEARCH_PASSWORD=likeme -e xpack.security.enabled=true docker.elastic.co/elasticsearch/elasticsearch:7.12.1
|
||||
#docker run -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.12.1
|
||||
#
|
||||
#
|
||||
#
|
||||
#echo "\nWaiting for 1.5 minute, then adding data"
|
||||
#sleep 90
|
||||
#echo "\nSlept 90 seconds: ADDING DATA"
|
||||
#curl -XPOST http://localhost:9200/_security/user/frikky -H "Content-Type: application/json" -d '{"enabled": true, "email": "frikky@shuffler.io"}'
|
||||
|
||||
#curl -XPOST -u frikky:likeme http://localhost:9200/samples/_doc -H "Content-Type: application/json" -d '{"src": "122.14.137.67", "dst": "103.35.191.16", "message": "alert", "md5": "CAEF973033E593C625FB2AA34F7026DC", "sha256": "DB1AEC5222075800EDA75D7205267569679B424E5C58A28102417F46D3B5790D", "hits": 0}'
|
||||
#echo
|
||||
#curl -XPOST -u frikky:likeme http://localhost:9200/samples/_doc -H "Content-Type: application/json" -d '{"src": "134.119.219.71", "dst": "103.35.191.41", "message": "alert", "md5": "9498FF82A64FF445398C8426ED63EA5B", "sha256": "8B2E701E91101955C73865589A4C72999AEABC11043F712E05FDB1C17C4AB19A", "hits": 0}'
|
||||
#
|
||||
#echo
|
||||
#curl -XPOST -u frikky:likeme http://localhost:9200/samples2/_doc -H "Content-Type: application/json" -d '{"src": "122.14.137.67", "dst": "103.35.191.16", "message": "alert", "md5": "CAEF973033E593C625FB2AA34F7026DC", "sha256": "DB1AEC5222075800EDA75D7205267569679B424E5C58A28102417F46D3B5790D"}'
|
||||
#echo
|
||||
#curl -XPOST -u frikky:likeme http://localhost:9200/samples2/_doc -H "Content-Type: application/json" -d '{"src": "134.119.219.71", "dst": "103.35.191.41", "message": "alert", "md5": "9498FF82A64FF445398C8426ED63EA5B", "sha256": "8B2E701E91101955C73865589A4C72999AEABC11043F712E05FDB1C17C4AB19A"}'
|
||||
#echo
|
23
shuffle/functions/extensions/k8s/shuffle/.helmignore
Normal file
23
shuffle/functions/extensions/k8s/shuffle/.helmignore
Normal file
@ -0,0 +1,23 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*.orig
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
24
shuffle/functions/extensions/k8s/shuffle/Chart.yaml
Normal file
24
shuffle/functions/extensions/k8s/shuffle/Chart.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
apiVersion: v2
|
||||
name: shuffle
|
||||
description: A Helm chart for Kubernetes
|
||||
|
||||
# A chart can be either an 'application' or a 'library' chart.
|
||||
#
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
#
|
||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.1.0
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "1.16.0"
|
22
shuffle/functions/extensions/k8s/shuffle/templates/NOTES.txt
Normal file
22
shuffle/functions/extensions/k8s/shuffle/templates/NOTES.txt
Normal file
@ -0,0 +1,22 @@
|
||||
1. Get the application URL by running these commands:
|
||||
{{- if .Values.ingress.enabled }}
|
||||
{{- range $host := .Values.ingress.hosts }}
|
||||
{{- range .paths }}
|
||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- else if contains "NodePort" .Values.service.type }}
|
||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "shuffle.fullname" . }})
|
||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||
echo http://$NODE_IP:$NODE_PORT
|
||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "shuffle.fullname" . }}'
|
||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "shuffle.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "shuffle.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
||||
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
||||
{{- end }}
|
@ -0,0 +1,62 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "shuffle.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "shuffle.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "shuffle.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "shuffle.labels" -}}
|
||||
helm.sh/chart: {{ include "shuffle.chart" . }}
|
||||
{{ include "shuffle.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "shuffle.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "shuffle.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "shuffle.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
{{- default (include "shuffle.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- default "default" .Values.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
@ -0,0 +1,253 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ .Values.name }}frontend
|
||||
namespace: {{ .Values.namespace | quote }}
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
service: shuffle
|
||||
app: shuffle-frontend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
service: shuffle
|
||||
app: shuffle-frontend
|
||||
spec:
|
||||
containers:
|
||||
- name: shuffle-frontend
|
||||
image: ghcr.io/frikky/shuffle-frontend:nightly
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
|
||||
env:
|
||||
- name: BACKEND_HOSTNAME
|
||||
value: backend-service
|
||||
- name: TZ
|
||||
value: Asia/Shanghai
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
hostPort: 3001
|
||||
- name: https
|
||||
containerPort: 443
|
||||
hostname: shuffle-frontend
|
||||
restartPolicy: Always
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ .Values.name }}backend
|
||||
namespace: {{ .Values.namespace | quote }}
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
service: shuffle
|
||||
app: shuffle-backend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
service: shuffle
|
||||
app: shuffle-backend
|
||||
spec:
|
||||
containers:
|
||||
- name: shuffle-backend
|
||||
image: ghcr.io/frikky/shuffle-backend:nightly
|
||||
env:
|
||||
- name: BACKEND_HOSTNAME
|
||||
value: "backend-service"
|
||||
- name: BACKEND_PORT
|
||||
value: "5001"
|
||||
- name: ENVIRONMENT_NAME
|
||||
value: "Shuffle"
|
||||
- name: HTTPS_PROXY
|
||||
- name: HTTP_PROXY
|
||||
- name: ORG_ID
|
||||
value: "Shuffle"
|
||||
- name: OUTER_HOSTNAME
|
||||
value: "backend-service"
|
||||
- name: SHUFFLE_APP_FORCE_UPDATE
|
||||
value: "false"
|
||||
- name: SHUFFLE_APP_HOTLOAD_FOLDER
|
||||
value: "/shuffle-apps"
|
||||
- name: SHUFFLE_APP_HOTLOAD_LOCATION
|
||||
value: "/shuffle-apps"
|
||||
- name: SHUFFLE_CONTAINER_AUTO_CLEANUP
|
||||
value: "false"
|
||||
- name: SHUFFLE_DEFAULT_APIKEY
|
||||
- name: SHUFFLE_DEFAULT_PASSWORD
|
||||
- name: SHUFFLE_DEFAULT_USERNAME
|
||||
- name: SHUFFLE_DOWNLOAD_AUTH_BRANCH
|
||||
- name: SHUFFLE_DOWNLOAD_AUTH_PASSWORD
|
||||
- name: SHUFFLE_DOWNLOAD_AUTH_USERNAME
|
||||
- name: SHUFFLE_DOWNLOAD_WORKFLOW_BRANCH
|
||||
- name: SHUFFLE_DOWNLOAD_WORKFLOW_LOCATION
|
||||
- name: SHUFFLE_DOWNLOAD_WORKFLOW_PASSWORD
|
||||
- name: SHUFFLE_DOWNLOAD_WORKFLOW_USERNAME
|
||||
- name: SHUFFLE_ELASTIC
|
||||
value: "true"
|
||||
- name: SHUFFLE_OPENSEARCH_APIKEY
|
||||
- name: SHUFFLE_OPENSEARCH_CERTIFICATE_FILE
|
||||
- name: SHUFFLE_OPENSEARCH_CLOUDID
|
||||
- name: SHUFFLE_OPENSEARCH_PASSWORD
|
||||
- name: SHUFFLE_OPENSEARCH_PROXY
|
||||
- name: SHUFFLE_OPENSEARCH_SKIPSSL_VERIFY
|
||||
value: "true"
|
||||
- name: SHUFFLE_OPENSEARCH_URL
|
||||
value: http://opensearch-service:9200
|
||||
- name: SHUFFLE_OPENSEARCH_USERNAME
|
||||
value: ""
|
||||
- name: SHUFFLE_PASS_APP_PROXY
|
||||
value: "FALSE"
|
||||
- name: SHUFFLE_PASS_WORKER_PROXY
|
||||
value: "FALSE"
|
||||
volumeMounts:
|
||||
- mountPath: /var/run/docker.sock
|
||||
name: docker-sock
|
||||
- mountPath: /shuffle-apps
|
||||
name: shuffle-app-hotload-location
|
||||
- mountPath: /shuffle-files
|
||||
name: shuffle-file-location
|
||||
hostname: shuffle-backend
|
||||
volumes:
|
||||
- name: docker-sock
|
||||
hostPath:
|
||||
path: /var/run/docker.sock
|
||||
- name: shuffle-app-hotload-location
|
||||
hostPath:
|
||||
path: /data/kubernetes/shuffle-apps
|
||||
type: DirectoryOrCreate
|
||||
- name: shuffle-file-location
|
||||
hostPath:
|
||||
path: /data/kubernetes/shuffle-files
|
||||
type: DirectoryOrCreate
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ .Values.name }}orborus
|
||||
namespace: {{ .Values.namespace | quote }}
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
service: shuffle
|
||||
app: shuffle-orborus
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
service: shuffle
|
||||
app: shuffle-orborus
|
||||
spec:
|
||||
containers:
|
||||
- name: shuffle-orborus
|
||||
image: ghcr.io/frikky/shuffle-orborus:nightly
|
||||
env:
|
||||
- name: RUNNING_MODE
|
||||
value: kubernetes
|
||||
- name: BASE_URL
|
||||
value: http://backend-service:5001
|
||||
- name: CLEANUP
|
||||
value: "false"
|
||||
- name: DOCKER_API_VERSION
|
||||
value: "1.40"
|
||||
- name: ENVIRONMENT_NAME
|
||||
value: Shuffle
|
||||
- name: HTTPS_PROXY
|
||||
- name: HTTP_PROXY
|
||||
- name: ORG_ID
|
||||
value: Shuffle
|
||||
- name: SHUFFLE_APP_SDK_VERSION
|
||||
value: 0.8.97
|
||||
- name: SHUFFLE_BASE_IMAGE_NAME
|
||||
value: frikky
|
||||
- name: SHUFFLE_BASE_IMAGE_REGISTRY
|
||||
value: ghcr.io
|
||||
- name: SHUFFLE_BASE_IMAGE_TAG_SUFFIX
|
||||
value: "-0.8.80"
|
||||
- name: SHUFFLE_ORBORUS_EXECUTION_TIMEOUT
|
||||
value: "600"
|
||||
- name: SHUFFLE_ORBORUS_EXECUTION_CONCURRENCY
|
||||
value: "50"
|
||||
- name: SHUFFLE_PASS_WORKER_PROXY
|
||||
value: "TRUE"
|
||||
- name: SHUFFLE_WORKER_VERSION
|
||||
value: nightly
|
||||
- name: TZ
|
||||
value: Asia/Shanghai
|
||||
volumeMounts:
|
||||
- mountPath: /var/run/docker.sock
|
||||
name: docker-sock
|
||||
hostname: shuffle-orborus
|
||||
volumes:
|
||||
- name: docker-sock
|
||||
hostPath:
|
||||
path: /var/run/docker.sock
|
||||
#---
|
||||
#apiVersion: apps/v1
|
||||
#kind: Deployment
|
||||
#metadata:
|
||||
# name: {{ .Values.name }}opensearch
|
||||
# namespace: {{ .Values.namespace | quote }}
|
||||
#spec:
|
||||
# replicas: 1
|
||||
# selector:
|
||||
# matchLabels:
|
||||
# service: shuffle
|
||||
# app: shuffle-opensearch
|
||||
# template:
|
||||
# metadata:
|
||||
# labels:
|
||||
# service: shuffle
|
||||
# app: shuffle-opensearch
|
||||
# spec:
|
||||
# nodeSelector:
|
||||
# node.bdlab-venus.com/opensearch: available
|
||||
# initContainers:
|
||||
# - name: permissions-fix
|
||||
# image: frikky/busybox
|
||||
# #volumeMounts:
|
||||
# # - name: opensearch-claim0
|
||||
# # mountPath: /usr/share/elasticsearch/data
|
||||
# command: [ 'chown' ]
|
||||
# args: [ '1000:1000', '/usr/share/elasticsearch/data' ]
|
||||
# containers:
|
||||
# - name: shuffle-opensearch
|
||||
# image: opensearchproject/opensearch:1.0.1
|
||||
# env:
|
||||
# - name: TZ
|
||||
# value: Asia/Shanghai
|
||||
# - name: bootstrap.memory_lock
|
||||
# value: "false"
|
||||
# - name: OPENSEARCH_JAVA_OPTS
|
||||
# value: "-Xms1024m -Xmx1024m"
|
||||
# - name: opendistro_security.disabled
|
||||
# value: "true"
|
||||
# - name: cluster.routing.allocation.disk.threshold_enabled
|
||||
# value: "false"
|
||||
# - name: cluster.name
|
||||
# value: shuffle-cluster
|
||||
# - name: node.name
|
||||
# value: opensearch-service
|
||||
# - name: discovery.seed_hosts
|
||||
# value: opensearch-service
|
||||
# - name: cluster.initial_master_nodes
|
||||
# value: opensearch-service
|
||||
# volumeMounts:
|
||||
# - mountPath: /usr/share/opensearch/data
|
||||
# name: opensearch-claim0
|
||||
#volumes:
|
||||
# - name: opensearch-claim0
|
||||
# persistentVolumeClaim:
|
||||
# claimName: opensearch-claim0
|
||||
# volumeMounts:
|
||||
# - mountPath: /usr/share/opensearch/data
|
||||
# readOnly: true
|
||||
# name: db-location
|
||||
# volumes:
|
||||
# - name: db-location
|
||||
# hostPath:
|
||||
# path: /data/kubernetes/shuffle-opensearch
|
||||
# type: DirectoryOrCreate
|
28
shuffle/functions/extensions/k8s/shuffle/templates/hpa.yaml
Normal file
28
shuffle/functions/extensions/k8s/shuffle/templates/hpa.yaml
Normal file
@ -0,0 +1,28 @@
|
||||
{{- if .Values.autoscaling.enabled }}
|
||||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ include "shuffle.fullname" . }}
|
||||
labels:
|
||||
{{- include "shuffle.labels" . | nindent 4 }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ include "shuffle.fullname" . }}
|
||||
minReplicas: {{ .Values.autoscaling.minReplicas }}
|
||||
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
|
||||
metrics:
|
||||
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- end }}
|
@ -0,0 +1,61 @@
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $fullName := include "shuffle.fullname" . -}}
|
||||
{{- $svcPort := .Values.service.port -}}
|
||||
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
|
||||
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
|
||||
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
{{- else -}}
|
||||
apiVersion: extensions/v1beta1
|
||||
{{- end }}
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
labels:
|
||||
{{- include "shuffle.labels" . | nindent 4 }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
|
||||
ingressClassName: {{ .Values.ingress.className }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
|
||||
pathType: {{ .pathType }}
|
||||
{{- end }}
|
||||
backend:
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ $fullName }}
|
||||
port:
|
||||
number: {{ $svcPort }}
|
||||
{{- else }}
|
||||
serviceName: {{ $fullName }}
|
||||
servicePort: {{ $svcPort }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
@ -0,0 +1,24 @@
|
||||
#apiVersion: v1
|
||||
#kind: PersistentVolume
|
||||
#metadata:
|
||||
# name: opensearch-claim0
|
||||
# labels:
|
||||
# app: opensearch-claim0
|
||||
#spec:
|
||||
# capacity:
|
||||
# storage: "10G"
|
||||
# volumeMode: Filesystem
|
||||
# persistentVolumeReclaimPolicy: Retain
|
||||
# storageClassName: local-storage
|
||||
# accessModes:
|
||||
# - "ReadWriteOnce"
|
||||
# local:
|
||||
# path: "/data/kubernetes/shuffle-opensearch"
|
||||
# nodeAffinity:
|
||||
# required:
|
||||
# nodeSelectorTerms:
|
||||
# - matchExpressions:
|
||||
# - key: node.dollar.com/opensearch
|
||||
# operator: In
|
||||
# values:
|
||||
# - available
|
@ -0,0 +1,17 @@
|
||||
#apiVersion: v1
|
||||
#kind: PersistentVolumeClaim
|
||||
#metadata:
|
||||
# name: opensearch-claim0
|
||||
# namespace: {{ .Values.namespace }}
|
||||
# labels:
|
||||
# app: opensearch-claim0
|
||||
#spec:
|
||||
# selector:
|
||||
# matchLabels:
|
||||
# app: opensearch-claim0
|
||||
# accessModes:
|
||||
# - ReadWriteOnce
|
||||
# storageClassName: local-storage
|
||||
# resources:
|
||||
# requests:
|
||||
# storage: 5Gi
|
@ -0,0 +1,52 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: backend-service
|
||||
namespace: {{ .Values.namespace | quote }}
|
||||
spec:
|
||||
ports:
|
||||
- name: "5001"
|
||||
port: 5001
|
||||
targetPort: 5001
|
||||
selector:
|
||||
app: shuffle-backend
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: frontend-service
|
||||
namespace: {{ .Values.namespace | quote }}
|
||||
spec:
|
||||
type: NodePort
|
||||
externalTrafficPolicy: Local
|
||||
ports:
|
||||
- name: "3001"
|
||||
port: 3001
|
||||
nodePort: 3001
|
||||
targetPort: 80
|
||||
- name: "3443"
|
||||
port: 3443
|
||||
nodePort: 3443
|
||||
targetPort: 443
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: shuffle-frontend
|
||||
|
||||
#---
|
||||
#apiVersion: v1
|
||||
#kind: Service
|
||||
#metadata:
|
||||
# name: opensearch-service
|
||||
# namespace: {{ .Values.namespace | quote }}
|
||||
#spec:
|
||||
# type: NodePort
|
||||
# externalTrafficPolicy: Local
|
||||
# ports:
|
||||
# - name: "9200"
|
||||
# port: 9200
|
||||
# targetPort: 9200
|
||||
# nodePort: 9200
|
||||
# protocol: TCP
|
||||
# selector:
|
||||
# app: shuffle-opensearch
|
@ -0,0 +1,12 @@
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "shuffle.serviceAccountName" . }}
|
||||
labels:
|
||||
{{- include "shuffle.labels" . | nindent 4 }}
|
||||
{{- with .Values.serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: "{{ include "shuffle.fullname" . }}-test-connection"
|
||||
labels:
|
||||
{{- include "shuffle.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
spec:
|
||||
containers:
|
||||
- name: wget
|
||||
image: busybox
|
||||
command: ['wget']
|
||||
args: ['{{ include "shuffle.fullname" . }}:{{ .Values.service.port }}']
|
||||
restartPolicy: Never
|
82
shuffle/functions/extensions/k8s/shuffle/values.yaml
Normal file
82
shuffle/functions/extensions/k8s/shuffle/values.yaml
Normal file
@ -0,0 +1,82 @@
|
||||
# Default values for shuffle.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: nginx
|
||||
pullPolicy: IfNotPresent
|
||||
# Overrides the image tag whose default is the chart appVersion.
|
||||
tag: ""
|
||||
|
||||
imagePullSecrets: []
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
create: true
|
||||
# Annotations to add to the service account
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
name: ""
|
||||
|
||||
podAnnotations: {}
|
||||
|
||||
podSecurityContext: {}
|
||||
# fsGroup: 2000
|
||||
|
||||
securityContext: {}
|
||||
# capabilities:
|
||||
# drop:
|
||||
# - ALL
|
||||
# readOnlyRootFilesystem: true
|
||||
# runAsNonRoot: true
|
||||
# runAsUser: 1000
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 80
|
||||
|
||||
ingress:
|
||||
enabled: false
|
||||
className: ""
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
- host: chart-example.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
tls: []
|
||||
# - secretName: chart-example-tls
|
||||
# hosts:
|
||||
# - chart-example.local
|
||||
|
||||
resources: {}
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 1
|
||||
maxReplicas: 100
|
||||
targetCPUUtilizationPercentage: 80
|
||||
# targetMemoryUtilizationPercentage: 80
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
23
shuffle/functions/extensions/misp/Dockerfile
Normal file
23
shuffle/functions/extensions/misp/Dockerfile
Normal file
@ -0,0 +1,23 @@
|
||||
FROM python:3.9.4-alpine as base
|
||||
|
||||
FROM base as builder
|
||||
|
||||
RUN mkdir /install
|
||||
WORKDIR /install
|
||||
|
||||
FROM base
|
||||
RUN apk add g++
|
||||
|
||||
COPY --from=builder /install /usr/local
|
||||
COPY requirements.txt /requirements.txt
|
||||
RUN pip3 install -r /requirements.txt
|
||||
|
||||
|
||||
RUN mkdir /app
|
||||
WORKDIR /app
|
||||
COPY requirements.txt /app/requirements.txt
|
||||
RUN python3 -m pip install -r /app/requirements.txt
|
||||
|
||||
COPY sub.py /app/sub.py
|
||||
|
||||
CMD ["python3", "sub.py"]
|
9
shuffle/functions/extensions/misp/docker-compose.yml
Normal file
9
shuffle/functions/extensions/misp/docker-compose.yml
Normal file
@ -0,0 +1,9 @@
|
||||
version: '3'
|
||||
services:
|
||||
zmq:
|
||||
image: ghcr.io/frikky/shuffle-zmq:latest
|
||||
environment:
|
||||
- ZMQ_HOSTNAME=localhost
|
||||
- ZMQ_PORT=50000
|
||||
- ZMQ_FORWARD_URL=https://shuffler.io/api/v1/hooks/webhook_e09bea36-9976-1421-82bc-b8764ca83c1e
|
||||
restart: unless-stopped
|
2
shuffle/functions/extensions/misp/requirements.txt
Normal file
2
shuffle/functions/extensions/misp/requirements.txt
Normal file
@ -0,0 +1,2 @@
|
||||
pyzmq
|
||||
requests
|
57
shuffle/functions/extensions/misp/sub.py
Normal file
57
shuffle/functions/extensions/misp/sub.py
Normal file
@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
print("Running imports")
|
||||
import sys
|
||||
import zmq
|
||||
import json
|
||||
import time
|
||||
import pprint
|
||||
import os
|
||||
import sys
|
||||
import requests
|
||||
|
||||
forward_url = os.getenv("ZMQ_FORWARD_URL", "")
|
||||
print("Checking forward url (ZMQ_FORWARD_URL): %s" % forward_url)
|
||||
def handle_hook(data):
|
||||
ret = requests.post(forward_url, json=data)
|
||||
print(ret.text)
|
||||
print(ret.status_code)
|
||||
|
||||
def main():
|
||||
host = os.getenv("ZMQ_HOST", "localhost")
|
||||
port = os.getenv("ZMQ_PORT", "50000")
|
||||
|
||||
if len(forward_url) == 0:
|
||||
print("Failed to start - define ZMQ_FORWARD_URL for webhook forwarder")
|
||||
exit(0)
|
||||
|
||||
print("Starting connection setup to %s:%s" % (host, port))
|
||||
context = zmq.Context()
|
||||
socket = context.socket(zmq.SUB)
|
||||
socket.connect ("tcp://%s:%s" % (host, port))
|
||||
socket.setsockopt(zmq.SUBSCRIBE, b'')
|
||||
|
||||
poller = zmq.Poller()
|
||||
poller.register(socket, zmq.POLLIN)
|
||||
|
||||
print("Starting zmq check for %s:%s" % (host, port))
|
||||
while True:
|
||||
socks = dict(poller.poll(timeout=None))
|
||||
if socket in socks and socks[socket] == zmq.POLLIN:
|
||||
message = socket.recv()
|
||||
#print(message)
|
||||
topic, s, m = message.decode('utf-8').partition(" ")
|
||||
|
||||
d = json.loads(m)
|
||||
try:
|
||||
# print test if you want status (heartbeat)
|
||||
test = d["status"]
|
||||
except KeyError:
|
||||
handle_hook(d)
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("In init ")
|
||||
main()
|
11
shuffle/functions/extensions/scripts/disable_disk_check.sh
Normal file
11
shuffle/functions/extensions/scripts/disable_disk_check.sh
Normal file
@ -0,0 +1,11 @@
|
||||
curl -XPUT -u admin:admin https://localhost:9200/_cluster/settings -H "Content-Type:application/json" -k -d \
|
||||
'{
|
||||
"transient": {
|
||||
"cluster.routing.allocation.disk.threshold_enabled": false
|
||||
}
|
||||
}'
|
||||
|
||||
curl -XPUT -u admin:admin https://localhost:9200/_all/_settings -H "Content-Type: application/json" -k -d \
|
||||
'{
|
||||
"index.blocks.read_only_allow_delete": null
|
||||
}'
|
1
shuffle/functions/extensions/swarm/.gitignore
vendored
Normal file
1
shuffle/functions/extensions/swarm/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
shuffle-database/nodes
|
131
shuffle/functions/extensions/swarm/docker-compose.yml
Normal file
131
shuffle/functions/extensions/swarm/docker-compose.yml
Normal file
@ -0,0 +1,131 @@
|
||||
version: '3.4'
|
||||
services:
|
||||
backend:
|
||||
image: ghcr.io/frikky/shuffle-backend:nightly
|
||||
#hostname: shuffle-backend
|
||||
environment:
|
||||
BACKEND_HOSTNAME: backend
|
||||
OUTER_HOSTNAME: backend
|
||||
BACKEND_PORT: '5001'
|
||||
HTTPS_PROXY: ''
|
||||
HTTP_PROXY: ''
|
||||
SHUFFLE_APP_DOWNLOAD_LOCATION: https://github.com/frikky/shuffle-apps
|
||||
SHUFFLE_APP_FORCE_UPDATE: 'false'
|
||||
SHUFFLE_APP_HOTLOAD_FOLDER: /shuffle-apps
|
||||
SHUFFLE_APP_HOTLOAD_LOCATION: ./shuffle-apps
|
||||
DATASTORE_EMULATOR_HOST: "shuffle-database:8000"
|
||||
DOCKER_API_VERSION: '1.40'
|
||||
SHUFFLE_BASE_IMAGE_NAME: frikky
|
||||
SHUFFLE_BASE_IMAGE_REGISTRY: ghcr.io
|
||||
SHUFFLE_BASE_IMAGE_TAG_SUFFIX: '-0.9.30'
|
||||
SHUFFLE_CONTAINER_AUTO_CLEANUP: 'true'
|
||||
SHUFFLE_DEFAULT_APIKEY: ''
|
||||
SHUFFLE_FILE_LOCATION: /shuffle-files
|
||||
SHUFFLE_OPENSEARCH_APIKEY: ''
|
||||
SHUFFLE_OPENSEARCH_CERTIFICATE_FILE: ''
|
||||
SHUFFLE_OPENSEARCH_CLOUDID: ''
|
||||
SHUFFLE_OPENSEARCH_PROXY: ''
|
||||
SHUFFLE_OPENSEARCH_SKIPSSL_VERIFY: 'true'
|
||||
SHUFFLE_OPENSEARCH_URL: http://opensearch:9200
|
||||
SHUFFLE_PASS_APP_PROXY: 'FALSE'
|
||||
SHUFFLE_PASS_WORKER_PROXY: 'TRUE'
|
||||
SHUFFLE_ELASTIC: 'true'
|
||||
#SHUFFLE_ENCRYPTION_MODIFIER:
|
||||
ports:
|
||||
- "5001:5001"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./shuffle-apps:/shuffle-apps
|
||||
- ./shuffle-files:/shuffle-files
|
||||
networks:
|
||||
- shuffle_prod
|
||||
#- reverseproxy
|
||||
depends_on:
|
||||
- opensearch
|
||||
logging:
|
||||
driver: json-file
|
||||
frontend:
|
||||
image: ghcr.io/frikky/shuffle-frontend:nightly
|
||||
healthcheck:
|
||||
test: curl -fs http://localhost:80 || exit 1
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
ports:
|
||||
- "3001:80"
|
||||
- "3443:443"
|
||||
networks:
|
||||
- shuffle_prod
|
||||
#- reverseproxy
|
||||
environment:
|
||||
- "BACKEND_HOSTNAME=backend"
|
||||
depends_on:
|
||||
- backend
|
||||
deploy:
|
||||
update_config:
|
||||
order: start-first
|
||||
opensearch:
|
||||
image: opensearchproject/opensearch:1.1.0
|
||||
healthcheck:
|
||||
test: curl -fs http://localhost:9200/_cat/health || exit 1
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
environment:
|
||||
- bootstrap.memory_lock=false
|
||||
- "OPENSEARCH_JAVA_OPTS=-Xms1024m -Xmx1024m" # minimum and maximum Java heap size, recommend setting both to 50% of system RAM
|
||||
- plugins.security.disabled=true
|
||||
- cluster.routing.allocation.disk.threshold_enabled=false
|
||||
- cluster.name=shuffle-cluster
|
||||
- node.name=opensearch
|
||||
- discovery.seed_hosts=opensearch
|
||||
- cluster.initial_master_nodes=opensearch
|
||||
- node.store.allow_mmap=false
|
||||
volumes:
|
||||
- ./shuffle-database:/usr/share/opensearch/data:rw
|
||||
networks:
|
||||
- shuffle_prod
|
||||
#- reverseproxy
|
||||
logging:
|
||||
driver: json-file
|
||||
|
||||
orborus:
|
||||
image: ghcr.io/frikky/shuffle-orborus:nightly
|
||||
#hostname: shuffle-orborus
|
||||
environment:
|
||||
#SHUFFLE_WORKER_VERSION: nightly
|
||||
SHUFFLE_APP_SDK_VERSION: 0.8.97
|
||||
SHUFFLE_WORKER_VERSION: nightly
|
||||
BASE_URL: http://backend:5001
|
||||
#BASE_URL: http://192.168.86.37:5001
|
||||
CLEANUP: 'true'
|
||||
DOCKER_API_VERSION: '1.40'
|
||||
ENVIRONMENT_NAME: Shuffle
|
||||
HTTPS_PROXY: ''
|
||||
HTTP_PROXY: ''
|
||||
ORG_ID: Shuffle
|
||||
SHUFFLE_BASE_IMAGE_NAME: frikky
|
||||
SHUFFLE_BASE_IMAGE_REGISTRY: ghcr.io
|
||||
SHUFFLE_BASE_IMAGE_TAG_SUFFIX: -0.8.80
|
||||
SHUFFLE_ORBORUS_EXECUTION_CONCURRENCY: '50'
|
||||
SHUFFLE_ORBORUS_EXECUTION_TIMEOUT: '800'
|
||||
SHUFFLE_PASS_APP_PROXY: 'FALSE'
|
||||
SHUFFLE_PASS_WORKER_PROXY: 'TRUE'
|
||||
SHUFFLE_SCALE_REPLICAS: 5
|
||||
SHUFFLE_SWARM_NETWORK_NAME: shuffle_prod
|
||||
SHUFFLE_SWARM_CONFIG: "run"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
networks:
|
||||
- shuffle_prod
|
||||
#- reverseproxy
|
||||
logging:
|
||||
driver: json-file
|
||||
|
||||
networks:
|
||||
shuffle_prod:
|
||||
driver: overlay
|
||||
external: true
|
||||
#reverseproxy:
|
||||
# driver: overlay
|
||||
# #external: true
|
1
shuffle/functions/extensions/swarm/network.sh
Normal file
1
shuffle/functions/extensions/swarm/network.sh
Normal file
@ -0,0 +1 @@
|
||||
docker network create -d overlay shuffle_prod
|
39
shuffle/functions/extensions/swarm/orborus.yml
Normal file
39
shuffle/functions/extensions/swarm/orborus.yml
Normal file
@ -0,0 +1,39 @@
|
||||
version: '3.4'
|
||||
services:
|
||||
orborus:
|
||||
image: ghcr.io/frikky/shuffle-orborus:nightly
|
||||
#hostname: shuffle-orborus
|
||||
environment:
|
||||
#SHUFFLE_WORKER_VERSION: nightly
|
||||
SHUFFLE_APP_SDK_VERSION: 0.8.97
|
||||
SHUFFLE_WORKER_VERSION: nightly
|
||||
BASE_URL: http://<BACKEND>:5001
|
||||
#BASE_URL: http://192.168.86.37:5001
|
||||
CLEANUP: 'true'
|
||||
DOCKER_API_VERSION: '1.40'
|
||||
ENVIRONMENT_NAME: Shuffle
|
||||
HTTPS_PROXY: ''
|
||||
HTTP_PROXY: ''
|
||||
ORG_ID: Shuffle
|
||||
SHUFFLE_BASE_IMAGE_NAME: frikky
|
||||
SHUFFLE_BASE_IMAGE_REGISTRY: ghcr.io
|
||||
SHUFFLE_BASE_IMAGE_TAG_SUFFIX: -0.8.80
|
||||
SHUFFLE_ORBORUS_EXECUTION_CONCURRENCY: '50'
|
||||
SHUFFLE_ORBORUS_EXECUTION_TIMEOUT: '800'
|
||||
SHUFFLE_PASS_APP_PROXY: 'FALSE'
|
||||
SHUFFLE_PASS_WORKER_PROXY: 'TRUE'
|
||||
SHUFFLE_SCALE_REPLICAS: 5
|
||||
SHUFFLE_SWARM_NETWORK_NAME: shuffle_prod
|
||||
SHUFFLE_SWARM_CONFIG: "run"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
networks:
|
||||
- shuffle_prod
|
||||
#- reverseproxy
|
||||
logging:
|
||||
driver: json-file
|
||||
|
||||
networks:
|
||||
shuffle_prod:
|
||||
driver: overlay
|
||||
external: true
|
4
shuffle/functions/extensions/swarm/run.sh
Normal file
4
shuffle/functions/extensions/swarm/run.sh
Normal file
@ -0,0 +1,4 @@
|
||||
docker swarm init
|
||||
chown 1000:1000 -R shuffle-database/
|
||||
docker network create -d overlay shuffle_prod
|
||||
docker stack deploy --compose-file=docker-compose.yml shuffle_swarm
|
4
shuffle/functions/extensions/swarm/run_orborus.sh
Normal file
4
shuffle/functions/extensions/swarm/run_orborus.sh
Normal file
@ -0,0 +1,4 @@
|
||||
docker swarm init
|
||||
chown 1000:1000 -R shuffle-database/
|
||||
docker network create -d overlay shuffle_prod
|
||||
docker stack deploy --compose-file=orborus.yml shuffle_orborus
|
0
shuffle/functions/extensions/swarm/shuffle-apps/tmp
Normal file
0
shuffle/functions/extensions/swarm/shuffle-apps/tmp
Normal file
3
shuffle/functions/extensions/swarm/stop.sh
Normal file
3
shuffle/functions/extensions/swarm/stop.sh
Normal file
@ -0,0 +1,3 @@
|
||||
docker stack rm shuffle_swarm
|
||||
|
||||
#
|
36
shuffle/functions/extensions/wazuh/custom-shuffle
Normal file
36
shuffle/functions/extensions/wazuh/custom-shuffle
Normal file
@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
# Created by Shuffle, AS. <frikky@shuffler.io>.
|
||||
|
||||
WPYTHON_BIN="framework/python/bin/python3"
|
||||
|
||||
SCRIPT_PATH_NAME="$0"
|
||||
|
||||
DIR_NAME="$(cd $(dirname ${SCRIPT_PATH_NAME}); pwd -P)"
|
||||
SCRIPT_NAME="$(basename ${SCRIPT_PATH_NAME})"
|
||||
|
||||
case ${DIR_NAME} in
|
||||
*/active-response/bin | */wodles*)
|
||||
if [ -z "${WAZUH_PATH}" ]; then
|
||||
WAZUH_PATH="$(cd ${DIR_NAME}/../..; pwd)"
|
||||
fi
|
||||
|
||||
PYTHON_SCRIPT="${DIR_NAME}/${SCRIPT_NAME}.py"
|
||||
;;
|
||||
*/bin)
|
||||
if [ -z "${WAZUH_PATH}" ]; then
|
||||
WAZUH_PATH="$(cd ${DIR_NAME}/..; pwd)"
|
||||
fi
|
||||
|
||||
PYTHON_SCRIPT="${WAZUH_PATH}/framework/scripts/${SCRIPT_NAME}.py"
|
||||
;;
|
||||
*/integrations)
|
||||
if [ -z "${WAZUH_PATH}" ]; then
|
||||
WAZUH_PATH="$(cd ${DIR_NAME}/..; pwd)"
|
||||
fi
|
||||
|
||||
PYTHON_SCRIPT="${DIR_NAME}/${SCRIPT_NAME}.py"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
${WAZUH_PATH}/${WPYTHON_BIN} ${PYTHON_SCRIPT} "$@"
|
206
shuffle/functions/extensions/wazuh/custom-shuffle.py
Normal file
206
shuffle/functions/extensions/wazuh/custom-shuffle.py
Normal file
@ -0,0 +1,206 @@
|
||||
#!/usr/bin/env python3
|
||||
# Created by Shuffle, AS. <frikky@shuffler.io>.
|
||||
# Based on the Slack integration using Webhooks
|
||||
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
import os
|
||||
|
||||
try:
|
||||
import requests
|
||||
from requests.auth import HTTPBasicAuth
|
||||
except Exception as e:
|
||||
print("No module 'requests' found. Install: pip install requests")
|
||||
sys.exit(1)
|
||||
|
||||
# ADD THIS TO ossec.conf configuration:
|
||||
# <integration>
|
||||
# <name>custom-shuffle</name>
|
||||
# <hook_url>http://<IP>:3001/api/v1/hooks/<HOOK_ID></hook_url>
|
||||
# <level>3</level>
|
||||
# <alert_format>json</alert_format>
|
||||
# </integration>
|
||||
|
||||
# Global vars
|
||||
debug_enabled = False
|
||||
pwd = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||
json_alert = {}
|
||||
now = time.strftime("%a %b %d %H:%M:%S %Z %Y")
|
||||
|
||||
# Set paths
|
||||
log_file = '{0}/logs/integrations.log'.format(pwd)
|
||||
|
||||
try:
|
||||
with open("/tmp/shuffle_start.txt", "w+") as tmp:
|
||||
tmp.write("Script started")
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def main(args):
|
||||
debug("# Starting")
|
||||
|
||||
# Read args
|
||||
alert_file_location = args[1]
|
||||
webhook = args[3]
|
||||
|
||||
debug("# Webhook")
|
||||
debug(webhook)
|
||||
|
||||
debug("# File location")
|
||||
debug(alert_file_location)
|
||||
|
||||
# Load alert. Parse JSON object.
|
||||
try:
|
||||
with open(alert_file_location) as alert_file:
|
||||
json_alert = json.load(alert_file)
|
||||
except:
|
||||
debug("# Alert file %s doesn't exist" % alert_file_location)
|
||||
|
||||
debug("# Processing alert")
|
||||
try:
|
||||
debug(json_alert)
|
||||
except Exception as e:
|
||||
debug("Failed getting json_alert %s" % e)
|
||||
sys.exit(1)
|
||||
|
||||
debug("# Generating message")
|
||||
msg = generate_msg(json_alert)
|
||||
if isinstance(msg, str):
|
||||
if len(msg) == 0:
|
||||
return
|
||||
debug(msg)
|
||||
|
||||
debug("# Sending message")
|
||||
|
||||
try:
|
||||
with open("/tmp/shuffle_end.txt", "w+") as tmp:
|
||||
tmp.write("Script done pre-msg sending")
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
send_msg(msg, webhook)
|
||||
|
||||
|
||||
def debug(msg):
|
||||
if debug_enabled:
|
||||
msg = "{0}: {1}\n".format(now, msg)
|
||||
print(msg)
|
||||
f = open(log_file, "a")
|
||||
f.write(msg)
|
||||
f.close()
|
||||
|
||||
# Skips container kills to stop self-recursion
|
||||
def filter_msg(alert):
|
||||
# These are things that recursively happen because Shuffle starts Docker containers
|
||||
skip = ["87924", "87900", "87901", "87902", "87903", "87904", "86001", "86002", "86003", "87932", "80710", "87929", "87928", "5710"]
|
||||
if alert["rule"]["id"] in skip:
|
||||
return False
|
||||
|
||||
#try:
|
||||
# if "docker" in alert["rule"]["description"].lower() and "
|
||||
#msg['text'] = alert.get('full_log')
|
||||
#except:
|
||||
# pass
|
||||
#msg['title'] = alert['rule']['description'] if 'description' in alert['rule'] else "N/A"
|
||||
|
||||
return True
|
||||
|
||||
def generate_msg(alert):
|
||||
if not filter_msg(alert):
|
||||
print("Skipping rule %s" % alert["rule"]["id"])
|
||||
return ""
|
||||
|
||||
level = alert['rule']['level']
|
||||
|
||||
if (level <= 4):
|
||||
severity = 1
|
||||
elif (level >= 5 and level <= 7):
|
||||
severity = 2
|
||||
else:
|
||||
severity = 3
|
||||
|
||||
msg = {}
|
||||
msg['severity'] = severity
|
||||
msg['pretext'] = "WAZUH Alert"
|
||||
msg['title'] = alert['rule']['description'] if 'description' in alert['rule'] else "N/A"
|
||||
msg['text'] = alert.get('full_log')
|
||||
msg['rule_id'] = alert["rule"]["id"]
|
||||
msg['timestamp'] = alert["timestamp"]
|
||||
msg['id'] = alert['id']
|
||||
msg["all_fields"] = alert
|
||||
|
||||
#msg['fields'] = []
|
||||
# msg['fields'].append({
|
||||
# "title": "Agent",
|
||||
# "value": "({0}) - {1}".format(
|
||||
# alert['agent']['id'],
|
||||
# alert['agent']['name']
|
||||
# ),
|
||||
# })
|
||||
#if 'agentless' in alert:
|
||||
# msg['fields'].append({
|
||||
# "title": "Agentless Host",
|
||||
# "value": alert['agentless']['host'],
|
||||
# })
|
||||
|
||||
#msg['fields'].append({"title": "Location", "value": alert['location']})
|
||||
#msg['fields'].append({
|
||||
# "title": "Rule ID",
|
||||
# "value": "{0} _(Level {1})_".format(alert['rule']['id'], level),
|
||||
#})
|
||||
|
||||
#attach = {'attachments': [msg]}
|
||||
|
||||
return json.dumps(msg)
|
||||
|
||||
|
||||
def send_msg(msg, url):
|
||||
debug("# In send msg")
|
||||
headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'}
|
||||
res = requests.post(url, data=msg, headers=headers, verify=False)
|
||||
debug("# After send msg: %s" % res)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
# Read arguments
|
||||
bad_arguments = False
|
||||
if len(sys.argv) >= 4:
|
||||
msg = '{0} {1} {2} {3} {4}'.format(
|
||||
now,
|
||||
sys.argv[1],
|
||||
sys.argv[2],
|
||||
sys.argv[3],
|
||||
sys.argv[4] if len(sys.argv) > 4 else '',
|
||||
)
|
||||
#debug_enabled = (len(sys.argv) > 4 and sys.argv[4] == 'debug')
|
||||
debug_enabled = True
|
||||
else:
|
||||
msg = '{0} Wrong arguments'.format(now)
|
||||
bad_arguments = True
|
||||
|
||||
# Logging the call
|
||||
try:
|
||||
f = open(log_file, 'a')
|
||||
except:
|
||||
f = open(log_file, 'w+')
|
||||
f.write("")
|
||||
f.close()
|
||||
|
||||
f = open(log_file, 'a')
|
||||
f.write(msg + '\n')
|
||||
f.close()
|
||||
|
||||
if bad_arguments:
|
||||
debug("# Exiting: Bad arguments. Inputted: %s" % sys.argv)
|
||||
sys.exit(1)
|
||||
|
||||
# Main function
|
||||
main(sys.argv)
|
||||
|
||||
except Exception as e:
|
||||
debug(str(e))
|
||||
raise
|
6
shuffle/functions/extensions/wazuh/ossec.conf
Normal file
6
shuffle/functions/extensions/wazuh/ossec.conf
Normal file
@ -0,0 +1,6 @@
|
||||
<integration>
|
||||
<name>custom-shuffle</name>
|
||||
<level>9</level>
|
||||
<hook_url>http://<IP>:<PORT>/api/v1/hooks/webhook_hookid</hook_url>
|
||||
<alert_format>json</alert_format>
|
||||
</integration>
|
Reference in New Issue
Block a user