Changed to docker setup and converting to cryptodome for aes/hashing

This commit is contained in:
Josh Krawczyk 2020-06-30 20:43:26 -04:00
parent 8bb4cabdf4
commit a234e84de4
8 changed files with 397 additions and 404 deletions

View File

@ -1,11 +1,11 @@
import requests
import datetime as dt
import time
import hashlib
import secrets
import base64
from Crypto.Cipher import AES
from binascii import unhexlify
from Crypto.Random import get_random_bytes
from Crypto.Hash import SHA3_384
from Crypto.Util.Padding import pad
import validators
import random
import string
@ -222,19 +222,16 @@ class Agent(models.Model):
msg = '{{"a":{}, "u":"{}","time":{}}}'.format(
action, user, int(time.time())
)
iv = secrets.token_bytes(16)
iv = get_random_bytes(16)
# sha
h = hashlib.sha3_384()
h = SHA3_384.new()
h.update(key1)
msg = h.digest() + msg.encode()
hashed_msg = h.digest() + msg.encode()
# aes
a = AES.new(key2, AES.MODE_CBC, iv)
n = 16 - (len(msg) % 16)
n = 16 if n == 0 else n
pad = unhexlify("%02x" % n)
msg = a.encrypt(msg + pad * n)
cipher = AES.new(key2, AES.MODE_CBC, iv)
msg = cipher.encrypt(pad(hashed_msg, 16))
return base64.b64encode(iv + msg, altchars=b"@$").decode("utf-8")
except Exception:

View File

@ -1,55 +1,49 @@
from django.core.management.base import BaseCommand
from django.conf import settings
from core.models import CoreSettings
from .helpers import get_auth_token
import asyncio
import ssl
import websockets
import json
class Command(BaseCommand):
help = "Sets up initial mesh central configuration"
def add_arguments(self, parser):
parser.add_argument("--event_loop")
async def websocket_call(self):
token = get_auth_token(
self.mesh_settings.mesh_username, self.mesh_settings.mesh_token
)
if settings.MESH_WS_URL:
uri = f"{settings.MESH_WS_URL}/control.ashx?auth={token}"
else:
site = self.mesh_settings.mesh_site.replace("https", "wss")
uri = f"{site}/control.ashx?auth={token}"
async with websockets.connect(uri) as websocket:
# Get Invitation Link
await websocket.send(
json.dumps(
{
"action": "createInviteLink",
"expire": 8,
"flags": 0,
"meshname": "TacticalRMM",
"responseid": "python",
}
)
)
async for message in websocket:
response = json.loads(message)
if response["action"] == "createInviteLink":
print(response["url"])
break
def handle(self, *args, **kwargs):
self.mesh_settings = CoreSettings.objects.first()
if kwargs["event_loop"]:
kwargs["event_loop"].run_until_complete(self.websocket_call())
else:
asyncio.get_event_loop().run_until_complete(self.websocket_call())
from django.core.management.base import BaseCommand
from django.conf import settings
from core.models import CoreSettings
from .helpers import get_auth_token
import asyncio
import ssl
import websockets
import json
class Command(BaseCommand):
help = "Sets up initial mesh central configuration"
async def websocket_call(self):
token = get_auth_token(
self.mesh_settings.mesh_username, self.mesh_settings.mesh_token
)
if settings.MESH_WS_URL:
uri = f"{settings.MESH_WS_URL}/control.ashx?auth={token}"
else:
site = self.mesh_settings.mesh_site.replace("https", "wss")
uri = f"{site}/control.ashx?auth={token}"
async with websockets.connect(uri) as websocket:
# Get Invitation Link
await websocket.send(
json.dumps(
{
"action": "createInviteLink",
"expire": 8,
"flags": 0,
"meshname": "TacticalRMM",
"responseid": "python",
}
)
)
async for message in websocket:
response = json.loads(message)
if response["action"] == "createInviteLink":
print(response["url"])
break
def handle(self, *args, **kwargs):
self.mesh_settings = CoreSettings.objects.first()
asyncio.get_event_loop().run_until_complete(self.websocket_call())

View File

