Skip to content

cn1289/domain-admin

 
 

Repository files navigation

Domain Admin

PyPI - Python Version PyPI PyPI - Downloads Docker Image Version (latest semver) Docker Pulls Build Status PyPI - License

基于Python + Vue3.js 技术栈实现的域名和SSL证书监测平台

用于解决,不同业务域名SSL证书,申请自不同的平台,到期后不能及时收到通知,导致线上访问异常,被老板责骂的问题

核心功能:域名SSL证书 的过期监控,到期提醒

支持证书:单域名证书、多域名证书、通配符证书、IP证书、自签名证书

证书部署: 单一主机部署、多主机部署、动态主机部署

通知渠道:支持邮件、Webhook、企业微信、钉钉、飞书等通知方式

支持平台:macOS、Linux、Windows

同时,Domain Admin也是一个轻量级监控方案,占用系统资源较少,安装包仅1.5 MB

项目截图

1、网页版:

2、移动端版:

账号密码随意,预览模式仅提供模拟数据,无法操作修改

使用文档:

安装

方式一:pip安装

运行环境:

  • Python >= 2.7 或者 Python >= 3.4

可以使用 pyenv + venv 管理多个Python版本和隔离虚拟环境

$ python3 --version
Python 3.7.0

# 创建名为 venv 的虚拟环境
$ python3 -m venv venv

# 激活虚拟环境
$ source venv/bin/activate

linux / macos 安装

# 安装 domain-admin
$ pip install gunicorn domain-admin

# 启动运行
$ gunicorn --bind '127.0.0.1:8000' 'domain_admin.main:app'

windows 安装

# 安装 domain-admin
$ pip install waitress domain-admin

# 启动运行
$ waitress-serve --listen=127.0.0.1:8000 'domain_admin.main:app'

访问地址:http://127.0.0.1:8000

默认的管理员账号:admin 密码:123456

强烈建议:登录系统后修改默认密码

升级到最新版本

$ pip3 install -U domain-admin -i https://pypi.org/simple

方式二:docker启动

感谢@miss85246 提供Docker支持

$ docker run -p 8000:8000 mouday/domain-admin

# 后台运行
$ docker run -d -p 8000:8000 mouday/domain-admin

# 本地文件夹和容器文件夹映射
$ docker run \
-v $(pwd)/database:/app/database \
-v $(pwd)/logs:/app/logs \
-p 8000:8000 \
--name domain-admin \
mouday/domain-admin:latest

方式三:克隆源码运行

本方式仅适用于二次开发,推荐采用 pip安装 或者 docker启动 的方式体验

# 后端项目
git clone https://github.com/mouday/domain-admin.git

# 安装依赖
pip install -r requirements.txt

# 启动开发服务
make dev


# 前端项目
git clone https://github.com/mouday/domain-admin-web.git

# 启动开发服务
make dev

为了更多地人参与到项目中来,现已开放前端代码

前端项目地址:https://github.com/mouday/domain-admin-web

项目简介

功能:

  • 权限

    • 用户登录
    • 用户退出
    • 修改密码
  • 域名管理

    • 域名添加
    • 域名删除
    • 域名搜索
    • 域名导入、导出功能
    • 域名信息
  • 证书监控

    • 定时监控
    • 到期邮件提醒
    • 微信提醒
    • 手动/自动更新证书信息
  • 用户管理

    • 添加用户
    • 删除用户
    • 禁用/启用用户
  • 监控日志

  • 管理界面

    • api接口(用于二次开发)
    • web浏览器
    • 桌面
    • 移动端(app+小程序)

使用说明

如果需要对域名进行到期监控和邮件提醒,必须设置

1、批量导入域名

导入文本示例: /docs/domain.txt

2、设置系统发送邮件的账号密码

3、设置邮件通知

4、其他通知方式

二次开发

接口文档:https://mouday.github.io/domain-admin/

代码推送

# github
git push -u origin master

# gitee
git push -u gitee master

技术选型

前端选型(网页版)

  • Node.js
  • Vite.js
  • Vue3.js
  • Vue Router
  • Pinia
  • Element Plus
  • Tailwind CSS

前端选型(桌面版)

  • node.js v16.15.1
  • vue3.js
  • quasar + electron

后端选型

问题

1、暂不支持多进程方式启动

