mirror of https://github.com/jumpserver/jumpserver
Merge branch 'pam' of github.com:jumpserver/jumpserver into pam
commit
d052b2a808
|
@ -1,8 +1,6 @@
|
||||||
import os
|
import os
|
||||||
|
from django.utils.translation import gettext_lazy as _, get_language
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils import translation
|
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
@ -34,16 +32,25 @@ class IntegrationApplicationViewSet(OrgBulkModelViewSet):
|
||||||
permission_classes=[IsValidUser]
|
permission_classes=[IsValidUser]
|
||||||
)
|
)
|
||||||
def get_sdks_info(self, request, *args, **kwargs):
|
def get_sdks_info(self, request, *args, **kwargs):
|
||||||
readme = ''
|
code_suffix_mapper = {
|
||||||
sdk_language = self.request.query_params.get('language', 'python')
|
'python': 'py',
|
||||||
filename = f'readme.{translation.get_language()}.md'
|
'java': 'java',
|
||||||
readme_path = os.path.join(
|
'go': 'go',
|
||||||
settings.APPS_DIR, 'accounts', 'demos', sdk_language, filename
|
'javascript': 'js',
|
||||||
)
|
'php': 'php',
|
||||||
if os.path.exists(readme_path):
|
}
|
||||||
with open(readme_path, 'r') as f:
|
sdk_language = request.query_params.get('language','python')
|
||||||
readme = f.read()
|
sdk_path = os.path.join(settings.APPS_DIR, 'accounts', 'demos', sdk_language)
|
||||||
return Response(data={'readme': readme})
|
readme_path = os.path.join(sdk_path, f'readme.{get_language()}.md')
|
||||||
|
demo_path = os.path.join(sdk_path, f'demo.{code_suffix_mapper[sdk_language]}')
|
||||||
|
|
||||||
|
def read_file(path):
|
||||||
|
if os.path.exists(path):
|
||||||
|
with open(path, 'r', encoding='utf-8') as f:
|
||||||
|
return f.read()
|
||||||
|
return ''
|
||||||
|
|
||||||
|
return Response(data={'readme': read_file(readme_path), 'code': read_file(demo_path)})
|
||||||
|
|
||||||
@action(
|
@action(
|
||||||
['GET'], detail=True, url_path='secret',
|
['GET'], detail=True, url_path='secret',
|
||||||
|
|
|
@ -37,7 +37,7 @@ class PamDashboardApi(APIView):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_account_risk_data(_all, query_params):
|
def get_account_risk_data(_all, query_params):
|
||||||
agg_map = {
|
agg_map = {
|
||||||
'total_privileged_accounts': ('long_time_no_login_count', Q(risk='long_time_no_login')),
|
'total_long_time_no_login_accounts': ('long_time_no_login_count', Q(risk='long_time_no_login')),
|
||||||
'total_new_found_accounts': ('new_found_count', Q(risk='new_found')),
|
'total_new_found_accounts': ('new_found_count', Q(risk='new_found')),
|
||||||
'total_group_changed_accounts': ('group_changed_count', Q(risk='group_changed')),
|
'total_group_changed_accounts': ('group_changed_count', Q(risk='group_changed')),
|
||||||
'total_sudo_changed_accounts': ('sudo_changed_count', Q(risk='sudo_changed')),
|
'total_sudo_changed_accounts': ('sudo_changed_count', Q(risk='sudo_changed')),
|
||||||
|
@ -74,7 +74,7 @@ class PamDashboardApi(APIView):
|
||||||
'total_privileged_accounts': ('privileged_count', Count('id', filter=Q(privileged=True))),
|
'total_privileged_accounts': ('privileged_count', Count('id', filter=Q(privileged=True))),
|
||||||
'total_connectivity_ok_accounts': ('connectivity_ok_count', Count('id', filter=Q(connectivity='ok'))),
|
'total_connectivity_ok_accounts': ('connectivity_ok_count', Count('id', filter=Q(connectivity='ok'))),
|
||||||
'total_secret_reset_accounts': ('secret_reset_count', Count('id', filter=Q(secret_reset=True))),
|
'total_secret_reset_accounts': ('secret_reset_count', Count('id', filter=Q(secret_reset=True))),
|
||||||
'total_unavailable_accounts': ('unavailable_count', Count('id', filter=Q(is_active=False))),
|
'total_valid_accounts': ('valid_count', Count('id', filter=Q(is_active=True))),
|
||||||
'total_week_add_accounts': ('week_add_count', Count('id', filter=Q(date_created__gte=local_monday()))),
|
'total_week_add_accounts': ('week_add_count', Count('id', filter=Q(date_created__gte=local_monday()))),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,6 @@ class PamDashboardApi(APIView):
|
||||||
'total_count_gathered_account_automation': GatherAccountsAutomation,
|
'total_count_gathered_account_automation': GatherAccountsAutomation,
|
||||||
'total_count_push_account_automation': PushAccountAutomation,
|
'total_count_push_account_automation': PushAccountAutomation,
|
||||||
'total_count_backup_account_automation': BackupAccountAutomation,
|
'total_count_backup_account_automation': BackupAccountAutomation,
|
||||||
'total_count_risk_account': AccountRisk,
|
|
||||||
'total_count_integration_application': IntegrationApplication,
|
'total_count_integration_application': IntegrationApplication,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,121 +1,45 @@
|
||||||
```go
|
# 使用说明
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
## 1. 简介
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type APIClient struct {
|
本 API 提供了 PAM 查看资产账号服务,支持 RESTful 风格的调用,返回数据采用 JSON 格式。
|
||||||
Client *http.Client
|
|
||||||
APIURL string
|
|
||||||
KeyID string
|
|
||||||
KeySecret string
|
|
||||||
OrgID string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewAPIClient() *APIClient {
|
## 2. 环境要求
|
||||||
return &APIClient{
|
|
||||||
Client: &http.Client{},
|
|
||||||
APIURL: getEnv("API_URL", "http://127.0.0.1:8080"),
|
|
||||||
KeyID: getEnv("API_KEY_ID", "72b0b0aa-ad82-4182-a631-ae4865e8ae0e"),
|
|
||||||
KeySecret: getEnv("API_KEY_SECRET", "6fuSO7P1m4cj8SSlgaYdblOjNAmnxDVD7tr8"),
|
|
||||||
OrgID: getEnv("ORG_ID", "00000000-0000-0000-0000-000000000002"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getEnv(key, defaultValue string) string {
|
- `Go 1.16+`
|
||||||
value := os.Getenv(key)
|
- `crypto/hmac`
|
||||||
if value == "" {
|
- `crypto/sha256`
|
||||||
return defaultValue
|
- `encoding/base64`
|
||||||
}
|
- `net/http`
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *APIClient) GetAccountSecret(asset, account string) (map[string]interface{}, error) {
|
## 3. 使用方法
|
||||||
u, err := url.Parse(c.APIURL)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to parse API URL: %v", err)
|
|
||||||
}
|
|
||||||
u.Path = "/api/v1/accounts/integration-applications/account-secret/"
|
|
||||||
|
|
||||||
q := u.Query()
|
**请求方式**: `GET api/v1/accounts/integration-applications/account-secret/`
|
||||||
q.Add("asset", asset)
|
|
||||||
q.Add("account", account)
|
|
||||||
u.RawQuery = q.Encode()
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", u.String(), nil)
|
**请求参数**
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create request: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
date := time.Now().UTC().Format("Mon, 02 Jan 2006 15:04:05 GMT")
|
| 参数名 | 类型 | 必填 | 说明 |
|
||||||
req.Header.Set("Accept", "application/json")
|
|----------|------|-----|---------------|
|
||||||
req.Header.Set("X-JMS-ORG", c.OrgID)
|
| asset | str | 是 | 资产 ID / 资产名称 |
|
||||||
req.Header.Set("Date", date)
|
| account | str | 是 | 账号 ID / 账号名称 |
|
||||||
req.Header.Set("X-Source", "jms-pam")
|
|
||||||
|
|
||||||
headersList := []string{"(request-target)", "accept", "date", "x-jms-org"}
|
**响应示例**:
|
||||||
var signatureParts []string
|
```json
|
||||||
|
{
|
||||||
for _, h := range headersList {
|
"id": "72b0b0aa-ad82-4182-a631-ae4865e8ae0e",
|
||||||
var value string
|
"secret": "123456"
|
||||||
if h == "(request-target)" {
|
|
||||||
value = strings.ToLower(req.Method) + " " + req.URL.RequestURI()
|
|
||||||
} else {
|
|
||||||
canonicalKey := http.CanonicalHeaderKey(h)
|
|
||||||
value = req.Header.Get(canonicalKey)
|
|
||||||
}
|
|
||||||
signatureParts = append(signatureParts, fmt.Sprintf("%s: %s", h, value))
|
|
||||||
}
|
|
||||||
|
|
||||||
signatureString := strings.Join(signatureParts, "\n")
|
|
||||||
mac := hmac.New(sha256.New, []byte(c.KeySecret))
|
|
||||||
mac.Write([]byte(signatureString))
|
|
||||||
signatureB64 := base64.StdEncoding.EncodeToString(mac.Sum(nil))
|
|
||||||
|
|
||||||
headersJoined := strings.Join(headersList, " ")
|
|
||||||
authHeader := fmt.Sprintf(
|
|
||||||
`Signature keyId="%s",algorithm="hmac-sha256",headers="%s",signature="%s"`,
|
|
||||||
c.KeyID,
|
|
||||||
headersJoined,
|
|
||||||
signatureB64,
|
|
||||||
)
|
|
||||||
req.Header.Set("Authorization", authHeader)
|
|
||||||
|
|
||||||
resp, err := c.Client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("request failed: %v", err)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return nil, fmt.Errorf("API returned non-200 status: %d", resp.StatusCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
var result map[string]interface{}
|
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to decode response: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
client := NewAPIClient()
|
|
||||||
result, err := client.GetAccountSecret("ubuntu_docker", "root")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error: %v", err)
|
|
||||||
}
|
|
||||||
fmt.Printf("Result: %+v\n", result)
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 常见问题(FAQ)
|
||||||
|
|
||||||
|
Q: API Key 如何获取?
|
||||||
|
|
||||||
|
A: 你可以在 PAM - 应用管理 创建应用生成 KEY_ID 和 KEY_SECRET。
|
||||||
|
|
||||||
|
## 版本历史(Changelog)
|
||||||
|
|
||||||
|
|
||||||
|
| 版本号 | 变更内容 | 日期 |
|
||||||
|
| ----- | ----------------- |------------|
|
||||||
|
| 1.0.0 | 初始版本 | 2025-02-11 |
|
|
@ -0,0 +1,119 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type APIClient struct {
|
||||||
|
Client *http.Client
|
||||||
|
APIURL string
|
||||||
|
KeyID string
|
||||||
|
KeySecret string
|
||||||
|
OrgID string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAPIClient() *APIClient {
|
||||||
|
return &APIClient{
|
||||||
|
Client: &http.Client{},
|
||||||
|
APIURL: getEnv("API_URL", "http://127.0.0.1:8080"),
|
||||||
|
KeyID: getEnv("API_KEY_ID", "72b0b0aa-ad82-4182-a631-ae4865e8ae0e"),
|
||||||
|
KeySecret: getEnv("API_KEY_SECRET", "6fuSO7P1m4cj8SSlgaYdblOjNAmnxDVD7tr8"),
|
||||||
|
OrgID: getEnv("ORG_ID", "00000000-0000-0000-0000-000000000002"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getEnv(key, defaultValue string) string {
|
||||||
|
value := os.Getenv(key)
|
||||||
|
if value == "" {
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *APIClient) GetAccountSecret(asset, account string) (map[string]interface{}, error) {
|
||||||
|
u, err := url.Parse(c.APIURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse API URL: %v", err)
|
||||||
|
}
|
||||||
|
u.Path = "/api/v1/accounts/integration-applications/account-secret/"
|
||||||
|
|
||||||
|
q := u.Query()
|
||||||
|
q.Add("asset", asset)
|
||||||
|
q.Add("account", account)
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", u.String(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create request: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
date := time.Now().UTC().Format("Mon, 02 Jan 2006 15:04:05 GMT")
|
||||||
|
req.Header.Set("Accept", "application/json")
|
||||||
|
req.Header.Set("X-JMS-ORG", c.OrgID)
|
||||||
|
req.Header.Set("Date", date)
|
||||||
|
req.Header.Set("X-Source", "jms-pam")
|
||||||
|
|
||||||
|
headersList := []string{"(request-target)", "accept", "date", "x-jms-org"}
|
||||||
|
var signatureParts []string
|
||||||
|
|
||||||
|
for _, h := range headersList {
|
||||||
|
var value string
|
||||||
|
if h == "(request-target)" {
|
||||||
|
value = strings.ToLower(req.Method) + " " + req.URL.RequestURI()
|
||||||
|
} else {
|
||||||
|
canonicalKey := http.CanonicalHeaderKey(h)
|
||||||
|
value = req.Header.Get(canonicalKey)
|
||||||
|
}
|
||||||
|
signatureParts = append(signatureParts, fmt.Sprintf("%s: %s", h, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
signatureString := strings.Join(signatureParts, "\n")
|
||||||
|
mac := hmac.New(sha256.New, []byte(c.KeySecret))
|
||||||
|
mac.Write([]byte(signatureString))
|
||||||
|
signatureB64 := base64.StdEncoding.EncodeToString(mac.Sum(nil))
|
||||||
|
|
||||||
|
headersJoined := strings.Join(headersList, " ")
|
||||||
|
authHeader := fmt.Sprintf(
|
||||||
|
`Signature keyId="%s",algorithm="hmac-sha256",headers="%s",signature="%s"`,
|
||||||
|
c.KeyID,
|
||||||
|
headersJoined,
|
||||||
|
signatureB64,
|
||||||
|
)
|
||||||
|
req.Header.Set("Authorization", authHeader)
|
||||||
|
|
||||||
|
resp, err := c.Client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("request failed: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return nil, fmt.Errorf("API returned non-200 status: %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
var result map[string]interface{}
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to decode response: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
client := NewAPIClient()
|
||||||
|
result, err := client.GetAccountSecret("ubuntu_docker", "root")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Result: %+v\n", result)
|
||||||
|
}
|
|
@ -1,45 +1,42 @@
|
||||||
```python
|
# 使用说明
|
||||||
import requests
|
|
||||||
import os
|
|
||||||
from datetime import datetime
|
|
||||||
from httpsig.requests_auth import HTTPSignatureAuth
|
|
||||||
|
|
||||||
API_URL = os.getenv("API_URL", "http://127.0.0.1:8080")
|
## 1. 简介
|
||||||
KEY_ID = os.getenv("API_KEY_ID", "72b0b0aa-ad82-4182-a631-ae4865e8ae0e")
|
|
||||||
KEY_SECRET = os.getenv("API_KEY_SECRET", "6fuSO7P1m4cj8SSlgaYdblOjNAmnxDVD7tr8")
|
|
||||||
ORG_ID = os.getenv("ORG_ID", "00000000-0000-0000-0000-000000000002")
|
|
||||||
|
|
||||||
|
本 API 提供了 PAM 查看资产账号服务,支持 RESTful 风格的调用,返回数据采用 JSON 格式。
|
||||||
|
|
||||||
class APIClient:
|
## 2. 环境要求
|
||||||
def __init__(self):
|
|
||||||
self.session = requests.Session()
|
|
||||||
self.auth = HTTPSignatureAuth(
|
|
||||||
key_id=KEY_ID, secret=KEY_SECRET,
|
|
||||||
algorithm='hmac-sha256', headers=['(request-target)', 'accept', 'date', 'x-jms-org']
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_account_secret(self, asset, account):
|
- `Python 3.11+`
|
||||||
url = f"{API_URL}/api/v1/accounts/integration-applications/account-secret/"
|
- `requests==2.31.0`
|
||||||
headers = {
|
- `httpsig==1.3.0`
|
||||||
'Accept': 'application/json',
|
|
||||||
'X-JMS-ORG': ORG_ID,
|
## 3. 使用方法
|
||||||
'Date': datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT'),
|
**请求方式**: `GET api/v1/accounts/integration-applications/account-secret/`
|
||||||
'X-Source': 'jms-pam'
|
|
||||||
|
**请求参数**
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 必填 | 说明 |
|
||||||
|
|------------|------|----|--------------|
|
||||||
|
| asset | str | 是 | 资产 ID / 资产名称 |
|
||||||
|
| account | str | 是 | 账号 ID / 账号名称 |
|
||||||
|
|
||||||
|
**响应示例**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "72b0b0aa-ad82-4182-a631-ae4865e8ae0e",
|
||||||
|
"secret": "123456"
|
||||||
}
|
}
|
||||||
params = {"asset": asset, "account": account}
|
|
||||||
|
|
||||||
try:
|
|
||||||
response = self.session.get(url, auth=self.auth, headers=headers, params=params, timeout=10)
|
|
||||||
response.raise_for_status()
|
|
||||||
return response.json()
|
|
||||||
except requests.RequestException as e:
|
|
||||||
print(f"API 请求失败: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
# 示例调用
|
|
||||||
if __name__ == "__main__":
|
|
||||||
client = APIClient()
|
|
||||||
result = client.get_account_secret(asset="ubuntu_docker", account="root")
|
|
||||||
print(result)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 常见问题(FAQ)
|
||||||
|
|
||||||
|
Q: API Key 如何获取?
|
||||||
|
|
||||||
|
A: 你可以在 PAM - 应用管理 创建应用生成 KEY_ID 和 KEY_SECRET。
|
||||||
|
|
||||||
|
## 版本历史(Changelog)
|
||||||
|
|
||||||
|
|
||||||
|
| 版本号 | 变更内容 | 日期 |
|
||||||
|
| ----- | ----------------- |------------|
|
||||||
|
| 1.0.0 | 初始版本 | 2025-02-11 |
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
# 示例调用
|
||||||
|
|
||||||
|
import requests
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
from httpsig.requests_auth import HTTPSignatureAuth
|
||||||
|
|
||||||
|
API_URL = os.getenv("API_URL", "http://127.0.0.1:8080")
|
||||||
|
KEY_ID = os.getenv("API_KEY_ID", "72b0b0aa-ad82-4182-a631-ae4865e8ae0e")
|
||||||
|
KEY_SECRET = os.getenv("API_KEY_SECRET", "6fuSO7P1m4cj8SSlgaYdblOjNAmnxDVD7tr8")
|
||||||
|
ORG_ID = os.getenv("ORG_ID", "00000000-0000-0000-0000-000000000002")
|
||||||
|
|
||||||
|
|
||||||
|
class APIClient:
|
||||||
|
def __init__(self):
|
||||||
|
self.session = requests.Session()
|
||||||
|
self.auth = HTTPSignatureAuth(
|
||||||
|
key_id=KEY_ID, secret=KEY_SECRET,
|
||||||
|
algorithm='hmac-sha256', headers=['(request-target)', 'accept', 'date', 'x-jms-org']
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_account_secret(self, asset, account):
|
||||||
|
url = f"{API_URL}/api/v1/accounts/integration-applications/account-secret/"
|
||||||
|
headers = {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'X-JMS-ORG': ORG_ID,
|
||||||
|
'Date': datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT'),
|
||||||
|
'X-Source': 'jms-pam'
|
||||||
|
}
|
||||||
|
params = {"asset": asset, "account": account}
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = self.session.get(url, auth=self.auth, headers=headers, params=params, timeout=10)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
except requests.RequestException as e:
|
||||||
|
print(f"API 请求失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
client = APIClient()
|
||||||
|
result = client.get_account_secret(asset="ubuntu_docker", account="root")
|
||||||
|
print(result)
|
|
@ -351,6 +351,7 @@
|
||||||
"ConvenientOperate": "Convenient action",
|
"ConvenientOperate": "Convenient action",
|
||||||
"Copy": "Copy",
|
"Copy": "Copy",
|
||||||
"CopySuccess": "Copy successful",
|
"CopySuccess": "Copy successful",
|
||||||
|
"CopyFailed": "Copy failed",
|
||||||
"Corporation": "Company",
|
"Corporation": "Company",
|
||||||
"Create": "Create",
|
"Create": "Create",
|
||||||
"CreateAccessKey": "Create access key",
|
"CreateAccessKey": "Create access key",
|
||||||
|
@ -857,7 +858,6 @@
|
||||||
"Password": "Password",
|
"Password": "Password",
|
||||||
"PasswordAndSSHKey": "Password & SSH key",
|
"PasswordAndSSHKey": "Password & SSH key",
|
||||||
"PasswordChangeLog": "Password change",
|
"PasswordChangeLog": "Password change",
|
||||||
"PasswordExpired": "Password expired",
|
|
||||||
"PasswordPlaceholder": "Please enter password",
|
"PasswordPlaceholder": "Please enter password",
|
||||||
"PasswordRecord": "Password record",
|
"PasswordRecord": "Password record",
|
||||||
"PasswordRule": "Password rules",
|
"PasswordRule": "Password rules",
|
||||||
|
@ -1425,7 +1425,6 @@
|
||||||
"LongTimeNoLogin": "Long time no login",
|
"LongTimeNoLogin": "Long time no login",
|
||||||
"UnmanagedAccount": "Unmanaged account",
|
"UnmanagedAccount": "Unmanaged account",
|
||||||
"UnavailableAccount": "Unavailable account",
|
"UnavailableAccount": "Unavailable account",
|
||||||
"WeakPassword": "Weak password",
|
|
||||||
"EmptyPassword": "Empty password",
|
"EmptyPassword": "Empty password",
|
||||||
"LongTimeNoChangeSecret": "The password has not been changed for a long time",
|
"LongTimeNoChangeSecret": "The password has not been changed for a long time",
|
||||||
"LongTimeNoVerify": "Long time no verify",
|
"LongTimeNoVerify": "Long time no verify",
|
||||||
|
@ -1436,5 +1435,29 @@
|
||||||
"CopyToAsset": "Copy to asset",
|
"CopyToAsset": "Copy to asset",
|
||||||
"MoveToAsset": "Move to asset",
|
"MoveToAsset": "Move to asset",
|
||||||
"Cloud": "Cloud",
|
"Cloud": "Cloud",
|
||||||
"Device": "Device"
|
"Device": "Device",
|
||||||
|
"NoLoginLongTime": "No login for long time",
|
||||||
|
"NewAccountsFound": "New accounts found",
|
||||||
|
"GroupChanged": "Group changed",
|
||||||
|
"SudoChanged": "Sudo changed",
|
||||||
|
"AuthorizedKeysChanged": "Authorized keys changed",
|
||||||
|
"AccountDeleted": "Account deleted",
|
||||||
|
"PasswordExpired": "Password expired",
|
||||||
|
"LongTimePassword": "Long time password",
|
||||||
|
"WeakPassword": "Weak password",
|
||||||
|
"LeakedPassword": "Leaked password",
|
||||||
|
"RepeatedPassword": "Repeated password",
|
||||||
|
"PasswordError": "Password error",
|
||||||
|
"NoAdminAccount": "No admin account",
|
||||||
|
"ProportionOfAccountTypes": "Account type proportion",
|
||||||
|
"CurrentStatus": "Current Status",
|
||||||
|
"ChangeSecretTaskStatus": "Secret Change Task Status",
|
||||||
|
"TaskCount": "Task Count",
|
||||||
|
"ScheduledTaskCount": "Scheduled Task Count",
|
||||||
|
"TaskExecutionCount": "Task Execution Count",
|
||||||
|
"SuccessCount": "Success Count",
|
||||||
|
"FailCount": "Failure Count",
|
||||||
|
"ChangeSecretFailAccounts": "Secret Change Failed Accounts",
|
||||||
|
"OngoingPwdChange": "Ongoing Secret Change",
|
||||||
|
"AccountResult": "Account Success/Failure"
|
||||||
}
|
}
|
|
@ -8,7 +8,7 @@
|
||||||
"AccessIP": "IP 白名单",
|
"AccessIP": "IP 白名单",
|
||||||
"AccessKey": "访问密钥",
|
"AccessKey": "访问密钥",
|
||||||
"Account": "账号",
|
"Account": "账号",
|
||||||
"AccountAmount": "账号数量",
|
"AccountAmount": "账号数",
|
||||||
"AccountBackup": "账号备份",
|
"AccountBackup": "账号备份",
|
||||||
"AccountBackupCreate": "创建账号备份",
|
"AccountBackupCreate": "创建账号备份",
|
||||||
"AccountBackupDetail": "账号备份详情",
|
"AccountBackupDetail": "账号备份详情",
|
||||||
|
@ -347,6 +347,7 @@
|
||||||
"ConvenientOperate": "便捷操作",
|
"ConvenientOperate": "便捷操作",
|
||||||
"Copy": "复制",
|
"Copy": "复制",
|
||||||
"CopySuccess": "复制成功",
|
"CopySuccess": "复制成功",
|
||||||
|
"CopyFailed": "复制失败",
|
||||||
"Corporation": "公司",
|
"Corporation": "公司",
|
||||||
"Create": "创建",
|
"Create": "创建",
|
||||||
"CreateAccessKey": "创建访问密钥",
|
"CreateAccessKey": "创建访问密钥",
|
||||||
|
@ -849,7 +850,6 @@
|
||||||
"Password": "密码",
|
"Password": "密码",
|
||||||
"PasswordAndSSHKey": "认证设置",
|
"PasswordAndSSHKey": "认证设置",
|
||||||
"PasswordChangeLog": "改密日志",
|
"PasswordChangeLog": "改密日志",
|
||||||
"PasswordExpired": "密码过期了",
|
|
||||||
"PasswordPlaceholder": "请输入密码",
|
"PasswordPlaceholder": "请输入密码",
|
||||||
"PasswordRecord": "密码记录",
|
"PasswordRecord": "密码记录",
|
||||||
"PasswordRule": "密码规则",
|
"PasswordRule": "密码规则",
|
||||||
|
@ -1422,7 +1422,6 @@
|
||||||
"LongTimeNoLogin": "长期未登录账号",
|
"LongTimeNoLogin": "长期未登录账号",
|
||||||
"UnmanagedAccount": "未托管账号",
|
"UnmanagedAccount": "未托管账号",
|
||||||
"UnavailableAccount": "不可用账号",
|
"UnavailableAccount": "不可用账号",
|
||||||
"WeakPassword": "弱密码",
|
|
||||||
"EmptyPassword": "空密码",
|
"EmptyPassword": "空密码",
|
||||||
"LongTimeNoChangeSecret": "长时间未改密",
|
"LongTimeNoChangeSecret": "长时间未改密",
|
||||||
"LongTimeNoVerify": "长时间未验证",
|
"LongTimeNoVerify": "长时间未验证",
|
||||||
|
@ -1435,5 +1434,29 @@
|
||||||
"Host": "主机",
|
"Host": "主机",
|
||||||
"Cloud": "云",
|
"Cloud": "云",
|
||||||
"Device": "网络设备",
|
"Device": "网络设备",
|
||||||
"Other": "其他"
|
"Other": "其他",
|
||||||
|
"NoLoginLongTime": "长时间未登录",
|
||||||
|
"NewAccountsFound": "发现新账户",
|
||||||
|
"GroupChanged": "组已更改",
|
||||||
|
"SudoChanged": "Sudo已更改",
|
||||||
|
"AuthorizedKeysChanged": "授权密钥已更改",
|
||||||
|
"AccountDeleted": "账户已删除",
|
||||||
|
"PasswordExpired": "密码过期",
|
||||||
|
"LongTimePassword": "长期使用的密码",
|
||||||
|
"WeakPassword": "弱密码",
|
||||||
|
"LeakedPassword": "泄露密码",
|
||||||
|
"RepeatedPassword": "重复密码",
|
||||||
|
"PasswordError": "密码错误",
|
||||||
|
"NoAdminAccount": "无管理员账户",
|
||||||
|
"ProportionOfAccountTypes": "账号类型占比",
|
||||||
|
"CurrentStatus": "当前状态",
|
||||||
|
"ChangeSecretTaskStatus": "改密任务执行状态",
|
||||||
|
"TaskCount": "任务数",
|
||||||
|
"ScheduledTaskCount": "定时任务数",
|
||||||
|
"TaskExecutionCount": "任务执行数",
|
||||||
|
"SuccessCount": "成功数",
|
||||||
|
"FailCount": "失败数",
|
||||||
|
"ChangeSecretFailAccounts": "改密失败账号",
|
||||||
|
"OngoingPwdChange": "当前正在改密情况",
|
||||||
|
"AccountResult": "账号成功/失败情况"
|
||||||
}
|
}
|
Loading…
Reference in New Issue