@ -1,18 +1,18 @@
import time
from base64 import b64encode
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
def get_auth_token(user, key):
key = bytes.fromhex(key)
key1 = key[0:32]
msg = '{{"userid":"{}", "domainid":"{}", "time":{}}}'.format(
f"user//{user}", "", int(time.time())
)
iv = get_random_bytes(12)
a = AES.new(key1, AES.MODE_GCM, iv)
msg, tag = a.encrypt_and_digest(bytes(msg, "utf-8"))
return b64encode(iv + tag + msg, altchars=b"@$").decode("utf-8")
import time
from base64 import b64encode
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
def get_auth_token(user, key):
key = bytes.fromhex(key)
key1 = key[0:32]
msg = '{{"userid":"{}", "domainid":"{}", "time":{}}}'.format(
f"user//{user}", "", int(time.time())
)
iv = get_random_bytes(12)
a = AES.new(key1, AES.MODE_GCM, iv)
msg, tag = a.encrypt_and_digest(bytes(msg, "utf-8"))
return b64encode(iv + tag + msg, altchars=b"@$").decode("utf-8")

View File

@ -1,53 +1,53 @@
from django.core.management.base import BaseCommand
from django.conf import settings
from core.models import CoreSettings
from .helpers import get_auth_token
import asyncio
import ssl
import websockets
import json
class Command(BaseCommand):
help = "Sets up initial mesh central configuration"
async def websocket_call(self):
print(self.mesh_settings.mesh_token)
token = get_auth_token(
self.mesh_settings.mesh_username, self.mesh_settings.mesh_token.rstrip()
)
if settings.MESH_WS_URL:
uri = f"{settings.MESH_WS_URL}/control.ashx?auth={token}"
else:
site = self.mesh_settings.mesh_site.replace("https", "wss")
uri = f"{site}/control.ashx?auth={token}"
async with websockets.connect(uri) as websocket:
# Get Device groups to see if it exists
await websocket.send(json.dumps({"action": "meshes"}))
async for message in websocket:
response = json.loads(message)
if response["action"] == "meshes":
# If no meshes are present
if not response["meshes"]:
await websocket.send(
json.dumps(
{
"action": "createmesh",
"meshname": "TacticalRMM",
"meshtype": 2,
"responseid": "python",
}
)
)
break
else:
break
def handle(self, *args, **kwargs):
self.mesh_settings = CoreSettings.objects.first()
asyncio.get_event_loop().run_until_complete(self.websocket_call())
from django.core.management.base import BaseCommand
from django.conf import settings
from core.models import CoreSettings
from .helpers import get_auth_token
import asyncio
import ssl
import websockets
import json
class Command(BaseCommand):
help = "Sets up initial mesh central configuration"
async def websocket_call(self):
print(self.mesh_settings.mesh_token)
token = get_auth_token(
self.mesh_settings.mesh_username, self.mesh_settings.mesh_token.rstrip()
)
if settings.MESH_WS_URL:
uri = f"{settings.MESH_WS_URL}/control.ashx?auth={token}"
else:
site = self.mesh_settings.mesh_site.replace("https", "wss")
uri = f"{site}/control.ashx?auth={token}"
async with websockets.connect(uri) as websocket:
# Get Device groups to see if it exists
await websocket.send(json.dumps({"action": "meshes"}))
async for message in websocket:
response = json.loads(message)
if response["action"] == "meshes":
# If no meshes are present
if not response["meshes"]:
await websocket.send(
json.dumps(
{
"action": "createmesh",
"meshname": "TacticalRMM",
"meshtype": 2,
"responseid": "python",
}
)
)
break
else:
break
def handle(self, *args, **kwargs):
self.mesh_settings = CoreSettings.objects.first()
asyncio.get_event_loop().run_until_complete(self.websocket_call())

View File

@ -1,37 +1,37 @@
amqp==2.6.0
asgiref==3.2.10
billiard==3.6.3.0
celery==4.4.5
certifi==2020.6.20
cffi==1.14.0
chardet==3.0.4
cryptography==2.9.2
decorator==4.4.2
Django==3.0.7
django-cors-headers==3.4.0
django-rest-knox==4.1.0
djangorestframework==3.11.0
future==0.18.2
idna==2.9
importlib-metadata==1.6.1
kombu==4.6.10
loguru==0.5.1
more-itertools==8.4.0
packaging==20.4
psycopg2-binary==2.8.5
pycparser==2.20
pycryptodome==3.9.7
pyotp==2.3.0
pyparsing==2.4.7
pytz==2020.1
qrcode==6.1
redis==3.5.3
requests==2.24.0
six==1.15.0
sqlparse==0.3.1
urllib3==1.25.9
uWSGI==2.0.19.1
validators==0.15.0
vine==1.3.0
websockets==8.1
zipp==3.1.0
amqp==2.6.0
asgiref==3.2.10
billiard==3.6.3.0
celery==4.4.5
certifi==2020.6.20
cffi==1.14.0
chardet==3.0.4
cryptography==2.9.2
decorator==4.4.2
Django==3.0.7
django-cors-headers==3.4.0
django-rest-knox==4.1.0
djangorestframework==3.11.0
future==0.18.2
idna==2.9
importlib-metadata==1.6.1
kombu==4.6.10
loguru==0.5.1
more-itertools==8.4.0
packaging==20.4
psycopg2-binary==2.8.5
pycparser==2.20
pycryptodome==3.9.8
pyotp==2.3.0
pyparsing==2.4.7
pytz==2020.1
qrcode==6.1
redis==3.5.3
requests==2.24.0
six==1.15.0
sqlparse==0.3.1
urllib3==1.25.9
uWSGI==2.0.19.1
validators==0.15.0
vine==1.3.0
websockets==8.1
zipp==3.1.0

