mirror of https://github.com/jumpserver/jumpserver
Merge pull request #4282 from jumpserver/dev_master
merge: Merge to master from branch devpull/4280/head
commit
f588093cd3
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
|
|
||||||
##### 使用版本
|
##### 使用版本
|
||||||
[请提供你使用的Jumpserver版本 1.x.x 注: 0.3.x不再提供支持]
|
[请提供你使用的JumpServer版本 如 2.0.1 注: 1.4及以下版本不再提供支持]
|
||||||
|
|
||||||
##### 问题复现步骤
|
##### 问题复现步骤
|
||||||
1. [步骤1]
|
1. [步骤1]
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
name-template: 'v$RESOLVED_VERSION'
|
||||||
|
tag-template: 'v$RESOLVED_VERSION'
|
||||||
|
categories:
|
||||||
|
- title: '🌱 新功能 Features'
|
||||||
|
labels:
|
||||||
|
- 'feature'
|
||||||
|
- 'enhancement'
|
||||||
|
- 'feat'
|
||||||
|
- '新功能'
|
||||||
|
- title: '🚀 性能优化 Optimization'
|
||||||
|
labels:
|
||||||
|
- 'perf'
|
||||||
|
- 'opt'
|
||||||
|
- 'refactor'
|
||||||
|
- 'Optimization'
|
||||||
|
- '优化'
|
||||||
|
- title: '🐛 Bug修复 Bug Fixes'
|
||||||
|
labels:
|
||||||
|
- 'fix'
|
||||||
|
- 'bugfix'
|
||||||
|
- 'bug'
|
||||||
|
- title: '🧰 其它 Maintenance'
|
||||||
|
labels:
|
||||||
|
- 'chore'
|
||||||
|
- 'docs'
|
||||||
|
exclude-labels:
|
||||||
|
- 'no'
|
||||||
|
- '无需处理'
|
||||||
|
- 'wontfix'
|
||||||
|
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
|
||||||
|
version-resolver:
|
||||||
|
major:
|
||||||
|
labels:
|
||||||
|
- 'major'
|
||||||
|
minor:
|
||||||
|
labels:
|
||||||
|
- 'minor'
|
||||||
|
patch:
|
||||||
|
labels:
|
||||||
|
- 'patch'
|
||||||
|
default: patch
|
||||||
|
template: |
|
||||||
|
## 版本变化 What’s Changed
|
||||||
|
$CHANGES
|
|
@ -0,0 +1,46 @@
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
# Sequence of patterns matched against refs/tags
|
||||||
|
tags:
|
||||||
|
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||||
|
|
||||||
|
name: Create Release And Upload assets
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
create-realese:
|
||||||
|
name: Create Release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Get version
|
||||||
|
id: get_version
|
||||||
|
run: |
|
||||||
|
TAG=$(basename ${GITHUB_REF})
|
||||||
|
VERSION=${TAG/v/}
|
||||||
|
echo "::set-output name=TAG::$TAG"
|
||||||
|
echo "::set-output name=VERSION::$VERSION"
|
||||||
|
- name: Create Release
|
||||||
|
id: create_release
|
||||||
|
uses: release-drafter/release-drafter@v5
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
config-name: release-config.yml
|
||||||
|
version: ${{ steps.get_version.outputs.TAG }}
|
||||||
|
tag: ${{ steps.get_version.outputs.TAG }}
|
||||||
|
|
||||||
|
build-and-release:
|
||||||
|
needs: create-realese
|
||||||
|
name: Build and Release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Build it and upload
|
||||||
|
uses: jumpserver/action-build-upload-assets@master
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ needs.create-realese.outputs.upload_url }}
|
|
@ -35,4 +35,6 @@ docs/_build/
|
||||||
xpack
|
xpack
|
||||||
logs/*
|
logs/*
|
||||||
### Vagrant ###
|
### Vagrant ###
|
||||||
.vagrant/
|
.vagrant/
|
||||||
|
release/*
|
||||||
|
releashe
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
[![Python3](https://img.shields.io/badge/python-3.6-green.svg?style=plastic)](https://www.python.org/)
|
[![Python3](https://img.shields.io/badge/python-3.6-green.svg?style=plastic)](https://www.python.org/)
|
||||||
[![Django](https://img.shields.io/badge/django-2.2-brightgreen.svg?style=plastic)](https://www.djangoproject.com/)
|
[![Django](https://img.shields.io/badge/django-2.2-brightgreen.svg?style=plastic)](https://www.djangoproject.com/)
|
||||||
|
[![Docker Pulls](https://img.shields.io/docker/pulls/jumpserver/jms_all.svg)](https://hub.docker.com/u/jumpserver)
|
||||||
|
|
||||||
JumpServer 是全球首款开源的堡垒机,使用 GNU GPL v2.0 开源协议,是符合 4A 规范的运维安全审计系统。
|
JumpServer 是全球首款开源的堡垒机,使用 GNU GPL v2.0 开源协议,是符合 4A 规范的运维安全审计系统。
|
||||||
|
|
||||||
|
|
|
@ -18,5 +18,5 @@ class GatheredUserViewSet(OrgModelViewSet):
|
||||||
permission_classes = [IsOrgAdmin]
|
permission_classes = [IsOrgAdmin]
|
||||||
extra_filter_backends = [AssetRelatedByNodeFilterBackend]
|
extra_filter_backends = [AssetRelatedByNodeFilterBackend]
|
||||||
|
|
||||||
filter_fields = ['asset', 'username', 'present', 'asset__ip', 'asset__hostname']
|
filter_fields = ['asset', 'username', 'present', 'asset__ip', 'asset__hostname', 'asset_id']
|
||||||
search_fields = ['username', 'asset__ip', 'asset__hostname']
|
search_fields = ['username', 'asset__ip', 'asset__hostname']
|
||||||
|
|
|
@ -28,7 +28,7 @@ class SystemUserViewSet(OrgBulkModelViewSet):
|
||||||
System user api set, for add,delete,update,list,retrieve resource
|
System user api set, for add,delete,update,list,retrieve resource
|
||||||
"""
|
"""
|
||||||
model = SystemUser
|
model = SystemUser
|
||||||
filter_fields = ("name", "username")
|
filter_fields = ("name", "username", "protocol")
|
||||||
search_fields = filter_fields
|
search_fields = filter_fields
|
||||||
serializer_class = serializers.SystemUserSerializer
|
serializer_class = serializers.SystemUserSerializer
|
||||||
serializer_classes = {
|
serializer_classes = {
|
||||||
|
|
|
@ -27,6 +27,7 @@ class FTPLogViewSet(CreateModelMixin,
|
||||||
]
|
]
|
||||||
filter_fields = ['user', 'asset', 'system_user', 'filename']
|
filter_fields = ['user', 'asset', 'system_user', 'filename']
|
||||||
search_fields = filter_fields
|
search_fields = filter_fields
|
||||||
|
ordering = ['-date_start']
|
||||||
|
|
||||||
|
|
||||||
class UserLoginLogViewSet(ListModelMixin, CommonGenericViewSet):
|
class UserLoginLogViewSet(ListModelMixin, CommonGenericViewSet):
|
||||||
|
|
|
@ -30,7 +30,7 @@ class JMSCSVRender(BaseRenderer):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _gen_table(data, fields):
|
def _gen_table(data, fields):
|
||||||
data = data[:100]
|
data = data[:10000]
|
||||||
yield ['*{}'.format(f.label) if f.required else f.label for f in fields]
|
yield ['*{}'.format(f.label) if f.required else f.label for f in fields]
|
||||||
|
|
||||||
for item in data:
|
for item in data:
|
||||||
|
|
|
@ -10,3 +10,7 @@ class HttpResponseTemporaryRedirect(HttpResponse):
|
||||||
def __init__(self, redirect_to):
|
def __init__(self, redirect_to):
|
||||||
HttpResponse.__init__(self)
|
HttpResponse.__init__(self)
|
||||||
self['Location'] = iri_to_uri(redirect_to)
|
self['Location'] = iri_to_uri(redirect_to)
|
||||||
|
|
||||||
|
|
||||||
|
def get_remote_addr(request):
|
||||||
|
return request.META.get("HTTP_X_FORWARDED_HOST") or request.META.get("REMOTE_ADDR")
|
||||||
|
|
|
@ -260,7 +260,8 @@ class Config(dict):
|
||||||
'WINDOWS_SKIP_ALL_MANUAL_PASSWORD': False,
|
'WINDOWS_SKIP_ALL_MANUAL_PASSWORD': False,
|
||||||
'ORG_CHANGE_TO_URL': '',
|
'ORG_CHANGE_TO_URL': '',
|
||||||
'LANGUAGE_CODE': 'zh',
|
'LANGUAGE_CODE': 'zh',
|
||||||
'TIME_ZONE': 'Asia/Shanghai'
|
'TIME_ZONE': 'Asia/Shanghai',
|
||||||
|
'CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED': True
|
||||||
}
|
}
|
||||||
|
|
||||||
def compatible_auth_openid_of_key(self):
|
def compatible_auth_openid_of_key(self):
|
||||||
|
|
|
@ -86,7 +86,11 @@ TASK_LOG_KEEP_DAYS = CONFIG.TASK_LOG_KEEP_DAYS
|
||||||
ORG_CHANGE_TO_URL = CONFIG.ORG_CHANGE_TO_URL
|
ORG_CHANGE_TO_URL = CONFIG.ORG_CHANGE_TO_URL
|
||||||
WINDOWS_SKIP_ALL_MANUAL_PASSWORD = CONFIG.WINDOWS_SKIP_ALL_MANUAL_PASSWORD
|
WINDOWS_SKIP_ALL_MANUAL_PASSWORD = CONFIG.WINDOWS_SKIP_ALL_MANUAL_PASSWORD
|
||||||
|
|
||||||
|
AUTH_EXPIRED_SECONDS = 60 * 5
|
||||||
|
|
||||||
# XPACK
|
# XPACK
|
||||||
XPACK_LICENSE_IS_VALID = DYNAMIC.XPACK_LICENSE_IS_VALID
|
XPACK_LICENSE_IS_VALID = DYNAMIC.XPACK_LICENSE_IS_VALID
|
||||||
|
|
||||||
LOGO_URLS = DYNAMIC.LOGO_URLS
|
LOGO_URLS = DYNAMIC.LOGO_URLS
|
||||||
|
|
||||||
|
CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED = CONFIG.CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from common.permissions import PermissionsMixin, IsValidUser
|
from common.permissions import PermissionsMixin, IsValidUser
|
||||||
|
|
||||||
|
@ -12,17 +11,3 @@ class IndexView(PermissionsMixin, TemplateView):
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
return redirect('/ui/')
|
return redirect('/ui/')
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
|
||||||
if not request.user.is_authenticated:
|
|
||||||
return self.handle_no_permission()
|
|
||||||
if request.user.is_common_user:
|
|
||||||
return redirect('assets:user-asset-list')
|
|
||||||
return super(IndexView, self).dispatch(request, *args, **kwargs)
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = super().get_context_data(**kwargs)
|
|
||||||
context.update({
|
|
||||||
'app': _("Dashboard"),
|
|
||||||
})
|
|
||||||
return context
|
|
||||||
|
|
Binary file not shown.
|
@ -3850,7 +3850,7 @@ msgstr "腾讯云"
|
||||||
|
|
||||||
#: xpack/plugins/cloud/serializers.py:56
|
#: xpack/plugins/cloud/serializers.py:56
|
||||||
msgid "History count"
|
msgid "History count"
|
||||||
msgstr "用户数量"
|
msgstr "执行次数"
|
||||||
|
|
||||||
#: xpack/plugins/cloud/serializers.py:57
|
#: xpack/plugins/cloud/serializers.py:57
|
||||||
msgid "Instance count"
|
msgid "Instance count"
|
||||||
|
|
|
@ -5,8 +5,8 @@ import re
|
||||||
import pyotp
|
import pyotp
|
||||||
import base64
|
import base64
|
||||||
import logging
|
import logging
|
||||||
|
import time
|
||||||
|
|
||||||
from django.http import Http404
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
@ -333,3 +333,15 @@ def get_source_choices():
|
||||||
if settings.AUTH_CAS:
|
if settings.AUTH_CAS:
|
||||||
choices.append((User.SOURCE_CAS, choices_all[User.SOURCE_CAS]))
|
choices.append((User.SOURCE_CAS, choices_all[User.SOURCE_CAS]))
|
||||||
return choices
|
return choices
|
||||||
|
|
||||||
|
|
||||||
|
def is_auth_time_valid(session, key):
|
||||||
|
return True if session.get(key, 0) > time.time() else False
|
||||||
|
|
||||||
|
|
||||||
|
def is_auth_password_time_valid(session):
|
||||||
|
return is_auth_time_valid(session, 'auth_password_expired_at')
|
||||||
|
|
||||||
|
|
||||||
|
def is_auth_otp_time_valid(session):
|
||||||
|
return is_auth_time_valid(session, 'auth_opt_expired_at')
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# ~*~ coding: utf-8 ~*~
|
# ~*~ coding: utf-8 ~*~
|
||||||
|
import time
|
||||||
|
|
||||||
from django.urls import reverse_lazy, reverse
|
from django.urls import reverse_lazy, reverse
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
@ -6,13 +7,17 @@ from django.views.generic.base import TemplateView
|
||||||
from django.views.generic.edit import FormView
|
from django.views.generic.edit import FormView
|
||||||
from django.contrib.auth import logout as auth_logout
|
from django.contrib.auth import logout as auth_logout
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.http.response import HttpResponseForbidden
|
||||||
|
|
||||||
from common.utils import get_logger
|
from authentication.mixins import AuthMixin
|
||||||
|
from users.models import User
|
||||||
|
from common.utils import get_logger, get_object_or_none
|
||||||
from common.permissions import IsValidUser
|
from common.permissions import IsValidUser
|
||||||
from ... import forms
|
from ... import forms
|
||||||
from .password import UserVerifyPasswordView
|
from .password import UserVerifyPasswordView
|
||||||
from ...utils import (
|
from ...utils import (
|
||||||
generate_otp_uri, check_otp_code, get_user_or_pre_auth_user,
|
generate_otp_uri, check_otp_code, get_user_or_pre_auth_user,
|
||||||
|
is_auth_password_time_valid, is_auth_otp_time_valid
|
||||||
)
|
)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
@ -46,11 +51,50 @@ class UserOtpEnableInstallAppView(TemplateView):
|
||||||
return super().get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class UserOtpEnableBindView(TemplateView, FormView):
|
class UserOtpEnableBindView(AuthMixin, TemplateView, FormView):
|
||||||
template_name = 'users/user_otp_enable_bind.html'
|
template_name = 'users/user_otp_enable_bind.html'
|
||||||
form_class = forms.UserCheckOtpCodeForm
|
form_class = forms.UserCheckOtpCodeForm
|
||||||
success_url = reverse_lazy('authentication:user-otp-settings-success')
|
success_url = reverse_lazy('authentication:user-otp-settings-success')
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
if self._check_can_bind():
|
||||||
|
return super().get(request, *args, **kwargs)
|
||||||
|
return HttpResponseForbidden()
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
if self._check_can_bind():
|
||||||
|
return super().post(request, *args, **kwargs)
|
||||||
|
return HttpResponseForbidden()
|
||||||
|
|
||||||
|
def _check_authenticated_user_can_bind(self):
|
||||||
|
user = self.request.user
|
||||||
|
session = self.request.session
|
||||||
|
|
||||||
|
if not user.mfa_enabled:
|
||||||
|
return is_auth_password_time_valid(session)
|
||||||
|
|
||||||
|
if not user.otp_secret_key:
|
||||||
|
return is_auth_password_time_valid(session)
|
||||||
|
|
||||||
|
return is_auth_otp_time_valid(session)
|
||||||
|
|
||||||
|
def _check_unauthenticated_user_can_bind(self):
|
||||||
|
session_user = None
|
||||||
|
if not self.request.session.is_empty():
|
||||||
|
user_id = self.request.session.get('user_id')
|
||||||
|
session_user = get_object_or_none(User, pk=user_id)
|
||||||
|
|
||||||
|
if session_user:
|
||||||
|
if all((is_auth_password_time_valid(self.request.session), session_user.mfa_enabled, not session_user.otp_secret_key)):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _check_can_bind(self):
|
||||||
|
if self.request.user.is_authenticated:
|
||||||
|
return self._check_authenticated_user_can_bind()
|
||||||
|
else:
|
||||||
|
return self._check_unauthenticated_user_can_bind()
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
otp_code = form.cleaned_data.get('otp_code')
|
otp_code = form.cleaned_data.get('otp_code')
|
||||||
otp_secret_key = self.request.session.get('otp_secret_key', '')
|
otp_secret_key = self.request.session.get('otp_secret_key', '')
|
||||||
|
@ -116,6 +160,7 @@ class UserOtpUpdateView(FormView):
|
||||||
|
|
||||||
valid = user.check_mfa(otp_code)
|
valid = user.check_mfa(otp_code)
|
||||||
if valid:
|
if valid:
|
||||||
|
self.request.session['auth_opt_expired_at'] = time.time() + settings.AUTH_EXPIRED_SECONDS
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
else:
|
else:
|
||||||
error = _('MFA code invalid, or ntp sync server time')
|
error = _('MFA code invalid, or ntp sync server time')
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
# ~*~ coding: utf-8 ~*~
|
# ~*~ coding: utf-8 ~*~
|
||||||
|
import time
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.contrib.auth import authenticate
|
from django.contrib.auth import authenticate
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.urls import reverse_lazy, reverse
|
from django.urls import reverse_lazy
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.views.generic.edit import UpdateView, FormView
|
from django.views.generic.edit import UpdateView, FormView
|
||||||
from django.contrib.auth import logout as auth_logout
|
from django.contrib.auth import logout as auth_logout
|
||||||
|
@ -76,6 +78,7 @@ class UserVerifyPasswordView(FormView):
|
||||||
user.save()
|
user.save()
|
||||||
self.request.session['user_id'] = str(user.id)
|
self.request.session['user_id'] = str(user.id)
|
||||||
self.request.session['auth_password'] = 1
|
self.request.session['auth_password'] = 1
|
||||||
|
self.request.session['auth_password_expired_at'] = time.time() + settings.AUTH_EXPIRED_SECONDS
|
||||||
return redirect(self.get_success_url())
|
return redirect(self.get_success_url())
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
|
|
11
build.sh
11
build.sh
|
@ -1,11 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
|
|
||||||
version=$1
|
|
||||||
if [ -z "$version" ];then
|
|
||||||
echo "Usage: sh build version"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
docker build -t jumpserver/jumpserver:$version .
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# 该build基于registry.fit2cloud.com/public/python:3
|
||||||
|
utils_dir=$(pwd)
|
||||||
|
project_dir=$(dirname "$utils_dir")
|
||||||
|
release_dir=${project_dir}/release
|
||||||
|
|
||||||
|
# 安装依赖包
|
||||||
|
command -v git || yum -y install git
|
||||||
|
|
||||||
|
# 打包
|
||||||
|
cd "${project_dir}" || exit 3
|
||||||
|
rm -rf "${release_dir:?}/*"
|
||||||
|
to_dir="${release_dir}/jumpserver"
|
||||||
|
mkdir -p "${to_dir}"
|
||||||
|
git archive --format tar HEAD | tar x -C "${to_dir}"
|
||||||
|
|
||||||
|
if [[ $(uname) == 'Darwin' ]];then
|
||||||
|
alias sedi="sed -i ''"
|
||||||
|
else
|
||||||
|
alias sedi='sed -i'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 修改版本号文件
|
||||||
|
if [[ -n ${VERSION} ]]; then
|
||||||
|
sedi "s@VERSION = .*@VERSION = \"${VERSION}\"@g" "${to_dir}/apps/jumpserver/const.py"
|
||||||
|
fi
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
utils_dir=$(dirname "$0")
|
||||||
|
project_dir=$(dirname "${utils_dir}")
|
||||||
|
|
||||||
|
version=$1
|
||||||
|
if [ -z "$version" ]; then
|
||||||
|
echo "Usage: sh build version"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "${project_dir}" && docker build -t "jumpserver/jumpserver:${version}" .
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
import requests
|
||||||
|
|
||||||
|
# 私有token页面上目前不允许创建,只能后台生成,见 https://docs.jumpserver.org/zh/master/dev/rest_api/
|
||||||
|
private_token = '10659d70a223235b8f76d45a3023eca1147488d7'
|
||||||
|
|
||||||
|
|
||||||
|
def do_request(url, data=None, method='get', params=None, org_id=''):
|
||||||
|
authorization = 'Token {}'.format(private_token)
|
||||||
|
headers = {'Authorization': authorization, 'Content-Type': 'application/json'}
|
||||||
|
if org_id:
|
||||||
|
headers['X-JMS-ORG'] = org_id
|
||||||
|
resp = requests.request(method=method, url=url, data=data, params=params, headers=headers)
|
||||||
|
return resp
|
||||||
|
|
||||||
|
|
||||||
|
def get_assets_list():
|
||||||
|
url = 'http://localhost:8080/api/v1/assets/assets/?limit=10'
|
||||||
|
resp = do_request(url)
|
||||||
|
print(resp.status_code)
|
||||||
|
print(resp.json())
|
||||||
|
print(resp)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
get_assets_list()
|
Loading…
Reference in New Issue