使用 master + 多worker 方式启动应用,会启动多个定时任务Scheduler,导致多次执行任务

如果小规模使用,启动一个进程即可

如果是需要支持并发访问,可自行改进应用

将定时器独立出来,单独一个进程控制,行成 scheduler + Flask(master + 多worker)

2、为什么外网访问不到?

# 启动运行
$ gunicorn 'domain_admin.main:app'

# 支持外网可访问,云服务器(阿里云或腾讯云)需要设置安全组 
# 默认内网访问 --bind 127.0.0.1:8000
$ gunicorn --bind '0.0.0.0:8000' domain_admin.main:app'

更多设置,可参考gunicorn

3、Windows平台启动报错,找不到模块 fcntl

gunicorn不支持Windows,可以使用waitress 替换,感谢@cbr252522489提供的解决方案

$ pip install waitress

$ waitress-serve --listen=127.0.0.1:8000 domain_admin.main:app

参考:https://stackoverflow.com/questions/45228395/error-no-module-named-fcntl

4、添加域名数据后系统异常

可按如下步骤删除异常数据

docker 启动方式

# 查看容器的运行信息
$ docker ps

# 进入容器
$ docker exec -it <容器id> /bin/sh

# 安装依赖
$ apk add sqlite

# 进入sqlite3
$ sqlite3

sqlite> .open /app/database/database.db

sqlite> .tables
log_scheduler  tb_group       tb_system      tb_version
tb_domain      tb_notify      tb_user

# 查看数据
sqlite> select * from tb_domain;

# 删除数据
sqlite> DELETE FROM tb_domain WHERE id = 1;

# 退出
sqlite> .quit

5、邮件发送失败

可尝试更换端口25或465

6、webhook模板

采用jinja2 模板引擎

传入模板的参数示例:

{
    "list":[
        {
            "domain": "www.demo.com",
            "start_date": "2023-06-01",
            "expire_date": "2023-06-21",
            "expire_days": 20
        }
    ]
}

参数说明

参数 类型 说明
domain string 域名/证书域名
start_date string 生效时间
expire_date string 过期时间
expire_days int 剩余天数

示例

{
  "title": "域名到期提醒",
  "content": "{% for row in list %}{{row.domain}} {{row.start_date or '-' }} - {{row.expire_date or '-' }} ({{row.expire_days}}){% endfor %}"
}

渲染结果

{
  "title": "域名到期提醒",
  "content": "www.demo.com 2023-06-01 - 2023-06-21 (20)"
}

可以参考接口文档:更新用户通知配置

7、监控域名非443的端口

域名格式

域名:端口

eg:

www.baidu.com:8080

8、修改数据库链接

通过配置.env 文件或者直接设置系统环境变量

# sqlite 默认
DB_CONNECT_URL=sqlite:///database/database.db

# mysql
# 需要安装模块 pymysql
# pip install pymysql
DB_CONNECT_URL=mysql://root:123456@127.0.0.1:3306/data_domain

# 来自群友 @〖斗魂〗繁←星 的分享
# 如果 mysql 开启了 ssl,mysql 连接字符串应该写成
DB_CONNECT_URL=mysql://root:123456@127.0.0.1:3306/data_domain?ssl_verify_cert=true

更多mysql的设置可参考:https://pymysql.readthedocs.io/en/latest/modules/connections.html

9、k8s部署

配置文件示例

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/instance: domain-admin-latest
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: domain-admin
    app.kubernetes.io/version: 1.16.0
    argocd.argoproj.io/instance: domain-admin-latest
    helm.sh/chart: domain-admin-0.1.0
  name: domain-admin-latest
  namespace: domain-admin-production
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/instance: domain-admin-latest
      app.kubernetes.io/name: domain-admin
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app.kubernetes.io/instance: domain-admin-latest
        app.kubernetes.io/name: domain-admin
    spec:
      containers:
      - name: domain-admin
        image: mouday/domain-admin:latest
        imagePullPolicy: Always
        env:
        - name: DB_CONNECT_URL
          value: "sqlite:///database/database.db"
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /
            port: http
            scheme: HTTP
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        ports:
        - containerPort: 8000
          name: http
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /
            port: http
            scheme: HTTP
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1

10、支持prometheus/metrics接口