View File

@ -1,99 +1,100 @@
# FOR DEV
version: '3.7'
services:
# Container that hosts Vue frontend
app:
image: node:12
command: /bin/bash -c "npm install && npm run serve -- --host 0.0.0.0 --port 80 --public ${APP_HOST}"
working_dir: /home/node
volumes:
- ../web:/home/node
networks:
- proxy
# Builds Python Virtual Env to share between containers
venv:
image: python:3.8
command: /bin/bash -c "pip install virtualenv && python -m virtualenv env && ./env/bin/pip install -r requirements.txt"
working_dir: /app
volumes:
- ../api/tacticalrmm:/app
# Container for Django backend
api:
image: python:3.8
command: /bin/bash -c "python manage.py collectstatic --clear --no-input && python manage.py migrate && python manage.py initial_db_setup && python manage.py initial_mesh_setup && python manage.py load_chocos && python manage.py runserver 0.0.0.0:80"
working_dir: /app
environment:
VIRTUAL_ENV: /env
PATH: /app/env/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
networks:
- proxy
- database
- redis
volumes:
- scripts:/srv
- mesh_token:/token
- ../api/tacticalrmm:/app
depends_on:
- db
- venv
# Container for Celery worker service
celery-service:
image: python:3.8
command: celery -A tacticalrmm worker -l debug
working_dir: /app
environment:
VIRTUAL_ENV: /env
PATH: /app/env/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
volumes:
- ../api/tacticalrmm:/app
networks:
- redis
- proxy
- database
depends_on:
- db
- redis
- venv
# Container for Celery beat service
celery-beat:
image: python:3.8
command: celery -A tacticalrmm beat -l debug
working_dir: /app
environment:
VIRTUAL_ENV: /env
PATH: /app/env/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
volumes:
- ../api/tacticalrmm:/app
networks:
- redis
- proxy
- database
depends_on:
- db
- redis
- venv
# Container for Celery Winupdate tasks
celery-winupdate:
image: python:3.8
command: celery -A tacticalrmm worker -Q wupdate -l debug
working_dir: /app
environment:
VIRTUAL_ENV: /env
PATH: /app/env/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
volumes:
- ../api/tacticalrmm:/app
networks:
- redis
- proxy
- database
depends_on:
- db
- redis
# FOR DEV
version: '3.7'
services:
# Container that hosts Vue frontend
app:
image: node:12
command: /bin/bash -c "npm install && npm run serve -- --host 0.0.0.0 --port 80 --public ${APP_HOST}"
working_dir: /home/node
volumes:
- ../web:/home/node
networks:
- proxy
# Builds Python Virtual Env to share between containers
venv:
image: python:3.8
command: /bin/bash -c "pip install virtualenv && python -m virtualenv env && ./env/bin/pip install -r requirements.txt"
working_dir: /app
volumes:
- ../api/tacticalrmm:/app
# Container for Django backend
api:
image: python:3.8
command: /bin/bash -c "python manage.py collectstatic --clear --no-input && python manage.py migrate && python manage.py initial_db_setup && python manage.py initial_mesh_setup && python manage.py load_chocos && python manage.py runserver 0.0.0.0:80"
working_dir: /app
environment:
VIRTUAL_ENV: /env
PATH: /app/env/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
networks:
- proxy
- database
- redis
volumes:
- scripts:/srv
- mesh_token:/token
- ../api/tacticalrmm:/app
depends_on:
- db
- venv
- meshcentral
# Container for Celery worker service
celery-service:
image: python:3.8
command: celery -A tacticalrmm worker -l debug
working_dir: /app
environment:
VIRTUAL_ENV: /env
PATH: /app/env/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
volumes:
- ../api/tacticalrmm:/app
networks:
- redis
- proxy
- database
depends_on:
- db
- redis
- venv
# Container for Celery beat service
celery-beat:
image: python:3.8
command: celery -A tacticalrmm beat -l debug
working_dir: /app
environment:
VIRTUAL_ENV: /env
PATH: /app/env/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
volumes:
- ../api/tacticalrmm:/app
networks:
- redis
- proxy
- database
depends_on:
- db
- redis
- venv
# Container for Celery Winupdate tasks
celery-winupdate:
image: python:3.8
command: celery -A tacticalrmm worker -Q wupdate -l debug
working_dir: /app
environment:
VIRTUAL_ENV: /env
PATH: /app/env/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
volumes:
- ../api/tacticalrmm:/app
networks:
- redis
- proxy
- database
depends_on:
- db
- redis
- venv

