Shuffle#
Shuffle is an Open Source SOAR I really appreciate as it does focus on CyberSecurity.
To know more about it go there: https://medium.com/shuffle-automation
Or there : Official Website
Hi Frikky !!! Hopefully, you will appreciate what you are seing here ^^
Preparaton#
Setup data locations#
Setup Docker Swarm#
Deploying Portainer and the Portainer Agent to manage a Swarm cluster is easy! You can directly deploy Portainer as a service in your Docker cluster. Note that this method will automatically deploy a single instance of the Portainer Server, and deploy the Portainer Agent as a global service on every node in your cluster.
# mkdir -p /mnt/configuration_data/compose_files/SOAR
Customisation#
At the time of this writing I may be the only one shufflying around with swarm :p So there is not yet a stack ready compose file.
Let's create one /mnt/configuration_data/compose_files/SOAR/shuffle.stack.yml
version: '3.8'
services:
backend:
image: ghcr.io/frikky/shuffle-backend:latest
environment:
BACKEND_HOSTNAME: backend
BACKEND_PORT: '5001'
DATASTORE_EMULATOR_HOST: shuffle-database:8000
DB_LOCATION: ./shuffle-database
ENVIRONMENT_NAME: Shuffle
FRONTEND_PORT: '3001'
FRONTEND_PORT_HTTPS: '3443'
HTTPS_PROXY: ''
HTTP_PROXY: ''
ORG_ID: Shuffle
OUTER_HOSTNAME: backend
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
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_DOWNLOAD_AUTH_BRANCH: ''
SHUFFLE_DOWNLOAD_AUTH_PASSWORD: ''
SHUFFLE_DOWNLOAD_AUTH_USERNAME: ''
SHUFFLE_DOWNLOAD_WORKFLOW_BRANCH: ''
SHUFFLE_DOWNLOAD_WORKFLOW_LOCATION: ''
SHUFFLE_DOWNLOAD_WORKFLOW_PASSWORD: ''
SHUFFLE_DOWNLOAD_WORKFLOW_USERNAME: ''
SHUFFLE_ELASTIC: 'true'
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_ENCRYPTION_MODIFIER: a7cee5f9-8e55-4e05-98d4-59aa9595339b
BASE_URL: https://shuffle.lab.local
SSO_REDIRECT_URL: https://shuffle.lab.local
#ports:
# - 5001:5001
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /mnt/swarm/container_data/Shuffle/shuffle-apps:/shuffle-apps
- /mnt/swarm/container_data/Shuffle/shuffle-files:/shuffle-files
networks:
- shuffle
depends_on:
- opensearch
logging:
driver: json-file
deploy:
placement:
constraints:
- node.labels.localisation==PROD
resources:
limits:
#cpus: '0.5'
memory: 8G
frontend:
image: ghcr.io/frikky/shuffle-frontend:latest
healthcheck:
test: curl -fs http://localhost:80 || exit 1
interval: 30s
timeout: 5s
retries: 3
environment:
BACKEND_HOSTNAME: backend
BASE_URL: https://shuffle.lab.local
SSO_REDIRECT_URL: https://shuffle.lab.local
#ports:
# - 3001:80
# - 3443:443
networks:
- shuffle
- reverseproxy
logging:
driver: json-file
depends_on:
- backend
deploy:
placement:
constraints:
- node.labels.localisation==PROD
labels:
- "traefik.enable=true"
- "traefik.http.routers.shuffle.rule=Host(`shuffle.lab.local`)"
- "traefik.http.routers.shuffle.entrypoints=web-secure,web"
- "traefik.http.routers.shuffle.tls=true"
- "traefik.http.services.shuffle.loadbalancer.server.port=80"
- "traefik.docker.network=reverseproxy"
opensearch:
image: opensearchproject/opensearch:2
healthcheck:
test: curl -fs http://localhost:9200/_cat/health || exit 1
interval: 30s
timeout: 5s
retries: 3
start_period: 45s
environment:
OPENSEARCH_JAVA_OPTS: -Xms4096m -Xmx4096m
bootstrap.memory_lock: 'true'
cluster.initial_master_nodes: opensearch
node.store.allow_mmap: 'false'
cluster.name: shuffle-cluster
cluster.routing.allocation.disk.threshold_enabled: 'false'
discovery.seed_hosts: opensearch
node.name: opensearch
plugins.security.disabled: 'true'
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
#ports:
#- 9200:9200
volumes:
- /mnt/swarm/container_data/Shuffle/shuffle-database:/usr/share/opensearch/data
#- /var/glusterfs/shuffle-database:/usr/share/opensearch/data
- /mnt/swarm/container_data/Shuffle/shuffle-backup/opensearch:/mnt/backup
networks:
- shuffle
logging:
driver: json-file
deploy:
#endpoint_mode: dnsrr
placement:
constraints:
- node.labels.localisation==PROD
resources:
limits:
#cpus: '0.5'
memory: 8G
orborus:
#image: ghcr.io/frikky/shuffle-orborus:latest
image: ghcr.io/frikky/shuffle-orborus:nightly
environment:
#SHUFFLE_APP_SDK_VERSION: 0.8.97
SHUFFLE_WORKER_VERSION: latest
BASE_URL: http://tasks.backend:5001
#BASE_URL: https://shuffle.lab.local
CLEANUP: 'true'
DOCKER_API_VERSION: '1.41'
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: 'FALSE'
SHUFFLE_SCALE_REPLICAS: 2
SHUFFLE_SWARM_CONFIG: run
SHUFFLE_LOGS_DISABLED: "true"
SHUFFLE_SWARM_NETWORK_NAME: shuffle
SSO_REDIRECT_URL: https://shuffle.lab.local
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- shuffle
depends_on:
- backend
logging:
driver: json-file
deploy:
placement:
constraints:
- node.labels.localisation==PROD
oauth2-proxy:
container_name: oauth2-proxy
image: quay.io/oauth2-proxy/oauth2-proxy:latest
command: --config /oauth2-proxy.cfg
hostname: oauth2-proxy
networks:
- shuffle
- reverseproxy
volumes:
- /mnt/swarm/container_data/Shuffle/oauth2-proxy/oauth2-proxy.cfg:/oauth2-proxy.cfg
- /mnt/swarm/container_data/Shuffle/oauth2-proxy/logs:/logs
- /etc/ssl/certs/:/etc/ssl/certs/:ro
restart: unless-stopped
deploy:
placement:
constraints:
- node.labels.localisation==PROD
labels:
- "traefik.enable=true"
- "traefik.http.routers.opensearch-secure.rule=Host(`shuffle.lab.local`)"
- "traefik.http.routers.opensearch-secure.entrypoints=opensearch-secure"
- "traefik.http.routers.opensearch-secure.tls=true"
- "traefik.http.services.opensearch-secure.loadbalancer.server.port=4180"
- "traefik.docker.network=reverseproxy"
dashboards:
image: opensearchproject/opensearch-dashboards:2
#ports:
#- 5601:5601
environment:
OPENSEARCH_HOSTS: '["http://opensearch:9200"]' # must be a string with no spaces when specified as an environment variable
DISABLE_INSTALL_DEMO_CONFIG: "true"
DISABLE_SECURITY_DASHBOARDS_PLUGIN: "true"
networks:
- shuffle
networks:
shuffle:
driver: overlay
external: true
reverseproxy:
driver: overlay
external: true
Setup data locations#
This could be made as a command but I like to run first and echo instead of the "mkdir -p" to be sure I didn't made a mistake.
# grep "/mnt/docker_data" /mnt/configuration_data/compose_files/SOAR/shuffle-stack.yml | awk -F "- " '{print $2'} | awk -F ":" '{ system("mkdir -p "$1"") }'
Deploy Shuffle stack#
Deploy the Shuffle stack by running docker stack deploy -c <path -to-docker-compose.yml> shuffle
Log into your new instance at any nodes on port https://node:3443.
Note#
Have you may have seen, all except database have a replica set to 3. This is done so we don't create a messy mess on DB if writing are done from different shuffle-database container at the same time on the same value which will lead to database corruption. Anyway, this container is up in 7 second in case of failure of the node ^^ .
App gonna be slow to run on it's first usage on all new nodes where Orborus is going to use the base image for the first time. As swarm distribute request around all replicas, sometime request gonna be fast as the node already run the image and sometime not. This all Replica and Clustering of Shuffle is not yet production ready as it is not yet properly implemented.
I recommend using only one database and one Orborus for now.