1、第一步、需要在 系统设置/API KEY 获取授权key

2、第二步、配置 prometheus.yml

scrape_configs:
    bearer_token: 'f60c03bfff8bb42dcf6821542e5fd11e'

请求地址:http://127.0.0.1:8000/metrics

返回数据示例:

# HELP domain_admin this is a domain admin data
# TYPE domain_admin gauge
domain_admin{domain="pgmanage.qnvip.com"} 0.0
domain_admin{domain="fanyi.baidu.com"} 37.0
domain_admin{domain="www.tmall.com"} 37.0
domain_admin{domain="www.baidu.com"} 37.0
domain_admin{domain="www.taobao.com"} 37.0

11、部分域名无法查询到信息

不支持的域名后缀:.lc.ml.ai

12、从k8s里面自动获取到ingress的域名,然后添加到domain-admin里面

安装依赖

pip install tldextract requests kubernetes

参考代码 由群友 @旺仔牛奶 贡献

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import json
import requests
import re
from kubernetes import config, client
import tldextract
import logging
logging.basicConfig(level=logging.INFO)


headers = {
    'Content-Type': 'application/json'
}


def get_token(host, username, password):
    url = '{}/api/login'.format(host)
    data = {
        'username': username,
        'password': password
    }
    try:
        response = requests.post(url=url, headers=headers, data=json.dumps(data))
        result = json.loads(response.text)
        if result['code'] == 0:
            token = result['data']['token']
            return token
        else:
            logging.error(response.text)
            return False
    except Exception as e:
        logging.error(e)


def add_domain(host, token, domain):
    url = '{}/api/addDomainInfo'.format(host)
    data = {
        'domain': domain
    }
    headers['X-Token'] = token
    try:
        response = requests.post(url=url, headers=headers, data=json.dumps(data))
        result = json.loads(response.text)
        if result['code'] == 0:
            return True
        else:
            logging.error(response.text)
            return False
    except Exception as e:
        logging.error(e)


def main():
    config.load_incluster_config()
    kube_api = client.ExtensionsV1beta1Api()
    ingresses = kube_api.list_ingress_for_all_namespaces()
    _set = set()
    for item in ingresses.items:
        if not re.search(os.getenv('NAMESPACE_MATCH'), item.metadata.namespace):
            continue
        if re.search(os.getenv('NAMESPACE_NOT_MATCH'), item.metadata.namespace):
            continue
        for rule in item.spec.rules:
            domain = tldextract.extract(rule.host).registered_domain
            _set.add(domain)
    token = get_token(host=os.getenv('DOMAIN_ADMIN_HOST'),
                      username=os.getenv('DOMAIN_ADMIN_USERNAME'),
                      password=os.getenv('DOMAIN_ADMIN_PASSWORD'))
    for item in _set:
        add_domain(host=os.getenv('DOMAIN_ADMIN_HOST'), token=token, domain=item)


if __name__ == '__main__':
    main()

问题反馈交流

QQ群号:731742868

邀请码:domain-admin

开发计划

  • 已完成 支持企业微信通知

  • 已完成 支持域名分组

  • 增加理员权限,权限分级:root 管理员 普通用户

  • 已完成 解决批量导入超时问题,支持1000条数据导入

  • 已完成 支持域名备注

  • 已完成 支持域名到期数据

  • 已完成 webhook支持变量

  • 已完成 异步操作的前端状态显示

  • 暗黑模式

  • 已完成 支持内网用户自己设置过期时间

  • 已完成 增加筛选功能: 筛选域名状态、证书状态、网站状态

  • 已完成 增加批量删除域名的功能

  • v1.5.0(开发中)

    • 新增网站监控 issues#17
    • SSL证书申请
    • SSL证书部署
    • admin拥有所有权限
    • 用户密码重置
    • 域名导出功能新增字段:主办单位名称、ICP备案
    • 域名列表新增字段:标签
    • 域名列表管理端支持修改:创建人

证书测试:https://badssl.com/

获取证书列表

JSON.stringify([...document.querySelectorAll('a')].map(a=>a.href))

批量域名列表 (746314个)

更新日志

CHANGELOG.md

参考文章

Releases

No releases published

Packages

No packages published

Languages

  • Python 96.7%
  • HTML 2.6%
  • Other 0.7%