提交 281fae45 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!105 move auth.py to api directory, check configuration items

Merge pull request !105 from chenyanpanHW/master
补丁跟踪 patch-tracking
=== ===
# 简介 # 简介
在 openEuler 发行版开发过程,需要及时更新上游社区各个软件包的最新代码,修改功能 bug 及安全问题,确保发布的 openEuler 发行版尽可能避免缺陷和漏洞。 在 openEuler 发行版开发过程,需要及时更新上游社区各个软件包的最新代码,修改功能 bug 及安全问题,确保发布的 openEuler 发行版尽可能避免缺陷和漏洞。
本工具对软件包进行补丁管理,主动监控上游社区提交,自动生成补丁,并自动提交 issue 给对应的 maintainer,同时自动验证补丁基础功能,减少验证工作量支持 maintainer 快速决策。 本工具对软件包进行补丁管理,主动监控上游社区提交,自动生成补丁,并自动提交 issue 给对应的 maintainer,同时自动验证补丁基础功能,减少验证工作量支持 maintainer 快速决策。
# 架构 # 架构
### 2.1 CS架构 ## C/S架构
补丁跟踪采用 C/S 架构,其中服务端(patch-tracking) 负责执行补丁跟踪任务,包括:维护跟踪项,识别上游仓库分支代码变更并形成补丁文件,向 Gitee 提交 issue 及 PR,同时 patch-tracking 提供 RESTful 接口,用于对跟踪项进行增删改查操作。客户端,即命令行工具(patch-tracking-cli),通过调用 patch-tracking 的 RESTful 接口,实现对跟踪项的增删改查操作 patch-tracking采用 C/S 架构
### 2.2 核心流程 服务端(patch-tracking) :负责执行补丁跟踪任务,包括:维护跟踪项,识别上游仓库分支代码变更并形成补丁文件,向 Gitee 提交 issue 及 PR,同时 patch-tracking 提供 RESTful 接口,用于对跟踪项进行增删改查操作。
客户端:即命令行工具(patch-tracking-cli),通过调用 patch-tracking 的 RESTful 接口,实现对跟踪项的增删改查操作。
## 软件下载
rpm包获取地址:https://117.78.1.88/package/show/openEuler:Mainline/patch-tracking
## 核心流程
* 补丁跟踪服务流程 * 补丁跟踪服务流程
**主要步骤:** **主要步骤:**
1. 命令行工具写入跟踪项。 1. 命令行工具写入跟踪项。
2. 自动从跟踪项配置的上游仓库(例如Github)获取补丁文件。 2. 自动从跟踪项配置的上游仓库(例如Github)获取补丁文件。
3. 创建临时分支,将获取到的补丁文件提交到临时分支。 3. 创建临时分支,将获取到的补丁文件提交到临时分支。
...@@ -34,7 +41,7 @@ ...@@ -34,7 +41,7 @@
![Maintainer](images/Maintainer.jpg) ![Maintainer](images/Maintainer.jpg)
### 2.3 数据结构 ## 数据结构
* Tracking表 * Tracking表
...@@ -57,136 +64,136 @@ ...@@ -57,136 +64,136 @@
| 2 | repo | 包源码在Gitee的仓库地址 | String | - | NO | | 2 | repo | 包源码在Gitee的仓库地址 | String | - | NO |
| 3 | branch | 包源码在Gitee的仓库分支 | String | - | NO | | 3 | branch | 包源码在Gitee的仓库分支 | String | - | NO |
# 部署 # 工具部署
>环境已安装 Python >= 3.7 以及 pip3 ## 环境要求
### 3.1 安装依赖 >* 安装 Python 3.7及以上版本
>* 已安装 pip3。
## 安装依赖
执行如下命令安装依赖包。
```shell script ```shell script
yum install -y gcc gcc-c++ python3-devel openssl-devel yum install -y gcc gcc-c++ python3-devel openssl-devel
pip3 install flask flask-sqlalchemy flask-apscheduler requests flask_httpauth pandas pip3 install flask flask-sqlalchemy flask-apscheduler requests flask_httpauth pandas numpy==1.16.5
pip3 install -I uwsgi pip3 install -I uwsgi
``` ```
## 安装工具
### 3.2 安装 `patch-tracking-1.0.0-1.oe1.noarch.rpm` 为例,执行如下命令安装工具。
这里以 `patch-tracking-1.0.0-1.oe1.noarch.rpm` 为例
```shell script ```shell script
rpm -ivh patch-tracking-1.0.0-1.oe1.noarch.rpm rpm -ivh patch-tracking-1.0.0-1.oe1.noarch.rpm
``` ```
### 3.3 生成证书 ## 生成证书
执行如下命令生成证书。
```shell script ```shell script
openssl req -x509 -days 3650 -subj "/CN=self-signed" \ openssl req -x509 -days 3650 -subj "/CN=self-signed" \
-nodes -newkey rsa:4096 -keyout self-signed.key -out self-signed.crt -nodes -newkey rsa:4096 -keyout self-signed.key -out self-signed.crt
``` ```
`self-signed.key``self-signed.crt` 拷贝到 __/etc/patch-tracking__ 目录 生成的 `self-signed.key``self-signed.crt` 文件拷贝到 __/etc/patch-tracking__ 目录
### 3.4 配置 ## 配置参数
在配置文件中进行对应参数的配置 在配置文件中对相应参数进行配置,配置文件路径为 `/etc/patch-tracking/settings.conf`
配置文件路径 `/etc/patch-tracking/settings.conf` 1. 配置服务监听地址
```
LISTEN = "127.0.0.1:5001"
```
- 服务监听地址 2. GitHub Token, 用于访问托管在 GitHub 上游开源软件仓的仓库信息 , 生成 GitHub Token 的方法参考 [Creating a personal access token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token)
```python ```
LISTEN = "127.0.0.1:5001" GITHUB_ACCESS_TOKEN = ""
``` ```
- GitHub Token,用于访问托管在 GitHub 上游开源软件仓的仓库信息 3. 对于托管在gitee上的需要跟踪的仓库,配置一个有该仓库权限的gitee的token,用于提交patch文件,提交issue,提交PR等操作。
生成 GitHub Token 的方法参考 [Creating a personal access token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) ```
GITEE_ACCESS_TOKEN = ""
```
```python 4. 定时扫描数据库中是否有新增或修改的跟踪项,对扫描到的跟踪项执行获取上游补丁任务,在这里配置扫描的时间间隔,数字单位是秒。
GITHUB_ACCESS_TOKEN = ""
```
- 对于托管在gitee上的需要跟踪的仓库,配置一个有该仓库权限的gitee的token,用于提交patch文件,提交issue,提交PR等操作。 ```
SCAN_DB_INTERVAL = 3600
```
```python 5. 命令行工具运行过程中,POST接口需要填写进行认证的用户名和口令哈希值。
GITEE_ACCESS_TOKEN = ""
```
- 定时扫描数据库中是否有新增或修改的跟踪项,对扫描到的跟踪项执行获取上游补丁任务,在这里配置扫描的时间间隔,数字单位是秒 ```
USER = "admin"
```python PASSWORD = ""
SCAN_DB_INTERVAL = 3600 ```
```
- 命令行工具运行过程中,POST接口需要进行认证的用户名和密码 > `USER`默认值为`admin`。
```python ​ 执行如下指令,获取口令的哈希值,其中Test@123为设置的口令。
USER = "admin"
PASSWORD = "" ```
[root]# generate_password Test@123
pbkdf2:sha256:150000$w38eLeRm$ebb5069ba3b4dda39a698bd1d9d7f5f848af3bd93b11e0cde2b28e9e34bfbbae
``` ```
`USER`默认值为`admin` > `口令值`需要满足如下复杂度要求:
>
>`PASSWORD`口令的复杂度要求: > * 长度大于等于6个字符
>* 长度大于等于6个字符 > * 必须包含大写字母、小写字母、数字、特殊字符(~!@#%^*-_=+)
>* 至少有一个数字
>* 至少有一个大写字母
>* 至少有一个小写字母
>* 至少有一个特殊字符 (~!@#%^*_+=-)
需要将口令的哈希值通过命令工具生成后将其配置到此处,获取方法为执行命令`generate_password <password>`,例如:
[root]# generate_password Test@123
pbkdf2:sha256:150000$w38eLeRm$ebb5069ba3b4dda39a698bd1d9d7f5f848af3bd93b11e0cde2b28e9e34bfbbae
`pbkdf2:sha256:150000$w38eLeRm$ebb5069ba3b4dda39a698bd1d9d7f5f848af3bd93b11e0cde2b28e9e34bfbbae`配置到`PASSWORD = ""`引号中。 将口令的哈希值`pbkdf2:sha256:150000$w38eLeRm$ebb5069ba3b4dda39a698bd1d9d7f5f848af3bd93b11e0cde2b28e9e34bfbbae`配置到`PASSWORD = ""`引号中。
### 3.5 启动补丁跟踪服务 ## 启动补丁跟踪服务
可以使用以下两种方式启动服务 可以使用以下两种方式启动服务
1. 使用 systemd 方式 * 使用systemd方式。
```shell script ```
systemctl start patch-tracking systemctl start patch-tracking
``` ```
2. 直接执行可执行程序 * 直接执行可执行程序。
```shell script ```
/usr/bin/patch-tracking /usr/bin/patch-tracking
``` ```
# 使用 # 工具使用
### 4.1 添加跟踪项 ## 添加跟踪项
将需要跟踪的软件仓库和分支与其上游开源软件仓库与分支关联起来,有 3 种使用方法 将需要跟踪的软件仓库和分支与其上游开源软件仓库与分支关联起来,可以通过以下三种方式实现
#### 4.1.1 命令行直接添加 ### 命令行直接添加
参数含义: 参数含义:
>--user :POST接口需要进行认证的用户名,同settings.conf中的USER参数 \ >--user :POST接口需要进行认证的用户名,同settings.conf中的USER参数 \
--password :POST接口需要进行认证的口令,为settings.conf中的PASSWORD哈希值对应的实际的口令字符串 \ --password :POST接口需要进行认证的口令,为settings.conf中的PASSWORD哈希值对应的实际的口令字符串 \
--server :启动Patch Tracking服务的URL,例如:127.0.0.1:5001 \ --server :启动Patch Tracking服务的URL,例如:127.0.0.1:5001 \
--version_control :上游仓库版本的控制工具,只支持github \ --version_control 上游仓库版本的控制工具,只支持github \
--repo 需要进行跟踪的仓库名称,格式:组织/仓库 \ --repo 需要进行跟踪的仓库名称,格式:组织/仓库 \
--branch 需要进行跟踪的仓库的分支名称 \ --branch 需要进行跟踪的仓库的分支名称 \
--scm_repo 被跟踪的上游仓库的仓库名称,github格式:组织/仓库 \ --scm_repo 被跟踪的上游仓库的仓库名称,github格式:组织/仓库 \
--scm_branch 被跟踪的上游仓库的仓库的分支 \ --scm_branch 被跟踪的上游仓库的仓库的分支 \
--enable 是否自动跟踪该仓库 --enable 是否自动跟踪该仓库
例如: 例如:
```shell script ```shell script
patch-tracking-cli add --server 127.0.0.1:5001 --user admin --password Test@123 --version_control github --repo testPatchTrack/testPatch1 --branch master --scm_repo BJMX/testPatch01 --scm_branch test --enable true patch-tracking-cli add --server 127.0.0.1:5001 --user admin --password Test@123 --version_control github --repo testPatchTrack/testPatch1 --branch master --scm_repo BJMX/testPatch01 --scm_branch test --enable true
``` ```
#### 4.1.2 指定文件添加 ### 指定文件添加
参数含义: 参数含义:
>--server :启动Patch Tracking服务的URL,例如:127.0.0.1:5001 \ >--server :启动Patch Tracking服务的URL,例如:127.0.0.1:5001 \
...@@ -194,14 +201,14 @@ patch-tracking-cli add --server 127.0.0.1:5001 --user admin --password Test@123 ...@@ -194,14 +201,14 @@ patch-tracking-cli add --server 127.0.0.1:5001 --user admin --password Test@123
--password :POST接口需要进行认证的口令,为settings.conf中的PASSWORD哈希值对应的实际的口令字符串 \ --password :POST接口需要进行认证的口令,为settings.conf中的PASSWORD哈希值对应的实际的口令字符串 \
--file :yaml文件路径 --file :yaml文件路径
文件内容是仓库、分支、版本管理工具、是否启动监控等信息,将这些写入文件名为xxx.yaml,例如tracking.yaml,文件路径作为`--file`的入参调用命令。 将仓库、分支、版本管理工具、是否启动监控等信息写入yaml文件(例如tracking.yaml),文件路径作为`--file`的入参调用命令。
例如: 例如:
```shell script ```shell script
patch-tracking-cli add --server 127.0.0.1:5001 --user admin --password Test@123 --file tracking.yaml patch-tracking-cli add --server 127.0.0.1:5001 --user admin --password Test@123 --file tracking.yaml
``` ```
yaml内容格式如下,冒号左边的内容不可修改,右边内容根据实际情况填写。 yaml文件内容格式如下,冒号左边的内容不可修改,右边内容根据实际情况填写。
```shell script ```shell script
version_control: github version_control: github
...@@ -212,16 +219,16 @@ branch: master ...@@ -212,16 +219,16 @@ branch: master
enabled: true enabled: true
``` ```
>version_control :上游仓库版本的控制工具,只支持github \ >version_control 上游仓库版本的控制工具,只支持github \
scm_repo 被跟踪的上游仓库的仓库名称,github格式:组织/仓库 \ scm_repo 被跟踪的上游仓库的仓库名称,github格式:组织/仓库 \
scm_branch 被跟踪的上游仓库的仓库的分支 \ scm_branch 被跟踪的上游仓库的仓库的分支 \
repo 需要进行跟踪的仓库名称,格式:组织/仓库 \ repo 需要进行跟踪的仓库名称,格式:组织/仓库 \
branch 需要进行跟踪的仓库的分支名称 \ branch 需要进行跟踪的仓库的分支名称 \
enable 是否自动跟踪该仓库 enable 是否自动跟踪该仓库
#### 4.1.3 指定目录添加 ### 指定目录添加
在指定的目录,例如`test_yaml`下放入多个`xxx.yaml`文件,执行命令,记录指定目录下所有yaml文件的跟踪项。yaml文件都放在不会读取子目录内文件。, 在指定的目录,例如`test_yaml`下放入多个`xxx.yaml`文件,执行如下命令,记录指定目录下所有yaml文件的跟踪项。
参数含义: 参数含义:
>--user :POST接口需要进行认证的用户名,同settings.conf中的USER参数 \ >--user :POST接口需要进行认证的用户名,同settings.conf中的USER参数 \
...@@ -233,16 +240,13 @@ enable 是否自动跟踪该仓库 ...@@ -233,16 +240,13 @@ enable 是否自动跟踪该仓库
patch-tracking-cli add --server 127.0.0.1:5001 --user admin --password Test@123 --dir /home/Work/test_yaml/ patch-tracking-cli add --server 127.0.0.1:5001 --user admin --password Test@123 --dir /home/Work/test_yaml/
``` ```
### 4.2 查询跟踪项 ## 查询跟踪项
参数含义: 参数含义:
>--server :必选参数,启动Patch Tracking服务的URL,例如:127.0.0.1:5001 \ >--server :必选参数,启动Patch Tracking服务的URL,例如:127.0.0.1:5001 \
--table :必选参数,需要查询的表 \ --table :必选参数,需要查询的表 \
--repo :可选参数,需要查询的repo;如果没有该参数查询表中所有内容 \ --repo :可选参数,需要查询的repo;如果没有该参数查询表中所有内容 \
--branch :可选参数,需要查询的branch,必须和--repo同时查询,没有--repo不允许单独查询该参数 --branch :可选参数,需要查询的branch
#### 4.2.1 查询tracking表
```shell script ```shell script
patch-tracking-cli query --server <LISTEN> --table tracking patch-tracking-cli query --server <LISTEN> --table tracking
``` ```
...@@ -251,7 +255,7 @@ patch-tracking-cli query --server <LISTEN> --table tracking ...@@ -251,7 +255,7 @@ patch-tracking-cli query --server <LISTEN> --table tracking
patch-tracking-cli query --server 127.0.0.1:5001 --table tracking patch-tracking-cli query --server 127.0.0.1:5001 --table tracking
``` ```
### 4.3 查询生成的 Issue 列表 ## 查询生成的 Issue
```shell script ```shell script
patch-tracking-cli query --server <LISTEN> --table issue patch-tracking-cli query --server <LISTEN> --table issue
...@@ -261,26 +265,22 @@ patch-tracking-cli query --server <LISTEN> --table issue ...@@ -261,26 +265,22 @@ patch-tracking-cli query --server <LISTEN> --table issue
patch-tracking-cli query --server 127.0.0.1:5001 --table issue patch-tracking-cli query --server 127.0.0.1:5001 --table issue
``` ```
### 4.4 删除 Tracking 跟踪项数据 ## 删除跟踪项
```shell script ```shell script
patch-tracking-cli delete --server SERVER --user USER --password PWD --table TABLE --repo REPO [--branch BRANCH] patch-tracking-cli delete --server SERVER --user USER --password PWD --table TABLE --repo REPO [--branch BRANCH]
``` ```
可以删除指定repo和branch的单条数据;也可直接删除指定repo下所有branch的数据。
例如: 例如:
```shell script ```shell script
patch-tracking-cli delete --server 127.0.0.1:5001 --user admin --password Test@123 --repo testPatchTrack/testPatch1 --branch master patch-tracking-cli delete --server 127.0.0.1:5001 --user admin --password Test@123 --repo testPatchTrack/testPatch1 --branch master
``` ```
### 4.5 码云查看 issue 及 PR > 可以删除指定repo和branch的单条数据;也可直接删除指定repo下所有branch的数据。
登录Gitee上进行跟踪的软件项目,在该项目的Issues和Pull Requests页签下,可以查看到名为`[patch tracking] TIME`,例如` [patch tracking] 20200713101548`的条目。 ## 码云查看 issue 及 PR
即是刚生成的补丁文件的issue和对应PR。 登录Gitee上进行跟踪的软件项目,在该项目的Issues和Pull Requests页签下,可以查看到名为`[patch tracking] TIME`,例如` [patch tracking] 20200713101548`的条目,该条目即是刚生成的补丁文件的issue和对应PR。
# 五 常见问题与解决方法
%define name patch-tracking %define name patch-tracking
%define version 1.0.0 %define version 1.0.0
%define release 1 %define release 2
Summary: This is a tool for automatically tracking upstream repository code patches Summary: This is a tool for automatically tracking upstream repository code patches
Name: %{name} Name: %{name}
......
""" """
http basic auth http basic auth
""" """
import logging
from werkzeug.security import check_password_hash from werkzeug.security import check_password_hash
from flask_httpauth import HTTPBasicAuth from flask_httpauth import HTTPBasicAuth
from flask import current_app as app from flask import current_app as app
logger = logging.getLogger(__name__)
auth = HTTPBasicAuth() auth = HTTPBasicAuth()
...@@ -13,7 +16,24 @@ def verify_password(username, password): ...@@ -13,7 +16,24 @@ def verify_password(username, password):
""" """
verify password verify password
""" """
if username == app.config["USER"] and \ try:
check_password_hash(app.config["PASSWORD"], password): if username == app.config["USER"] and \
return username check_password_hash(app.config["PASSWORD"], password):
return username
except ValueError as err:
logger.error(err)
return None
logger.error("verify password failed")
return None return None
if __name__ == "__main__":
try:
print(
check_password_hash(
" pbkdf2:sha256:150000$ClAZjafb$ec0718c193c000e70812a0709919596e7523ab581c25ea6883aadba33c2edf0d",
"Test@123"
)
)
except ValueError as err:
print(err)
...@@ -7,7 +7,7 @@ from sqlalchemy.exc import SQLAlchemyError ...@@ -7,7 +7,7 @@ from sqlalchemy.exc import SQLAlchemyError
from patch_tracking.database.models import Tracking from patch_tracking.database.models import Tracking
from patch_tracking.api.business import create_tracking, update_tracking, delete_tracking from patch_tracking.api.business import create_tracking, update_tracking, delete_tracking
from patch_tracking.api.constant import ResponseCode from patch_tracking.api.constant import ResponseCode
from patch_tracking.util.auth import auth from patch_tracking.api.auth import auth
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
tracking = Blueprint('tracking', __name__) tracking = Blueprint('tracking', __name__)
...@@ -36,8 +36,9 @@ def delete(): ...@@ -36,8 +36,9 @@ def delete():
logger.info('Delete tracking repo: %s, branch: %s', input_params['repo'], input_params['branch']) logger.info('Delete tracking repo: %s, branch: %s', input_params['repo'], input_params['branch'])
return ResponseCode.ret_message(code=ResponseCode.SUCCESS) return ResponseCode.ret_message(code=ResponseCode.SUCCESS)
else: else:
logger.info('Delete tracking repo: %s, branch: %s not found.', input_params['repo'], logger.info(
input_params['branch']) 'Delete tracking repo: %s, branch: %s not found.', input_params['repo'], input_params['branch']
)
return ResponseCode.ret_message(code=ResponseCode.DELETE_DB_NOT_FOUND) return ResponseCode.ret_message(code=ResponseCode.DELETE_DB_NOT_FOUND)
else: else:
if Tracking.query.filter(Tracking.repo == input_params['repo']).first(): if Tracking.query.filter(Tracking.repo == input_params['repo']).first():
......
...@@ -9,6 +9,7 @@ from patch_tracking.api.issue import issue ...@@ -9,6 +9,7 @@ from patch_tracking.api.issue import issue
from patch_tracking.api.tracking import tracking from patch_tracking.api.tracking import tracking
from patch_tracking.database import db from patch_tracking.database import db
from patch_tracking.task import task from patch_tracking.task import task
from patch_tracking.util import github_api, gitee_api
logging.config.fileConfig('logging.conf', disable_existing_loggers=False) logging.config.fileConfig('logging.conf', disable_existing_loggers=False)
...@@ -16,6 +17,43 @@ app = Flask(__name__) ...@@ -16,6 +17,43 @@ app = Flask(__name__)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def check_token():
""" check gitee/github token """
gitee_token = app.config['GITEE_ACCESS_TOKEN']
github_token = app.config['GITHUB_ACCESS_TOKEN']
token_error = False
github_ret = github_api.get_user_info(github_token)
if github_ret[0] != "success":
logger.error('github token is bad credentials.')
token_error = True
gitee_ret = gitee_api.get_user_info(gitee_token)
if gitee_ret[0] != "success":
logger.error('gitee token is bad credentials.')
token_error = True
if token_error:
sys.exit()
def check_listen(listen_param):
""" check LISTEN """
check_ret = True
if ":" in listen_param and listen_param.count(":") == 1:
host, port = listen_param.split(":")
if int(port) > 65535 or int(port) <= 0:
check_ret = False
if "." in host and host.count(".") == 3:
for item in host.split("."):
if int(item) < 0 or int(item) > 255:
check_ret = False
else:
check_ret = False
else:
check_ret = False
return check_ret
def check_settings_conf(): def check_settings_conf():
""" """
check settings.conf check settings.conf
...@@ -24,9 +62,21 @@ def check_settings_conf(): ...@@ -24,9 +62,21 @@ def check_settings_conf():
required_settings = ['LISTEN', 'GITHUB_ACCESS_TOKEN', 'GITEE_ACCESS_TOKEN', 'SCAN_DB_INTERVAL', 'USER', 'PASSWORD'] required_settings = ['LISTEN', 'GITHUB_ACCESS_TOKEN', 'GITEE_ACCESS_TOKEN', 'SCAN_DB_INTERVAL', 'USER', 'PASSWORD']
for setting in required_settings: for setting in required_settings:
if setting in app.config: if setting in app.config:
if not app.config[setting]: if app.config[setting] == "":
logger.error('%s is empty in settings.conf.', setting) logger.error('%s is empty in settings.conf.', setting)
setting_error = True setting_error = True
else:
if setting == "LISTEN" and (not check_listen(app.config[setting])):
logger.error('LISTEN error: illegal param in /etc/patch-tracking/settings.conf.')
setting_error = True
if setting == "SCAN_DB_INTERVAL" and int(app.config[setting]) <= 0:
logger.error(
'SCAN_DB_INTERVAL error: must be greater than zero in /etc/patch-tracking/settings.conf.'
)
setting_error = True
if setting == "USER" and len(app.config[setting]) > 32:
logger.error('USER value error: user name too long, USER character should less than 32.')
setting_error = True
else: else:
logger.error('%s not configured in settings.conf.', setting) logger.error('%s not configured in settings.conf.', setting)
setting_error = True setting_error = True
...@@ -37,16 +87,10 @@ def check_settings_conf(): ...@@ -37,16 +87,10 @@ def check_settings_conf():
settings_file = os.path.join(os.path.abspath(os.curdir), "settings.conf") settings_file = os.path.join(os.path.abspath(os.curdir), "settings.conf")
app.config.from_pyfile(settings_file) app.config.from_pyfile(settings_file)
check_settings_conf() check_settings_conf()
check_token()
GITHUB_ACCESS_TOKEN = app.config['GITHUB_ACCESS_TOKEN']
GITEE_ACCESS_TOKEN = app.config['GITEE_ACCESS_TOKEN']
SCAN_DB_INTERVAL = app.config['SCAN_DB_INTERVAL']
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite?check_same_thread=False' app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite?check_same_thread=False'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SWAGGER_UI_DOC_EXPANSION'] = 'list'
app.config['ERROR_404_HELP'] = False
app.config['RESTX_MASK_SWAGGER'] = False
app.config['SCHEDULER_EXECUTORS'] = {'default': {'type': 'threadpool', 'max_workers': 100}} app.config['SCHEDULER_EXECUTORS'] = {'default': {'type': 'threadpool', 'max_workers': 100}}
app.register_blueprint(issue, url_prefix="/issue") app.register_blueprint(issue, url_prefix="/issue")
......
...@@ -8,6 +8,32 @@ import re ...@@ -8,6 +8,32 @@ import re
from werkzeug.security import generate_password_hash from werkzeug.security import generate_password_hash
def usage():
""" usage """
print(
"""usage: generate_password PASSWORD
Requirements:
1. PASSWORD must be within the 'latin1' character set
2. PASSWORD strength require:
6 characters or more
at least 1 digit [0-9]
at least 1 alphabet [a-z]
at least 1 alphabet of Upper Case [A-Z]
at least 1 special character from [~!@#%^*_+=-]
"""
)
def password_encode_check(password):
""" check if password within the latin1 character set """
try:
password.encode("latin1")
except UnicodeEncodeError as err:
return str(err)
return None
def password_strength_check(password): def password_strength_check(password):
""" """
Verify the strength of 'password' Verify the strength of 'password'
...@@ -44,21 +70,26 @@ def password_strength_check(password): ...@@ -44,21 +70,26 @@ def password_strength_check(password):
} }
ret = password_strength_check(sys.argv[1]) if __name__ == "__main__":
if not ret['ok']: if len(sys.argv) != 2:
print("Password strength is not satisfied.") usage()
for item in ret['error']: sys.exit(1)
if ret['error'][item]:
print("{} not satisfied.".format(item)) password_ = sys.argv[1]
print(
""" ret = password_encode_check(password_)
password strength require: if ret:
6 characters or more usage()
at least 1 digit [0-9] print("PASSWORD: only latin1 character set are allowed")
at least 1 alphabet [a-z] sys.exit(1)
at least 1 alphabet of Upper Case [A-Z]
at least 1 special character from [~!@#%^*_+=-] ret = password_strength_check(password_)
""" if not ret['ok']:
) usage()
else: print("Password strength is not satisfied:")
print(generate_password_hash(sys.argv[1])) for item in ret['error']:
if ret['error'][item]:
print("{} not satisfied.".format(item))
sys.exit(1)
else:
print(generate_password_hash(password_))
...@@ -112,6 +112,15 @@ def repo_branch_check(url): ...@@ -112,6 +112,15 @@ def repo_branch_check(url):
return 'error', ret.text return 'error', ret.text
def latin1_encode(text):
""" latin1 encode """
try:
text.encode("latin1")
except UnicodeEncodeError as err:
return str(err)
return None
def params_input_track(params, file_path=None): def params_input_track(params, file_path=None):
""" """
load tracking from command line arguments load tracking from command line arguments
...@@ -132,6 +141,13 @@ def params_input_track(params, file_path=None): ...@@ -132,6 +141,13 @@ def params_input_track(params, file_path=None):
user = params['user'] user = params['user']
password = params['password'] password = params['password']
err = latin1_encode(user)
if err:
return "error", "ERROR: user: only latin1 character set are allowed."
err = latin1_encode(password)
if err:
return "error", "ERROR: user: only latin1 character set are allowed."
enabled = bool(enabled == 'true') enabled = bool(enabled == 'true')
url = '/'.join(['https:/', server, 'tracking']) url = '/'.join(['https:/', server, 'tracking'])
...@@ -165,7 +181,11 @@ def check_add_param(params): ...@@ -165,7 +181,11 @@ def check_add_param(params):
miss_params.append(param) miss_params.append(param)
success = False success = False
if not success: if not success:
print("patch_tracking_cli add: error: the following arguments are required: --{}".format(", --".join(miss_params))) print(
"patch_tracking_cli add: error: the following arguments are required: --{}".format(
", --".join(miss_params)
)
)
return success return success
...@@ -180,8 +200,8 @@ def add(args): ...@@ -180,8 +200,8 @@ def add(args):
style3 = bool(args.dir) style3 = bool(args.dir)
if str([style1, style2, style3]).count('True') >= 2: if str([style1, style2, style3]).count('True') >= 2:
print("mix different usage style") print("usage:" + add_usage)
print(add_usage) print("patch_tracking_cli add: error: mix different usage style")
return return
if style2: if style2:
...@@ -215,6 +235,15 @@ def delete(args): ...@@ -215,6 +235,15 @@ def delete(args):
user = args.user user = args.user
password = args.password password = args.password
err = latin1_encode(user)
if err:
print("ERROR: user: only latin1 character set are allowed.")
return
err = latin1_encode(password)
if err:
print("ERROR: password: Only latin1 character set are allowed.")
return
url = '/'.join(['https:/', server, 'tracking']) url = '/'.join(['https:/', server, 'tracking'])
if args.branch: if args.branch:
params = {'repo': args.repo, 'branch': args.branch} params = {'repo': args.repo, 'branch': args.branch}
...@@ -310,11 +339,11 @@ authentication_parser.add_argument('--password', required=True, help='authentica ...@@ -310,11 +339,11 @@ authentication_parser.add_argument('--password', required=True, help='authentica
# add # add
add_usage = """ add_usage = """
%(prog)s --server SERVER --user USER --password PASSWORD patch_tracking_cli add --server SERVER --user USER --password PASSWORD
--version_control github --scm_repo SCM_REPO --scm_branch SCM_BRANCH --version_control github --scm_repo SCM_REPO --scm_branch SCM_BRANCH
--repo REPO --branch BRANCH --enabled True --repo REPO --branch BRANCH --enabled True
%(prog)s --server SERVER --user USER --password PASSWORD --file FILE patch_tracking_cli add --server SERVER --user USER --password PASSWORD --file FILE
%(prog)s --server SERVER --user USER --password PASSWORD --dir DIR""" patch_tracking_cli add --server SERVER --user USER --password PASSWORD --dir DIR"""
parser_add = subparsers.add_parser( parser_add = subparsers.add_parser(
'add', parents=[common_parser, authentication_parser], help="add tracking", usage=add_usage, allow_abbrev=False 'add', parents=[common_parser, authentication_parser], help="add tracking", usage=add_usage, allow_abbrev=False
) )
...@@ -329,16 +358,14 @@ parser_add.add_argument('--file', help='import patch tracking from file') ...@@ -329,16 +358,14 @@ parser_add.add_argument('--file', help='import patch tracking from file')
parser_add.add_argument('--dir', help='import patch tracking from files in directory') parser_add.add_argument('--dir', help='import patch tracking from files in directory')
# delete # delete
del_usage = """ parser_delete = subparsers.add_parser(
%(prog)s --server SERVER --table TABLE --repo REPO [--branch BRANCH]""" 'delete', parents=[common_parser, authentication_parser], help="delete tracking", allow_abbrev=False
parser_delete = subparsers.add_parser('delete', parents=[common_parser, authentication_parser], help="delete tracking", allow_abbrev=False) )
parser_delete.set_defaults(func=delete) parser_delete.set_defaults(func=delete)
parser_delete.add_argument("--repo", required=True, help="source package repository") parser_delete.add_argument("--repo", required=True, help="source package repository")
parser_delete.add_argument("--branch", help="source package branch") parser_delete.add_argument("--branch", help="source package branch")
# query # query
query_usage = """
%(prog)s --server SERVER --table {tracking,issue} [--repo REPO] [--branch BRANCH]"""
parser_query = subparsers.add_parser('query', parents=[common_parser], help="query tracking/issue", allow_abbrev=False) parser_query = subparsers.add_parser('query', parents=[common_parser], help="query tracking/issue", allow_abbrev=False)
parser_query.set_defaults(func=query) parser_query.set_defaults(func=query)
parser_query.add_argument("--table", required=True, choices=["tracking", "issue"], help="query tracking or issue") parser_query.add_argument("--table", required=True, choices=["tracking", "issue"], help="query tracking or issue")
......
...@@ -8,4 +8,4 @@ settings_file='/etc/patch-tracking/settings.conf' ...@@ -8,4 +8,4 @@ settings_file='/etc/patch-tracking/settings.conf'
server=`grep 'LISTEN' $settings_file | awk -F'=' '{print $2}' | sed -e 's/^[ ]"//g' | sed -e 's/"$//g'` server=`grep 'LISTEN' $settings_file | awk -F'=' '{print $2}' | sed -e 's/^[ ]"//g' | sed -e 's/"$//g'`
/usr/local/bin/uwsgi --master --https ${server},/etc/patch-tracking/self-signed.crt,/etc/patch-tracking/self-signed.key --wsgi-file ${app_file} --callable app --chdir ${chdir_path} --threads 100 --lazy /usr/local/bin/uwsgi --master --https "${server},/etc/patch-tracking/self-signed.crt,/etc/patch-tracking/self-signed.key" --wsgi-file "${app_file}" --callable app --chdir "${chdir_path}" --threads 100 --lazy
...@@ -12,6 +12,19 @@ ORG_URL = "https://gitee.com/api/v5/orgs" ...@@ -12,6 +12,19 @@ ORG_URL = "https://gitee.com/api/v5/orgs"
REPO_URL = "https://gitee.com/api/v5/repos" REPO_URL = "https://gitee.com/api/v5/repos"
def get_user_info(token):
"""
get user info
"""
url = "https://gitee.com/api/v5/user"
gitee_token = token
param = {'access_token': gitee_token}
ret = requests.get(url, params=param)
if ret.status_code == 200:
return "success", ret.text
return "error", ret.json()
def get_path_content(repo, branch, path): def get_path_content(repo, branch, path):
""" """
get file content get file content
......
...@@ -10,6 +10,37 @@ from flask import current_app ...@@ -10,6 +10,37 @@ from flask import current_app
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def get_user_info(token):
"""
get user info
"""
url = "https://api.github.com/user"
count = 30
token = 'token ' + token
headers = {
'User-Agent': 'Mozilla/5.0',
'Authorization': token,
'Content-Type': 'application/json',
'Connection': 'close',
'method': 'GET',
'Accept': 'application/json'
}
while count > 0:
try:
ret = requests.get(url, headers=headers)
if ret.status_code == 200:
return 'success', ret.text
return 'error', ret.json()
except requests_connectionError as err:
logger.warning(err)
time.sleep(10)
count -= 1
continue
if count == 0:
logger.error('Fail to connnect to github: %s after retry 30 times.', url)
return 'connect error'
class GitHubApi: class GitHubApi:
""" """
Encapsulates GitHub functionality Encapsulates GitHub functionality
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册