rework agent installation auth token to have minimal perms

This commit is contained in:
wh1te909 2021-06-30 06:45:50 +00:00
parent cf03ee03ee
commit b6dd03138d
13 changed files with 63 additions and 7 deletions

View File

@ -114,6 +114,7 @@ EOF
"${VIRTUAL_ENV}"/bin/python manage.py load_chocos "${VIRTUAL_ENV}"/bin/python manage.py load_chocos
"${VIRTUAL_ENV}"/bin/python manage.py load_community_scripts "${VIRTUAL_ENV}"/bin/python manage.py load_community_scripts
"${VIRTUAL_ENV}"/bin/python manage.py reload_nats "${VIRTUAL_ENV}"/bin/python manage.py reload_nats
"${VIRTUAL_ENV}"/bin/python manage.py create_installer_user
# create super user # create super user
echo "from accounts.models import User; User.objects.create_superuser('${TRMM_USER}', 'admin@example.com', '${TRMM_PASS}') if not User.objects.filter(username='${TRMM_USER}').exists() else 0;" | python manage.py shell echo "from accounts.models import User; User.objects.create_superuser('${TRMM_USER}', 'admin@example.com', '${TRMM_PASS}') if not User.objects.filter(username='${TRMM_USER}').exists() else 0;" | python manage.py shell

View File

@ -0,0 +1,18 @@
import uuid
from django.core.management.base import BaseCommand
from accounts.models import User
class Command(BaseCommand):
help = "Creates the installer user"
def handle(self, *args, **kwargs):
if User.objects.filter(is_installer_user=True).exists():
return
User.objects.create_user( # type: ignore
username=uuid.uuid4().hex,
is_installer_user=True,
password=User.objects.make_random_password(60), # type: ignore
)

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.4 on 2021-06-30 03:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0022_user_clear_search_when_switching'),
]
operations = [
migrations.AddField(
model_name='user',
name='is_installer_user',
field=models.BooleanField(default=False),
),
]

View File

@ -47,6 +47,7 @@ class User(AbstractUser, BaseAuditModel):
client_tree_splitter = models.PositiveIntegerField(default=11) client_tree_splitter = models.PositiveIntegerField(default=11)
loading_bar_color = models.CharField(max_length=255, default="red") loading_bar_color = models.CharField(max_length=255, default="red")
clear_search_when_switching = models.BooleanField(default=True) clear_search_when_switching = models.BooleanField(default=True)
is_installer_user = models.BooleanField(default=False)
agent = models.OneToOneField( agent = models.OneToOneField(
"agents.Agent", "agents.Agent",

View File

@ -87,7 +87,7 @@ class GetAddUsers(APIView):
permission_classes = [IsAuthenticated, AccountsPerms] permission_classes = [IsAuthenticated, AccountsPerms]
def get(self, request): def get(self, request):
users = User.objects.filter(agent=None) users = User.objects.filter(agent=None, is_installer_user=False)
return Response(UserSerializer(users, many=True).data) return Response(UserSerializer(users, many=True).data)

View File

@ -390,6 +390,7 @@ class Reboot(APIView):
@permission_classes([IsAuthenticated, InstallAgentPerms]) @permission_classes([IsAuthenticated, InstallAgentPerms])
def install_agent(request): def install_agent(request):
from knox.models import AuthToken from knox.models import AuthToken
from accounts.models import User
from agents.utils import get_winagent_url from agents.utils import get_winagent_url
@ -415,8 +416,10 @@ def install_agent(request):
) )
download_url = get_winagent_url(arch) download_url = get_winagent_url(arch)
installer_user = User.objects.filter(is_installer_user=True).first()
_, token = AuthToken.objects.create( _, token = AuthToken.objects.create(
user=request.user, expiry=dt.timedelta(hours=request.data["expires"]) user=installer_user, expiry=dt.timedelta(hours=request.data["expires"])
) )
if request.data["installMethod"] == "exe": if request.data["installMethod"] == "exe":

View File

@ -251,16 +251,19 @@ class AgentDeployment(APIView):
def post(self, request): def post(self, request):
from knox.models import AuthToken from knox.models import AuthToken
from accounts.models import User
client = get_object_or_404(Client, pk=request.data["client"]) client = get_object_or_404(Client, pk=request.data["client"])
site = get_object_or_404(Site, pk=request.data["site"]) site = get_object_or_404(Site, pk=request.data["site"])
installer_user = User.objects.filter(is_installer_user=True).first()
expires = dt.datetime.strptime( expires = dt.datetime.strptime(
request.data["expires"], "%Y-%m-%d %H:%M" request.data["expires"], "%Y-%m-%d %H:%M"
).astimezone(pytz.timezone("UTC")) ).astimezone(pytz.timezone("UTC"))
now = djangotime.now() now = djangotime.now()
delta = expires - now delta = expires - now
obj, token = AuthToken.objects.create(user=request.user, expiry=delta) obj, token = AuthToken.objects.create(user=installer_user, expiry=delta)
flags = { flags = {
"power": request.data["power"], "power": request.data["power"],

View File

@ -105,7 +105,9 @@ class FilterOptionsAuditLog(APIView):
if request.data["type"] == "user": if request.data["type"] == "user":
users = User.objects.filter( users = User.objects.filter(
username__icontains=request.data["pattern"], agent=None username__icontains=request.data["pattern"],
agent=None,
is_installer_user=False,
) )
return Response(UserSerializer(users, many=True).data) return Response(UserSerializer(users, many=True).data)

View File

@ -1,3 +1,4 @@
import uuid
from django.test import TestCase, override_settings from django.test import TestCase, override_settings
from model_bakery import baker from model_bakery import baker
from rest_framework.authtoken.models import Token from rest_framework.authtoken.models import Token
@ -20,6 +21,12 @@ class TacticalTestCase(TestCase):
self.client_setup() self.client_setup()
self.client.force_authenticate(user=self.john) self.client.force_authenticate(user=self.john)
User.objects.create_user( # type: ignore
username=uuid.uuid4().hex,
is_installer_user=True,
password=User.objects.make_random_password(60), # type: ignore
)
def setup_agent_auth(self, agent): def setup_agent_auth(self, agent):
agent_user = User.objects.create_user( agent_user = User.objects.create_user(
username=agent.agent_id, username=agent.agent_id,

View File

@ -124,6 +124,7 @@ EOF
python manage.py load_chocos python manage.py load_chocos
python manage.py load_community_scripts python manage.py load_community_scripts
python manage.py reload_nats python manage.py reload_nats
python manage.py create_installer_user
# create super user # create super user
echo "from accounts.models import User; User.objects.create_superuser('${TRMM_USER}', 'admin@example.com', '${TRMM_PASS}') if not User.objects.filter(username='${TRMM_USER}').exists() else 0;" | python manage.py shell echo "from accounts.models import User; User.objects.create_superuser('${TRMM_USER}', 'admin@example.com', '${TRMM_PASS}') if not User.objects.filter(username='${TRMM_USER}').exists() else 0;" | python manage.py shell

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
SCRIPT_VERSION="50" SCRIPT_VERSION="51"
SCRIPT_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/install.sh' SCRIPT_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/install.sh'
sudo apt install -y curl wget dirmngr gnupg lsb-release sudo apt install -y curl wget dirmngr gnupg lsb-release
@ -380,6 +380,7 @@ printf >&2 "\n"
echo -ne "Username: " echo -ne "Username: "
read djangousername read djangousername
python manage.py createsuperuser --username ${djangousername} --email ${letsemail} python manage.py createsuperuser --username ${djangousername} --email ${letsemail}
python manage.py create_installer_user
RANDBASE=$(python manage.py generate_totp) RANDBASE=$(python manage.py generate_totp)
cls cls
python manage.py generate_barcode ${RANDBASE} ${djangousername} ${frontenddomain} python manage.py generate_barcode ${RANDBASE} ${djangousername} ${frontenddomain}

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
SCRIPT_VERSION="123" SCRIPT_VERSION="124"
SCRIPT_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/update.sh' SCRIPT_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/update.sh'
LATEST_SETTINGS_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/api/tacticalrmm/tacticalrmm/settings.py' LATEST_SETTINGS_URL='https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/api/tacticalrmm/tacticalrmm/settings.py'
YELLOW='\033[1;33m' YELLOW='\033[1;33m'
@ -274,6 +274,7 @@ python manage.py delete_tokens
python manage.py collectstatic --no-input python manage.py collectstatic --no-input
python manage.py reload_nats python manage.py reload_nats
python manage.py load_chocos python manage.py load_chocos
python manage.py create_installer_user
python manage.py post_update_tasks python manage.py post_update_tasks
deactivate deactivate

View File

@ -97,7 +97,7 @@ export default {
client: null, client: null,
site: null, site: null,
agenttype: "server", agenttype: "server",
expires: 720, expires: 24,
power: false, power: false,
rdp: false, rdp: false,
ping: false, ping: false,