View File

@ -1,131 +1,132 @@
# FOR PROD
version: "3.7"
services:
# Container that hosts Vue frontend
app:
build:
context: ..
args:
- APP_HOST=${APP_HOST}
- API_HOST=${API_HOST}
dockerfile: "./docker/app/dockerfile"
networks:
- proxy
# Container for Django backend
api:
build:
context: ..
dockerfile: "./docker/api/dockerfile"
args:
- DJANGO_SEKRET=${DJANGO_SEKRET}
- DJANGO_DEBUG=${DJANGO_DEBUG}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASS=${POSTGRES_PASS}
- POSTGRES_HOST=${POSTGRES_HOST}
- SALT_PASS=${SALT_PASS}
- SALT_USER=${SALT_USER}
- SALT_HOST=${SALT_HOST}
- REDIS_HOST=${REDIS_HOST}
- MESH_USER=${MESH_USER}
- MESH_HOST=${MESH_HOST}
- APP_HOST=${APP_HOST}
- API_HOST=${API_HOST}
- ADMIN_URL=${ADMIN_URL}
networks:
- proxy
- database
- redis
volumes:
- scripts:/srv
- mesh_token:/token
depends_on:
- db
# Container for Celery worker service
celery-service:
build:
context: ..
dockerfile: "./docker/api/dockerfile"
args:
- DJANGO_SEKRET=${DJANGO_SEKRET}
- DJANGO_DEBUG=${DJANGO_DEBUG}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASS=${POSTGRES_PASS}
- POSTGRES_HOST=${POSTGRES_HOST}
- SALT_PASS=${SALT_PASS}
- SALT_USER=${SALT_USER}
- SALT_HOST=${SALT_HOST}
- REDIS_HOST=${REDIS_HOST}
- MESH_USER=${MESH_USER}
- MESH_HOST=${MESH_HOST}
- APP_HOST=${APP_HOST}
- API_HOST=${API_HOST}
- ADMIN_URL=${ADMIN_URL}
command: celery -A tacticalrmm worker -l debug
networks:
- redis
- proxy
- database
depends_on:
- db
- redis
# Container for Celery beat service
celery-beat:
build:
context: ..
dockerfile: "./docker/api/dockerfile"
args:
- DJANGO_SEKRET=${DJANGO_SEKRET}
- DJANGO_DEBUG=${DJANGO_DEBUG}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASS=${POSTGRES_PASS}
- POSTGRES_HOST=${POSTGRES_HOST}
- SALT_PASS=${SALT_PASS}
- SALT_USER=${SALT_USER}
- SALT_HOST=${SALT_HOST}
- REDIS_HOST=${REDIS_HOST}
- MESH_USER=${MESH_USER}
- MESH_HOST=${MESH_HOST}
- APP_HOST=${APP_HOST}
- API_HOST=${API_HOST}
- ADMIN_URL=${ADMIN_URL}
command: celery -A tacticalrmm beat -l debug
networks:
- redis
- proxy
- database
depends_on:
- db
- redis
# Container for Celery Winupdate tasks
celery-winupdate:
build:
context: ..
dockerfile: "./docker/api/dockerfile"
args:
- DJANGO_SEKRET=${DJANGO_SEKRET}
- DJANGO_DEBUG=${DJANGO_DEBUG}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASS=${POSTGRES_PASS}
- POSTGRES_HOST=${POSTGRES_HOST}
- SALT_PASS=${SALT_PASS}
- SALT_USER=${SALT_USER}
- SALT_HOST=${SALT_HOST}
- REDIS_HOST=${REDIS_HOST}
- MESH_USER=${MESH_USER}
- MESH_HOST=${MESH_HOST}
- APP_HOST=${APP_HOST}
- API_HOST=${API_HOST}
- ADMIN_URL=${ADMIN_URL}
command: celery -A tacticalrmm worker -Q wupdate -l debug
networks:
- redis
- proxy
- database
depends_on:
- db
- redis
# FOR PROD
version: "3.7"
services:
# Container that hosts Vue frontend
app:
build:
context: ..
args:
- APP_HOST=${APP_HOST}
- API_HOST=${API_HOST}
dockerfile: "./docker/app/dockerfile"
networks:
- proxy
# Container for Django backend
api:
build:
context: ..
dockerfile: "./docker/api/dockerfile"
args:
- DJANGO_SEKRET=${DJANGO_SEKRET}
- DJANGO_DEBUG=${DJANGO_DEBUG}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASS=${POSTGRES_PASS}
- POSTGRES_HOST=${POSTGRES_HOST}
- SALT_PASS=${SALT_PASS}
- SALT_USER=${SALT_USER}
- SALT_HOST=${SALT_HOST}
- REDIS_HOST=${REDIS_HOST}
- MESH_USER=${MESH_USER}
- MESH_HOST=${MESH_HOST}
- APP_HOST=${APP_HOST}
- API_HOST=${API_HOST}
- ADMIN_URL=${ADMIN_URL}
networks:
- proxy
- database
- redis
volumes:
- scripts:/srv
- mesh_token:/token
depends_on:
- db
- meshcentral
# Container for Celery worker service
celery-service:
build:
context: ..
dockerfile: "./docker/api/dockerfile"
args:
- DJANGO_SEKRET=${DJANGO_SEKRET}
- DJANGO_DEBUG=${DJANGO_DEBUG}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASS=${POSTGRES_PASS}
- POSTGRES_HOST=${POSTGRES_HOST}
- SALT_PASS=${SALT_PASS}
- SALT_USER=${SALT_USER}
- SALT_HOST=${SALT_HOST}
- REDIS_HOST=${REDIS_HOST}
- MESH_USER=${MESH_USER}
- MESH_HOST=${MESH_HOST}
- APP_HOST=${APP_HOST}
- API_HOST=${API_HOST}
- ADMIN_URL=${ADMIN_URL}
command: celery -A tacticalrmm worker -l debug
networks:
- redis
- proxy
- database
depends_on:
- db
- redis
# Container for Celery beat service
celery-beat:
build:
context: ..
dockerfile: "./docker/api/dockerfile"
args:
- DJANGO_SEKRET=${DJANGO_SEKRET}
- DJANGO_DEBUG=${DJANGO_DEBUG}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASS=${POSTGRES_PASS}
- POSTGRES_HOST=${POSTGRES_HOST}
- SALT_PASS=${SALT_PASS}
- SALT_USER=${SALT_USER}
- SALT_HOST=${SALT_HOST}
- REDIS_HOST=${REDIS_HOST}
- MESH_USER=${MESH_USER}
- MESH_HOST=${MESH_HOST}
- APP_HOST=${APP_HOST}
- API_HOST=${API_HOST}
- ADMIN_URL=${ADMIN_URL}
command: celery -A tacticalrmm beat -l debug
networks:
- redis
- proxy
- database
depends_on:
- db
- redis
# Container for Celery Winupdate tasks
celery-winupdate:
build:
context: ..
dockerfile: "./docker/api/dockerfile"
args:
- DJANGO_SEKRET=${DJANGO_SEKRET}
- DJANGO_DEBUG=${DJANGO_DEBUG}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASS=${POSTGRES_PASS}
- POSTGRES_HOST=${POSTGRES_HOST}
- SALT_PASS=${SALT_PASS}
- SALT_USER=${SALT_USER}
- SALT_HOST=${SALT_HOST}
- REDIS_HOST=${REDIS_HOST}
- MESH_USER=${MESH_USER}
- MESH_HOST=${MESH_HOST}
- APP_HOST=${APP_HOST}
- API_HOST=${API_HOST}
- ADMIN_URL=${ADMIN_URL}
command: celery -A tacticalrmm worker -Q wupdate -l debug
networks:
- redis
- proxy
- database
depends_on:
- db
- redis

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
node node_modules/meshcentral --createaccount ${MESH_USER} --pass ${MESH_PASS} --email ${EMAIL_USER}
node node_modules/meshcentral --adminaccount ${MESH_USER}