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

pull/9028/head
ibuler 2022-11-04 20:16:29 +08:00
commit 045bc3661a
13 changed files with 100 additions and 107 deletions

View File

@ -23,6 +23,7 @@ class PushOrVerifyHostCallbackMixin:
execution: callable
host_account_mapper: dict
ignore_account: bool
need_privilege_account: bool
generate_public_key: callable
generate_private_key_path: callable
@ -32,7 +33,7 @@ class PushOrVerifyHostCallbackMixin:
return host
accounts = asset.accounts.all()
if self.ignore_account and account:
if self.need_privilege_account and accounts.count() > 1 and account:
accounts = accounts.exclude(id=account.id)
if '*' not in self.execution.snapshot['accounts']:
@ -114,9 +115,9 @@ class BasePlaybookManager:
method_attr = '{}_method'.format(self.__class__.method_type())
method_enabled = automation and \
getattr(automation, enabled_attr) and \
getattr(automation, method_attr) and \
getattr(automation, method_attr) in self.method_id_meta_mapper
getattr(automation, enabled_attr) and \
getattr(automation, method_attr) and \
getattr(automation, method_attr) in self.method_id_meta_mapper
if not method_enabled:
host['error'] = _('{} disabled'.format(self.__class__.method_type()))
@ -198,6 +199,9 @@ class BasePlaybookManager:
result = cb.host_results.get(host)
if state == 'ok':
self.on_host_success(host, result)
elif state == 'skipped':
# TODO
print('skipped: ', hosts)
else:
error = hosts.get(host)
self.on_host_error(host, error, result)

View File

@ -2,8 +2,8 @@
gather_facts: no
tasks:
- name: Add user account.username
ansible.builtin.user:
name: "{{ account.username }}"
ansible.builtin.user:
name: "{{ account.username }}"
- name: Set account.username password
ansible.builtin.user:

View File

@ -6,7 +6,7 @@ logger = get_logger(__name__)
class PushAccountManager(PushOrVerifyHostCallbackMixin, BasePlaybookManager):
ignore_account = True
need_privilege_account = True
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

View File

@ -6,7 +6,7 @@ logger = get_logger(__name__)
class VerifyAccountManager(PushOrVerifyHostCallbackMixin, BasePlaybookManager):
ignore_account = False
need_privilege_account = False
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

View File

@ -9,7 +9,7 @@ __all__ = ['PushAccountAutomation']
class PushAccountAutomation(BaseAutomation):
def save(self, *args, **kwargs):
self.type = AutomationTypes.verify_account
self.type = AutomationTypes.push_account
super().save(*args, **kwargs)
class Meta:

View File

