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

View File

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

View File

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

View File

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

View File

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

View File

@ -65,8 +65,8 @@ class AssetSerializer(OrgResourceSerializerMixin, WritableNestedModelSerializer)
platform = ObjectRelatedField(required=False, queryset=Platform.objects, label=_('Platform')) platform = ObjectRelatedField(required=False, queryset=Platform.objects, label=_('Platform'))
nodes = ObjectRelatedField(many=True, required=False, queryset=Node.objects, label=_('Nodes')) nodes = ObjectRelatedField(many=True, required=False, queryset=Node.objects, label=_('Nodes'))
labels = AssetLabelSerializer(many=True, required=False, label=_('Labels')) labels = AssetLabelSerializer(many=True, required=False, label=_('Labels'))
accounts = AssetAccountSerializer(many=True, required=False, label=_('Accounts'))
protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols')) protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols'))
accounts = AssetAccountSerializer(many=True, required=False, label=_('Accounts'))
class Meta: class Meta:
model = Asset model = Asset
@ -74,7 +74,7 @@ class AssetSerializer(OrgResourceSerializerMixin, WritableNestedModelSerializer)
fields_small = fields_mini + ['is_active', 'comment'] fields_small = fields_mini + ['is_active', 'comment']
fields_fk = ['domain', 'platform', 'platform'] fields_fk = ['domain', 'platform', 'platform']
fields_m2m = [ fields_m2m = [
'nodes', 'labels', 'accounts', 'protocols', 'nodes_display', 'nodes', 'labels', 'protocols', 'accounts', 'nodes_display',
] ]
read_only_fields = [ read_only_fields = [
'category', 'type', 'specific', '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): def push_accounts_to_assets(account_ids, asset_ids):
from assets.models import Asset, Account from assets.models import Asset, Account
with tmp_to_root_org(): with tmp_to_root_org():
assets = Asset.objects.get(id=asset_ids) assets = Asset.objects.filter(id__in=asset_ids)
accounts = Account.objects.get(id=account_ids) accounts = Account.objects.filter(id__in=account_ids)
return push_accounts_to_assets_util(accounts, assets) 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): def verify_accounts_connectivity(account_ids, asset_ids):
from assets.models import Asset, Account from assets.models import Asset, Account
with tmp_to_root_org(): with tmp_to_root_org():
assets = Asset.objects.get(id=asset_ids) assets = Asset.objects.filter(id__in=asset_ids)
accounts = Account.objects.get(id=account_ids) accounts = Account.objects.filter(id__in=account_ids)
task_name = gettext_noop("Verify accounts connectivity") task_name = gettext_noop("Verify accounts connectivity")
return verify_accounts_connectivity_util(accounts, assets, task_name) return verify_accounts_connectivity_util(accounts, assets, task_name)

View File

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from .common import *
from .nodes import * from .nodes import *
from .assets import * from .assets import *
from .nodes_with_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 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 from .mixin import RoleAdminMixin, RoleUserMixin
logger = get_logger(__name__)
__all__ = ['UserAllGrantedAccountsApi', 'MyAllGrantedAccountsApi']
class UserAllGrantedAccountsApi(RoleAdminMixin, generics.ListAPIView): __all__ = [
'UserAllGrantedAccountsApi',
'MyAllGrantedAccountsApi',
'UserGrantedAssetAccountsApi',
'MyGrantedAssetAccountsApi',
'UserGrantedAssetSpecialAccountsApi',
'MyGrantedAssetSpecialAccountsApi',
]
class UserAllGrantedAccountsApi(RoleAdminMixin, ListAPIView):
""" 授权给用户的所有账号列表 """ """ 授权给用户的所有账号列表 """
serializer_class = AccountSerializer serializer_class = AccountSerializer
filterset_fields = ("name", "username", "privileged", "version") filterset_fields = ("name", "username", "privileged", "version")
@ -22,3 +38,59 @@ class UserAllGrantedAccountsApi(RoleAdminMixin, generics.ListAPIView):
class MyAllGrantedAccountsApi(RoleUserMixin, UserAllGrantedAccountsApi): class MyAllGrantedAccountsApi(RoleUserMixin, UserAllGrantedAccountsApi):
""" 授权给我的所有账号列表 """ """ 授权给我的所有账号列表 """
pass 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: for aid in account_ids:
aid_actions_map[str(aid)] |= actions aid_actions_map[str(aid)] |= actions
account_ids = list(aid_actions_map.keys()) 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: if with_actions:
for account in accounts: for account in accounts:
account.actions = aid_actions_map.get(str(account.id)) 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() .values_list('assetpermission_id', flat=True).distinct()
perm_ids.update(asset_perm_ids) perm_ids.update(asset_perm_ids)
if with_node: 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) node_perm_ids = self.get_permissions_for_nodes(nodes, flat=True)
perm_ids.update(node_perm_ids) perm_ids.update(node_perm_ids)
if flat: if flat: