Merge branch 'v3' of github.com:jumpserver/jumpserver into v3

pull/9075/head
ibuler 2022-11-15 10:43:51 +08:00
commit 22dd9906c7
9 changed files with 283 additions and 186 deletions

View File

@ -10,11 +10,11 @@ __all__ = ["SpecialAccount", "ActionChoices"]
class ActionChoices(BitChoices):
connect = bit(0), _("Connect")
upload = bit(1), _("Upload")
download = bit(2), _("Download")
copy = bit(3), _("Copy")
paste = bit(4), _("Paste")
connect = bit(1), _("Connect")
upload = bit(2), _("Upload")
download = bit(3), _("Download")
copy = bit(4), _("Copy")
paste = bit(5), _("Paste")
@classmethod
def is_tree(cls):

View File

@ -2,16 +2,15 @@ from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from common.permissions import IsServiceAccount
from common.drf.api import JMSModelViewSet
from common.permissions import IsServiceAccount
from orgs.utils import tmp_to_builtin_org
from terminal.models import AppletHost, AppletHostDeployment
from terminal.serializers import (
AppletHostSerializer, AppletHostDeploymentSerializer,
AppletHostStartupSerializer
AppletHostStartupSerializer, AppletHostDeployAppletSerializer
)
from terminal.models import AppletHost, AppletHostDeployment
from terminal.tasks import run_applet_host_deployment
from terminal.tasks import run_applet_host_deployment, run_applet_host_deployment_install_applet
__all__ = ['AppletHostViewSet', 'AppletHostDeploymentViewSet']
@ -41,6 +40,9 @@ class AppletHostViewSet(JMSModelViewSet):
class AppletHostDeploymentViewSet(viewsets.ModelViewSet):
serializer_class = AppletHostDeploymentSerializer
queryset = AppletHostDeployment.objects.all()
rbac_perms = (
('applets', 'terminal.view_AppletHostDeployment'),
)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
@ -49,3 +51,11 @@ class AppletHostDeploymentViewSet(viewsets.ModelViewSet):
task = run_applet_host_deployment.delay(instance.id)
return Response({'task': str(task.id)}, status=201)
@action(methods=['post'], detail=False, serializer_class=AppletHostDeployAppletSerializer)
def applets(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
applet_id = serializer.validated_data.get('applet_id')
instance = serializer.save()
task = run_applet_host_deployment_install_applet.delay(instance.id, applet_id)
return Response({'task': str(task.id)}, status=201)

View File

@ -1,22 +1,23 @@
import os
import datetime
import shutil
import os
import yaml
from django.utils import timezone
from django.conf import settings
from django.utils import timezone
from common.utils import get_logger
from common.db.utils import safe_db_connection
from common.utils import get_logger
from ops.ansible import PlaybookRunner, JMSInventory
from terminal.models import Applet, AppletHostDeployment
logger = get_logger(__name__)
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
class DeployAppletHostManager:
def __init__(self, deployment):
def __init__(self, deployment: AppletHostDeployment, applet: Applet = None):
self.deployment = deployment
self.applet = applet
self.run_dir = self.get_run_dir()
@staticmethod
@ -25,29 +26,56 @@ class DeployAppletHostManager:
now = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
return os.path.join(base, now)
def generate_playbook(self):
playbook_src = os.path.join(CURRENT_DIR, "playbook.yml")
base_site_url = settings.BASE_SITE_URL
def run(self, **kwargs):
self._run(self._run_initial_deploy, **kwargs)
def install_applet(self, **kwargs):
self._run(self._run_install_applet, **kwargs)
def _run_initial_deploy(self, **kwargs):
playbook = self.generate_initial_playbook
return self._run_playbook(playbook, **kwargs)
def _run_install_applet(self, **kwargs):
if self.applet:
generate_playbook = self.generate_install_applet_playbook
else:
generate_playbook = self.generate_install_all_playbook
return self._run_playbook(generate_playbook, **kwargs)
def generate_initial_playbook(self):
site_url = settings.SITE_URL
bootstrap_token = settings.BOOTSTRAP_TOKEN
host_id = str(self.deployment.host.id)
if not base_site_url:
base_site_url = "http://localhost:8080"
with open(playbook_src) as f:
plays = yaml.safe_load(f)
if not site_url:
site_url = "http://localhost:8080"
options = self.deployment.host.deploy_options
def handler(plays):
for play in plays:
play["vars"].update(self.deployment.host.deploy_options)
play["vars"]["DownloadHost"] = base_site_url + "/download"
play["vars"]["CORE_HOST"] = base_site_url
play["vars"].update(options)
play["vars"]["DownloadHost"] = site_url + "/download"
play["vars"]["CORE_HOST"] = site_url
play["vars"]["BOOTSTRAP_TOKEN"] = bootstrap_token
play["vars"]["HOST_ID"] = host_id
play["vars"]["HOST_NAME"] = self.deployment.host.name
playbook_dir = os.path.join(self.run_dir, "playbook")
playbook_dst = os.path.join(playbook_dir, "main.yml")
os.makedirs(playbook_dir, exist_ok=True)
with open(playbook_dst, "w") as f:
yaml.safe_dump(plays, f)
return playbook_dst
return self._generate_playbook("playbook.yml", handler)
def generate_install_all_playbook(self):
return self._generate_playbook("install_all.yml")
def generate_install_applet_playbook(self):
applet_name = self.applet.name
options = self.deployment.host.deploy_options
def handler(plays):
for play in plays:
play["vars"].update(options)
play["vars"]["applet_name"] = applet_name
return plays
return self._generate_playbook("install_applet.yml", handler)
def generate_inventory(self):
inventory = JMSInventory(
@ -58,18 +86,31 @@ class DeployAppletHostManager:
inventory.write_to_file(inventory_path)
return inventory_path
def _run(self, **kwargs):
def _generate_playbook(self, playbook_template_name, plays_handler: callable = None):
playbook_src = os.path.join(CURRENT_DIR, playbook_template_name)
with open(playbook_src) as f:
plays = yaml.safe_load(f)
if plays_handler:
plays = plays_handler(plays)
playbook_dir = os.path.join(self.run_dir, "playbook")
playbook_dst = os.path.join(playbook_dir, "main.yml")
os.makedirs(playbook_dir, exist_ok=True)
with open(playbook_dst, "w") as f:
yaml.safe_dump(plays, f)
return playbook_dst
def _run_playbook(self, generate_playbook: callable, **kwargs):
inventory = self.generate_inventory()
playbook = self.generate_playbook()
playbook = generate_playbook()
runner = PlaybookRunner(
inventory=inventory, playbook=playbook, project_dir=self.run_dir
)
return runner.run(**kwargs)
def run(self, **kwargs):
def _run(self, cb_func: callable, **kwargs):
try:
self.deployment.date_start = timezone.now()
cb = self._run(**kwargs)
cb = cb_func(**kwargs)
self.deployment.status = cb.status
except Exception as e:
logger.error("Error: {}".format(e))

View File

@ -0,0 +1,8 @@
---
- hosts: all
tasks:
- name: Install all applets
ansible.windows.win_shell:
"tinkerd install all"

View File

@ -0,0 +1,11 @@
---
- hosts: all
vars:
applet_name: chrome
tasks:
- name: Install applet
ansible.windows.win_shell:
"tinkerd install --name {{ applet_name }}"
when: applet_name != 'all'

View File

@ -3,7 +3,6 @@
- hosts: all
vars:
DownloadHost: https://demo.jumpserver.org/download
Initial: 0
HOST_NAME: test
HOST_ID: 00000000-0000-0000-0000-000000000000
CORE_HOST: https://demo.jumpserver.org

View File

@ -110,3 +110,13 @@ class AppletHostDeployment(JMSBaseModel):
from ...automations.deploy_applet_host import DeployAppletHostManager
manager = DeployAppletHostManager(self)
manager.run(**kwargs)
def install_applet(self, applet_id, **kwargs):
from ...automations.deploy_applet_host import DeployAppletHostManager
from .applet import Applet
if applet_id:
applet = Applet.objects.get(id=applet_id)
else:
applet = None
manager = DeployAppletHostManager(self, applet=applet)
manager.install_applet(**kwargs)

View File

@ -1,19 +1,18 @@
from rest_framework import serializers
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from common.validators import ProjectUniqueValidator
from common.drf.fields import ObjectRelatedField, LabeledChoiceField
from assets.models import Platform, Account
from assets.serializers import HostSerializer
from ..models import AppletHost, AppletHostDeployment, Applet
from common.drf.fields import LabeledChoiceField
from common.validators import ProjectUniqueValidator
from .applet import AppletSerializer
from .. import const
from ..models import AppletHost, AppletHostDeployment
__all__ = [
'AppletHostSerializer', 'AppletHostDeploymentSerializer',
'AppletHostAccountSerializer', 'AppletHostAppletReportSerializer',
'AppletHostStartupSerializer',
'AppletHostStartupSerializer', 'AppletHostDeployAppletSerializer'
]
@ -29,7 +28,8 @@ class DeployOptionsSerializer(serializers.Serializer):
RDS_Licensing = serializers.BooleanField(default=False, label=_("RDS Licensing"))
RDS_LicenseServer = serializers.CharField(default='127.0.0.1', label=_('RDS License Server'), max_length=1024)
RDS_LicensingMode = serializers.ChoiceField(choices=LICENSE_MODE_CHOICES, default=4, label=_('RDS Licensing Mode'))
RDS_fSingleSessionPerUser = serializers.ChoiceField(choices=SESSION_PER_USER, default=1, label=_("RDS fSingleSessionPerUser"))
RDS_fSingleSessionPerUser = serializers.ChoiceField(choices=SESSION_PER_USER, default=1,
label=_("RDS fSingleSessionPerUser"))
RDS_MaxDisconnectionTime = serializers.IntegerField(default=60000, label=_("RDS Max Disconnection Time"))
RDS_RemoteAppLogoffTimeLimit = serializers.IntegerField(default=0, label=_("RDS Remote App Logoff Time Limit"))
@ -94,6 +94,18 @@ class AppletHostDeploymentSerializer(serializers.ModelSerializer):
fields = fields_mini + ['comment'] + read_only_fields
class AppletHostDeployAppletSerializer(AppletHostDeploymentSerializer):
applet_id = serializers.UUIDField(write_only=True, allow_null=True, required=False)
class Meta(AppletHostDeploymentSerializer.Meta):
fields = AppletHostDeploymentSerializer.Meta.fields + ['applet_id']
def create(self, validated_data):
applet_id = validated_data.pop('applet_id', None)
deployment = super().create(validated_data)
return deployment
class AppletHostAccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account

View File

@ -1,26 +1,25 @@
# -*- coding: utf-8 -*-
#
import datetime
import os
import subprocess
import datetime
from celery import shared_task
from celery.utils.log import get_task_logger
from django.utils import timezone
from django.core.files.storage import default_storage
from django.utils import timezone
from common.utils import get_log_keep_day
from ops.celery.decorator import (
register_as_period_task, after_app_ready_start,
after_app_shutdown_clean_periodic
)
from .models import (
Status, Session, Command, Task, AppletHost,
AppletHostDeployment
)
from orgs.utils import tmp_to_builtin_org
from .backends import server_replay_storage
from .models import (
Status, Session, Command, Task, AppletHostDeployment
)
from .utils import find_session_replay_local
CACHE_REFRESH_INTERVAL = 10
@ -114,3 +113,10 @@ def run_applet_host_deployment(did):
with tmp_to_builtin_org(system=1):
deployment = AppletHostDeployment.objects.get(id=did)
deployment.start()
@shared_task
def run_applet_host_deployment_install_applet(did, applet_id):
with tmp_to_builtin_org(system=1):
deployment = AppletHostDeployment.objects.get(id=did)
deployment.install_applet(applet_id)