@ -65,8 +65,8 @@ class AssetSerializer(OrgResourceSerializerMixin, WritableNestedModelSerializer)
platform = ObjectRelatedField(required=False, queryset=Platform.objects, label=_('Platform'))
nodes = ObjectRelatedField(many=True, required=False, queryset=Node.objects, label=_('Nodes'))
labels = AssetLabelSerializer(many=True, required=False, label=_('Labels'))
accounts = AssetAccountSerializer(many=True, required=False, label=_('Accounts'))
protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols'))
accounts = AssetAccountSerializer(many=True, required=False, label=_('Accounts'))
class Meta:
model = Asset
@ -74,7 +74,7 @@ class AssetSerializer(OrgResourceSerializerMixin, WritableNestedModelSerializer)
fields_small = fields_mini + ['is_active', 'comment']
fields_fk = ['domain', 'platform', 'platform']
fields_m2m = [
'nodes', 'labels', 'accounts', 'protocols', 'nodes_display',
'nodes', 'labels', 'protocols', 'accounts', 'nodes_display',
]
read_only_fields = [
'category', 'type', 'specific',

View File

@ -31,7 +31,7 @@ def push_accounts_to_assets_util(accounts, assets):
def push_accounts_to_assets(account_ids, asset_ids):
from assets.models import Asset, Account
with tmp_to_root_org():
assets = Asset.objects.get(id=asset_ids)
accounts = Account.objects.get(id=account_ids)
assets = Asset.objects.filter(id__in=asset_ids)
accounts = Account.objects.filter(id__in=account_ids)
return push_accounts_to_assets_util(accounts, assets)

View File

@ -30,8 +30,8 @@ def verify_accounts_connectivity_util(accounts, assets, task_name):
def verify_accounts_connectivity(account_ids, asset_ids):
from assets.models import Asset, Account
with tmp_to_root_org():
assets = Asset.objects.get(id=asset_ids)
accounts = Account.objects.get(id=account_ids)
assets = Asset.objects.filter(id__in=asset_ids)
accounts = Account.objects.filter(id__in=account_ids)
task_name = gettext_noop("Verify accounts connectivity")
return verify_accounts_connectivity_util(accounts, assets, task_name)

View File

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
#
from .common import *
from .nodes import *
from .assets import *
from .nodes_with_assets import *

View File

@ -1,13 +1,29 @@
from rest_framework import generics
from django.shortcuts import get_object_or_404
from rest_framework.generics import ListAPIView, get_object_or_404
from common.permissions import IsValidUser
from common.utils import get_logger, lazyproperty
from assets.serializers import AccountSerializer
from perms.utils.account import PermAccountUtil
from perms.hands import User, Asset, Account
from perms import serializers
from perms.models import Action
from perms.utils import PermAccountUtil
from .mixin import RoleAdminMixin, RoleUserMixin
__all__ = ['UserAllGrantedAccountsApi', 'MyAllGrantedAccountsApi']
logger = get_logger(__name__)
class UserAllGrantedAccountsApi(RoleAdminMixin, generics.ListAPIView):
__all__ = [
'UserAllGrantedAccountsApi',
'MyAllGrantedAccountsApi',
'UserGrantedAssetAccountsApi',
'MyGrantedAssetAccountsApi',
'UserGrantedAssetSpecialAccountsApi',
'MyGrantedAssetSpecialAccountsApi',
]
class UserAllGrantedAccountsApi(RoleAdminMixin, ListAPIView):
""" 授权给用户的所有账号列表 """
serializer_class = AccountSerializer
filterset_fields = ("name", "username", "privileged", "version")
@ -22,3 +38,59 @@ class UserAllGrantedAccountsApi(RoleAdminMixin, generics.ListAPIView):
class MyAllGrantedAccountsApi(RoleUserMixin, UserAllGrantedAccountsApi):
""" 授权给我的所有账号列表 """
pass
class UserGrantedAssetAccountsApi(ListAPIView):
serializer_class = serializers.AccountsGrantedSerializer
@lazyproperty
def user(self) -> User:
user_id = self.kwargs.get('pk')
return User.objects.get(id=user_id)
@lazyproperty
def asset(self):
asset_id = self.kwargs.get('asset_id')
kwargs = {'id': asset_id, 'is_active': True}
asset = get_object_or_404(Asset, **kwargs)
return asset
def get_queryset(self):
accounts = PermAccountUtil().get_perm_accounts_for_user_asset(
self.user, self.asset, with_actions=True
)
return accounts
class MyGrantedAssetAccountsApi(UserGrantedAssetAccountsApi):
permission_classes = (IsValidUser,)
@lazyproperty
def user(self):
return self.request.user
class UserGrantedAssetSpecialAccountsApi(ListAPIView):
serializer_class = serializers.AccountsGrantedSerializer
@lazyproperty
def user(self):
return self.request.user
def get_queryset(self):
# 构造默认包含的账号,如: @INPUT @USER
accounts = [
Account.get_input_account(),
Account.get_user_account(self.user.username)
]
for account in accounts:
account.actions = Action.ALL
return accounts
class MyGrantedAssetSpecialAccountsApi(UserGrantedAssetSpecialAccountsApi):
permission_classes = (IsValidUser,)
@lazyproperty
def user(self):
return self.request.user

View File

@ -1,84 +0,0 @@
# -*- coding: utf-8 -*-
#
from django.shortcuts import get_object_or_404
from rest_framework.generics import (
ListAPIView, get_object_or_404
)
from common.permissions import IsValidUser
from common.utils import get_logger, lazyproperty
from perms.hands import User, Asset, Account
from perms import serializers
from perms.models import Action
from perms.utils import PermAccountUtil
logger = get_logger(__name__)
__all__ = [
'UserGrantedAssetAccountsApi',
'MyGrantedAssetAccountsApi',
'UserGrantedAssetSpecialAccountsApi',
'MyGrantedAssetSpecialAccountsApi',
]
class UserGrantedAssetAccountsApi(ListAPIView):
serializer_class = serializers.AccountsGrantedSerializer
rbac_perms = {
'list': 'perms.view_userassets'
}
@lazyproperty
def user(self) -> User:
user_id = self.kwargs.get('pk')
return User.objects.get(id=user_id)
@lazyproperty
def asset(self):
asset_id = self.kwargs.get('asset_id')
kwargs = {'id': asset_id, 'is_active': True}
asset = get_object_or_404(Asset, **kwargs)
return asset
def get_queryset(self):
accounts = PermAccountUtil().get_perm_accounts_for_user_asset(
self.user, self.asset, with_actions=True
)
return accounts
class MyGrantedAssetAccountsApi(UserGrantedAssetAccountsApi):
permission_classes = (IsValidUser,)
@lazyproperty
def user(self):
return self.request.user
class UserGrantedAssetSpecialAccountsApi(ListAPIView):
serializer_class = serializers.AccountsGrantedSerializer
rbac_perms = {
'list': 'perms.view_userassets'
}
@lazyproperty
def user(self):
return self.request.user
def get_queryset(self):
# 构造默认包含的账号,如: @INPUT @USER
accounts = [
Account.get_input_account(),
Account.get_user_account(self.user.username)
]
for account in accounts:
account.actions = Action.ALL
return accounts
class MyGrantedAssetSpecialAccountsApi(UserGrantedAssetSpecialAccountsApi):
permission_classes = (IsValidUser,)
@lazyproperty
def user(self):
return self.request.user

View File

@ -39,7 +39,9 @@ class PermAccountUtil(AssetPermissionUtil):
for aid in account_ids:
aid_actions_map[str(aid)] |= actions
account_ids = list(aid_actions_map.keys())
accounts = Account.objects.filter(id__in=account_ids)
accounts = Account.objects.filter(id__in=account_ids).order_by(
'asset__name', 'name', 'username'
)
if with_actions:
for account in accounts:
account.actions = aid_actions_map.get(str(account.id))

View File

@ -52,7 +52,7 @@ class AssetPermissionUtil(object):
.values_list('assetpermission_id', flat=True).distinct()
perm_ids.update(asset_perm_ids)
if with_node:
nodes = asset.get_all_nodes(flat=True)
nodes = asset.get_all_nodes()
node_perm_ids = self.get_permissions_for_nodes(nodes, flat=True)
perm_ids.update(node_perm_ids)
if flat: