Compare commits
477 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c130f9596 | ||
|
|
f156f4cb4e | ||
|
|
fa3bfa2ea8 | ||
|
|
ab5c7bb75a | ||
|
|
81b322cd60 | ||
|
|
e6dd7cd54a | ||
|
|
aa1da7c11a | ||
|
|
3f74d4d9e5 | ||
|
|
297d09c5ad | ||
|
|
07e1dbb4cc | ||
|
|
3c6618b4fc | ||
|
|
54db744282 | ||
|
|
03b751fa13 | ||
|
|
ec342708b2 | ||
|
|
405591c5d0 | ||
|
|
67af67b92d | ||
|
|
8644348fc4 | ||
|
|
00dc226bd2 | ||
|
|
b6b7c3e2e0 | ||
|
|
246ef348d3 | ||
|
|
3e9ba1a30a | ||
|
|
598cde4865 | ||
|
|
fc4a716b4e | ||
|
|
ed5634ff83 | ||
|
|
884af1ea62 | ||
|
|
01ad62df16 | ||
|
|
512a667e44 | ||
|
|
d0e841f7de | ||
|
|
c04641d835 | ||
|
|
f9128d4d45 | ||
|
|
2026211622 | ||
|
|
9d0f21a9e5 | ||
|
|
26adf7d437 | ||
|
|
d2d6f12218 | ||
|
|
b31c0b6a8d | ||
|
|
472f06c2d1 | ||
|
|
f5ec9870fd | ||
|
|
66fb9e5f49 | ||
|
|
a323f3aa2c | ||
|
|
fe4786e168 | ||
|
|
83185c8c50 | ||
|
|
83ae9db02d | ||
|
|
8bf328ca94 | ||
|
|
36993cb6f8 | ||
|
|
c854415319 | ||
|
|
aecc1cd979 | ||
|
|
b2f3b0b584 | ||
|
|
c937f5afc7 | ||
|
|
2d580a26af | ||
|
|
4a00a3cc1b | ||
|
|
d3935219f2 | ||
|
|
040788c793 | ||
|
|
005622307e | ||
|
|
8ebf95a222 | ||
|
|
7f596ed315 | ||
|
|
ffa4de6911 | ||
|
|
cb27d4b490 | ||
|
|
bb4910f4e5 | ||
|
|
89c7f07034 | ||
|
|
b150b2f034 | ||
|
|
45d6347f5b | ||
|
|
67d762b6a5 | ||
|
|
faa28f88f9 | ||
|
|
9c8c7a7812 | ||
|
|
a019956698 | ||
|
|
d70e2b66a3 | ||
|
|
5d568efac3 | ||
|
|
08111f1418 | ||
|
|
45839f227a | ||
|
|
8814ffeda6 | ||
|
|
d224c4c124 | ||
|
|
549525fb37 | ||
|
|
1c8e25beb3 | ||
|
|
eda45c1528 | ||
|
|
53c38cf714 | ||
|
|
0e7578043e | ||
|
|
21f50e0b38 | ||
|
|
515f00c7cd | ||
|
|
8057586dc1 | ||
|
|
b101ac7c7f | ||
|
|
64319937a1 | ||
|
|
1c0cfd6769 | ||
|
|
f8e17d5285 | ||
|
|
d4385ad8a5 | ||
|
|
da07ce419f | ||
|
|
714e0206c4 | ||
|
|
40da82666a | ||
|
|
79f7ec4672 | ||
|
|
0f5c69040b | ||
|
|
c9d1c45d97 | ||
|
|
ea8fdb120c | ||
|
|
f6fa830ffe | ||
|
|
992e50c014 | ||
|
|
bd705d91ba | ||
|
|
2656394195 | ||
|
|
c8df9e698c | ||
|
|
19b78a1d2f | ||
|
|
8039e8baf8 | ||
|
|
9c5142c73c | ||
|
|
8e3dcdde17 | ||
|
|
34023adafb | ||
|
|
79914e8d08 | ||
|
|
454fbda581 | ||
|
|
2c32703e6b | ||
|
|
b561535626 | ||
|
|
1fc684d995 | ||
|
|
7595d9fdfd | ||
|
|
3bf7732a21 | ||
|
|
71b5aaf8ab | ||
|
|
e1e5347476 | ||
|
|
cdcdb6a2d9 | ||
|
|
ec79104ad2 | ||
|
|
ff083ce684 | ||
|
|
0f051e322e | ||
|
|
657a2ae032 | ||
|
|
0db3570026 | ||
|
|
0ae39f160a | ||
|
|
b45977c29a | ||
|
|
b7f5740c57 | ||
|
|
21e23369d3 | ||
|
|
fca598991a | ||
|
|
aa5b909486 | ||
|
|
0a888cf51a | ||
|
|
e5c164065c | ||
|
|
8bc241ca14 | ||
|
|
15beb79631 | ||
|
|
fef1305e41 | ||
|
|
498cf34999 | ||
|
|
7cde1fdc4a | ||
|
|
228fdf0a0d | ||
|
|
fdb5ea0ff4 | ||
|
|
a0e838d1ee | ||
|
|
30ddf5ec41 | ||
|
|
cfd3b7b3ae | ||
|
|
a6cd532035 | ||
|
|
b1db952fcb | ||
|
|
51e8bab352 | ||
|
|
618ec93786 | ||
|
|
a673f9c8ca | ||
|
|
e8c9c2a47d | ||
|
|
aafa5d5f90 | ||
|
|
8b9c47daf1 | ||
|
|
4042577c0b | ||
|
|
6c9f9940e3 | ||
|
|
8f7b3f29ce | ||
|
|
6bca7333c9 | ||
|
|
3dfeeec899 | ||
|
|
138dc286f6 | ||
|
|
07cee2aadf | ||
|
|
1b267813c9 | ||
|
|
96b5981f8c | ||
|
|
a2fd9559c5 | ||
|
|
3f06419d47 | ||
|
|
2aefca3813 | ||
|
|
6aa487269c | ||
|
|
393ea27fa4 | ||
|
|
febe87508c | ||
|
|
30db27980c | ||
|
|
4e768ec50f | ||
|
|
4467e09426 | ||
|
|
66b95d52fd | ||
|
|
1398417829 | ||
|
|
58dd5e2750 | ||
|
|
70210f567a | ||
|
|
49e7dc56e1 | ||
|
|
72cc586f88 | ||
|
|
94fa77fcd2 | ||
|
|
2c0cbdd29e | ||
|
|
68a503796c | ||
|
|
48cf28dd7f | ||
|
|
7e103b7744 | ||
|
|
79d637c9bf | ||
|
|
7c8d551fe1 | ||
|
|
72862c8be8 | ||
|
|
4f1bb48bf7 | ||
|
|
15740a6d8a | ||
|
|
2bc3456400 | ||
|
|
5a607efa9f | ||
|
|
1c8163dd82 | ||
|
|
327a919958 | ||
|
|
a847e66c4f | ||
|
|
0772d3b3fd | ||
|
|
61d6b06c56 | ||
|
|
1534f45236 | ||
|
|
aedc462135 | ||
|
|
7b55337c5e | ||
|
|
87bbf6f140 | ||
|
|
0d8913ea2f | ||
|
|
387bcc5fa4 | ||
|
|
5a20242111 | ||
|
|
196f7d9dc2 | ||
|
|
954b6df360 | ||
|
|
8002a56efc | ||
|
|
7e5ea0cee0 | ||
|
|
3254afc756 | ||
|
|
e3553d4c8c | ||
|
|
7be14ee905 | ||
|
|
fc234314b7 | ||
|
|
cf19363092 | ||
|
|
589b38c75d | ||
|
|
90a8f818bf | ||
|
|
642f57ff6d | ||
|
|
cbccd9e3d0 | ||
|
|
cf7a3e6f70 | ||
|
|
8993687c37 | ||
|
|
ff1d7b115a | ||
|
|
98bd5149e9 | ||
|
|
4efa2e0c6a | ||
|
|
f805036054 | ||
|
|
3c723c4325 | ||
|
|
14a83f6b52 | ||
|
|
ff0686670c | ||
|
|
3198d07553 | ||
|
|
c7e2896326 | ||
|
|
0db5381a8b | ||
|
|
cb86151deb | ||
|
|
d6c7326467 | ||
|
|
92c6c45e77 | ||
|
|
c6fff4950d | ||
|
|
81a8123725 | ||
|
|
d0d3e74d55 | ||
|
|
b54ae272eb | ||
|
|
3af6d96e6e | ||
|
|
f38b33ea39 | ||
|
|
dd2b0a1595 | ||
|
|
c96fcb7afc | ||
|
|
b805a29259 | ||
|
|
5450246f06 | ||
|
|
d9a00eeaf7 | ||
|
|
131ed13df1 | ||
|
|
5f8d70028a | ||
|
|
c222b702c3 | ||
|
|
de43391e4c | ||
|
|
547c0b8399 | ||
|
|
fcbb5e46a1 | ||
|
|
7c5166c8bb | ||
|
|
fab66606b3 | ||
|
|
1d143f7103 | ||
|
|
4955fcd12a | ||
|
|
817e9663fa | ||
|
|
85ca850453 | ||
|
|
3baefb2b60 | ||
|
|
ffea5a0e02 | ||
|
|
be55695691 | ||
|
|
ea27c96362 | ||
|
|
7a73a01999 | ||
|
|
018dee6c38 | ||
|
|
c7cf2e6f16 | ||
|
|
9ab9a6e8b0 | ||
|
|
67ccff3e86 | ||
|
|
40c09ce26a | ||
|
|
3e0d4a0bed | ||
|
|
e8a6d38ac6 | ||
|
|
80159ecca8 | ||
|
|
c82bb730b2 | ||
|
|
26dad399d5 | ||
|
|
2689e6d6c0 | ||
|
|
90d1b68bd6 | ||
|
|
c7c4318c11 | ||
|
|
d6a2e4aee9 | ||
|
|
c6488b58f5 | ||
|
|
18bfcc24ad | ||
|
|
d8a134fe7e | ||
|
|
989f48c47a | ||
|
|
111a32b5e8 | ||
|
|
993ca754b5 | ||
|
|
381a37fbaa | ||
|
|
0ca61b4d99 | ||
|
|
16748a75d5 | ||
|
|
0e33dfa019 | ||
|
|
4a2f7ebf87 | ||
|
|
e9f18b79ea | ||
|
|
66629a591a | ||
|
|
8f22a358cf | ||
|
|
1f5f1596e5 | ||
|
|
339554bdbf | ||
|
|
9b6b614857 | ||
|
|
e6e99d4239 | ||
|
|
f4ae5125dc | ||
|
|
c3cfbd8474 | ||
|
|
86dd03c917 | ||
|
|
6410e34bf3 | ||
|
|
2db7fee745 | ||
|
|
4e8908e715 | ||
|
|
67d8020147 | ||
|
|
b4b9f33b2c | ||
|
|
d091703dc0 | ||
|
|
509b5291c3 | ||
|
|
111a0823e9 | ||
|
|
48bc7a45a9 | ||
|
|
1eb70d4cfd | ||
|
|
eae63b7c57 | ||
|
|
ec0862f99e | ||
|
|
79ca6f4acb | ||
|
|
66a9690dc9 | ||
|
|
01c65578b0 | ||
|
|
dd462989b5 | ||
|
|
da6ac1626b | ||
|
|
a38ff69cbd | ||
|
|
70db327eda | ||
|
|
8c3f86c690 | ||
|
|
b66542cb40 | ||
|
|
873ad871da | ||
|
|
889eaaea92 | ||
|
|
d2ce72e4aa | ||
|
|
bcfac02c96 | ||
|
|
60a2ed48c2 | ||
|
|
087c0b8253 | ||
|
|
a9a0967a6f | ||
|
|
7bbaa3806b | ||
|
|
7f910a13d5 | ||
|
|
6841c2328e | ||
|
|
ae072929df | ||
|
|
5d756eb54b | ||
|
|
9fe5d6655c | ||
|
|
37b5b22713 | ||
|
|
ee731e4759 | ||
|
|
0dbe3133cf | ||
|
|
843219c38b | ||
|
|
810d5f3c1f | ||
|
|
4a5bd0db05 | ||
|
|
0120e4d1f5 | ||
|
|
d199a18a91 | ||
|
|
ffc0981fbc | ||
|
|
27ca9b027b | ||
|
|
b0ff699b31 | ||
|
|
3a0178b294 | ||
|
|
7bd40c94c7 | ||
|
|
d1c497df7f | ||
|
|
e59deb23c2 | ||
|
|
dd3fc90372 | ||
|
|
89686399f9 | ||
|
|
e8b571590e | ||
|
|
19294db942 | ||
|
|
f47e4a78d7 | ||
|
|
c58250e1f0 | ||
|
|
576e60a2b5 | ||
|
|
3f5499be90 | ||
|
|
4dcf6e87bc | ||
|
|
028758c4e0 | ||
|
|
edd6615bcf | ||
|
|
3c919ee5d1 | ||
|
|
fdc6eef921 | ||
|
|
0c645b6e66 | ||
|
|
1ba1007261 | ||
|
|
1c33fb4e14 | ||
|
|
cd83a6f209 | ||
|
|
17638f3d3a | ||
|
|
61b14b52d9 | ||
|
|
8dd648f85d | ||
|
|
256e27cd90 | ||
|
|
0c3a812825 | ||
|
|
80f8fd49f1 | ||
|
|
80c500f618 | ||
|
|
77c9a7e2fa | ||
|
|
027c0f41e5 | ||
|
|
f9fc83bfb0 | ||
|
|
372bc2d9d6 | ||
|
|
82606e63c0 | ||
|
|
3feb3f592c | ||
|
|
dfd6857069 | ||
|
|
b8724ac8c3 | ||
|
|
1d8515bce0 | ||
|
|
c747ffee5a | ||
|
|
7d601b45a2 | ||
|
|
8be886daf6 | ||
|
|
d471d2416d | ||
|
|
f4c00ee0b6 | ||
|
|
009c131819 | ||
|
|
b6722897a0 | ||
|
|
1b46278f86 | ||
|
|
1274f56da8 | ||
|
|
0f572f4cb3 | ||
|
|
cbe3498125 | ||
|
|
e6ab0b6864 | ||
|
|
5b3931ecb7 | ||
|
|
ddd70ab8ce | ||
|
|
ba4cc234ae | ||
|
|
3563a4cc36 | ||
|
|
0526734ca1 | ||
|
|
f4f8d45a8e | ||
|
|
b3153eed64 | ||
|
|
ba11febad6 | ||
|
|
0cea8db0f9 | ||
|
|
8b7572a9e5 | ||
|
|
dd20af4ba0 | ||
|
|
222ef2f850 | ||
|
|
fc9ac23725 | ||
|
|
0f426b9c19 | ||
|
|
a7d4710702 | ||
|
|
b1117ed54a | ||
|
|
7ad4b55ee0 | ||
|
|
396dc34a84 | ||
|
|
9b4a31fa6a | ||
|
|
8c7f976ef5 | ||
|
|
01f61d3c73 | ||
|
|
69b4bcbd09 | ||
|
|
bb397fb8d0 | ||
|
|
17ecf05215 | ||
|
|
e340b3e6fa | ||
|
|
4ab8677173 | ||
|
|
343d803d8e | ||
|
|
c643d7edc3 | ||
|
|
a4b37d01ab | ||
|
|
a59eb0c4c7 | ||
|
|
2dcc3206e1 | ||
|
|
dc9040a68e | ||
|
|
5160b9fbd6 | ||
|
|
a2af45e1c7 | ||
|
|
0165ccbaac | ||
|
|
b817cb4a1b | ||
|
|
584378a32b | ||
|
|
6d9ef26eca | ||
|
|
1bc170b069 | ||
|
|
babd5897ae | ||
|
|
63ec5b5519 | ||
|
|
e5e468a463 | ||
|
|
6946279f03 | ||
|
|
ee65c9f47d | ||
|
|
f92935d93f | ||
|
|
d282045683 | ||
|
|
129bf53edc | ||
|
|
6113c388b7 | ||
|
|
764326ab16 | ||
|
|
262ad0b51c | ||
|
|
8cc2b64066 | ||
|
|
ceb4b76cdb | ||
|
|
80af1fa9e6 | ||
|
|
844fd4358c | ||
|
|
79b41954f9 | ||
|
|
5a4a7814e1 | ||
|
|
c4630aaf7b | ||
|
|
d35ad50254 | ||
|
|
b1cc6f2a9c | ||
|
|
0d94329940 | ||
|
|
04150e1c0a | ||
|
|
385757b54b | ||
|
|
ccfe922c30 | ||
|
|
b3e0546f78 | ||
|
|
aaaf8d7db3 | ||
|
|
b1b2cd088b | ||
|
|
d1ea61debc | ||
|
|
12cebea29e | ||
|
|
81a3fdbc29 | ||
|
|
fea4669d82 | ||
|
|
241f9ed383 | ||
|
|
3d06ce444c | ||
|
|
06fed944c9 | ||
|
|
5d225c2583 | ||
|
|
e626367a06 | ||
|
|
5c992c3214 | ||
|
|
5575c83970 | ||
|
|
6dabad76ba | ||
|
|
1c656f8b90 | ||
|
|
51b6fed468 | ||
|
|
f92d918a1e | ||
|
|
3e290f057f | ||
|
|
13eb0231ac | ||
|
|
6089f0aa8e | ||
|
|
b0c4050567 | ||
|
|
3f9244542d | ||
|
|
70b6098ee5 | ||
|
|
1656e91296 | ||
|
|
5b7df9c175 | ||
|
|
8d8600aaa8 | ||
|
|
54d136cc6a | ||
|
|
661293c189 | ||
|
|
d10d42e206 | ||
|
|
b780eab5f5 | ||
|
|
315e43746b | ||
|
|
526c48450b | ||
|
|
abd2dcf2e8 | ||
|
|
87defa569c | ||
|
|
b4db5518db | ||
|
|
a50b635424 | ||
|
|
40a794f624 | ||
|
|
6876790374 |
79
.github/workflows/build-image-for-test.yml
vendored
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
name: build-image-for-test
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ['v2-dev']
|
||||||
|
paths:
|
||||||
|
- "build-dev.trigger"
|
||||||
|
|
||||||
|
# schedule:
|
||||||
|
# - # 国际时间 19:17 执行,北京时间3:17 ↙↙↙ 改成你想要每天自动执行的时间
|
||||||
|
# - cron: '17 19 * * *'
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-certd-image:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout Code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
ref: v2-dev
|
||||||
|
|
||||||
|
- name: get_certd_version
|
||||||
|
id: get_certd_version
|
||||||
|
uses: actions/github-script@v6
|
||||||
|
with:
|
||||||
|
result-encoding: string
|
||||||
|
script: |
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const pnpmWorkspace = "./pnpm-workspace.yaml";
|
||||||
|
fs.unlinkSync(pnpmWorkspace)
|
||||||
|
const jsonFilePath = "./packages/ui/certd-server/package.json";
|
||||||
|
const jsonContent = fs.readFileSync(jsonFilePath, 'utf-8');
|
||||||
|
const pkg = JSON.parse(jsonContent)
|
||||||
|
console.log("certd_version:",pkg.version);
|
||||||
|
return pkg.version
|
||||||
|
# - name: Use Node.js
|
||||||
|
# uses: actions/setup-node@v4
|
||||||
|
# with:
|
||||||
|
# node-version: 18
|
||||||
|
# cache: 'npm'
|
||||||
|
# working-directory: ./packages/ui/certd-client
|
||||||
|
- run: |
|
||||||
|
npm install -g pnpm@8.15.7
|
||||||
|
pnpm install
|
||||||
|
npm run build
|
||||||
|
working-directory: ./packages/ui/certd-client
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Login to aliyun container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: registry.cn-shenzhen.aliyuncs.com
|
||||||
|
username: ${{ secrets.aliyun_cs_username }}
|
||||||
|
password: ${{ secrets.aliyun_cs_password }}
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.dockerhub_username }}
|
||||||
|
password: ${{ secrets.dockerhub_password }}
|
||||||
|
|
||||||
|
- name: Build default platforms
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
context: ./packages/ui/
|
||||||
|
tags: |
|
||||||
|
registry.cn-shenzhen.aliyuncs.com/handsfree/certd-dev:latest
|
||||||
|
greper/certd-dev:latest
|
||||||
|
|
||||||
47
.github/workflows/build-image.yml
vendored
@@ -17,6 +17,9 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout Code
|
- name: Checkout Code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
lfs: true
|
||||||
|
|
||||||
- name: get_certd_version
|
- name: get_certd_version
|
||||||
id: get_certd_version
|
id: get_certd_version
|
||||||
@@ -76,26 +79,26 @@ jobs:
|
|||||||
greper/certd:latest
|
greper/certd:latest
|
||||||
greper/certd:${{steps.get_certd_version.outputs.result}}
|
greper/certd:${{steps.get_certd_version.outputs.result}}
|
||||||
|
|
||||||
- name: Build armv7
|
# - name: Build armv7
|
||||||
uses: docker/build-push-action@v6
|
# uses: docker/build-push-action@v6
|
||||||
with:
|
# with:
|
||||||
platforms: linux/arm/v7
|
# platforms: linux/arm/v7
|
||||||
push: true
|
# push: true
|
||||||
context: ./packages/ui/
|
# context: ./packages/ui/
|
||||||
tags: |
|
# tags: |
|
||||||
registry.cn-shenzhen.aliyuncs.com/handsfree/certd:armv7
|
# registry.cn-shenzhen.aliyuncs.com/handsfree/certd:armv7
|
||||||
registry.cn-shenzhen.aliyuncs.com/handsfree/certd:${{steps.get_certd_version.outputs.result}}-armv7
|
# registry.cn-shenzhen.aliyuncs.com/handsfree/certd:${{steps.get_certd_version.outputs.result}}-armv7
|
||||||
greper/certd:armv7
|
# greper/certd:armv7
|
||||||
greper/certd:${{steps.get_certd_version.outputs.result}}-armv7
|
# greper/certd:${{steps.get_certd_version.outputs.result}}-armv7
|
||||||
|
|
||||||
- name: Build agent
|
# - name: Build agent
|
||||||
uses: docker/build-push-action@v6
|
# uses: docker/build-push-action@v6
|
||||||
with:
|
# with:
|
||||||
platforms: linux/amd64,linux/arm64
|
# platforms: linux/amd64,linux/arm64
|
||||||
push: true
|
# push: true
|
||||||
context: ./packages/ui/agent/
|
# context: ./packages/ui/agent/
|
||||||
tags: |
|
# tags: |
|
||||||
registry.cn-shenzhen.aliyuncs.com/handsfree/certd-agent:latest
|
# registry.cn-shenzhen.aliyuncs.com/handsfree/certd-agent:latest
|
||||||
registry.cn-shenzhen.aliyuncs.com/handsfree/certd-agent:${{steps.get_certd_version.outputs.result}}
|
# registry.cn-shenzhen.aliyuncs.com/handsfree/certd-agent:${{steps.get_certd_version.outputs.result}}
|
||||||
greper/certd-agent:latest
|
# greper/certd-agent:latest
|
||||||
greper/certd-agent:${{steps.get_certd_version.outputs.result}}
|
# greper/certd-agent:${{steps.get_certd_version.outputs.result}}
|
||||||
|
|||||||
11
.github/workflows/deploy-demo.yml
vendored
@@ -2,8 +2,8 @@ name: deploy-demo
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: ['v2-dev']
|
branches: ['v2-dev']
|
||||||
# paths:
|
paths:
|
||||||
# - "deploy.trigger"
|
- "deploy.trigger"
|
||||||
workflow_run:
|
workflow_run:
|
||||||
workflows: [ "build-image" ]
|
workflows: [ "build-image" ]
|
||||||
types:
|
types:
|
||||||
@@ -21,6 +21,9 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout Code
|
- name: Checkout Code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
ref: v2-dev
|
||||||
- name: get_certd_version
|
- name: get_certd_version
|
||||||
id: get_certd_version
|
id: get_certd_version
|
||||||
uses: actions/github-script@v6
|
uses: actions/github-script@v6
|
||||||
@@ -38,7 +41,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
time: '10' # for 60 seconds
|
time: '10' # for 60 seconds
|
||||||
- name: deploy-certd-demo
|
- name: deploy-certd-demo
|
||||||
id: request
|
|
||||||
uses: tyrrrz/action-http-request@master
|
uses: tyrrrz/action-http-request@master
|
||||||
with:
|
with:
|
||||||
url: http://flow-openapi.aliyun.com/pipeline/webhook/lzCzlGrLCOHQaTMMt0mG
|
url: http://flow-openapi.aliyun.com/pipeline/webhook/lzCzlGrLCOHQaTMMt0mG
|
||||||
@@ -53,11 +55,12 @@ jobs:
|
|||||||
retry-delay: 5000
|
retry-delay: 5000
|
||||||
|
|
||||||
- name: deploy-certd-doc
|
- name: deploy-certd-doc
|
||||||
id: request
|
|
||||||
uses: tyrrrz/action-http-request@master
|
uses: tyrrrz/action-http-request@master
|
||||||
with:
|
with:
|
||||||
url: http://flow-openapi.aliyun.com/pipeline/webhook/IiSxLDp9aOhgDUxJPytv
|
url: http://flow-openapi.aliyun.com/pipeline/webhook/IiSxLDp9aOhgDUxJPytv
|
||||||
method: POST
|
method: POST
|
||||||
|
body: |
|
||||||
|
{}
|
||||||
headers: |
|
headers: |
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
retry-count: 3
|
retry-count: 3
|
||||||
|
|||||||
3
.github/workflows/sync-to-gitee-dev.yml
vendored
@@ -13,9 +13,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout work repo # 1. 检出当前仓库(certd-sync-work)
|
- name: Checkout work repo # 1. 检出当前仓库(certd-sync-work)
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
lfs: true
|
||||||
- name: Set git user # 2. 给git命令设置用户名和邮箱,↙↙↙ 改成你的name和email
|
- name: Set git user # 2. 给git命令设置用户名和邮箱,↙↙↙ 改成你的name和email
|
||||||
run: |
|
run: |
|
||||||
git config --global user.name "xiaojunnuo"
|
git config --global user.name "xiaojunnuo"
|
||||||
|
|||||||
3
.github/workflows/sync-to-gitee.yml
vendored
@@ -13,9 +13,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout work repo # 1. 检出当前仓库(certd-sync-work)
|
- name: Checkout work repo # 1. 检出当前仓库(certd-sync-work)
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
lfs: true
|
||||||
- name: Set git user # 2. 给git命令设置用户名和邮箱,↙↙↙ 改成你的name和email
|
- name: Set git user # 2. 给git命令设置用户名和邮箱,↙↙↙ 改成你的name和email
|
||||||
run: |
|
run: |
|
||||||
git config --global user.name "xiaojunnuo"
|
git config --global user.name "xiaojunnuo"
|
||||||
|
|||||||
2
.gitignore
vendored
@@ -29,3 +29,5 @@ test/**/*.js
|
|||||||
/packages/ui/certd-server/data/db.sqlite
|
/packages/ui/certd-server/data/db.sqlite
|
||||||
/packages/ui/certd-server/data/keys.yaml
|
/packages/ui/certd-server/data/keys.yaml
|
||||||
/packages/pro/
|
/packages/pro/
|
||||||
|
|
||||||
|
test.js
|
||||||
2
.npmrc
@@ -1,2 +1,2 @@
|
|||||||
link-workspace-packages=true
|
link-workspace-packages=deep
|
||||||
prefer-workspace-packages=true
|
prefer-workspace-packages=true
|
||||||
|
|||||||
297
CHANGELOG.md
@@ -3,6 +3,303 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.29.3](https://github.com/certd/certd/compare/v1.29.2...v1.29.3) (2025-01-04)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复系统级授权无法查看密钥的bug ([8644348](https://github.com/certd/certd/commit/8644348fc41ae2e1672f946ca37e5d3a674e0218))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 优化站点证书检查页面,检查增加3次重试 ([e6dd7cd](https://github.com/certd/certd/commit/e6dd7cd54a3e23897031b5df6e0c3cdc0545d35a))
|
||||||
|
* 优化acme sdk ([54db744](https://github.com/certd/certd/commit/54db74428259de64d12230c2ab7353ae11197bbc))
|
||||||
|
* 支持http校验方式申请证书 ([405591c](https://github.com/certd/certd/commit/405591c5d08fa1a3b228ee3980199e7731cfec4a))
|
||||||
|
* http校验方式,支持七牛云oss、阿里云oss、腾讯云cos ([3f74d4d](https://github.com/certd/certd/commit/3f74d4d9e5f5d0e629b44cff1895b3f7a8fbcafc))
|
||||||
|
|
||||||
|
## [1.29.2](https://github.com/certd/certd/compare/v1.29.1...v1.29.2) (2024-12-25)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复套餐关闭状态下,仍然限制用户流水线数量的bug ([66fb9e5](https://github.com/certd/certd/commit/66fb9e5f49491f9c159363b48af14720a37673b1))
|
||||||
|
|
||||||
|
## [1.29.1](https://github.com/certd/certd/compare/v1.29.0...v1.29.1) (2024-12-25)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 免费套餐支持购买 ([f5ec987](https://github.com/certd/certd/commit/f5ec9870fd6af1f0c9099852bbdb4d07813ccce8))
|
||||||
|
* 修复某处金额转换丢失精度的bug ([d2d6f12](https://github.com/certd/certd/commit/d2d6f12218cbe7bd55f4ae082b93084be85f0a7b))
|
||||||
|
* 修复新版本小红点显示错误问题 ([fe4786e](https://github.com/certd/certd/commit/fe4786e168afe03a5243dd67971476c348339809))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 用户创建证书流水线没有购买套餐或者超限时提前报错 ([472f06c](https://github.com/certd/certd/commit/472f06c2d190d0ae48e8b53c18bc278437656a1c))
|
||||||
|
* 优化插件名称显示 ([26adf7d](https://github.com/certd/certd/commit/26adf7d437e674385f26a8f92fded6521a620671))
|
||||||
|
|
||||||
|
# [1.29.0](https://github.com/certd/certd/compare/v1.28.4...v1.29.0) (2024-12-24)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复手机模式下,查询框被文字遮盖的bug ([040788c](https://github.com/certd/certd/commit/040788c793642c3bb2a3ede87fe30fcf3be471bd))
|
||||||
|
* 修复左侧菜单收起时无法展开子菜单的bug ([0056223](https://github.com/certd/certd/commit/005622307e612717a5408aa1484717ef03003a22))
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 基础版不再限制流水线数量 ([cb27d4b](https://github.com/certd/certd/commit/cb27d4b4906b2782eaceb0a95bbdc5d0534370d2))
|
||||||
|
* 套餐购买支持易支付、支付宝支付 ([faa28f8](https://github.com/certd/certd/commit/faa28f88f954cba4c1dd29125562e5acd2fd99af))
|
||||||
|
* 用户套餐,用户支付功能 ([a019956](https://github.com/certd/certd/commit/a019956698acaf2c4beb620b5ad8c18918ead6a1))
|
||||||
|
* 站点证书监控 ([9c8c7a7](https://github.com/certd/certd/commit/9c8c7a781223f4217f45510db1e89495600e3cd5))
|
||||||
|
* 支持微信支付 ([45d6347](https://github.com/certd/certd/commit/45d6347f5b6199493b11aabdd74177f6dca2cea4))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 调整创建证书表单字段的顺序 ([d393521](https://github.com/certd/certd/commit/d3935219f2aa50d6662c5b5ebf7ee25ad696ab2b))
|
||||||
|
* 同一时间只允许一个套餐生效 ([8ebf95a](https://github.com/certd/certd/commit/8ebf95a222a900d1707716c7b1f3b39f8a6d8f94))
|
||||||
|
* 用户名支持修改 ([89c7f07](https://github.com/certd/certd/commit/89c7f070343e86453c84677ebe1669f9b266d871))
|
||||||
|
* 优化证书申请跳过的状态显示,成功通知现在在跳过时不会发送 ([67d762b](https://github.com/certd/certd/commit/67d762b6a520f1fa24719a124e5ae975a81f5f82))
|
||||||
|
* 站点证书监控通知发送,每天定时检查 ([bb4910f](https://github.com/certd/certd/commit/bb4910f4e57234e42b44505f4620ae7af66025c5))
|
||||||
|
* 支持一体证书 ([53c38cf](https://github.com/certd/certd/commit/53c38cf714a6f7486abbf1d71c9f48f56a790100))
|
||||||
|
* 支持plesk网站证书部署 ([eda45c1](https://github.com/certd/certd/commit/eda45c1528199648b3970505e87f492d398226cd))
|
||||||
|
|
||||||
|
## [1.28.4](https://github.com/certd/certd/compare/v1.28.3...v1.28.4) (2024-12-12)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复证书成功通知发送失败的bug ([0f5c690](https://github.com/certd/certd/commit/0f5c69040ba77340c909813220a26bc7ddada3ea))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 群晖支持6.x ([79f7ec4](https://github.com/certd/certd/commit/79f7ec4672f4fd5744cc45e4a6f104da943f4026))
|
||||||
|
|
||||||
|
## [1.28.3](https://github.com/certd/certd/compare/v1.28.2...v1.28.3) (2024-12-12)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复没有配置eab时,报order无法读取的问题 ([657a2ae](https://github.com/certd/certd/commit/657a2ae032e6f61ac27fbdd26c7bf169c041219e))
|
||||||
|
* 修复授权被删除后,无法清空的bug ([b45977c](https://github.com/certd/certd/commit/b45977c29a29084c11e496bec3415eaaebafdd74))
|
||||||
|
* mysql下access.setting字段改成text ([b7f5740](https://github.com/certd/certd/commit/b7f5740c57743914f754f3b4fdd94b59a2e8338c))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 点击版本红点按钮,跳转到升级帮助页面 ([454fbda](https://github.com/certd/certd/commit/454fbda581bbe22abca5b91e5086ea9d9d58a020))
|
||||||
|
* 通知标题优化 ([ff083ce](https://github.com/certd/certd/commit/ff083ce6848a8bee3c8248e4b881086ae1517c28))
|
||||||
|
* 支持腾讯虚拟机开关机([@wujingke](https://github.com/wujingke)) ([8039e8b](https://github.com/certd/certd/commit/8039e8baf83c82d03f1a6198cf61c372026b962b))
|
||||||
|
* 支持aws cloudfront ([0ae39f1](https://github.com/certd/certd/commit/0ae39f160a7c6b6696b3bf513d68aa28905810ad))
|
||||||
|
|
||||||
|
## [1.28.2](https://github.com/certd/certd/compare/v1.28.1...v1.28.2) (2024-12-09)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复创建流水线通知设置无效的bug ([498cf34](https://github.com/certd/certd/commit/498cf34999fddfa24ce088e2e678469fa669abb8))
|
||||||
|
* 修复流水线分组可以被所有人看见的bug ([a0e838d](https://github.com/certd/certd/commit/a0e838d1eec918e5dc92fe95dc72ac14facb930e))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 优化数据表索引 ([228fdf0](https://github.com/certd/certd/commit/228fdf0a0d28013f5dd156a97bbde80537e8e97e))
|
||||||
|
* 支持mysql ([7cde1fd](https://github.com/certd/certd/commit/7cde1fdc4a9ed851900d231a5460c8dbfbcd148e))
|
||||||
|
|
||||||
|
## [1.28.1](https://github.com/certd/certd/compare/v1.28.0...v1.28.1) (2024-12-08)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复cname排查方法 nslookup命令显示黑色的问题 ([3dfeeec](https://github.com/certd/certd/commit/3dfeeec899d7d0d7292695ce410f78548e076c03))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 通知选择器优化 ([2c0cbdd](https://github.com/certd/certd/commit/2c0cbdd29ecb74cc939b2ae7ee86b8d40f70ba31))
|
||||||
|
* 新增七牛云插件分组 ([49e7dc5](https://github.com/certd/certd/commit/49e7dc56e1a95fbdea3e30cdeb945b48415b69e3))
|
||||||
|
* 新增server酱3通知 ([6aa4872](https://github.com/certd/certd/commit/6aa487269c9f6862e188b37a0d6c73f79c937d94))
|
||||||
|
* 支持邀请奖励 ([618ec93](https://github.com/certd/certd/commit/618ec937866b24ebcf8164db43acb1ed66a5b329))
|
||||||
|
* 支持易发云短信 ([94fa77f](https://github.com/certd/certd/commit/94fa77fcd2b9bea294fb05736c0d8cdc81f56103))
|
||||||
|
* cname value优化 ([e8c9c2a](https://github.com/certd/certd/commit/e8c9c2a47d47048ae743b16f7bc932dbe18a89e9))
|
||||||
|
* favicon支持自定义 ([8b9c47d](https://github.com/certd/certd/commit/8b9c47daf194515006689a212ae9cf586bdf5993))
|
||||||
|
|
||||||
|
# [1.28.0](https://github.com/certd/certd/compare/v1.27.9...v1.28.0) (2024-11-30)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复自定义webhook contextType的bug ([7e5ea0c](https://github.com/certd/certd/commit/7e5ea0cee003acda952d922ca70592f1e8a2ed80))
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 手机号登录、邮箱验证码注册 ([7b55337](https://github.com/certd/certd/commit/7b55337c5edb470cca7aa62201eda8d274784004))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 部署到IIS插件 ([1534f45](https://github.com/certd/certd/commit/1534f4523633265d219d7b3a249a9ea1af99c512))
|
||||||
|
* 登录失败增加重试次数限制及冷却时间 ([954b6df](https://github.com/certd/certd/commit/954b6df3608695fe074130f8149a33e311d80cc4))
|
||||||
|
* 流水线支持批量修改分组,批量删除 ([a847e66](https://github.com/certd/certd/commit/a847e66c4fc843b98f1520b2b8072d3586ce8b81))
|
||||||
|
* 取消docker-compose的dns配置 ([87bbf6f](https://github.com/certd/certd/commit/87bbf6f14080b9fa287c250d7fc4d33279c83ff7))
|
||||||
|
* 首页新增修改密码提示 ([0772d3b](https://github.com/certd/certd/commit/0772d3b3fd24afdde4086d9f09ef19d037b431b4))
|
||||||
|
* 选项显示图标 ([aedc462](https://github.com/certd/certd/commit/aedc46213571a3bd93809b7af7fa17a08d546237))
|
||||||
|
* 优化七牛云cdn,获取域名列表可以选择 ([5a20242](https://github.com/certd/certd/commit/5a20242111d6bd255b25dac86fe1f062c8543096))
|
||||||
|
* 优化七牛云cdn部署,保持http2和forceHttp设置,当未开启https时,主动开启https ([196f7d9](https://github.com/certd/certd/commit/196f7d9dc23d7dd96b663c686542e85270b81aef))
|
||||||
|
* 优化证书申请成功通知发送方式 ([8002a56](https://github.com/certd/certd/commit/8002a56efc5998aa03db5711ae87f9eb4bc9e160))
|
||||||
|
* 支持短信验证码登录 ([387bcc5](https://github.com/certd/certd/commit/387bcc5fa418cdeea81a06da5e3f8cd6b43cd082))
|
||||||
|
* 支持威联通证书部署 ([0d8913e](https://github.com/certd/certd/commit/0d8913ea2f56fdebbcc9bb207eae59e8ddbb8cad))
|
||||||
|
* 自定义webhook显示详细的错误信息 ([3254afc](https://github.com/certd/certd/commit/3254afc75640eed3729d0fc02a818fefbe5c7fc3))
|
||||||
|
|
||||||
|
## [1.27.9](https://github.com/certd/certd/compare/v1.27.8...v1.27.9) (2024-11-26)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 通知支持自定义webhook、anpush、iyuu、server酱 ([cbccd9e](https://github.com/certd/certd/commit/cbccd9e3d0a4c24aba772af62734666d40b22c57))
|
||||||
|
* 通知支持vocechat、bark、telegram、discord、slack ([642f57f](https://github.com/certd/certd/commit/642f57ff6d7152a9e14f59c7fc0e32a6b1751fb7))
|
||||||
|
|
||||||
|
## [1.27.8](https://github.com/certd/certd/compare/v1.27.7...v1.27.8) (2024-11-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package root
|
||||||
|
|
||||||
|
## [1.27.7](https://github.com/certd/certd/compare/v1.27.6...v1.27.7) (2024-11-25)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复关键字查询bug ([fab6660](https://github.com/certd/certd/commit/fab66606b35a540fac31fee902331ba1ffdebc16))
|
||||||
|
* 修复CNAME时子域名级数超出限制的问题 ([3af6d96](https://github.com/certd/certd/commit/3af6d96e6e353c9b2111cff81679b79c55195a0a))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 谷歌EAB绑定邮箱改成必填 ([81a8123](https://github.com/certd/certd/commit/81a8123725d7bf4bd6a32a64a066bd760b7b6a7f))
|
||||||
|
* 华为云密钥获取提示及访问链接 ([de43391](https://github.com/certd/certd/commit/de43391e4c12dc3ad976f8fa8787f4eb70a41e75))
|
||||||
|
* 通知管理 ([d9a00ee](https://github.com/certd/certd/commit/d9a00eeaf72735ced67c59d7983d84e3c730064a))
|
||||||
|
* 通知渠道支持测试按钮 ([b54ae27](https://github.com/certd/certd/commit/b54ae272ebc2d31b32b049d44e2299a6be7f153c))
|
||||||
|
* 优化插件开发,dnsProvider无需写http logger 变量 ([fcbb5e4](https://github.com/certd/certd/commit/fcbb5e46a112174150a62648319b8224fce3b7ed))
|
||||||
|
* 支持部署到阿里云WAF ([c96fcb7](https://github.com/certd/certd/commit/c96fcb7afced979435cffa73591275008033c90d))
|
||||||
|
* 支持企业微信群聊机器人通知 ([b805a29](https://github.com/certd/certd/commit/b805a2925984144a31575b8aaa622f0c30d41b56))
|
||||||
|
|
||||||
|
## [1.27.6](https://github.com/certd/certd/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* .env 读取 \r 问题 ([0e33dfa](https://github.com/certd/certd/commit/0e33dfa019a55ea76193c428ec756af386adeb9d))
|
||||||
|
* 修复vip试用secret报错的bug ([018dee6](https://github.com/certd/certd/commit/018dee6c383233560f078dfd30f6c2857a7e15ee))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 当步骤全部都禁用时,任务本身显示删除线 ([9ab9a6e](https://github.com/certd/certd/commit/9ab9a6e8b083e19793894f23e59f29c604ec98e5))
|
||||||
|
|
||||||
|
## [1.27.5](https://github.com/certd/certd/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复1Panel面板本身证书更新导致判定执行失败的问题 ([2689e6d](https://github.com/certd/certd/commit/2689e6d6c03aba21da90d5d45232c6ba08696be1))
|
||||||
|
* 修复角色无法删除的bug ([66629a5](https://github.com/certd/certd/commit/66629a591aecc2d8364ea415c7afc3f9d0406562))
|
||||||
|
* 修复Cname情况下,无法使用DNS类型的bug ([26dad39](https://github.com/certd/certd/commit/26dad399d5768b3205da099ddc11809aef7d6224))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 日志查看自动滚动到底部 ([4a2f7eb](https://github.com/certd/certd/commit/4a2f7ebf87b7c027cebff7cb763f8f35f6d2aa36))
|
||||||
|
* 系统设置中的代理设置优化为可全局生效,环境变量中的https_proxy设置将无效 ([381a37f](https://github.com/certd/certd/commit/381a37fbaa6b61c887eda743897ae00afb825bdf))
|
||||||
|
* 新手导航在非编辑模式下不显示 ([18bfcc2](https://github.com/certd/certd/commit/18bfcc24ad0bde57bb04db8a4209861ec6b8ff1d))
|
||||||
|
* 优化腾讯云 cloudflare 重复解析记录时的返回值 ([90d1b68](https://github.com/certd/certd/commit/90d1b68bd6cf232fbe085234efe07d29b7690044))
|
||||||
|
* 支持namesilo ([80159ec](https://github.com/certd/certd/commit/80159ecca895103d0495f3217311199e66056572))
|
||||||
|
* 专业版试用,无需绑定账号 ([c7c4318](https://github.com/certd/certd/commit/c7c4318c11b65a76089787aa58939832d338a232))
|
||||||
|
|
||||||
|
## [1.27.4](https://github.com/certd/certd/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复未设置pfx密码,导致jks转换报错的bug ([c3cfbd8](https://github.com/certd/certd/commit/c3cfbd8474155aed4379f91075de37d5d8c73ef0))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 公共cname服务支持关闭 ([f4ae512](https://github.com/certd/certd/commit/f4ae5125dc4cd97816976779cb3586b5ee78947e))
|
||||||
|
|
||||||
|
## [1.27.3](https://github.com/certd/certd/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复偶发性cname一直验证超时的bug ([d2ce72e](https://github.com/certd/certd/commit/d2ce72e4aaacdf726ba8b91fcd71db40a27714ba))
|
||||||
|
* 修复邮件配置,忽略证书校验设置不生效的bug ([66a9690](https://github.com/certd/certd/commit/66a9690dc958732e1b3c672d965db502296446f9))
|
||||||
|
* 修复ipv6未开启情况下,请求带有ipv6地址域名报ETIMEDOUT的bug ([a9a0967](https://github.com/certd/certd/commit/a9a0967a6f1d0bd27e69f3ec52c31d90d470bc23))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 修复站点个性化,浏览器标题没有生效的bug ([bcfac02](https://github.com/certd/certd/commit/bcfac02c96ceaf23d1a0b05b48d8047da933beaf))
|
||||||
|
* 优化上传到主机插 路径选择,根据证书格式显示 ([8c3f86c](https://github.com/certd/certd/commit/8c3f86c6909ed91f48bb2880e78834e22f6f6a29))
|
||||||
|
* 支持jks ([889eaae](https://github.com/certd/certd/commit/889eaaea92818f628b922dae540c026630611707))
|
||||||
|
* ipv6支持 ([da6ac16](https://github.com/certd/certd/commit/da6ac1626b3574be2fabeeb18a1f10d60bdcbe49))
|
||||||
|
|
||||||
|
## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复某些容器管理ui无法识别端口列表的bug ([576e60a](https://github.com/certd/certd/commit/576e60a2b52315909e659d2a58cf98b130e69e6f))
|
||||||
|
* 修复删除腾讯云过期证书时间判断上的bug,导致已过期仍然没有删除证书 ([1ba1007](https://github.com/certd/certd/commit/1ba10072615015d91b81fc56a3b01dae6a2ae9d1))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 优化部署到阿里云CDN插件,支持多域名,更易用 ([80c500f](https://github.com/certd/certd/commit/80c500f618b169a1f64c57fe442242a4d0d9d833))
|
||||||
|
* 优化流水线页面切换回来不丢失查询条件 ([4dcf6e8](https://github.com/certd/certd/commit/4dcf6e87bc5f7657ce8a56c5331e8723a0fee8ee))
|
||||||
|
* 支持公共cname服务 ([3c919ee](https://github.com/certd/certd/commit/3c919ee5d1aef5d26cf3620a7c49d920786bc941))
|
||||||
|
* 执行历史支持点击查看流水线详情 ([8968639](https://github.com/certd/certd/commit/89686399f90058835435b92872fc236fac990148))
|
||||||
|
* 专业版7天试用 ([c58250e](https://github.com/certd/certd/commit/c58250e1f065a9bd8b4e82acc1df754504c0010c))
|
||||||
|
|
||||||
|
## [1.27.1](https://github.com/certd/certd/compare/v1.27.0...v1.27.1) (2024-11-04)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复头像没有更新的bug ([9b4a31f](https://github.com/certd/certd/commit/9b4a31fa6a32b9cab2e22bd141cf96ca29120445))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 禁止页面缓存,点击tab页签可以刷新数据 ([7ad4b55](https://github.com/certd/certd/commit/7ad4b55ee000c1dd0747832b11107f32b0ffb889))
|
||||||
|
* 优化时间选择器,自动填写分钟和秒钟 ([396dc34](https://github.com/certd/certd/commit/396dc34a841c7d016b033736afdba8366fb2d211))
|
||||||
|
* cname 域名映射记录可读性优化 ([b1117ed](https://github.com/certd/certd/commit/b1117ed54a3ef015752999324ff72b821ef5e4b9))
|
||||||
|
|
||||||
|
# [1.27.0](https://github.com/certd/certd/compare/v1.26.16...v1.27.0) (2024-10-31)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复历史记录不能按名称查询的bug ([6113c38](https://github.com/certd/certd/commit/6113c388b7fc58b11ca19ff05cc1286d096c8d28))
|
||||||
|
* pfx兼容windows server 2016 ([e5e468a](https://github.com/certd/certd/commit/e5e468a463f66d02f235de54b7c1e09ace5f1cb1))
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 首页全新改版 ([63ec5b5](https://github.com/certd/certd/commit/63ec5b5519c760a3330569c0da6dac157302a330))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 管理控制台数据统计 ([babd589](https://github.com/certd/certd/commit/babd5897ae013ff7c04ebfcbfac8a00d84dd627c))
|
||||||
|
* 增加向导 ([6d9ef26](https://github.com/certd/certd/commit/6d9ef26ecab71d752c2c55d75aed4fb5f6c05a39))
|
||||||
|
* lego 升级到 4.19.2 ([129bf53](https://github.com/certd/certd/commit/129bf53edc9bbb001fe49fbd7e239bd1d09cc128))
|
||||||
|
|
||||||
|
## [1.26.16](https://github.com/certd/certd/compare/v1.26.15...v1.26.16) (2024-10-30)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复lego No help topic for 错误 ([aaaf8d7](https://github.com/certd/certd/commit/aaaf8d7db34896cf8f2ff8f12eec1ab0cae58f0f))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 支持白山云cdn部署 ([b1b2cd0](https://github.com/certd/certd/commit/b1b2cd088b684eda764962abd61754c26a204d1c))
|
||||||
|
* 支持华为云cdn ([81a3fdb](https://github.com/certd/certd/commit/81a3fdbc29b71f380762008cc151493ec97458f9))
|
||||||
|
|
||||||
|
## [1.26.15](https://github.com/certd/certd/compare/v1.26.14...v1.26.15) (2024-10-28)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 顶部菜单变...的bug ([6dabad7](https://github.com/certd/certd/commit/6dabad76baba96be0f8af36a3fbfb9f5182aecf1))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 默认证书更新时间设置为35天,增加腾讯云删除过期证书插件,可以避免腾讯云过期证书邮件 ([51b6fed](https://github.com/certd/certd/commit/51b6fed468eaa6f28ce4497ce303ace1a52abb96))
|
||||||
|
* 授权加密支持解密查看 ([5575c83](https://github.com/certd/certd/commit/5575c839705f6987ad2bdcd33256b0962c6a9c6a))
|
||||||
|
* 重置管理员密码同时启用管理员账户,避免之前禁用了,重置密码还是登录不进去 ([f92d918](https://github.com/certd/certd/commit/f92d918a1e28e29b794ad4754661ea760c18af46))
|
||||||
|
|
||||||
|
## [1.26.14](https://github.com/certd/certd/compare/v1.26.13...v1.26.14) (2024-10-26)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复阿里云部署大杀器报插件_还未注册错误的bug ([abd2dcf](https://github.com/certd/certd/commit/abd2dcf2e85a545321bae6451406d081f773b132))
|
||||||
|
* 修复启动时自签证书无法保存的bug ([526c484](https://github.com/certd/certd/commit/526c48450bcd37b3ccded9b448f17de8140bdc6e))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 顶部菜单自定义 ([54d136c](https://github.com/certd/certd/commit/54d136cc6ae122f7c891b7a5c7232fe5de8e5cb5))
|
||||||
|
* 禁用readonly用户 ([d10d42e](https://github.com/certd/certd/commit/d10d42e20619bb55a50d636b8867ff33db4e3b4b))
|
||||||
|
* 限制其他用户流水线数量 ([315e437](https://github.com/certd/certd/commit/315e43746baf01682737f82e41579237a48409af))
|
||||||
|
* 用户管理优化头像上传 ([661293c](https://github.com/certd/certd/commit/661293c189a3abf3cdc953b5225192372f57930d))
|
||||||
|
|
||||||
## [1.26.13](https://github.com/certd/certd/compare/v1.26.12...v1.26.13) (2024-10-26)
|
## [1.26.13](https://github.com/certd/certd/compare/v1.26.12...v1.26.13) (2024-10-26)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
128
README.md
@@ -5,48 +5,67 @@ Certd 是一个免费全自动申请和自动部署更新SSL证书的管理系
|
|||||||
|
|
||||||
关键字:证书自动申请、证书自动更新、证书自动续期、证书自动续签、证书管理工具
|
关键字:证书自动申请、证书自动更新、证书自动续期、证书自动续签、证书管理工具
|
||||||
|
|
||||||
|
|
||||||
## 一、特性
|
## 一、特性
|
||||||
本项目不仅支持证书申请过程自动化,还可以自动化部署更新证书,让你的证书永不过期。
|
本项目不仅支持证书申请过程自动化,还可以自动化部署更新证书,让你的证书永不过期。
|
||||||
|
|
||||||
* 全自动申请证书(支持所有注册商注册的域名)
|
* 全自动申请证书(支持所有注册商注册的域名)
|
||||||
* 全自动部署更新证书(目前支持部署到主机、部署到阿里云、腾讯云等,目前已支持30+部署插件)
|
* 全自动部署更新证书(目前支持部署到主机、阿里云、腾讯云等,目前已支持40+部署插件)
|
||||||
* 支持通配符域名/泛域名,支持多个域名打到一个证书上
|
* 支持DNS-01、HTTP-01、CNAME代理等多种域名验证方式
|
||||||
* 邮件通知
|
* 支持通配符域名/泛域名,支持多个域名打到一个证书上,支持pem、pfx、der、jks等多种证书格式
|
||||||
* 私有化部署,保障数据安全
|
* 邮件通知、webhook通知
|
||||||
* 支持sqlite,postgresql数据库
|
* 私有化部署,数据保存本地,授权信息加密存储,镜像由Github Actions构建,过程公开透明
|
||||||
|
* 支持SQLite,PostgreSQL、MySQL数据库
|
||||||
|
|
||||||
|
|
||||||
|
>
|
||||||
|
> 流水线数量现已调整为无限制,欢迎大家使用
|
||||||
|
>
|
||||||
|
|
||||||
|
> 关于证书续期:
|
||||||
|
>* 实际上没有办法不改变证书文件本身情况下直接续期或者续签。
|
||||||
|
>* 我们所说的续期,其实就是按照全套流程重新申请一份新证书,然后重新部署上去。
|
||||||
|
|
||||||
|
|
||||||
## 二、在线体验
|
## 二、在线体验
|
||||||
|
|
||||||
官方Demo地址,自助注册后体验
|
官方Demo地址,自助注册后体验
|
||||||
|
|
||||||
https://certd.handsfree.work/
|
https://certd.handfree.work/
|
||||||
|
|
||||||
> 注意数据将不定期清理,不定期停止定时任务,生产使用请自行部署
|
> 注意数据将不定期清理,不定期停止定时任务,生产使用请自行部署
|
||||||
> 包含敏感信息,务必自己本地部署进行生产使用
|
> 包含敏感信息,务必自己本地部署进行生产使用
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## 三、使用教程
|
## 三、使用教程
|
||||||
|
|
||||||
更多教程请访问文档网站 [certd.docmirror.cn](https://certd.docmirror.cn/)
|
仅需3步,让你的证书永不过期
|
||||||
|
|
||||||
|
### 1. 创建证书流水线
|
||||||
|

|
||||||
|
|
||||||
本案例演示,如何配置自动申请证书,并部署到阿里云CDN,然后快要到期前自动更新证书并重新部署
|
> 添加成功后,就可以直接运行流水线申请证书了
|
||||||
|
|
||||||

|
### 2. 添加部署任务
|
||||||

|
当然我们一般需要把证书部署到应用上,certd支持海量的部署插件,您可以根据自身实际情况进行选择,比如部署到Nginx、阿里云、腾讯云、K8S、CDN、宝塔、1Panel等等
|
||||||

|
|
||||||
|
此处演示部署证书到主机的nginx上
|
||||||
|

|
||||||
|
|
||||||
|
如果目前的部署插件都无法满足,您也可以手动下载,然后自行部署
|
||||||

|

|
||||||

|
|
||||||
|
### 3. 定时运行
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
|
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
|
||||||
-------> [点我查看详细使用步骤演示](./step.md) <--------
|
-------> [点我查看详细使用步骤演示](./step.md) <--------
|
||||||
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
|
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
|
||||||
|
|
||||||
当前支持的部署插件列表
|
更多教程请访问文档网站 [certd.docmirror.cn](https://certd.docmirror.cn/)
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
## 四、私有化部署
|
## 四、私有化部署
|
||||||
|
|
||||||
@@ -54,10 +73,10 @@ https://certd.handsfree.work/
|
|||||||
|
|
||||||
您可以根据实际情况从如下方式中选择一种方式进行私有化部署:
|
您可以根据实际情况从如下方式中选择一种方式进行私有化部署:
|
||||||
|
|
||||||
1. [宝塔面板方式部署](./install/baota/)
|
1. [宝塔面板方式部署](https://certd.docmirror.cn/guide/install/docker/)
|
||||||
2. [1Panel面板方式部署](./install/1panel/)
|
2. [1Panel面板方式部署](https://certd.docmirror.cn/guide/install/1panel/)
|
||||||
2. [Docker方式部署](./install/docker/)
|
3. [Docker方式部署](https://certd.docmirror.cn/guide/install/docker/)
|
||||||
3. [源码方式部署](./install/source/)
|
4. [源码方式部署](https://certd.docmirror.cn/guide/install/source/)
|
||||||
|
|
||||||
#### Docker镜像说明:
|
#### Docker镜像说明:
|
||||||
* 国内镜像地址:
|
* 国内镜像地址:
|
||||||
@@ -75,11 +94,13 @@ https://certd.handsfree.work/
|
|||||||
|
|
||||||
|
|
||||||
## 五、 升级
|
## 五、 升级
|
||||||
如果使用固定版本号
|
|
||||||
|
### docker-compose方式部署
|
||||||
|
#### 1. 如果使用固定版本号
|
||||||
1. 修改`docker-compose.yaml`中的镜像版本号
|
1. 修改`docker-compose.yaml`中的镜像版本号
|
||||||
2. 运行`docker compose up -d` 即可
|
2. 运行`docker compose up -d` 即可
|
||||||
|
|
||||||
如果使用`latest`版本
|
#### 2. 如果需要使用最新版本
|
||||||
```shell
|
```shell
|
||||||
#重新拉取镜像
|
#重新拉取镜像
|
||||||
docker pull registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest
|
docker pull registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest
|
||||||
@@ -87,24 +108,59 @@ docker pull registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest
|
|||||||
docker compose down
|
docker compose down
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
> 数据默认存在`/data/certd`目录下,不用担心数据丢失
|
||||||
|
|
||||||
> 数据默认存在`/data/certd`目录下,不用担心数据丢失
|
### 自动升级(仅限尝鲜建议非生产使用)
|
||||||
|
```yaml
|
||||||
|
version: '3.3'
|
||||||
|
services:
|
||||||
|
certd:
|
||||||
|
image: registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest
|
||||||
|
container_name: certd
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /data/certd:/app/data
|
||||||
|
ports:
|
||||||
|
- "7001:7001"
|
||||||
|
- "7002:7002"
|
||||||
|
environment:
|
||||||
|
- certd_system_resetAdminPasswd=false
|
||||||
|
labels:
|
||||||
|
com.centurylinklabs.watchtower.enable: "true"
|
||||||
|
|
||||||
|
certd-updater: # 添加 Watchtower 服务
|
||||||
|
image: containrrr/watchtower:latest
|
||||||
|
container_name: certd-updater
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
# 配置 自动更新
|
||||||
|
environment:
|
||||||
|
- WATCHTOWER_CLEANUP=true # 自动清理旧版本容器
|
||||||
|
- WATCHTOWER_INCLUDE_STOPPED=false # 不更新已停止的容器
|
||||||
|
- WATCHTOWER_LABEL_ENABLE=true # 根据容器标签进行更新
|
||||||
|
- WATCHTOWER_POLL_INTERVAL=300 # 每 5 分钟检查一次更新
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### 其他部署方式升级方法
|
||||||
|
请参考 https://certd.docmirror.cn/guide/install/upgrade.html
|
||||||
|
|
||||||
|
|
||||||
更新日志: [CHANGELOG](./CHANGELOG.md)
|
|
||||||
|
### 更新日志:
|
||||||
|
|
||||||
|
[CHANGELOG](./CHANGELOG.md)
|
||||||
|
|
||||||
|
|
||||||
## 六、一些说明
|
## 六、一些说明
|
||||||
* 本项目ssl证书提供商为letencrypt/Google/ZeroSSL
|
* 本项目ssl证书提供商为letencrypt/Google/ZeroSSL
|
||||||
* 申请过程遵循acme协议
|
* 申请过程遵循acme协议
|
||||||
* 需要验证域名所有权,一般有两种方式(目前本项目仅支持dns-01)
|
|
||||||
* http-01: 在网站根目录下放置一份txt文件
|
|
||||||
* dns-01: 需要给域名添加txt解析记录,通配符域名只能用这种方式
|
|
||||||
* 证书续期:
|
* 证书续期:
|
||||||
* 实际上没有办法不改变证书文件本身情况下直接续期或者续签。
|
* 实际上没有办法不改变证书文件本身情况下直接续期或者续签。
|
||||||
* 我们所说的续期,其实就是按照全套流程重新申请一份新证书,然后重新部署上去。
|
* 我们所说的续期,其实就是按照全套流程重新申请一份新证书,然后重新部署上去。
|
||||||
* 免费证书过期时间90天,以后可能还会缩短,所以自动化部署必不可少
|
* 免费证书过期时间90天,以后可能还会缩短,所以自动化部署必不可少
|
||||||
* 设置每天自动运行,当证书过期前20天,会自动重新申请证书并部署
|
* 设置每天自动运行,当证书过期前35天,会自动重新申请证书并部署
|
||||||
|
|
||||||
|
|
||||||
## 七、不同平台的设置说明
|
## 七、不同平台的设置说明
|
||||||
@@ -144,18 +200,20 @@ https://afdian.com/a/greper
|
|||||||
|
|
||||||
专业版特权对比
|
专业版特权对比
|
||||||
|
|
||||||
| 功能 | 免费版 | 专业版 |
|
| 功能 | 基础版 | 专业版 |
|
||||||
|---------|-------------------|-----------------------|
|
|------|-----------------|-------------------|
|
||||||
| 免费证书申请 | 免费无限制 | 免费无限制 |
|
| 免费证书申请 | 免费无限制 | 无限制 |
|
||||||
| 自动部署插件 | 阿里云、腾讯云、七牛云、主机部署等 | 支持群晖、宝塔、1Panel等,持续开发中 |
|
| 域名数量 | 免费无限制 | 无限制 |
|
||||||
| 发邮件功能 | 需要配置 | 免配置 |
|
| 证书流水线条数 | 免费无限制 | 无限制 |
|
||||||
| 证书流水线条数 | 10条 | 无限制 |
|
| 站点证书监控 | 1条 | 无限制 |
|
||||||
|
| 自动部署插件 | 阿里云、腾讯云、七牛云、SSH | 支持群晖、宝塔、1Panel等,持续开发中 |
|
||||||
|
| 通知 | 邮件、webhook | server酱、企微、anpush等 |
|
||||||
|
|
||||||
************************
|
************************
|
||||||
|
|
||||||
## 十一、贡献代码
|
## 十一、贡献代码
|
||||||
|
|
||||||
1. 本地开发 [贡献插件教程](https://certd.docmirror.cn/guide/development/)
|
1. 本地开发 [贡献插件](https://certd.docmirror.cn/guide/development/)
|
||||||
2. 作为贡献者,代表您同意您贡献的代码如下许可:
|
2. 作为贡献者,代表您同意您贡献的代码如下许可:
|
||||||
1. 可以调整开源协议以使其更严格或更宽松。
|
1. 可以调整开源协议以使其更严格或更宽松。
|
||||||
2. 可以用于商业用途。
|
2. 可以用于商业用途。
|
||||||
@@ -164,7 +222,7 @@ https://afdian.com/a/greper
|
|||||||
|
|
||||||
## 十二、 开源许可
|
## 十二、 开源许可
|
||||||
* 本项目遵循 GNU Affero General Public License(AGPL)开源协议。
|
* 本项目遵循 GNU Affero General Public License(AGPL)开源协议。
|
||||||
* 允许个人和公司使用、复制、修改和分发本项目,禁止任何形式的商业用途
|
* 允许个人和公司内部自由使用、复制、修改和分发本项目,未获得商业授权情况下禁止任何形式的商业用途
|
||||||
* 未获得商业授权情况下,禁止任何对logo、版权信息及授权许可相关代码的修改。
|
* 未获得商业授权情况下,禁止任何对logo、版权信息及授权许可相关代码的修改。
|
||||||
* 如需商业授权,请联系作者。
|
* 如需商业授权,请联系作者。
|
||||||
|
|
||||||
|
|||||||
1
build-dev.trigger
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1
|
||||||
@@ -1 +1 @@
|
|||||||
00:01
|
01:55
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
version: '3.3' # 兼容旧版docker-compose
|
version: '3.3' # 兼容旧版docker-compose
|
||||||
services:
|
services:
|
||||||
certd:
|
certd:
|
||||||
# 镜像 # ↓↓↓↓↓ ---- 镜像版本号,建议改成固定版本号
|
# 镜像 # ↓↓↓↓↓ ---- 镜像版本号,建议改成固定版本号,例如:certd:1.29.0
|
||||||
image: registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest
|
image: registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest
|
||||||
container_name: certd # 容器名
|
container_name: certd # 容器名
|
||||||
restart: unless-stopped # 自动重启
|
restart: unless-stopped # 自动重启
|
||||||
@@ -11,42 +11,73 @@ services:
|
|||||||
ports: # 端口映射
|
ports: # 端口映射
|
||||||
# ↓↓↓↓ ---------------------------------------------------------- 如果端口有冲突,可以修改第一个7001为其他不冲突的端口号
|
# ↓↓↓↓ ---------------------------------------------------------- 如果端口有冲突,可以修改第一个7001为其他不冲突的端口号
|
||||||
- "7001:7001"
|
- "7001:7001"
|
||||||
# ↓↓↓↓ ---------------------------------------------------------- https端口,可以根据实际情况,是否暴露相关服务端口
|
# ↓↓↓↓ ---------------------------------------------------------- https端口,可以根据实际情况,是否暴露该端口
|
||||||
- "7002:7002"
|
- "7002:7002"
|
||||||
dns:
|
#↓↓↓↓ -------------------------------------------------------------- 如果出现getaddrinfo ENOTFOUND错误,可以尝试设置dns
|
||||||
# ↓↓↓↓ ---------------------------------------------------------- 如果出现getaddrinfo ENOTFOUND等错误,可以尝试修改或注释dns配置
|
# dns:
|
||||||
- 223.5.5.5
|
# - 223.5.5.5 # 阿里云公共dns
|
||||||
- 223.6.6.6
|
# - 223.6.6.6
|
||||||
# ↓↓↓↓ ---------------------------------------------------------- 如果你服务器部署在国外,可以用8.8.8.8替换上面的dns
|
# # ↓↓↓↓ --------------------------------------------------------- 如果你服务器在腾讯云,可以用这个替换上面阿里云的公共dns
|
||||||
# - 8.8.8.8
|
# - 119.29.29.29 # 腾讯云公共dns
|
||||||
|
# - 182.254.116.116
|
||||||
|
# # ↓↓↓↓ --------------------------------------------------------- 如果你服务器部署在国外,可以用这个替换上面阿里云的公共dns
|
||||||
|
# - 8.8.8.8 # 谷歌公共dns
|
||||||
# - 8.8.4.4
|
# - 8.8.4.4
|
||||||
# extra_hosts:
|
# extra_hosts:
|
||||||
# ↓↓↓↓ ---------------------------------------------------------- 这里可以配置自定义hosts,外网域名可以指向本地局域网ip地址
|
# # ↓↓↓↓ -------------------------------------------------------- 这里可以配置自定义hosts,外网域名可以指向本地局域网ip地址
|
||||||
# - "localdomain.comm:192.168.1.3"
|
# - "localdomain.com:192.168.1.3"
|
||||||
environment: # 环境变量
|
labels:
|
||||||
- TZ=Asia/Shanghai
|
com.centurylinklabs.watchtower.enable: "true"
|
||||||
# 设置环境变量即可自定义certd配置
|
# ↓↓↓↓ -------------------------------------------------------------- 启用ipv6网络,还需要把下面networks的注释放开
|
||||||
# 配置项见: packages/ui/certd-server/src/config/config.default.ts
|
# networks:
|
||||||
# 配置规则: certd_ + 配置项, 点号用_代替
|
# - ip6net
|
||||||
|
environment:
|
||||||
# ↓↓↓↓ ------------------------------------ 这里可以设置http代理
|
# 设置环境变量即可自定义certd配置
|
||||||
#- HTTPS_PROXY=http://xxxxxx:xx
|
# 配置项见: packages/ui/certd-server/src/config/config.default.ts
|
||||||
#- HTTP_PROXY=http://xxxxxx:xx
|
# 配置规则: certd_ + 配置项, 点号用_代替
|
||||||
# ↓↓↓↓ ----------------------------- 如果忘记管理员密码,可以设置为true,重启之后,管理员密码将改成123456,然后请及时修改回false
|
# #↓↓↓↓ ----------------------------- 如果忘记管理员密码,可以设置为true,重启之后,管理员密码将改成123456,然后请及时修改回false
|
||||||
- certd_system_resetAdminPasswd=false
|
- certd_system_resetAdminPasswd=false
|
||||||
# ↓↓↓↓ -------------------------- 如果设置为true,启动后所有配置了cron的流水线任务都将被立即触发一次
|
|
||||||
- certd_cron_immediateTriggerOnce=false
|
|
||||||
# ↓↓↓↓ -------------------------------- 配置证书和key,则表示https方式启动,使用https协议访问,https://your.domain:7001
|
|
||||||
#- certd_koa_key=./data/ssl/cert.key
|
|
||||||
#- certd_koa_cert=./data/ssl/cert.crt
|
|
||||||
|
|
||||||
# ↓↓↓↓ ------------------------------- 使用postgresql数据库
|
# 默认使用sqlite文件数据库,如果需要使用其他数据库,请设置以下环境变量
|
||||||
# - certd_flyway_scriptDir=./db/migration-pg # 升级脚本目录
|
# 注意: 选定使用一种数据库之后,不支持更换数据库。
|
||||||
# - certd_typeorm_dataSource_default_type=postgres # 数据库类型
|
# 数据库迁移方法:1、使用新数据库重新部署一套,然后将旧数据同步过去,注意flyway_history表的数据不要同步
|
||||||
# - certd_typeorm_dataSource_default_host=localhost # 数据库地址
|
# #↓↓↓↓ ----------------------------- 使用postgresql数据库,需要提前创建数据库
|
||||||
# - certd_typeorm_dataSource_default_port=5433 # 数据库端口
|
# - certd_flyway_scriptDir=./db/migration-pg # 升级脚本目录
|
||||||
# - certd_typeorm_dataSource_default_username=postgres # 用户名
|
# - certd_typeorm_dataSource_default_type=postgres # 数据库类型
|
||||||
# - certd_typeorm_dataSource_default_password=yourpasswd # 密码
|
# - certd_typeorm_dataSource_default_host=localhost # 数据库地址
|
||||||
# - certd_typeorm_dataSource_default_database=certd # 数据库名
|
# - certd_typeorm_dataSource_default_port=5433 # 数据库端口
|
||||||
|
# - certd_typeorm_dataSource_default_username=postgres # 用户名
|
||||||
|
# - certd_typeorm_dataSource_default_password=yourpasswd # 密码
|
||||||
|
# - certd_typeorm_dataSource_default_database=certd # 数据库名
|
||||||
|
|
||||||
|
# #↓↓↓↓ ----------------------------- 使用mysql数据库,需要提前创建数据库 charset=utf8mb4, collation=utf8mb4_bin
|
||||||
|
# - certd_flyway_scriptDir=./db/migration-mysql # 升级脚本目录
|
||||||
|
# - certd_typeorm_dataSource_default_type=mysql # 数据库类型, 或者 mariadb
|
||||||
|
# - certd_typeorm_dataSource_default_host=localhost # 数据库地址
|
||||||
|
# - certd_typeorm_dataSource_default_port=3306 # 数据库端口
|
||||||
|
# - certd_typeorm_dataSource_default_username=root # 用户名
|
||||||
|
# - certd_typeorm_dataSource_default_password=yourpasswd # 密码
|
||||||
|
# - certd_typeorm_dataSource_default_database=certd # 数据库名
|
||||||
|
|
||||||
|
# ↓↓↓↓ --------------------------------------------------------- 自动升级,上面certd的版本号要保持为latest
|
||||||
|
# certd-updater: # 添加 Watchtower 服务
|
||||||
|
# image: containrrr/watchtower:latest
|
||||||
|
# container_name: certd-updater
|
||||||
|
# restart: unless-stopped
|
||||||
|
# volumes:
|
||||||
|
# - /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
# # 配置 自动更新
|
||||||
|
# environment:
|
||||||
|
# - WATCHTOWER_CLEANUP=true # 自动清理旧版本容器
|
||||||
|
# - WATCHTOWER_INCLUDE_STOPPED=false # 不更新已停止的容器
|
||||||
|
# - WATCHTOWER_LABEL_ENABLE=true # 根据容器标签进行更新
|
||||||
|
# - WATCHTOWER_POLL_INTERVAL=600 # 每 10 分钟检查一次更新
|
||||||
|
|
||||||
|
|
||||||
|
# ↓↓↓↓ -------------------------------------------------------------- 启用ipv6网络,还需要把上面networks的注释放开
|
||||||
|
#networks:
|
||||||
|
# ip6net:
|
||||||
|
# enable_ipv6: true
|
||||||
|
# ipam:
|
||||||
|
# config:
|
||||||
|
# - subnet: 2001:db8::/64
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import lightbox from "vitepress-plugin-lightbox";
|
|||||||
// https://vitepress.dev/reference/site-config
|
// https://vitepress.dev/reference/site-config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
title: "Certd",
|
title: "Certd",
|
||||||
description: "Certd帮助文档,Certd是一款开源免费的全自动SSL证书管理工具;自动证书申请、更新、续期;通配符证书,泛域名证书申请;证书自动化部署到阿里云、腾讯云、主机、群晖、宝塔。",
|
description: "Certd帮助文档,Certd是一款开源免费的全自动SSL证书管理工具;证书自动化申请部署流水线;自动证书申请、更新、续期;通配符证书,泛域名证书申请;证书自动化部署到阿里云、腾讯云、主机、群晖、宝塔。",
|
||||||
markdown: {
|
markdown: {
|
||||||
config: (md) => {
|
config: (md) => {
|
||||||
// Use lightbox plugin
|
// Use lightbox plugin
|
||||||
@@ -23,7 +23,7 @@ export default defineConfig({
|
|||||||
// ],
|
// ],
|
||||||
["meta", {
|
["meta", {
|
||||||
name: "keywords",
|
name: "keywords",
|
||||||
content: "证书自动申请、证书自动更新、证书自动续期、证书自动续签、证书管理工具、Certd、SSL证书自动部署、证书自动化,https证书,pfx证书,der证书,TLS证书,nginx证书自动续签自动部署,SSL平台,证书管理平台"
|
content: "证书自动申请、证书自动更新、证书自动续期、证书自动续签、证书管理工具、Certd、SSL证书自动部署、证书自动化,https证书,pfx证书,der证书,TLS证书,nginx证书自动续签自动部署,SSL平台,证书管理平台,证书流水线"
|
||||||
}],
|
}],
|
||||||
["meta", { name: "google-site-verification",content: "V5XLTSnXoT15uQotwpxJoQolUo2d5UbSL-TacsyOsC0"}],
|
["meta", { name: "google-site-verification",content: "V5XLTSnXoT15uQotwpxJoQolUo2d5UbSL-TacsyOsC0"}],
|
||||||
//<meta name="baidu-site-verification" content="codeva-MiWN8Y07Ua" />
|
//<meta name="baidu-site-verification" content="codeva-MiWN8Y07Ua" />
|
||||||
@@ -57,7 +57,7 @@ export default defineConfig({
|
|||||||
nav: [
|
nav: [
|
||||||
{ text: "首页", link: "/" },
|
{ text: "首页", link: "/" },
|
||||||
{ text: "指南", link: "/guide/" },
|
{ text: "指南", link: "/guide/" },
|
||||||
{ text: "Demo体验", link: "https://certd.handsfree.work" }
|
{ text: "Demo体验", link: "https://certd.handfree.work" }
|
||||||
],
|
],
|
||||||
sidebar: {
|
sidebar: {
|
||||||
"/guide/": [
|
"/guide/": [
|
||||||
@@ -76,8 +76,8 @@ export default defineConfig({
|
|||||||
{ text: "源码部署", link: "/guide/install/source/" }
|
{ text: "源码部署", link: "/guide/install/source/" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{ text: "演示教程", link: "/guide/tutorial.md" }
|
{ text: "演示教程", link: "/guide/tutorial.md" },
|
||||||
|
{ text: "版本升级", link: "/guide/install/upgrade.md" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -98,6 +98,9 @@ export default defineConfig({
|
|||||||
{ text: "忘记密码", link: "/guide/use/forgotpasswd/" },
|
{ text: "忘记密码", link: "/guide/use/forgotpasswd/" },
|
||||||
{ text: "数据备份", link: "/guide/use/backup/" },
|
{ text: "数据备份", link: "/guide/use/backup/" },
|
||||||
{ text: "Certd本身的证书更新", link: "/guide/use/https/index.md" },
|
{ text: "Certd本身的证书更新", link: "/guide/use/https/index.md" },
|
||||||
|
{ text: "js脚本插件使用", link: "/guide/use/custom-script/index.md" },
|
||||||
|
{ text: "邮箱配置", link: "/guide/use/email/index.md" },
|
||||||
|
{ text: "IPv6支持", link: "/guide/use/setting/ipv6.md" },
|
||||||
{ text: "如何贡献代码", link: "/guide/development/index.md" },
|
{ text: "如何贡献代码", link: "/guide/development/index.md" },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,353 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.29.2](https://github.com/certd/certd/compare/v1.29.1...v1.29.2) (2024-12-25)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复套餐关闭状态下,仍然限制用户流水线数量的bug ([66fb9e5](https://github.com/certd/certd/commit/66fb9e5f49491f9c159363b48af14720a37673b1))
|
||||||
|
|
||||||
|
## [1.29.1](https://github.com/certd/certd/compare/v1.29.0...v1.29.1) (2024-12-25)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 免费套餐支持购买 ([f5ec987](https://github.com/certd/certd/commit/f5ec9870fd6af1f0c9099852bbdb4d07813ccce8))
|
||||||
|
* 修复某处金额转换丢失精度的bug ([d2d6f12](https://github.com/certd/certd/commit/d2d6f12218cbe7bd55f4ae082b93084be85f0a7b))
|
||||||
|
* 修复新版本小红点显示错误问题 ([fe4786e](https://github.com/certd/certd/commit/fe4786e168afe03a5243dd67971476c348339809))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 用户创建证书流水线没有购买套餐或者超限时提前报错 ([472f06c](https://github.com/certd/certd/commit/472f06c2d190d0ae48e8b53c18bc278437656a1c))
|
||||||
|
* 优化插件名称显示 ([26adf7d](https://github.com/certd/certd/commit/26adf7d437e674385f26a8f92fded6521a620671))
|
||||||
|
|
||||||
|
# [1.29.0](https://github.com/certd/certd/compare/v1.28.4...v1.29.0) (2024-12-24)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复手机模式下,查询框被文字遮盖的bug ([040788c](https://github.com/certd/certd/commit/040788c793642c3bb2a3ede87fe30fcf3be471bd))
|
||||||
|
* 修复左侧菜单收起时无法展开子菜单的bug ([0056223](https://github.com/certd/certd/commit/005622307e612717a5408aa1484717ef03003a22))
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 基础版不再限制流水线数量 ([cb27d4b](https://github.com/certd/certd/commit/cb27d4b4906b2782eaceb0a95bbdc5d0534370d2))
|
||||||
|
* 套餐购买支持易支付、支付宝支付 ([faa28f8](https://github.com/certd/certd/commit/faa28f88f954cba4c1dd29125562e5acd2fd99af))
|
||||||
|
* 用户套餐,用户支付功能 ([a019956](https://github.com/certd/certd/commit/a019956698acaf2c4beb620b5ad8c18918ead6a1))
|
||||||
|
* 站点证书监控 ([9c8c7a7](https://github.com/certd/certd/commit/9c8c7a781223f4217f45510db1e89495600e3cd5))
|
||||||
|
* 支持微信支付 ([45d6347](https://github.com/certd/certd/commit/45d6347f5b6199493b11aabdd74177f6dca2cea4))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 调整创建证书表单字段的顺序 ([d393521](https://github.com/certd/certd/commit/d3935219f2aa50d6662c5b5ebf7ee25ad696ab2b))
|
||||||
|
* 同一时间只允许一个套餐生效 ([8ebf95a](https://github.com/certd/certd/commit/8ebf95a222a900d1707716c7b1f3b39f8a6d8f94))
|
||||||
|
* 用户名支持修改 ([89c7f07](https://github.com/certd/certd/commit/89c7f070343e86453c84677ebe1669f9b266d871))
|
||||||
|
* 优化证书申请跳过的状态显示,成功通知现在在跳过时不会发送 ([67d762b](https://github.com/certd/certd/commit/67d762b6a520f1fa24719a124e5ae975a81f5f82))
|
||||||
|
* 站点证书监控通知发送,每天定时检查 ([bb4910f](https://github.com/certd/certd/commit/bb4910f4e57234e42b44505f4620ae7af66025c5))
|
||||||
|
* 支持一体证书 ([53c38cf](https://github.com/certd/certd/commit/53c38cf714a6f7486abbf1d71c9f48f56a790100))
|
||||||
|
* 支持plesk网站证书部署 ([eda45c1](https://github.com/certd/certd/commit/eda45c1528199648b3970505e87f492d398226cd))
|
||||||
|
|
||||||
|
## [1.28.4](https://github.com/certd/certd/compare/v1.28.3...v1.28.4) (2024-12-12)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复证书成功通知发送失败的bug ([0f5c690](https://github.com/certd/certd/commit/0f5c69040ba77340c909813220a26bc7ddada3ea))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 群晖支持6.x ([79f7ec4](https://github.com/certd/certd/commit/79f7ec4672f4fd5744cc45e4a6f104da943f4026))
|
||||||
|
|
||||||
|
## [1.28.3](https://github.com/certd/certd/compare/v1.28.2...v1.28.3) (2024-12-12)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复没有配置eab时,报order无法读取的问题 ([657a2ae](https://github.com/certd/certd/commit/657a2ae032e6f61ac27fbdd26c7bf169c041219e))
|
||||||
|
* 修复授权被删除后,无法清空的bug ([b45977c](https://github.com/certd/certd/commit/b45977c29a29084c11e496bec3415eaaebafdd74))
|
||||||
|
* mysql下access.setting字段改成text ([b7f5740](https://github.com/certd/certd/commit/b7f5740c57743914f754f3b4fdd94b59a2e8338c))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 点击版本红点按钮,跳转到升级帮助页面 ([454fbda](https://github.com/certd/certd/commit/454fbda581bbe22abca5b91e5086ea9d9d58a020))
|
||||||
|
* 通知标题优化 ([ff083ce](https://github.com/certd/certd/commit/ff083ce6848a8bee3c8248e4b881086ae1517c28))
|
||||||
|
* 支持腾讯虚拟机开关机([@wujingke](https://github.com/wujingke)) ([8039e8b](https://github.com/certd/certd/commit/8039e8baf83c82d03f1a6198cf61c372026b962b))
|
||||||
|
* 支持aws cloudfront ([0ae39f1](https://github.com/certd/certd/commit/0ae39f160a7c6b6696b3bf513d68aa28905810ad))
|
||||||
|
|
||||||
|
## [1.28.2](https://github.com/certd/certd/compare/v1.28.1...v1.28.2) (2024-12-09)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复创建流水线通知设置无效的bug ([498cf34](https://github.com/certd/certd/commit/498cf34999fddfa24ce088e2e678469fa669abb8))
|
||||||
|
* 修复流水线分组可以被所有人看见的bug ([a0e838d](https://github.com/certd/certd/commit/a0e838d1eec918e5dc92fe95dc72ac14facb930e))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 优化数据表索引 ([228fdf0](https://github.com/certd/certd/commit/228fdf0a0d28013f5dd156a97bbde80537e8e97e))
|
||||||
|
* 支持mysql ([7cde1fd](https://github.com/certd/certd/commit/7cde1fdc4a9ed851900d231a5460c8dbfbcd148e))
|
||||||
|
|
||||||
|
## [1.28.1](https://github.com/certd/certd/compare/v1.28.0...v1.28.1) (2024-12-08)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复cname排查方法 nslookup命令显示黑色的问题 ([3dfeeec](https://github.com/certd/certd/commit/3dfeeec899d7d0d7292695ce410f78548e076c03))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 通知选择器优化 ([2c0cbdd](https://github.com/certd/certd/commit/2c0cbdd29ecb74cc939b2ae7ee86b8d40f70ba31))
|
||||||
|
* 新增七牛云插件分组 ([49e7dc5](https://github.com/certd/certd/commit/49e7dc56e1a95fbdea3e30cdeb945b48415b69e3))
|
||||||
|
* 新增server酱3通知 ([6aa4872](https://github.com/certd/certd/commit/6aa487269c9f6862e188b37a0d6c73f79c937d94))
|
||||||
|
* 支持邀请奖励 ([618ec93](https://github.com/certd/certd/commit/618ec937866b24ebcf8164db43acb1ed66a5b329))
|
||||||
|
* 支持易发云短信 ([94fa77f](https://github.com/certd/certd/commit/94fa77fcd2b9bea294fb05736c0d8cdc81f56103))
|
||||||
|
* cname value优化 ([e8c9c2a](https://github.com/certd/certd/commit/e8c9c2a47d47048ae743b16f7bc932dbe18a89e9))
|
||||||
|
* favicon支持自定义 ([8b9c47d](https://github.com/certd/certd/commit/8b9c47daf194515006689a212ae9cf586bdf5993))
|
||||||
|
|
||||||
|
# [1.28.0](https://github.com/certd/certd/compare/v1.27.9...v1.28.0) (2024-11-30)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复自定义webhook contextType的bug ([7e5ea0c](https://github.com/certd/certd/commit/7e5ea0cee003acda952d922ca70592f1e8a2ed80))
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 手机号登录、邮箱验证码注册 ([7b55337](https://github.com/certd/certd/commit/7b55337c5edb470cca7aa62201eda8d274784004))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 部署到IIS插件 ([1534f45](https://github.com/certd/certd/commit/1534f4523633265d219d7b3a249a9ea1af99c512))
|
||||||
|
* 登录失败增加重试次数限制及冷却时间 ([954b6df](https://github.com/certd/certd/commit/954b6df3608695fe074130f8149a33e311d80cc4))
|
||||||
|
* 流水线支持批量修改分组,批量删除 ([a847e66](https://github.com/certd/certd/commit/a847e66c4fc843b98f1520b2b8072d3586ce8b81))
|
||||||
|
* 取消docker-compose的dns配置 ([87bbf6f](https://github.com/certd/certd/commit/87bbf6f14080b9fa287c250d7fc4d33279c83ff7))
|
||||||
|
* 首页新增修改密码提示 ([0772d3b](https://github.com/certd/certd/commit/0772d3b3fd24afdde4086d9f09ef19d037b431b4))
|
||||||
|
* 选项显示图标 ([aedc462](https://github.com/certd/certd/commit/aedc46213571a3bd93809b7af7fa17a08d546237))
|
||||||
|
* 优化七牛云cdn,获取域名列表可以选择 ([5a20242](https://github.com/certd/certd/commit/5a20242111d6bd255b25dac86fe1f062c8543096))
|
||||||
|
* 优化七牛云cdn部署,保持http2和forceHttp设置,当未开启https时,主动开启https ([196f7d9](https://github.com/certd/certd/commit/196f7d9dc23d7dd96b663c686542e85270b81aef))
|
||||||
|
* 优化证书申请成功通知发送方式 ([8002a56](https://github.com/certd/certd/commit/8002a56efc5998aa03db5711ae87f9eb4bc9e160))
|
||||||
|
* 支持短信验证码登录 ([387bcc5](https://github.com/certd/certd/commit/387bcc5fa418cdeea81a06da5e3f8cd6b43cd082))
|
||||||
|
* 支持威联通证书部署 ([0d8913e](https://github.com/certd/certd/commit/0d8913ea2f56fdebbcc9bb207eae59e8ddbb8cad))
|
||||||
|
* 自定义webhook显示详细的错误信息 ([3254afc](https://github.com/certd/certd/commit/3254afc75640eed3729d0fc02a818fefbe5c7fc3))
|
||||||
|
|
||||||
|
## [1.27.9](https://github.com/certd/certd/compare/v1.27.8...v1.27.9) (2024-11-26)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 通知支持自定义webhook、anpush、iyuu、server酱 ([cbccd9e](https://github.com/certd/certd/commit/cbccd9e3d0a4c24aba772af62734666d40b22c57))
|
||||||
|
* 通知支持vocechat、bark、telegram、discord、slack ([642f57f](https://github.com/certd/certd/commit/642f57ff6d7152a9e14f59c7fc0e32a6b1751fb7))
|
||||||
|
|
||||||
|
## [1.27.8](https://github.com/certd/certd/compare/v1.27.7...v1.27.8) (2024-11-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package root
|
||||||
|
|
||||||
|
## [1.27.7](https://github.com/certd/certd/compare/v1.27.6...v1.27.7) (2024-11-25)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复关键字查询bug ([fab6660](https://github.com/certd/certd/commit/fab66606b35a540fac31fee902331ba1ffdebc16))
|
||||||
|
* 修复CNAME时子域名级数超出限制的问题 ([3af6d96](https://github.com/certd/certd/commit/3af6d96e6e353c9b2111cff81679b79c55195a0a))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 谷歌EAB绑定邮箱改成必填 ([81a8123](https://github.com/certd/certd/commit/81a8123725d7bf4bd6a32a64a066bd760b7b6a7f))
|
||||||
|
* 华为云密钥获取提示及访问链接 ([de43391](https://github.com/certd/certd/commit/de43391e4c12dc3ad976f8fa8787f4eb70a41e75))
|
||||||
|
* 通知管理 ([d9a00ee](https://github.com/certd/certd/commit/d9a00eeaf72735ced67c59d7983d84e3c730064a))
|
||||||
|
* 通知渠道支持测试按钮 ([b54ae27](https://github.com/certd/certd/commit/b54ae272ebc2d31b32b049d44e2299a6be7f153c))
|
||||||
|
* 优化插件开发,dnsProvider无需写http logger 变量 ([fcbb5e4](https://github.com/certd/certd/commit/fcbb5e46a112174150a62648319b8224fce3b7ed))
|
||||||
|
* 支持部署到阿里云WAF ([c96fcb7](https://github.com/certd/certd/commit/c96fcb7afced979435cffa73591275008033c90d))
|
||||||
|
* 支持企业微信群聊机器人通知 ([b805a29](https://github.com/certd/certd/commit/b805a2925984144a31575b8aaa622f0c30d41b56))
|
||||||
|
|
||||||
|
## [1.27.6](https://github.com/certd/certd/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* .env 读取 \r 问题 ([0e33dfa](https://github.com/certd/certd/commit/0e33dfa019a55ea76193c428ec756af386adeb9d))
|
||||||
|
* 修复vip试用secret报错的bug ([018dee6](https://github.com/certd/certd/commit/018dee6c383233560f078dfd30f6c2857a7e15ee))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 当步骤全部都禁用时,任务本身显示删除线 ([9ab9a6e](https://github.com/certd/certd/commit/9ab9a6e8b083e19793894f23e59f29c604ec98e5))
|
||||||
|
|
||||||
|
## [1.27.5](https://github.com/certd/certd/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复1Panel面板本身证书更新导致判定执行失败的问题 ([2689e6d](https://github.com/certd/certd/commit/2689e6d6c03aba21da90d5d45232c6ba08696be1))
|
||||||
|
* 修复角色无法删除的bug ([66629a5](https://github.com/certd/certd/commit/66629a591aecc2d8364ea415c7afc3f9d0406562))
|
||||||
|
* 修复Cname情况下,无法使用DNS类型的bug ([26dad39](https://github.com/certd/certd/commit/26dad399d5768b3205da099ddc11809aef7d6224))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 日志查看自动滚动到底部 ([4a2f7eb](https://github.com/certd/certd/commit/4a2f7ebf87b7c027cebff7cb763f8f35f6d2aa36))
|
||||||
|
* 系统设置中的代理设置优化为可全局生效,环境变量中的https_proxy设置将无效 ([381a37f](https://github.com/certd/certd/commit/381a37fbaa6b61c887eda743897ae00afb825bdf))
|
||||||
|
* 新手导航在非编辑模式下不显示 ([18bfcc2](https://github.com/certd/certd/commit/18bfcc24ad0bde57bb04db8a4209861ec6b8ff1d))
|
||||||
|
* 优化腾讯云 cloudflare 重复解析记录时的返回值 ([90d1b68](https://github.com/certd/certd/commit/90d1b68bd6cf232fbe085234efe07d29b7690044))
|
||||||
|
* 支持namesilo ([80159ec](https://github.com/certd/certd/commit/80159ecca895103d0495f3217311199e66056572))
|
||||||
|
* 专业版试用,无需绑定账号 ([c7c4318](https://github.com/certd/certd/commit/c7c4318c11b65a76089787aa58939832d338a232))
|
||||||
|
|
||||||
|
## [1.27.4](https://github.com/certd/certd/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复未设置pfx密码,导致jks转换报错的bug ([c3cfbd8](https://github.com/certd/certd/commit/c3cfbd8474155aed4379f91075de37d5d8c73ef0))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 公共cname服务支持关闭 ([f4ae512](https://github.com/certd/certd/commit/f4ae5125dc4cd97816976779cb3586b5ee78947e))
|
||||||
|
|
||||||
|
## [1.27.3](https://github.com/certd/certd/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复偶发性cname一直验证超时的bug ([d2ce72e](https://github.com/certd/certd/commit/d2ce72e4aaacdf726ba8b91fcd71db40a27714ba))
|
||||||
|
* 修复邮件配置,忽略证书校验设置不生效的bug ([66a9690](https://github.com/certd/certd/commit/66a9690dc958732e1b3c672d965db502296446f9))
|
||||||
|
* 修复ipv6未开启情况下,请求带有ipv6地址域名报ETIMEDOUT的bug ([a9a0967](https://github.com/certd/certd/commit/a9a0967a6f1d0bd27e69f3ec52c31d90d470bc23))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 修复站点个性化,浏览器标题没有生效的bug ([bcfac02](https://github.com/certd/certd/commit/bcfac02c96ceaf23d1a0b05b48d8047da933beaf))
|
||||||
|
* 优化上传到主机插 路径选择,根据证书格式显示 ([8c3f86c](https://github.com/certd/certd/commit/8c3f86c6909ed91f48bb2880e78834e22f6f6a29))
|
||||||
|
* 支持jks ([889eaae](https://github.com/certd/certd/commit/889eaaea92818f628b922dae540c026630611707))
|
||||||
|
* ipv6支持 ([da6ac16](https://github.com/certd/certd/commit/da6ac1626b3574be2fabeeb18a1f10d60bdcbe49))
|
||||||
|
|
||||||
|
## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复某些容器管理ui无法识别端口列表的bug ([576e60a](https://github.com/certd/certd/commit/576e60a2b52315909e659d2a58cf98b130e69e6f))
|
||||||
|
* 修复删除腾讯云过期证书时间判断上的bug,导致已过期仍然没有删除证书 ([1ba1007](https://github.com/certd/certd/commit/1ba10072615015d91b81fc56a3b01dae6a2ae9d1))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 优化部署到阿里云CDN插件,支持多域名,更易用 ([80c500f](https://github.com/certd/certd/commit/80c500f618b169a1f64c57fe442242a4d0d9d833))
|
||||||
|
* 优化流水线页面切换回来不丢失查询条件 ([4dcf6e8](https://github.com/certd/certd/commit/4dcf6e87bc5f7657ce8a56c5331e8723a0fee8ee))
|
||||||
|
* 支持公共cname服务 ([3c919ee](https://github.com/certd/certd/commit/3c919ee5d1aef5d26cf3620a7c49d920786bc941))
|
||||||
|
* 执行历史支持点击查看流水线详情 ([8968639](https://github.com/certd/certd/commit/89686399f90058835435b92872fc236fac990148))
|
||||||
|
* 专业版7天试用 ([c58250e](https://github.com/certd/certd/commit/c58250e1f065a9bd8b4e82acc1df754504c0010c))
|
||||||
|
|
||||||
|
## [1.27.1](https://github.com/certd/certd/compare/v1.27.0...v1.27.1) (2024-11-04)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复头像没有更新的bug ([9b4a31f](https://github.com/certd/certd/commit/9b4a31fa6a32b9cab2e22bd141cf96ca29120445))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 禁止页面缓存,点击tab页签可以刷新数据 ([7ad4b55](https://github.com/certd/certd/commit/7ad4b55ee000c1dd0747832b11107f32b0ffb889))
|
||||||
|
* 优化时间选择器,自动填写分钟和秒钟 ([396dc34](https://github.com/certd/certd/commit/396dc34a841c7d016b033736afdba8366fb2d211))
|
||||||
|
* cname 域名映射记录可读性优化 ([b1117ed](https://github.com/certd/certd/commit/b1117ed54a3ef015752999324ff72b821ef5e4b9))
|
||||||
|
|
||||||
|
# [1.27.0](https://github.com/certd/certd/compare/v1.26.16...v1.27.0) (2024-10-31)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复历史记录不能按名称查询的bug ([6113c38](https://github.com/certd/certd/commit/6113c388b7fc58b11ca19ff05cc1286d096c8d28))
|
||||||
|
* pfx兼容windows server 2016 ([e5e468a](https://github.com/certd/certd/commit/e5e468a463f66d02f235de54b7c1e09ace5f1cb1))
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 首页全新改版 ([63ec5b5](https://github.com/certd/certd/commit/63ec5b5519c760a3330569c0da6dac157302a330))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 管理控制台数据统计 ([babd589](https://github.com/certd/certd/commit/babd5897ae013ff7c04ebfcbfac8a00d84dd627c))
|
||||||
|
* 增加向导 ([6d9ef26](https://github.com/certd/certd/commit/6d9ef26ecab71d752c2c55d75aed4fb5f6c05a39))
|
||||||
|
* lego 升级到 4.19.2 ([129bf53](https://github.com/certd/certd/commit/129bf53edc9bbb001fe49fbd7e239bd1d09cc128))
|
||||||
|
|
||||||
|
## [1.26.16](https://github.com/certd/certd/compare/v1.26.15...v1.26.16) (2024-10-30)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复lego No help topic for 错误 ([aaaf8d7](https://github.com/certd/certd/commit/aaaf8d7db34896cf8f2ff8f12eec1ab0cae58f0f))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 支持白山云cdn部署 ([b1b2cd0](https://github.com/certd/certd/commit/b1b2cd088b684eda764962abd61754c26a204d1c))
|
||||||
|
* 支持华为云cdn ([81a3fdb](https://github.com/certd/certd/commit/81a3fdbc29b71f380762008cc151493ec97458f9))
|
||||||
|
|
||||||
|
## [1.26.15](https://github.com/certd/certd/compare/v1.26.14...v1.26.15) (2024-10-28)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 顶部菜单变...的bug ([6dabad7](https://github.com/certd/certd/commit/6dabad76baba96be0f8af36a3fbfb9f5182aecf1))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 默认证书更新时间设置为35天,增加腾讯云删除过期证书插件,可以避免腾讯云过期证书邮件 ([51b6fed](https://github.com/certd/certd/commit/51b6fed468eaa6f28ce4497ce303ace1a52abb96))
|
||||||
|
* 授权加密支持解密查看 ([5575c83](https://github.com/certd/certd/commit/5575c839705f6987ad2bdcd33256b0962c6a9c6a))
|
||||||
|
* 重置管理员密码同时启用管理员账户,避免之前禁用了,重置密码还是登录不进去 ([f92d918](https://github.com/certd/certd/commit/f92d918a1e28e29b794ad4754661ea760c18af46))
|
||||||
|
|
||||||
|
## [1.26.14](https://github.com/certd/certd/compare/v1.26.13...v1.26.14) (2024-10-26)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复阿里云部署大杀器报插件_还未注册错误的bug ([abd2dcf](https://github.com/certd/certd/commit/abd2dcf2e85a545321bae6451406d081f773b132))
|
||||||
|
* 修复启动时自签证书无法保存的bug ([526c484](https://github.com/certd/certd/commit/526c48450bcd37b3ccded9b448f17de8140bdc6e))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 顶部菜单自定义 ([54d136c](https://github.com/certd/certd/commit/54d136cc6ae122f7c891b7a5c7232fe5de8e5cb5))
|
||||||
|
* 禁用readonly用户 ([d10d42e](https://github.com/certd/certd/commit/d10d42e20619bb55a50d636b8867ff33db4e3b4b))
|
||||||
|
* 限制其他用户流水线数量 ([315e437](https://github.com/certd/certd/commit/315e43746baf01682737f82e41579237a48409af))
|
||||||
|
* 用户管理优化头像上传 ([661293c](https://github.com/certd/certd/commit/661293c189a3abf3cdc953b5225192372f57930d))
|
||||||
|
|
||||||
|
## [1.26.13](https://github.com/certd/certd/compare/v1.26.12...v1.26.13) (2024-10-26)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复对话框全屏按钮与关闭按钮重叠的bug ([95df56c](https://github.com/certd/certd/commit/95df56cc5ca5e3eb843cd17cb7078cde47729f1e))
|
||||||
|
* deprecated的运行时不要报错,只报警告 ([bcbefaa](https://github.com/certd/certd/commit/bcbefaaa35cf6d0eec085b3a2c5bfc7c6a8de9e1))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 更新certd本身的证书文档说明 ([0c50ede](https://github.com/certd/certd/commit/0c50ede129337b82df54575cbd2f4c2a783a0732))
|
||||||
|
* 支持同时监听https端口,7002 ([d5a17f9](https://github.com/certd/certd/commit/d5a17f9e6afd63fda2df0981118480f25a1fac2e))
|
||||||
|
|
||||||
|
## [1.26.12](https://github.com/certd/certd/compare/v1.26.11...v1.26.12) (2024-10-25)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 部署到阿里云任意云资源,阿里云部署大杀器 ([4075be7](https://github.com/certd/certd/commit/4075be7849b140acb92bd8da8a9acbf4eef85180))
|
||||||
|
* 文件名特殊字符限制输入 ([c4164c6](https://github.com/certd/certd/commit/c4164c66e29f3ec799f98108a344806ca61e94ff))
|
||||||
|
* 新增部署到百度云CDN插件 ([f126f9f](https://github.com/certd/certd/commit/f126f9f932d37fa01fff1accc7bdd17d349f8db5))
|
||||||
|
* 新增部署到腾讯云CDN-v2,推荐使用 ([d782655](https://github.com/certd/certd/commit/d782655cb4dfbb74138178afbffeee76fc755115))
|
||||||
|
* 优化cron选择器,增加下次触发时间显示 ([5b148b7](https://github.com/certd/certd/commit/5b148b7ed960ca6f7f5b733b2eadd56eeecbd4c2))
|
||||||
|
* 支持部署到腾讯云COS ([a8a45d7](https://github.com/certd/certd/commit/a8a45d7f757820990e278533277a3deda5ba48f3))
|
||||||
|
* 支持配置公共ZeroSSL授权 ([a90d1e6](https://github.com/certd/certd/commit/a90d1e68ee9cbc3705223457b8a86f071b150968))
|
||||||
|
|
||||||
|
## [1.26.11](https://github.com/certd/certd/compare/v1.26.10...v1.26.11) (2024-10-23)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 申请证书没有使用到系统设置的http代理的bug ([3db216f](https://github.com/certd/certd/commit/3db216f515ba404cb4330fdab452971b22a50f08))
|
||||||
|
* 修复移动任务后出现空阶段的bug ([4ea3edd](https://github.com/certd/certd/commit/4ea3edd59e93ca4f5b2e43b20dd4ef33909caddb))
|
||||||
|
* 修复google证书*.xx.com与xx.com同时申请时报错的bug ([f8b99b8](https://github.com/certd/certd/commit/f8b99b81a23e7e9fd5e05ebd5caf355c41d67a90))
|
||||||
|
* 允许七牛云cdn插件输入.号开头的通配符域名 ([18ee87d](https://github.com/certd/certd/commit/18ee87daff6eafc2201b58e28d85aafd3cb7a5b9))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 申请证书启用新的反代地址 ([a705182](https://github.com/certd/certd/commit/a705182b85e51157883e48f23463263793bf3c12))
|
||||||
|
* 优化日志颜色 ([1291e98](https://github.com/certd/certd/commit/1291e98e821c5b1810aab7f0aebe3f5f5cd44a20))
|
||||||
|
* 优化证书申请速度和成功率,反代地址优化,google基本可以稳定请求。增加请求重试。 ([41d9c3a](https://github.com/certd/certd/commit/41d9c3ac8398def541e65351cbe920d4a927182d))
|
||||||
|
* 优化pfx密码密码输入框,让浏览器不自动填写密码 ([ffeede3](https://github.com/certd/certd/commit/ffeede38afa70c5ff6f2015516bead23d2c4df87))
|
||||||
|
|
||||||
|
## [1.26.10](https://github.com/certd/certd/compare/v1.26.9...v1.26.10) (2024-10-20)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复cname服务普通用户access访问权限问题 ([c1e3e2e](https://github.com/certd/certd/commit/c1e3e2ee1f923ee5806479dd5f178c3286a01ae0))
|
||||||
|
|
||||||
|
## [1.26.9](https://github.com/certd/certd/compare/v1.26.8...v1.26.9) (2024-10-19)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复普通用户无法校验cname配置的bug ([6285497](https://github.com/certd/certd/commit/62854978bf0bdbe749b42f8e40ab227ab31ec92f))
|
||||||
|
* 修复切换普通用户登录时,左侧菜单没有同步更新的bug ([12116a8](https://github.com/certd/certd/commit/12116a89f43cf8b98f16d2ea6073f6b72a643215))
|
||||||
|
* 修正邮箱设置跳转路由 ([17d8890](https://github.com/certd/certd/commit/17d88900a1f0e3af609b74597f5b1978230db32d))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 触发证书重新申请input变化对比规则优化,减少升级版本后触发申请证书的情况 ([c46a2a9](https://github.com/certd/certd/commit/c46a2a9a399c2a9a8bb59a48b9fb6e93227cce9b))
|
||||||
|
* 任务下所有步骤都跳过时,整个任务显示跳过 ([84fd3b2](https://github.com/certd/certd/commit/84fd3b250dd1161ea06c5582fdadece4b29c2e53))
|
||||||
|
* 授权配置去除前后空格 ([57d8d48](https://github.com/certd/certd/commit/57d8d48046fbf51c52b041d2dec03d51fb018587))
|
||||||
|
* 数据库备份插件,先压缩再备份 ([304ef49](https://github.com/certd/certd/commit/304ef494fd5787c996ad0dcb6edd2f517afce9e2))
|
||||||
|
* 优化菜单 ([1f4f157](https://github.com/certd/certd/commit/1f4f15757de1015cf7563f7022599eef58cc93d7))
|
||||||
|
* 增加文档站 https://certd.docmirror.cn ([6e2ac1c](https://github.com/certd/certd/commit/6e2ac1c089f6ddccb396f1f2738509c05333e1bb))
|
||||||
|
|
||||||
## [1.26.8](https://github.com/certd/certd/compare/v1.26.7...v1.26.8) (2024-10-15)
|
## [1.26.8](https://github.com/certd/certd/compare/v1.26.7...v1.26.8) (2024-10-15)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
# 本地开发
|
# 本地开发
|
||||||
欢迎贡献插件
|
欢迎贡献插件
|
||||||
|
|
||||||
## 1.本地调试运行
|
建议nodejs版本 `20.x` 及以上
|
||||||
|
|
||||||
|
## 一、本地调试运行
|
||||||
|
|
||||||
### 克隆代码
|
### 克隆代码
|
||||||
```shell
|
```shell
|
||||||
|
|
||||||
# 克隆代码
|
# 克隆代码
|
||||||
git clone https://github.com/certd/certd
|
git clone https://github.com/certd/certd --depth=1
|
||||||
|
|
||||||
#进入项目目录
|
#进入项目目录
|
||||||
cd certd
|
cd certd
|
||||||
|
|
||||||
# 切换到最新版本代码
|
|
||||||
git checkout v1.26.7 # 这里换成最新版本号
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 修改pnpm-workspace.yaml文件
|
### 修改pnpm-workspace.yaml文件
|
||||||
@@ -55,7 +54,7 @@ npm run dev
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 开发插件
|
## 二、开发插件
|
||||||
进入 `packages/ui/certd-server/src/plugins`
|
进入 `packages/ui/certd-server/src/plugins`
|
||||||
|
|
||||||
### 1.复制`plugin-demo`目录作为你的插件目录
|
### 1.复制`plugin-demo`目录作为你的插件目录
|
||||||
@@ -89,8 +88,22 @@ export * from './plugins/plugin-deploy-to-xx'
|
|||||||
export * from "./plugin-cloudflare.js"
|
export * from "./plugin-cloudflare.js"
|
||||||
```
|
```
|
||||||
|
|
||||||
## 重启服务进行调试
|
### 6. 重启服务进行调试
|
||||||
刷新浏览器,检查你的插件是否工作正常, 确保能够正常进行证书申请和部署
|
刷新浏览器,检查你的插件是否工作正常, 确保能够正常进行证书申请和部署
|
||||||
|
|
||||||
## 提交PR
|
## 三、提交PR
|
||||||
我们将尽快审核PR
|
我们将尽快审核PR
|
||||||
|
|
||||||
|
## 四、 注意事项
|
||||||
|
### 1. 如何让任务报错停止
|
||||||
|
|
||||||
|
```js
|
||||||
|
// 抛出异常即可使任务停止,否则会判定为成功
|
||||||
|
throw new Error("错误信息")
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## 五、贡献插件送激活码
|
||||||
|
|
||||||
|
- PR要求,插件功能完整,代码规范
|
||||||
|
- PR通过后,联系我们,送您一个半年期专业版激活码
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
## 2. 原理
|
## 2. 原理
|
||||||
* 假设你要申请证书的域名叫:`cert.com` ,它是在`Certd`不支持的服务商注册的
|
* 假设你要申请证书的域名叫:`cert.com` ,它是在`Certd`不支持的服务商注册的
|
||||||
* 假设你还有另外一个域名叫:`proxy.com`,它是在`Certd`支持的服务商注册的。
|
* 假设我们还有另外一个域名叫:`proxy.com`,它是在`Certd`支持的服务商注册的。
|
||||||
* 当我们按照如下进行配置时
|
* 当我们按照如下进行配置时
|
||||||
```
|
```
|
||||||
CNAME记录(手动、固定) TXT记录(自动、随机)
|
CNAME记录(手动、固定) TXT记录(自动、随机)
|
||||||
@@ -19,20 +19,17 @@ _acme-challenge.cert.com ---> xxxxx.cname.proxy.com ----> txt-record-abcdefg
|
|||||||
|
|
||||||
```
|
```
|
||||||
* 证书颁发机构就可以从`_acme-challenge.cert.com`查到TXT记录 `txt-record-abcdefg`,从而完成域名所有权校验。
|
* 证书颁发机构就可以从`_acme-challenge.cert.com`查到TXT记录 `txt-record-abcdefg`,从而完成域名所有权校验。
|
||||||
* 以上可以看出 `xxxxx.cname.proxy.com ----> txt-record-abcdefg` 这一段`Certd`可以自动添加的。
|
* 以上可以看出 `xxxxx.cname.proxy.com ----> txt-record-abcdefg` 这一段`Certd` 是可以自动添加的。
|
||||||
* 剩下的只需要在你的`cert.com`域名中手动添加一条固定的`CNAME解析`即可
|
* 剩下的只需要在你的`cert.com`域名中手动添加一条固定的`CNAME解析`即可
|
||||||
|
|
||||||
|
|
||||||
## 3. Certd CNAME使用步骤
|
## 3. Certd CNAME使用步骤
|
||||||
|
|
||||||
1. 准备`一个`支持的服务商的注册的域名(`proxy.com`),或者将你众多域名其中`一个`的`DNS服务器`转到这几家服务商。
|
|
||||||
2. 然后到`Certd`的 `CNAME服务管理`界面,用`cname.proxy.com`创建一条默认的CNAME服务,提供DNS提供商授权。
|
1. 创建证书流水线,输入你要申请证书的域名,假设就是`cert.com`,然后选择`CNAME`校验方式
|
||||||

|
2. 此时需要配置验证计划,Certd会生成一个随机的CNAME记录模版,例如:`_acme-challenge`->`xxxxxx.cname.proxy.com`
|
||||||
2. 然后创建证书流水线,输入`cert.com`,选择`CNAME`校验方式
|
|
||||||
|
|
||||||
3. 此时需要配置验证计划,Certd会生成一个随机的CNAME记录,例如:`_acme-challenge`->`xxxxxx.cname.proxy.com`
|
|
||||||

|

|
||||||
3. 您需要手动在你的`cert.com`域名中添加CNAME解析,点击校验,校验成功后就可以开始申请证书了 (此操作每个域名只需要做一次,后续可以重复使用,注意不要删除添加的CNAME记录)
|
3. 您需要手动在你的`cert.com`域名中添加CNAME解析,点击验证,校验成功后就可以开始申请证书了 (此操作每个域名只需要做一次,后续可以重复使用,注意不要删除添加的CNAME记录)
|
||||||

|

|
||||||

|

|
||||||
4. 申请过程中,Certd会在`xxxxxx.cname.proxy.com`下自动添加TXT记录。
|
4. 申请过程中,Certd会在`xxxxxx.cname.proxy.com`下自动添加TXT记录。
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Certd 是一款开源、免费、全自动申请和部署更新SSL证书的工
|
|||||||
* 支持通配符域名/泛域名,支持多个域名打到一个证书上
|
* 支持通配符域名/泛域名,支持多个域名打到一个证书上
|
||||||
* 邮件通知
|
* 邮件通知
|
||||||
* 私有化部署,保障数据安全
|
* 私有化部署,保障数据安全
|
||||||
* 支持sqlite,postgresql数据库
|
* 支持SQLite、Postgresql、MySQL数据库
|
||||||
|
|
||||||
|
|
||||||
## 二、一些说明
|
## 二、一些说明
|
||||||
@@ -26,5 +26,9 @@ Certd 是一款开源、免费、全自动申请和部署更新SSL证书的工
|
|||||||
* 实际上没有办法不改变证书文件本身情况下直接续期或者续签。
|
* 实际上没有办法不改变证书文件本身情况下直接续期或者续签。
|
||||||
* 我们所说的续期,其实就是按照全套流程重新申请一份新证书,然后重新部署上去。
|
* 我们所说的续期,其实就是按照全套流程重新申请一份新证书,然后重新部署上去。
|
||||||
* 免费证书过期时间90天,以后可能还会缩短,所以自动化部署必不可少
|
* 免费证书过期时间90天,以后可能还会缩短,所以自动化部署必不可少
|
||||||
* 设置每天自动运行,当证书过期前20天,会自动重新申请证书并部署
|
* 设置每天自动运行,当证书过期前35天,会自动重新申请证书并部署
|
||||||
|
|
||||||
|
## 三、证书颁发机构对比
|
||||||
|
* Let's Encrypt:申请最简单。
|
||||||
|
* Google: 大厂光环,兼容性好,首次需要翻墙获取EAB。
|
||||||
|
* ZeroSSL: 需要EAB,获取EAB无需翻墙。
|
||||||
BIN
docs/guide/install/1panel/images/upgrade-1.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
docs/guide/install/1panel/images/upgrade-2.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
@@ -31,15 +31,12 @@ admin/123456
|
|||||||
|
|
||||||
## 三、升级
|
## 三、升级
|
||||||
|
|
||||||
1. 找到容器,点击编辑
|
1. 找到容器,点击更多->升级
|
||||||

|

|
||||||
|
|
||||||
2. 将latest修改为最新版本号
|
2. 选择强制拉取镜像,点击确认即可
|
||||||

|

|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
3. 点击确定,重启容器
|
|
||||||
|
|
||||||
## 四、数据备份
|
## 四、数据备份
|
||||||
|
|
||||||
@@ -48,4 +45,4 @@ admin/123456
|
|||||||
|
|
||||||
## 五、备份恢复
|
## 五、备份恢复
|
||||||
|
|
||||||
将备份的`db.sqlite`覆盖到原来的位置即可
|
将备份的`db.sqlite`及同目录下的其他文件一起覆盖到原来的位置,重启certd即可
|
||||||
|
|||||||
@@ -38,28 +38,12 @@ admin/123456
|
|||||||
登录后请及时修改密码
|
登录后请及时修改密码
|
||||||
|
|
||||||
## 三、如何升级
|
## 三、如何升级
|
||||||
|
宝塔升级certd非常简单
|
||||||
|
|
||||||
### 1. 应用商店安装,直接更新镜像即可
|
`docker`->`容器编排`->`左侧选择Certd`->`更新镜像`
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
### 2. latest更新方式
|
|
||||||
在主机上拉取最新镜像,然后面板上重启容器
|
|
||||||
```shell
|
|
||||||
docker pull registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 固定版本号方式
|
|
||||||
|
|
||||||
修改容器编排模版中的镜像版本号,然后面板上重启容器
|
|
||||||
```shell
|
|
||||||
services:
|
|
||||||
certd:
|
|
||||||
# 镜像 # 修改最新版本号 ---- ↓↓↓↓↓
|
|
||||||
image: registry.cn-shenzhen.aliyuncs.com/handsfree/certd:v1.xx.x
|
|
||||||
```
|
|
||||||
|
|
||||||
## 四、数据备份
|
## 四、数据备份
|
||||||
|
|
||||||
### 4.1 应用商店部署方式
|
### 4.1 应用商店部署方式
|
||||||
@@ -81,4 +65,4 @@ services:
|
|||||||
|
|
||||||
## 五、备份恢复
|
## 五、备份恢复
|
||||||
|
|
||||||
将备份的`db.sqlite`覆盖到原来的位置即可
|
将备份的`db.sqlite`及同目录下的其他文件一起覆盖到原来的位置,重启certd即可
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ docker compose up -d
|
|||||||
|
|
||||||
> 如果提示 没有docker compose命令,请安装docker-compose
|
> 如果提示 没有docker compose命令,请安装docker-compose
|
||||||
> https://docs.docker.com/compose/install/linux/
|
> https://docs.docker.com/compose/install/linux/
|
||||||
> 然后使用 `docker-compose up -d` 启动
|
|
||||||
|
|
||||||
### 3. 访问测试
|
### 3. 访问测试
|
||||||
|
|
||||||
@@ -71,4 +71,4 @@ docker compose up -d
|
|||||||
|
|
||||||
## 四、备份恢复
|
## 四、备份恢复
|
||||||
|
|
||||||
将备份的`db.sqlite`覆盖到原来的位置即可
|
将备份的`db.sqlite`及同目录下的其他文件一起覆盖到原来的位置,重启certd即可
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
# 源码部署
|
# 源码部署
|
||||||
|
不推荐
|
||||||
## 一、源码安装
|
## 一、源码安装
|
||||||
|
|
||||||
|
### 环境要求
|
||||||
|
- nodejs 20 及以上
|
||||||
### 源码启动
|
### 源码启动
|
||||||
```shell
|
```shell
|
||||||
# 克隆代码
|
# 克隆代码
|
||||||
git clone https://github.com/certd/certd
|
git clone https://github.com/certd/certd
|
||||||
# git checkout v1.x.x # 1.x.x换成最新版本号,当v2主干分支代码无法正常启动时,可以尝试此命令
|
# git checkout v1.x.x # 当v2主干分支代码无法正常启动时,可以尝试此命令,1.x.x换成最新版本号
|
||||||
cd certd
|
cd certd
|
||||||
# 启动服务
|
# 启动服务
|
||||||
./start.sh
|
./start.sh
|
||||||
@@ -26,9 +29,15 @@ https://your_server_ip:7002
|
|||||||
## 二、升级
|
## 二、升级
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# 更新代码并启动
|
|
||||||
cd certd
|
cd certd
|
||||||
|
# 确保数据安全,备份一下数据
|
||||||
|
cp -rf ./packages/ui/certd-server/data ../certd-data-backup
|
||||||
|
|
||||||
git pull
|
git pull
|
||||||
|
# 如果提示pull失败,可以尝试强制更新
|
||||||
|
# git checkout v2 -f && git pull
|
||||||
|
|
||||||
# 先停止旧的服务,7001是certd的默认端口
|
# 先停止旧的服务,7001是certd的默认端口
|
||||||
kill -9 $(lsof -t -i:7001)
|
kill -9 $(lsof -t -i:7001)
|
||||||
# 重新编译启动
|
# 重新编译启动
|
||||||
@@ -42,4 +51,4 @@ kill -9 $(lsof -t -i:7001)
|
|||||||
|
|
||||||
## 四、备份恢复
|
## 四、备份恢复
|
||||||
|
|
||||||
将备份的`db.sqlite`覆盖到原来的位置即可
|
将备份的`db.sqlite`及同目录下的其他文件覆盖到原来的位置,重启certd即可
|
||||||
|
|||||||
12
docs/guide/install/upgrade.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# 版本升级
|
||||||
|
|
||||||
|
## 升级方法
|
||||||
|
根据不同部署方式查看升级方法
|
||||||
|
|
||||||
|
1. [Docker方式部署升级](./docker/#二、升级)
|
||||||
|
2. [宝塔面板方式部署升级](./baota/#三、如何升级)
|
||||||
|
3. [1Panel面板方式部署升级](./1panel/#三、升级)
|
||||||
|
4. [源码方式部署](./source/#二、升级)
|
||||||
|
|
||||||
|
## 升级日志
|
||||||
|
[CHANGELOG](../changelogs/CHANGELOG.md)
|
||||||
@@ -8,4 +8,14 @@
|
|||||||
ALIYUN_CLIENT_CONNECT_TIMEOUT=10000 # 连接超时,单位毫秒
|
ALIYUN_CLIENT_CONNECT_TIMEOUT=10000 # 连接超时,单位毫秒
|
||||||
ALIYUN_CLIENT_READ_TIMEOUT=10000 #读取数据超时,单位毫秒
|
ALIYUN_CLIENT_READ_TIMEOUT=10000 #读取数据超时,单位毫秒
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## 阿里云Access权限设置
|
||||||
|
|
||||||
|
|
||||||
|
* 申请证书 :`AliyunDNSFullAccess`
|
||||||
|
* 上传证书到阿里云: `AliyunYundunCertFullAccess`
|
||||||
|
* 部署证书到OSS: `AliyunYundunCertFullAccess`、`AliyunOSSFullAccess`
|
||||||
|
* 部署证书到CDN: `AliyunYundunCertFullAccess`、`AliyunCDNFullAccess`
|
||||||
|
* 部署证书到DCDN: `AliyunYundunCertFullAccess`、`AliyunDCDNFullAccess`
|
||||||
@@ -27,4 +27,4 @@
|
|||||||
|
|
||||||
## 三、备份恢复
|
## 三、备份恢复
|
||||||
|
|
||||||
将备份的`db.sqlite`覆盖到原来的位置即可
|
将备份的`db.sqlite`覆盖到原来的位置,重启certd即可
|
||||||
10
docs/guide/use/cert/index.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# 证书申请失败情况
|
||||||
|
|
||||||
|
|
||||||
|
## DNS记录问题
|
||||||
|
|
||||||
|
1. DNS 不要设置CAA记录,删除即可
|
||||||
|
|
||||||
|
2. DNSSEC相关报错,DNSSEC管理中删除即可
|
||||||
|
|
||||||
|
3. DNS 有其他平台申请过的_acme-challenge记录,删除即可
|
||||||
86
docs/guide/use/custom-script/index.md
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# 自定义脚本插件
|
||||||
|
|
||||||
|
## 1. 介绍
|
||||||
|
|
||||||
|
自定义脚本插件是一个通用的插件,可以通过编写脚本来实现各种功能,例如:调用第三方API、执行系统命令、发送邮件等。
|
||||||
|
|
||||||
|
## 2. 使用示例
|
||||||
|
```js
|
||||||
|
const certPem = ctx.self.cert.crt
|
||||||
|
const certKey = ctx.self.cert.key
|
||||||
|
|
||||||
|
//axios发起http请求上传证书
|
||||||
|
const res = await ctx.http.request({
|
||||||
|
url:"your_cert_deploy_url",
|
||||||
|
method:"post",
|
||||||
|
data:{
|
||||||
|
crt : certPem,
|
||||||
|
key : certKey
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if(!res || res.code !== 0){
|
||||||
|
//抛异常才能让任务失败
|
||||||
|
throw new Error("上传失败")
|
||||||
|
}
|
||||||
|
//不能用console.log,需要用ctx.logger 才能把日志打印在ui上
|
||||||
|
ctx.logger.info("上传成功",res.data)
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
## 3. API
|
||||||
|
下面是`ctx`对象的`typescript`类型定义
|
||||||
|
|
||||||
|
```ts
|
||||||
|
|
||||||
|
type ctx = {
|
||||||
|
CertReader: typeof CertReader;
|
||||||
|
self: CustomScriptPlugin;
|
||||||
|
//流水线定义
|
||||||
|
pipeline: Pipeline;
|
||||||
|
//步骤定义
|
||||||
|
step: Step;
|
||||||
|
//日志
|
||||||
|
logger: Logger;
|
||||||
|
//当前步骤输入参数跟上一次执行比较是否有变化
|
||||||
|
inputChanged: boolean;
|
||||||
|
//授权获取服务
|
||||||
|
accessService: IAccessService;
|
||||||
|
//邮件服务
|
||||||
|
emailService: IEmailService;
|
||||||
|
//cname记录服务
|
||||||
|
cnameProxyService: ICnameProxyService;
|
||||||
|
//插件配置服务
|
||||||
|
pluginConfigService: IPluginConfigService;
|
||||||
|
//流水线上下文
|
||||||
|
pipelineContext: IContext;
|
||||||
|
//用户上下文
|
||||||
|
userContext: IContext;
|
||||||
|
//http请求客户端
|
||||||
|
http: HttpClient; // http.request(AxiosConfig)
|
||||||
|
//文件存储
|
||||||
|
fileStore: FileStore;
|
||||||
|
//上一次执行结果状态
|
||||||
|
lastStatus?: Runnable;
|
||||||
|
//用户取消信号
|
||||||
|
signal: AbortSignal;
|
||||||
|
//工具类
|
||||||
|
utils: typeof utils;
|
||||||
|
//用户信息
|
||||||
|
user: UserInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
type CertInfo = {
|
||||||
|
crt:string; //fullchain证书,即 cert.pem, cert.crt
|
||||||
|
key:string; // 私钥
|
||||||
|
ic: string; //中间证书
|
||||||
|
pfx: string;//PFX证书,base64编码
|
||||||
|
der: string;//DER证书,base64编码
|
||||||
|
}
|
||||||
|
|
||||||
|
type CustomScriptPlugin = {
|
||||||
|
//可以获取证书
|
||||||
|
cert: CertInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
BIN
docs/guide/use/email/images/qq-0.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/guide/use/email/images/qq-1.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
docs/guide/use/email/images/qq-11.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
docs/guide/use/email/images/qq-2.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
docs/guide/use/email/images/qq-3.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
23
docs/guide/use/email/index.md
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# 邮箱配置
|
||||||
|
|
||||||
|
|
||||||
|
## 腾讯企业邮箱配置
|
||||||
|
1. 开启smtp
|
||||||
|

|
||||||
|
2. 获取授权码作为密码
|
||||||
|

|
||||||
|

|
||||||
|
3. 填写域名、端口和密码
|
||||||
|

|
||||||
|
|
||||||
|
## QQ邮箱配置
|
||||||
|
1. smtp配置
|
||||||
|
```yaml
|
||||||
|
smtp域名: smtp.qq.com
|
||||||
|
smtp端口: 465
|
||||||
|
密码: 授权码,获取方式见下方
|
||||||
|
是否SSL: 是
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 获取授权码
|
||||||
|

|
||||||
@@ -4,7 +4,10 @@
|
|||||||
|
|
||||||
## windows开启OpenSSH Server
|
## windows开启OpenSSH Server
|
||||||
### 1. 安装OpenSSH Server
|
### 1. 安装OpenSSH Server
|
||||||
请前往Microsoft官方文档查看如何开启openSSH
|
|
||||||
|
* 下载安装包安装: https://github.com/PowerShell/Win32-OpenSSH/releases OpenSSH-Win64-vxx.xx.x.msi
|
||||||
|
|
||||||
|
* 前往Microsoft官方文档查看如何开启openSSH,以及其他设置
|
||||||
https://learn.microsoft.com/zh-cn/windows-server/administration/openssh/openssh_install_firstuse?tabs=gui#install-openssh-for-windows
|
https://learn.microsoft.com/zh-cn/windows-server/administration/openssh/openssh_install_firstuse?tabs=gui#install-openssh-for-windows
|
||||||
|
|
||||||
### 2. 启动OpenSSH Server服务
|
### 2. 启动OpenSSH Server服务
|
||||||
@@ -22,3 +25,15 @@ win+R 弹出运行对话框,输入 services.msc 打开服务管理器
|
|||||||
C:\Users\xxxxx>
|
C:\Users\xxxxx>
|
||||||
↑↑↑↑---------这个就是windows ssh的登录用户名
|
↑↑↑↑---------这个就是windows ssh的登录用户名
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 4. 切换默认shell终端
|
||||||
|
安装openssh后,默认终端是cmd,建议切换成powershell
|
||||||
|
```shell
|
||||||
|
# powershell中执行如下命令切换
|
||||||
|
# 设置默认shell为powershell 【推荐】
|
||||||
|
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force
|
||||||
|
|
||||||
|
# 恢复默认shell为cmd 【不推荐】
|
||||||
|
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\cmd.exe" -PropertyType String -Force
|
||||||
|
|
||||||
|
```
|
||||||
BIN
docs/guide/use/setting/images/ipv6.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
21
docs/guide/use/setting/ipv6.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# IPv6支持
|
||||||
|
|
||||||
|
## 启用IPv6
|
||||||
|
在`docker-compose.yaml`中启用IPv6支持,放开如下注释:
|
||||||
|
```yaml
|
||||||
|
# #↓↓↓↓ ------------------------------------------------------------- 启用ipv6网络
|
||||||
|
networks:
|
||||||
|
- ip6net
|
||||||
|
networks:
|
||||||
|
ip6net:
|
||||||
|
enable_ipv6: true
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: 2001:db8::/64
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## 设置双栈网络优先级
|
||||||
|
可根据实际情况设置
|
||||||
|
|
||||||
|

|
||||||
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 53 KiB |
@@ -1,8 +1,12 @@
|
|||||||
# 群晖部署和证书更新
|
# 群晖部署和证书更新
|
||||||
|
|
||||||
|
支持群晖`6.x`、`7.x`
|
||||||
|
|
||||||
## 一、群晖部署Certd
|
## 一、群晖部署Certd
|
||||||
|
|
||||||
|
以下是群晖`7.x`的部署`certd`步骤。
|
||||||
|
群晖`6.x`请参考[docker部署](./../../install/docker/)
|
||||||
|
|
||||||
### 1. 打开Container Manager
|
### 1. 打开Container Manager
|
||||||
|
|
||||||

|

|
||||||
@@ -32,6 +36,8 @@
|
|||||||
|
|
||||||
## 二、更新群晖证书
|
## 二、更新群晖证书
|
||||||
|
|
||||||
|
证书部署插件支持群晖`6.x`、`7.x`
|
||||||
|
|
||||||
## 1. 前提条件
|
## 1. 前提条件
|
||||||
* 已经部署了certd
|
* 已经部署了certd
|
||||||
* 群晖上已经设置好了证书(证书建议设置好描述,插件需要根据描述查找证书)
|
* 群晖上已经设置好了证书(证书建议设置好描述,插件需要根据描述查找证书)
|
||||||
|
|||||||
BIN
docs/guide/use/tencent/images/delete.png
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
docs/guide/use/tencent/images/delete2.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
@@ -6,3 +6,16 @@
|
|||||||
打开 https://console.cloud.tencent.com/cam/capi
|
打开 https://console.cloud.tencent.com/cam/capi
|
||||||
然后按如下方式获取腾讯云的API密钥
|
然后按如下方式获取腾讯云的API密钥
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
## 如何避免收到腾讯云证书过期邮件
|
||||||
|
|
||||||
|
腾讯云在证书有效期还剩28天时会发送过期通知邮件
|
||||||
|
您可以通过配置“腾讯云过期证书删除”任务来避免收到此类邮件。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
注意点:
|
||||||
|
> 1. 选择腾讯云授权,需授权`服务角色SSL_QCSLinkedRoleInReplaceLoadCertificate`权限
|
||||||
|
> 2. `1.26.14`版本之前Certd创建的证书流水线默认是到期前20天才更新证书,需要将之前创建的证书申请任务的更新天数修改为35天,保证删除之前就已经替换掉即将过期证书
|
||||||
|

|
||||||
BIN
docs/images/start/home.png
Normal file
|
After Width: | Height: | Size: 163 KiB |
@@ -18,7 +18,7 @@ hero:
|
|||||||
link: /guide/tutorial.md
|
link: /guide/tutorial.md
|
||||||
- theme: alt
|
- theme: alt
|
||||||
text: demo体验
|
text: demo体验
|
||||||
link: https://certd.handsfree.work
|
link: https://certd.handfree.work
|
||||||
|
|
||||||
features:
|
features:
|
||||||
- title: 全自动申请证书
|
- title: 全自动申请证书
|
||||||
@@ -28,9 +28,9 @@ features:
|
|||||||
- title: 多域名、泛域名打到一个证书上
|
- title: 多域名、泛域名打到一个证书上
|
||||||
details: 支持通配符域名/泛域名,支持多个域名打到一个证书上
|
details: 支持通配符域名/泛域名,支持多个域名打到一个证书上
|
||||||
- title: 多证书格式支持
|
- title: 多证书格式支持
|
||||||
details: 支持pem、pfx、der等多种证书格式,支持Google、Letsencrypt、ZeroSSL证书颁发机构
|
details: 支持pem、pfx、der、jks等多种证书格式,支持Google、Letsencrypt、ZeroSSL证书颁发机构
|
||||||
- title: 支持私有化部署
|
- title: 支持私有化部署
|
||||||
details: 保障数据安全
|
details: 授权数据加密存储,保障数据安全
|
||||||
- title: 多数据库支持
|
- title: 多数据库支持
|
||||||
details: 支持sqlite,postgresql数据库
|
details: 支持SQLite、Postgresql、MySQL数据库
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -9,5 +9,5 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"npmClient": "pnpm",
|
"npmClient": "pnpm",
|
||||||
"version": "1.26.13"
|
"version": "1.29.3"
|
||||||
}
|
}
|
||||||
|
|||||||
11
package.json
@@ -14,13 +14,14 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "lerna bootstrap --hoist",
|
"start": "lerna bootstrap --hoist",
|
||||||
|
"devb": "lerna run dev-build",
|
||||||
"i-all": "lerna link && lerna exec npm install ",
|
"i-all": "lerna link && lerna exec npm install ",
|
||||||
"publish": "npm run prepublishOnly2 && lerna publish --force-publish=pro/plus-core --conventional-commits --create-release github && npm run afterpublishOnly && npm run commitAll",
|
"publish": "npm run prepublishOnly2 && lerna publish --force-publish=pro/plus-core --conventional-commits --create-release github && npm run afterpublishOnly && npm run commitAll",
|
||||||
"afterpublishOnly": "time /t >build.trigger && git add ./build.trigger && git commit -m \"build: trigger build image\" && TIMEOUT /T 10 && git push",
|
"afterpublishOnly": "npm run copylogs && time /t >build.trigger && git add ./build.trigger && git commit -m \"build: trigger build image\" && TIMEOUT /T 10 && git push",
|
||||||
"transform-sql": "cd ./packages/ui/certd-server/db/ && node --experimental-json-modules transform.js",
|
"transform-sql": "cd ./packages/ui/certd-server/db/ && node --experimental-json-modules transform.js",
|
||||||
"commitAll": "git add . && git commit -m \"build: publish\" && git push && npm run commitPro",
|
"commitAll": "git add . && git commit -m \"build: publish\" && git push && npm run commitPro",
|
||||||
"commitPro": "cd ./packages/core/ && git add . && git commit -m \"build: publish\" && git push",
|
"commitPro": "cd ./packages/core/ && git add . && git commit -m \"build: publish\" && git push",
|
||||||
"copylogs": "copyfiles \"CHANGELOG.md\" ./docs/guide/other/changelogs/",
|
"copylogs": "copyfiles \"CHANGELOG.md\" ./docs/guide/changelogs/",
|
||||||
"prepublishOnly1": "npm run check && lerna run build ",
|
"prepublishOnly1": "npm run check && lerna run build ",
|
||||||
"prepublishOnly2": "npm run check && npm run before-build && lerna run build ",
|
"prepublishOnly2": "npm run check && npm run before-build && lerna run build ",
|
||||||
"before-build": "npm run transform-sql && cd ./packages/core/basic && time /t >build.md && git add ./build.md && git commit -m \"build: prepare to build\"",
|
"before-build": "npm run transform-sql && cd ./packages/core/basic && time /t >build.md && git add ./build.md && git commit -m \"build: prepare to build\"",
|
||||||
@@ -34,9 +35,11 @@
|
|||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"lodash-es": "^4.17.21"
|
"copyfiles": "^2.4.1",
|
||||||
|
"lodash-es": "^4.17.21",
|
||||||
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/**"
|
"packages/**"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
28
packages/core/acme-client/.eslintrc
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"extends": [
|
||||||
|
"plugin:prettier/recommended",
|
||||||
|
"prettier"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"eslint-plugin-import"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"mocha": true
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"@typescript-eslint/no-var-requires": "off",
|
||||||
|
"@typescript-eslint/ban-ts-comment": "off",
|
||||||
|
"@typescript-eslint/ban-ts-ignore": "off",
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/no-empty-function": "off",
|
||||||
|
// "no-unused-expressions": "off",
|
||||||
|
"max-len": [
|
||||||
|
0,
|
||||||
|
160,
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
"ignoreUrls": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
extends:
|
|
||||||
- 'airbnb-base'
|
|
||||||
|
|
||||||
env:
|
|
||||||
browser: false
|
|
||||||
node: true
|
|
||||||
mocha: true
|
|
||||||
|
|
||||||
rules:
|
|
||||||
indent: [2, 4, { SwitchCase: 1, VariableDeclarator: 1 }]
|
|
||||||
brace-style: [2, 'stroustrup', { allowSingleLine: true }]
|
|
||||||
func-names: 0
|
|
||||||
class-methods-use-this: 0
|
|
||||||
no-param-reassign: 0
|
|
||||||
max-len: [1, 200, 2, { ignoreUrls: true, ignoreComments: false }]
|
|
||||||
import/no-useless-path-segments: 0
|
|
||||||
@@ -3,6 +3,100 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.29.3](https://github.com/publishlab/node-acme-client/compare/v1.29.2...v1.29.3) (2025-01-04)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 优化acme sdk ([54db744](https://github.com/publishlab/node-acme-client/commit/54db74428259de64d12230c2ab7353ae11197bbc))
|
||||||
|
|
||||||
|
## [1.29.2](https://github.com/publishlab/node-acme-client/compare/v1.29.1...v1.29.2) (2024-12-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.29.1](https://github.com/publishlab/node-acme-client/compare/v1.29.0...v1.29.1) (2024-12-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
# [1.29.0](https://github.com/publishlab/node-acme-client/compare/v1.28.4...v1.29.0) (2024-12-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.28.4](https://github.com/publishlab/node-acme-client/compare/v1.28.3...v1.28.4) (2024-12-12)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.28.3](https://github.com/publishlab/node-acme-client/compare/v1.28.2...v1.28.3) (2024-12-12)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.28.2](https://github.com/publishlab/node-acme-client/compare/v1.28.1...v1.28.2) (2024-12-09)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 支持mysql ([7cde1fd](https://github.com/publishlab/node-acme-client/commit/7cde1fdc4a9ed851900d231a5460c8dbfbcd148e))
|
||||||
|
|
||||||
|
## [1.28.1](https://github.com/publishlab/node-acme-client/compare/v1.28.0...v1.28.1) (2024-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
# [1.28.0](https://github.com/publishlab/node-acme-client/compare/v1.27.9...v1.28.0) (2024-11-30)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.27.9](https://github.com/publishlab/node-acme-client/compare/v1.27.8...v1.27.9) (2024-11-26)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.27.8](https://github.com/publishlab/node-acme-client/compare/v1.27.7...v1.27.8) (2024-11-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.27.7](https://github.com/publishlab/node-acme-client/compare/v1.27.6...v1.27.7) (2024-11-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.27.6](https://github.com/publishlab/node-acme-client/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.27.5](https://github.com/publishlab/node-acme-client/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.27.4](https://github.com/publishlab/node-acme-client/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.27.3](https://github.com/publishlab/node-acme-client/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.27.2](https://github.com/publishlab/node-acme-client/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.27.1](https://github.com/publishlab/node-acme-client/compare/v1.27.0...v1.27.1) (2024-11-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
# [1.27.0](https://github.com/publishlab/node-acme-client/compare/v1.26.16...v1.27.0) (2024-10-31)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.26.16](https://github.com/publishlab/node-acme-client/compare/v1.26.15...v1.26.16) (2024-10-30)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.26.15](https://github.com/publishlab/node-acme-client/compare/v1.26.14...v1.26.15) (2024-10-28)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.26.14](https://github.com/publishlab/node-acme-client/compare/v1.26.13...v1.26.14) (2024-10-26)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复启动时自签证书无法保存的bug ([526c484](https://github.com/publishlab/node-acme-client/commit/526c48450bcd37b3ccded9b448f17de8140bdc6e))
|
||||||
|
|
||||||
## [1.26.13](https://github.com/publishlab/node-acme-client/compare/v1.26.12...v1.26.13) (2024-10-26)
|
## [1.26.13](https://github.com/publishlab/node-acme-client/compare/v1.26.12...v1.26.13) (2024-10-26)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/acme-client
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|||||||
@@ -6,6 +6,38 @@
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
## Constants
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><a href="#createPrivateEcdsaKey">createPrivateEcdsaKey</a> ⇒ <code>Promise.<buffer></code></dt>
|
||||||
|
<dd><p>Generate a private ECDSA key</p>
|
||||||
|
</dd>
|
||||||
|
<dt><a href="#getPublicKey">getPublicKey</a> ⇒ <code>buffer</code></dt>
|
||||||
|
<dd><p>Get a public key derived from a RSA or ECDSA key</p>
|
||||||
|
</dd>
|
||||||
|
<dt><a href="#getPemBodyAsB64u">getPemBodyAsB64u</a> ⇒ <code>string</code></dt>
|
||||||
|
<dd><p>Parse body of PEM encoded object and return a Base64URL string
|
||||||
|
If multiple objects are chained, the first body will be returned</p>
|
||||||
|
</dd>
|
||||||
|
<dt><a href="#readCsrDomains">readCsrDomains</a> ⇒ <code>object</code></dt>
|
||||||
|
<dd><p>Read domains from a Certificate Signing Request</p>
|
||||||
|
</dd>
|
||||||
|
<dt><a href="#readCertificateInfo">readCertificateInfo</a> ⇒ <code>object</code></dt>
|
||||||
|
<dd><p>Read information from a certificate
|
||||||
|
If multiple certificates are chained, the first will be read</p>
|
||||||
|
</dd>
|
||||||
|
<dt><a href="#createCsr">createCsr</a> ⇒ <code>Promise.<Array.<buffer>></code></dt>
|
||||||
|
<dd><p>Create a Certificate Signing Request</p>
|
||||||
|
</dd>
|
||||||
|
<dt><a href="#createAlpnCertificate">createAlpnCertificate</a> ⇒ <code>Promise.<Array.<buffer>></code></dt>
|
||||||
|
<dd><p>Create a self-signed ALPN certificate for TLS-ALPN-01 challenges</p>
|
||||||
|
<p><a href="https://datatracker.ietf.org/doc/html/rfc8737">https://datatracker.ietf.org/doc/html/rfc8737</a></p>
|
||||||
|
</dd>
|
||||||
|
<dt><a href="#isAlpnCertificateAuthorizationValid">isAlpnCertificateAuthorizationValid</a> ⇒ <code>boolean</code></dt>
|
||||||
|
<dd><p>Validate that a ALPN certificate contains the expected key authorization</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
## Functions
|
## Functions
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
@@ -15,12 +47,6 @@
|
|||||||
<dt><a href="#createPrivateKey">createPrivateKey()</a></dt>
|
<dt><a href="#createPrivateKey">createPrivateKey()</a></dt>
|
||||||
<dd><p>Alias of <code>createPrivateRsaKey()</code></p>
|
<dd><p>Alias of <code>createPrivateRsaKey()</code></p>
|
||||||
</dd>
|
</dd>
|
||||||
<dt><a href="#createPrivateEcdsaKey">createPrivateEcdsaKey([namedCurve])</a> ⇒ <code>Promise.<buffer></code></dt>
|
|
||||||
<dd><p>Generate a private ECDSA key</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#getPublicKey">getPublicKey(keyPem)</a> ⇒ <code>buffer</code></dt>
|
|
||||||
<dd><p>Get a public key derived from a RSA or ECDSA key</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#getJwk">getJwk(keyPem)</a> ⇒ <code>object</code></dt>
|
<dt><a href="#getJwk">getJwk(keyPem)</a> ⇒ <code>object</code></dt>
|
||||||
<dd><p>Get a JSON Web Key derived from a RSA or ECDSA key</p>
|
<dd><p>Get a JSON Web Key derived from a RSA or ECDSA key</p>
|
||||||
<p><a href="https://datatracker.ietf.org/doc/html/rfc7517">https://datatracker.ietf.org/doc/html/rfc7517</a></p>
|
<p><a href="https://datatracker.ietf.org/doc/html/rfc7517">https://datatracker.ietf.org/doc/html/rfc7517</a></p>
|
||||||
@@ -28,27 +54,6 @@
|
|||||||
<dt><a href="#splitPemChain">splitPemChain(chainPem)</a> ⇒ <code>Array.<string></code></dt>
|
<dt><a href="#splitPemChain">splitPemChain(chainPem)</a> ⇒ <code>Array.<string></code></dt>
|
||||||
<dd><p>Split chain of PEM encoded objects from string into array</p>
|
<dd><p>Split chain of PEM encoded objects from string into array</p>
|
||||||
</dd>
|
</dd>
|
||||||
<dt><a href="#getPemBodyAsB64u">getPemBodyAsB64u(pem)</a> ⇒ <code>string</code></dt>
|
|
||||||
<dd><p>Parse body of PEM encoded object and return a Base64URL string
|
|
||||||
If multiple objects are chained, the first body will be returned</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#readCsrDomains">readCsrDomains(csrPem)</a> ⇒ <code>object</code></dt>
|
|
||||||
<dd><p>Read domains from a Certificate Signing Request</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#readCertificateInfo">readCertificateInfo(certPem)</a> ⇒ <code>object</code></dt>
|
|
||||||
<dd><p>Read information from a certificate
|
|
||||||
If multiple certificates are chained, the first will be read</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#createCsr">createCsr(data, [keyPem])</a> ⇒ <code>Promise.<Array.<buffer>></code></dt>
|
|
||||||
<dd><p>Create a Certificate Signing Request</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#createAlpnCertificate">createAlpnCertificate(authz, keyAuthorization, [keyPem])</a> ⇒ <code>Promise.<Array.<buffer>></code></dt>
|
|
||||||
<dd><p>Create a self-signed ALPN certificate for TLS-ALPN-01 challenges</p>
|
|
||||||
<p><a href="https://datatracker.ietf.org/doc/html/rfc8737">https://datatracker.ietf.org/doc/html/rfc8737</a></p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#isAlpnCertificateAuthorizationValid">isAlpnCertificateAuthorizationValid(certPem, keyAuthorization)</a> ⇒ <code>boolean</code></dt>
|
|
||||||
<dd><p>Validate that a ALPN certificate contains the expected key authorization</p>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<a name="crypto"></a>
|
<a name="crypto"></a>
|
||||||
@@ -57,40 +62,12 @@ If multiple certificates are chained, the first will be read</p>
|
|||||||
Native Node.js crypto interface
|
Native Node.js crypto interface
|
||||||
|
|
||||||
**Kind**: global namespace
|
**Kind**: global namespace
|
||||||
<a name="createPrivateRsaKey"></a>
|
|
||||||
|
|
||||||
## createPrivateRsaKey([modulusLength]) ⇒ <code>Promise.<buffer></code>
|
|
||||||
Generate a private RSA key
|
|
||||||
|
|
||||||
**Kind**: global function
|
|
||||||
**Returns**: <code>Promise.<buffer></code> - PEM encoded private RSA key
|
|
||||||
|
|
||||||
| Param | Type | Default | Description |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| [modulusLength] | <code>number</code> | <code>2048</code> | Size of the keys modulus in bits, default: `2048` |
|
|
||||||
|
|
||||||
**Example**
|
|
||||||
Generate private RSA key
|
|
||||||
```js
|
|
||||||
const privateKey = await acme.crypto.createPrivateRsaKey();
|
|
||||||
```
|
|
||||||
**Example**
|
|
||||||
Private RSA key with modulus size 4096
|
|
||||||
```js
|
|
||||||
const privateKey = await acme.crypto.createPrivateRsaKey(4096);
|
|
||||||
```
|
|
||||||
<a name="createPrivateKey"></a>
|
|
||||||
|
|
||||||
## createPrivateKey()
|
|
||||||
Alias of `createPrivateRsaKey()`
|
|
||||||
|
|
||||||
**Kind**: global function
|
|
||||||
<a name="createPrivateEcdsaKey"></a>
|
<a name="createPrivateEcdsaKey"></a>
|
||||||
|
|
||||||
## createPrivateEcdsaKey([namedCurve]) ⇒ <code>Promise.<buffer></code>
|
## createPrivateEcdsaKey ⇒ <code>Promise.<buffer></code>
|
||||||
Generate a private ECDSA key
|
Generate a private ECDSA key
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global constant
|
||||||
**Returns**: <code>Promise.<buffer></code> - PEM encoded private ECDSA key
|
**Returns**: <code>Promise.<buffer></code> - PEM encoded private ECDSA key
|
||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
@@ -109,10 +86,10 @@ const privateKey = await acme.crypto.createPrivateEcdsaKey('P-384');
|
|||||||
```
|
```
|
||||||
<a name="getPublicKey"></a>
|
<a name="getPublicKey"></a>
|
||||||
|
|
||||||
## getPublicKey(keyPem) ⇒ <code>buffer</code>
|
## getPublicKey ⇒ <code>buffer</code>
|
||||||
Get a public key derived from a RSA or ECDSA key
|
Get a public key derived from a RSA or ECDSA key
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global constant
|
||||||
**Returns**: <code>buffer</code> - PEM encoded public key
|
**Returns**: <code>buffer</code> - PEM encoded public key
|
||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
@@ -124,44 +101,13 @@ Get public key
|
|||||||
```js
|
```js
|
||||||
const publicKey = acme.crypto.getPublicKey(privateKey);
|
const publicKey = acme.crypto.getPublicKey(privateKey);
|
||||||
```
|
```
|
||||||
<a name="getJwk"></a>
|
|
||||||
|
|
||||||
## getJwk(keyPem) ⇒ <code>object</code>
|
|
||||||
Get a JSON Web Key derived from a RSA or ECDSA key
|
|
||||||
|
|
||||||
https://datatracker.ietf.org/doc/html/rfc7517
|
|
||||||
|
|
||||||
**Kind**: global function
|
|
||||||
**Returns**: <code>object</code> - JSON Web Key
|
|
||||||
|
|
||||||
| Param | Type | Description |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| keyPem | <code>buffer</code> \| <code>string</code> | PEM encoded private or public key |
|
|
||||||
|
|
||||||
**Example**
|
|
||||||
Get JWK
|
|
||||||
```js
|
|
||||||
const jwk = acme.crypto.getJwk(privateKey);
|
|
||||||
```
|
|
||||||
<a name="splitPemChain"></a>
|
|
||||||
|
|
||||||
## splitPemChain(chainPem) ⇒ <code>Array.<string></code>
|
|
||||||
Split chain of PEM encoded objects from string into array
|
|
||||||
|
|
||||||
**Kind**: global function
|
|
||||||
**Returns**: <code>Array.<string></code> - Array of PEM objects including headers
|
|
||||||
|
|
||||||
| Param | Type | Description |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| chainPem | <code>buffer</code> \| <code>string</code> | PEM encoded object chain |
|
|
||||||
|
|
||||||
<a name="getPemBodyAsB64u"></a>
|
<a name="getPemBodyAsB64u"></a>
|
||||||
|
|
||||||
## getPemBodyAsB64u(pem) ⇒ <code>string</code>
|
## getPemBodyAsB64u ⇒ <code>string</code>
|
||||||
Parse body of PEM encoded object and return a Base64URL string
|
Parse body of PEM encoded object and return a Base64URL string
|
||||||
If multiple objects are chained, the first body will be returned
|
If multiple objects are chained, the first body will be returned
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global constant
|
||||||
**Returns**: <code>string</code> - Base64URL-encoded body
|
**Returns**: <code>string</code> - Base64URL-encoded body
|
||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
@@ -170,10 +116,10 @@ If multiple objects are chained, the first body will be returned
|
|||||||
|
|
||||||
<a name="readCsrDomains"></a>
|
<a name="readCsrDomains"></a>
|
||||||
|
|
||||||
## readCsrDomains(csrPem) ⇒ <code>object</code>
|
## readCsrDomains ⇒ <code>object</code>
|
||||||
Read domains from a Certificate Signing Request
|
Read domains from a Certificate Signing Request
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global constant
|
||||||
**Returns**: <code>object</code> - {commonName, altNames}
|
**Returns**: <code>object</code> - {commonName, altNames}
|
||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
@@ -190,11 +136,11 @@ console.log(`Alt names: ${altNames.join(', ')}`);
|
|||||||
```
|
```
|
||||||
<a name="readCertificateInfo"></a>
|
<a name="readCertificateInfo"></a>
|
||||||
|
|
||||||
## readCertificateInfo(certPem) ⇒ <code>object</code>
|
## readCertificateInfo ⇒ <code>object</code>
|
||||||
Read information from a certificate
|
Read information from a certificate
|
||||||
If multiple certificates are chained, the first will be read
|
If multiple certificates are chained, the first will be read
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global constant
|
||||||
**Returns**: <code>object</code> - Certificate info
|
**Returns**: <code>object</code> - Certificate info
|
||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
@@ -215,10 +161,10 @@ console.log(`Alt names: ${altNames.join(', ')}`);
|
|||||||
```
|
```
|
||||||
<a name="createCsr"></a>
|
<a name="createCsr"></a>
|
||||||
|
|
||||||
## createCsr(data, [keyPem]) ⇒ <code>Promise.<Array.<buffer>></code>
|
## createCsr ⇒ <code>Promise.<Array.<buffer>></code>
|
||||||
Create a Certificate Signing Request
|
Create a Certificate Signing Request
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global constant
|
||||||
**Returns**: <code>Promise.<Array.<buffer>></code> - [privateKey, certificateSigningRequest]
|
**Returns**: <code>Promise.<Array.<buffer>></code> - [privateKey, certificateSigningRequest]
|
||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
@@ -276,12 +222,12 @@ const [, certificateRequest] = await acme.crypto.createCsr({
|
|||||||
```
|
```
|
||||||
<a name="createAlpnCertificate"></a>
|
<a name="createAlpnCertificate"></a>
|
||||||
|
|
||||||
## createAlpnCertificate(authz, keyAuthorization, [keyPem]) ⇒ <code>Promise.<Array.<buffer>></code>
|
## createAlpnCertificate ⇒ <code>Promise.<Array.<buffer>></code>
|
||||||
Create a self-signed ALPN certificate for TLS-ALPN-01 challenges
|
Create a self-signed ALPN certificate for TLS-ALPN-01 challenges
|
||||||
|
|
||||||
https://datatracker.ietf.org/doc/html/rfc8737
|
https://datatracker.ietf.org/doc/html/rfc8737
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global constant
|
||||||
**Returns**: <code>Promise.<Array.<buffer>></code> - [privateKey, certificate]
|
**Returns**: <code>Promise.<Array.<buffer>></code> - [privateKey, certificate]
|
||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
@@ -303,10 +249,10 @@ const [, alpnCertificate] = await acme.crypto.createAlpnCertificate(authz, keyAu
|
|||||||
```
|
```
|
||||||
<a name="isAlpnCertificateAuthorizationValid"></a>
|
<a name="isAlpnCertificateAuthorizationValid"></a>
|
||||||
|
|
||||||
## isAlpnCertificateAuthorizationValid(certPem, keyAuthorization) ⇒ <code>boolean</code>
|
## isAlpnCertificateAuthorizationValid ⇒ <code>boolean</code>
|
||||||
Validate that a ALPN certificate contains the expected key authorization
|
Validate that a ALPN certificate contains the expected key authorization
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global constant
|
||||||
**Returns**: <code>boolean</code> - True when valid
|
**Returns**: <code>boolean</code> - True when valid
|
||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
@@ -314,3 +260,62 @@ Validate that a ALPN certificate contains the expected key authorization
|
|||||||
| certPem | <code>buffer</code> \| <code>string</code> | PEM encoded certificate |
|
| certPem | <code>buffer</code> \| <code>string</code> | PEM encoded certificate |
|
||||||
| keyAuthorization | <code>string</code> | Expected challenge key authorization |
|
| keyAuthorization | <code>string</code> | Expected challenge key authorization |
|
||||||
|
|
||||||
|
<a name="createPrivateRsaKey"></a>
|
||||||
|
|
||||||
|
## createPrivateRsaKey([modulusLength]) ⇒ <code>Promise.<buffer></code>
|
||||||
|
Generate a private RSA key
|
||||||
|
|
||||||
|
**Kind**: global function
|
||||||
|
**Returns**: <code>Promise.<buffer></code> - PEM encoded private RSA key
|
||||||
|
|
||||||
|
| Param | Type | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| [modulusLength] | <code>number</code> | Size of the keys modulus in bits, default: `2048` |
|
||||||
|
|
||||||
|
**Example**
|
||||||
|
Generate private RSA key
|
||||||
|
```js
|
||||||
|
const privateKey = await acme.crypto.createPrivateRsaKey();
|
||||||
|
```
|
||||||
|
**Example**
|
||||||
|
Private RSA key with modulus size 4096
|
||||||
|
```js
|
||||||
|
const privateKey = await acme.crypto.createPrivateRsaKey(4096);
|
||||||
|
```
|
||||||
|
<a name="createPrivateKey"></a>
|
||||||
|
|
||||||
|
## createPrivateKey()
|
||||||
|
Alias of `createPrivateRsaKey()`
|
||||||
|
|
||||||
|
**Kind**: global function
|
||||||
|
<a name="getJwk"></a>
|
||||||
|
|
||||||
|
## getJwk(keyPem) ⇒ <code>object</code>
|
||||||
|
Get a JSON Web Key derived from a RSA or ECDSA key
|
||||||
|
|
||||||
|
https://datatracker.ietf.org/doc/html/rfc7517
|
||||||
|
|
||||||
|
**Kind**: global function
|
||||||
|
**Returns**: <code>object</code> - JSON Web Key
|
||||||
|
|
||||||
|
| Param | Type | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| keyPem | <code>buffer</code> \| <code>string</code> | PEM encoded private or public key |
|
||||||
|
|
||||||
|
**Example**
|
||||||
|
Get JWK
|
||||||
|
```js
|
||||||
|
const jwk = acme.crypto.getJwk(privateKey);
|
||||||
|
```
|
||||||
|
<a name="splitPemChain"></a>
|
||||||
|
|
||||||
|
## splitPemChain(chainPem) ⇒ <code>Array.<string></code>
|
||||||
|
Split chain of PEM encoded objects from string into array
|
||||||
|
|
||||||
|
**Kind**: global function
|
||||||
|
**Returns**: <code>Array.<string></code> - Array of PEM objects including headers
|
||||||
|
|
||||||
|
| Param | Type | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| chainPem | <code>buffer</code> \| <code>string</code> | PEM encoded object chain |
|
||||||
|
|
||||||
|
|||||||
@@ -8,37 +8,42 @@ major release. Please migrate to the new <code>acme.crypto</code> interface at y
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
## Constants
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><a href="#createPublicKey">createPublicKey</a> ⇒ <code>Promise.<buffer></code></dt>
|
||||||
|
<dd><p>Create public key from a private RSA key</p>
|
||||||
|
</dd>
|
||||||
|
<dt><a href="#getPemBody">getPemBody</a> ⇒ <code>string</code></dt>
|
||||||
|
<dd><p>Parse body of PEM encoded object from buffer or string
|
||||||
|
If multiple objects are chained, the first body will be returned</p>
|
||||||
|
</dd>
|
||||||
|
<dt><a href="#splitPemChain">splitPemChain</a> ⇒ <code>Array.<string></code></dt>
|
||||||
|
<dd><p>Split chain of PEM encoded objects from buffer or string into array</p>
|
||||||
|
</dd>
|
||||||
|
<dt><a href="#getModulus">getModulus</a> ⇒ <code>Promise.<buffer></code></dt>
|
||||||
|
<dd><p>Get modulus</p>
|
||||||
|
</dd>
|
||||||
|
<dt><a href="#getPublicExponent">getPublicExponent</a> ⇒ <code>Promise.<buffer></code></dt>
|
||||||
|
<dd><p>Get public exponent</p>
|
||||||
|
</dd>
|
||||||
|
<dt><a href="#readCsrDomains">readCsrDomains</a> ⇒ <code>Promise.<object></code></dt>
|
||||||
|
<dd><p>Read domains from a Certificate Signing Request</p>
|
||||||
|
</dd>
|
||||||
|
<dt><a href="#readCertificateInfo">readCertificateInfo</a> ⇒ <code>Promise.<object></code></dt>
|
||||||
|
<dd><p>Read information from a certificate</p>
|
||||||
|
</dd>
|
||||||
|
<dt><a href="#createCsr">createCsr</a> ⇒ <code>Promise.<Array.<buffer>></code></dt>
|
||||||
|
<dd><p>Create a Certificate Signing Request</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
## Functions
|
## Functions
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt><a href="#createPrivateKey">createPrivateKey([size])</a> ⇒ <code>Promise.<buffer></code></dt>
|
<dt><a href="#createPrivateKey">createPrivateKey([size])</a> ⇒ <code>Promise.<buffer></code></dt>
|
||||||
<dd><p>Generate a private RSA key</p>
|
<dd><p>Generate a private RSA key</p>
|
||||||
</dd>
|
</dd>
|
||||||
<dt><a href="#createPublicKey">createPublicKey(key)</a> ⇒ <code>Promise.<buffer></code></dt>
|
|
||||||
<dd><p>Create public key from a private RSA key</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#getPemBody">getPemBody(str)</a> ⇒ <code>string</code></dt>
|
|
||||||
<dd><p>Parse body of PEM encoded object from buffer or string
|
|
||||||
If multiple objects are chained, the first body will be returned</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#splitPemChain">splitPemChain(str)</a> ⇒ <code>Array.<string></code></dt>
|
|
||||||
<dd><p>Split chain of PEM encoded objects from buffer or string into array</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#getModulus">getModulus(input)</a> ⇒ <code>Promise.<buffer></code></dt>
|
|
||||||
<dd><p>Get modulus</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#getPublicExponent">getPublicExponent(input)</a> ⇒ <code>Promise.<buffer></code></dt>
|
|
||||||
<dd><p>Get public exponent</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#readCsrDomains">readCsrDomains(csr)</a> ⇒ <code>Promise.<object></code></dt>
|
|
||||||
<dd><p>Read domains from a Certificate Signing Request</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#readCertificateInfo">readCertificateInfo(cert)</a> ⇒ <code>Promise.<object></code></dt>
|
|
||||||
<dd><p>Read information from a certificate</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#createCsr">createCsr(data, [key])</a> ⇒ <code>Promise.<Array.<buffer>></code></dt>
|
|
||||||
<dd><p>Create a Certificate Signing Request</p>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<a name="forge"></a>
|
<a name="forge"></a>
|
||||||
@@ -50,34 +55,12 @@ DEPRECATION WARNING: This crypto interface is deprecated and will be removed fro
|
|||||||
major release. Please migrate to the new `acme.crypto` interface at your earliest convenience.
|
major release. Please migrate to the new `acme.crypto` interface at your earliest convenience.
|
||||||
|
|
||||||
**Kind**: global namespace
|
**Kind**: global namespace
|
||||||
<a name="createPrivateKey"></a>
|
|
||||||
|
|
||||||
## createPrivateKey([size]) ⇒ <code>Promise.<buffer></code>
|
|
||||||
Generate a private RSA key
|
|
||||||
|
|
||||||
**Kind**: global function
|
|
||||||
**Returns**: <code>Promise.<buffer></code> - PEM encoded private RSA key
|
|
||||||
|
|
||||||
| Param | Type | Default | Description |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| [size] | <code>number</code> | <code>2048</code> | Size of the key, default: `2048` |
|
|
||||||
|
|
||||||
**Example**
|
|
||||||
Generate private RSA key
|
|
||||||
```js
|
|
||||||
const privateKey = await acme.forge.createPrivateKey();
|
|
||||||
```
|
|
||||||
**Example**
|
|
||||||
Private RSA key with defined size
|
|
||||||
```js
|
|
||||||
const privateKey = await acme.forge.createPrivateKey(4096);
|
|
||||||
```
|
|
||||||
<a name="createPublicKey"></a>
|
<a name="createPublicKey"></a>
|
||||||
|
|
||||||
## createPublicKey(key) ⇒ <code>Promise.<buffer></code>
|
## createPublicKey ⇒ <code>Promise.<buffer></code>
|
||||||
Create public key from a private RSA key
|
Create public key from a private RSA key
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global constant
|
||||||
**Returns**: <code>Promise.<buffer></code> - PEM encoded public RSA key
|
**Returns**: <code>Promise.<buffer></code> - PEM encoded public RSA key
|
||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
@@ -91,11 +74,11 @@ const publicKey = await acme.forge.createPublicKey(privateKey);
|
|||||||
```
|
```
|
||||||
<a name="getPemBody"></a>
|
<a name="getPemBody"></a>
|
||||||
|
|
||||||
## getPemBody(str) ⇒ <code>string</code>
|
## getPemBody ⇒ <code>string</code>
|
||||||
Parse body of PEM encoded object from buffer or string
|
Parse body of PEM encoded object from buffer or string
|
||||||
If multiple objects are chained, the first body will be returned
|
If multiple objects are chained, the first body will be returned
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global constant
|
||||||
**Returns**: <code>string</code> - PEM body
|
**Returns**: <code>string</code> - PEM body
|
||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
@@ -104,10 +87,10 @@ If multiple objects are chained, the first body will be returned
|
|||||||
|
|
||||||
<a name="splitPemChain"></a>
|
<a name="splitPemChain"></a>
|
||||||
|
|
||||||
## splitPemChain(str) ⇒ <code>Array.<string></code>
|
## splitPemChain ⇒ <code>Array.<string></code>
|
||||||
Split chain of PEM encoded objects from buffer or string into array
|
Split chain of PEM encoded objects from buffer or string into array
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global constant
|
||||||
**Returns**: <code>Array.<string></code> - Array of PEM bodies
|
**Returns**: <code>Array.<string></code> - Array of PEM bodies
|
||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
@@ -116,10 +99,10 @@ Split chain of PEM encoded objects from buffer or string into array
|
|||||||
|
|
||||||
<a name="getModulus"></a>
|
<a name="getModulus"></a>
|
||||||
|
|
||||||
## getModulus(input) ⇒ <code>Promise.<buffer></code>
|
## getModulus ⇒ <code>Promise.<buffer></code>
|
||||||
Get modulus
|
Get modulus
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global constant
|
||||||
**Returns**: <code>Promise.<buffer></code> - Modulus
|
**Returns**: <code>Promise.<buffer></code> - Modulus
|
||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
@@ -135,10 +118,10 @@ const m3 = await acme.forge.getModulus(certificateRequest);
|
|||||||
```
|
```
|
||||||
<a name="getPublicExponent"></a>
|
<a name="getPublicExponent"></a>
|
||||||
|
|
||||||
## getPublicExponent(input) ⇒ <code>Promise.<buffer></code>
|
## getPublicExponent ⇒ <code>Promise.<buffer></code>
|
||||||
Get public exponent
|
Get public exponent
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global constant
|
||||||
**Returns**: <code>Promise.<buffer></code> - Exponent
|
**Returns**: <code>Promise.<buffer></code> - Exponent
|
||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
@@ -154,10 +137,10 @@ const e3 = await acme.forge.getPublicExponent(certificateRequest);
|
|||||||
```
|
```
|
||||||
<a name="readCsrDomains"></a>
|
<a name="readCsrDomains"></a>
|
||||||
|
|
||||||
## readCsrDomains(csr) ⇒ <code>Promise.<object></code>
|
## readCsrDomains ⇒ <code>Promise.<object></code>
|
||||||
Read domains from a Certificate Signing Request
|
Read domains from a Certificate Signing Request
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global constant
|
||||||
**Returns**: <code>Promise.<object></code> - {commonName, altNames}
|
**Returns**: <code>Promise.<object></code> - {commonName, altNames}
|
||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
@@ -174,10 +157,10 @@ console.log(`Alt names: ${altNames.join(', ')}`);
|
|||||||
```
|
```
|
||||||
<a name="readCertificateInfo"></a>
|
<a name="readCertificateInfo"></a>
|
||||||
|
|
||||||
## readCertificateInfo(cert) ⇒ <code>Promise.<object></code>
|
## readCertificateInfo ⇒ <code>Promise.<object></code>
|
||||||
Read information from a certificate
|
Read information from a certificate
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global constant
|
||||||
**Returns**: <code>Promise.<object></code> - Certificate info
|
**Returns**: <code>Promise.<object></code> - Certificate info
|
||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
@@ -198,10 +181,10 @@ console.log(`Alt names: ${altNames.join(', ')}`);
|
|||||||
```
|
```
|
||||||
<a name="createCsr"></a>
|
<a name="createCsr"></a>
|
||||||
|
|
||||||
## createCsr(data, [key]) ⇒ <code>Promise.<Array.<buffer>></code>
|
## createCsr ⇒ <code>Promise.<Array.<buffer>></code>
|
||||||
Create a Certificate Signing Request
|
Create a Certificate Signing Request
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global constant
|
||||||
**Returns**: <code>Promise.<Array.<buffer>></code> - [privateKey, certificateSigningRequest]
|
**Returns**: <code>Promise.<Array.<buffer>></code> - [privateKey, certificateSigningRequest]
|
||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
@@ -256,3 +239,25 @@ const certificateKey = await acme.forge.createPrivateKey();
|
|||||||
const [, certificateRequest] = await acme.forge.createCsr({
|
const [, certificateRequest] = await acme.forge.createCsr({
|
||||||
altNames: ['test.example.com'],
|
altNames: ['test.example.com'],
|
||||||
}, certificateKey);
|
}, certificateKey);
|
||||||
|
<a name="createPrivateKey"></a>
|
||||||
|
|
||||||
|
## createPrivateKey([size]) ⇒ <code>Promise.<buffer></code>
|
||||||
|
Generate a private RSA key
|
||||||
|
|
||||||
|
**Kind**: global function
|
||||||
|
**Returns**: <code>Promise.<buffer></code> - PEM encoded private RSA key
|
||||||
|
|
||||||
|
| Param | Type | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| [size] | <code>number</code> | Size of the key, default: `2048` |
|
||||||
|
|
||||||
|
**Example**
|
||||||
|
Generate private RSA key
|
||||||
|
```js
|
||||||
|
const privateKey = await acme.forge.createPrivateKey();
|
||||||
|
```
|
||||||
|
**Example**
|
||||||
|
Private RSA key with defined size
|
||||||
|
```js
|
||||||
|
const privateKey = await acme.forge.createPrivateKey(4096);
|
||||||
|
```
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
"description": "Simple and unopinionated ACME client",
|
"description": "Simple and unopinionated ACME client",
|
||||||
"private": false,
|
"private": false,
|
||||||
"author": "nmorsman",
|
"author": "nmorsman",
|
||||||
"version": "1.26.13",
|
"version": "1.29.3",
|
||||||
|
"type": "module",
|
||||||
|
"module": "scr/index.js",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"types": "types/index.d.ts",
|
"types": "types/index.d.ts",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -16,12 +18,14 @@
|
|||||||
"types"
|
"types"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@certd/basic": "^1.29.3",
|
||||||
"@peculiar/x509": "^1.11.0",
|
"@peculiar/x509": "^1.11.0",
|
||||||
"asn1js": "^3.0.5",
|
"asn1js": "^3.0.5",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"debug": "^4.3.5",
|
"debug": "^4.3.5",
|
||||||
"http-proxy-agent": "^7.0.2",
|
"http-proxy-agent": "^7.0.2",
|
||||||
"https-proxy-agent": "^7.0.5",
|
"https-proxy-agent": "^7.0.5",
|
||||||
|
"lodash-es": "^4.17.21",
|
||||||
"node-forge": "^1.3.1"
|
"node-forge": "^1.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -29,14 +33,15 @@
|
|||||||
"chai": "^4.4.1",
|
"chai": "^4.4.1",
|
||||||
"chai-as-promised": "^7.1.2",
|
"chai-as-promised": "^7.1.2",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-airbnb-base": "^15.0.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"jsdoc-to-markdown": "^8.0.1",
|
"jsdoc-to-markdown": "^8.0.1",
|
||||||
"mocha": "^10.6.0",
|
"mocha": "^10.6.0",
|
||||||
"nock": "^13.5.4",
|
"nock": "^13.5.4",
|
||||||
|
"prettier": "^2.8.8",
|
||||||
"tsd": "^0.31.1",
|
"tsd": "^0.31.1",
|
||||||
"typescript": "^5.4.2",
|
"typescript": "^5.4.2"
|
||||||
"uuid": "^8.3.2"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build-docs": "jsdoc2md src/client.js > docs/client.md && jsdoc2md src/crypto/index.js > docs/crypto.md && jsdoc2md src/crypto/forge.js > docs/forge.md",
|
"build-docs": "jsdoc2md src/client.js > docs/client.md && jsdoc2md src/crypto/index.js > docs/crypto.md && jsdoc2md src/crypto/forge.js > docs/forge.md",
|
||||||
@@ -60,5 +65,5 @@
|
|||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/publishlab/node-acme-client/issues"
|
"url": "https://github.com/publishlab/node-acme-client/issues"
|
||||||
},
|
},
|
||||||
"gitHead": "11d0daa59ae409c229037189066414f29b787de0"
|
"gitHead": "ed5634ff83405ad0eb13a8456f59270ed4218734"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,101 +0,0 @@
|
|||||||
const nodeHttp = require('node:http');
|
|
||||||
const https = require('node:https');
|
|
||||||
const { HttpProxyAgent } = require('http-proxy-agent');
|
|
||||||
const { HttpsProxyAgent } = require('https-proxy-agent');
|
|
||||||
const { log } = require('./logger');
|
|
||||||
|
|
||||||
function createAgent(opts = {}) {
|
|
||||||
let httpAgent;
|
|
||||||
let
|
|
||||||
httpsAgent;
|
|
||||||
const httpProxy = process.env.HTTP_PROXY || process.env.http_proxy;
|
|
||||||
if (httpProxy) {
|
|
||||||
log(`acme use httpProxy:${httpProxy}`);
|
|
||||||
httpAgent = new HttpProxyAgent(httpProxy, opts);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
httpAgent = new nodeHttp.Agent(opts);
|
|
||||||
}
|
|
||||||
const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy;
|
|
||||||
if (httpsProxy) {
|
|
||||||
log(`acme use httpsProxy:${httpsProxy}`);
|
|
||||||
httpsAgent = new HttpsProxyAgent(httpsProxy, opts);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
httpsAgent = new https.Agent(opts);
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
httpAgent,
|
|
||||||
httpsAgent,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let defaultAgents = createAgent();
|
|
||||||
|
|
||||||
function getGlobalAgents() {
|
|
||||||
return defaultAgents;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setGlobalProxy(opts) {
|
|
||||||
log('acme setGlobalProxy:', opts);
|
|
||||||
if (opts.httpProxy) {
|
|
||||||
process.env.HTTP_PROXY = opts.httpProxy;
|
|
||||||
}
|
|
||||||
if (opts.httpsProxy) {
|
|
||||||
process.env.HTTPS_PROXY = opts.httpsProxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultAgents = createAgent();
|
|
||||||
}
|
|
||||||
|
|
||||||
class HttpError extends Error {
|
|
||||||
constructor(error) {
|
|
||||||
super(error || error.message);
|
|
||||||
if (!error) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error.message.indexOf('ssl3_get_record:wrong version number') >= 0) {
|
|
||||||
this.message = 'http协议错误,服务端要求http协议,请检查是否使用了https请求';
|
|
||||||
}
|
|
||||||
|
|
||||||
this.name = error.name;
|
|
||||||
this.code = error.code;
|
|
||||||
this.cause = error.cause;
|
|
||||||
|
|
||||||
if (error.response) {
|
|
||||||
this.status = error.response.status;
|
|
||||||
this.statusText = error.response.statusText;
|
|
||||||
this.response = {
|
|
||||||
data: error.response.data,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let url = '';
|
|
||||||
if (error.config) {
|
|
||||||
this.request = {
|
|
||||||
baseURL: error.config.baseURL,
|
|
||||||
url: error.config.url,
|
|
||||||
method: error.config.method,
|
|
||||||
params: error.config.params,
|
|
||||||
data: error.config.data,
|
|
||||||
};
|
|
||||||
url = error.config.baseURL + error.config.url;
|
|
||||||
}
|
|
||||||
if (url) {
|
|
||||||
this.message = `${this.message}:${url}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete error.response;
|
|
||||||
delete error.config;
|
|
||||||
delete error.request;
|
|
||||||
// logger.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
setGlobalProxy,
|
|
||||||
createAgent,
|
|
||||||
getGlobalAgents,
|
|
||||||
HttpError,
|
|
||||||
};
|
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* ACME API client
|
* ACME API client
|
||||||
*/
|
*/
|
||||||
|
import * as util from './util.js';
|
||||||
const util = require('./util');
|
|
||||||
const { log } = require('./logger');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AcmeApi
|
* AcmeApi
|
||||||
@@ -248,4 +246,4 @@ class AcmeApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Export API */
|
/* Export API */
|
||||||
module.exports = AcmeApi;
|
export default AcmeApi;
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* ACME auto helper
|
* ACME auto helper
|
||||||
*/
|
*/
|
||||||
|
import { readCsrDomains } from './crypto/index.js';
|
||||||
|
import { log } from './logger.js';
|
||||||
|
import { wait } from './wait.js';
|
||||||
|
import { CancelError } from './error.js';
|
||||||
|
|
||||||
const { readCsrDomains } = require('./crypto');
|
|
||||||
const { log } = require('./logger');
|
|
||||||
const { wait } = require('./wait');
|
|
||||||
|
|
||||||
const defaultOpts = {
|
const defaultOpts = {
|
||||||
csr: null,
|
csr: null,
|
||||||
@@ -29,7 +30,7 @@ const defaultOpts = {
|
|||||||
* @returns {Promise<buffer>} Certificate
|
* @returns {Promise<buffer>} Certificate
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = async (client, userOpts) => {
|
export default async (client, userOpts) => {
|
||||||
const opts = { ...defaultOpts, ...userOpts };
|
const opts = { ...defaultOpts, ...userOpts };
|
||||||
const accountPayload = { termsOfServiceAgreed: opts.termsOfServiceAgreed };
|
const accountPayload = { termsOfServiceAgreed: opts.termsOfServiceAgreed };
|
||||||
|
|
||||||
@@ -98,31 +99,14 @@ module.exports = async (client, userOpts) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const keyAuthorizationGetter = async (challenge) => {
|
||||||
|
return await client.getChallengeKeyAuthorization(challenge);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
/* Select challenge based on priority */
|
|
||||||
const challenge = authz.challenges.sort((a, b) => {
|
|
||||||
const aidx = opts.challengePriority.indexOf(a.type);
|
|
||||||
const bidx = opts.challengePriority.indexOf(b.type);
|
|
||||||
|
|
||||||
if (aidx === -1) return 1;
|
|
||||||
if (bidx === -1) return -1;
|
|
||||||
return aidx - bidx;
|
|
||||||
}).slice(0, 1)[0];
|
|
||||||
|
|
||||||
if (!challenge) {
|
|
||||||
throw new Error(`Unable to select challenge for ${d}, no challenge found`);
|
|
||||||
}
|
|
||||||
|
|
||||||
log(`[auto] [${d}] Found ${authz.challenges.length} challenges, selected type: ${challenge.type}`);
|
|
||||||
|
|
||||||
/* Trigger challengeCreateFn() */
|
|
||||||
log(`[auto] [${d}] Trigger challengeCreateFn()`);
|
log(`[auto] [${d}] Trigger challengeCreateFn()`);
|
||||||
const keyAuthorization = await client.getChallengeKeyAuthorization(challenge);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { recordReq, recordRes, dnsProvider } = await opts.challengeCreateFn(authz, challenge, keyAuthorization);
|
const { recordReq, recordRes, dnsProvider,challenge ,keyAuthorization} = await opts.challengeCreateFn(authz, keyAuthorizationGetter);
|
||||||
log(`[auto] [${d}] challengeCreateFn success`);
|
|
||||||
log(`[auto] [${d}] add challengeRemoveFn()`);
|
|
||||||
clearTasks.push(async () => {
|
clearTasks.push(async () => {
|
||||||
/* Trigger challengeRemoveFn(), suppress errors */
|
/* Trigger challengeRemoveFn(), suppress errors */
|
||||||
log(`[auto] [${d}] Trigger challengeRemoveFn()`);
|
log(`[auto] [${d}] Trigger challengeRemoveFn()`);
|
||||||
@@ -140,7 +124,7 @@ module.exports = async (client, userOpts) => {
|
|||||||
await wait(60 * 1000);
|
await wait(60 * 1000);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log(`[auto] [${d}] Running challenge verification`);
|
log(`[auto] [${d}] Running challenge verification, type = ${challenge.type}`);
|
||||||
try {
|
try {
|
||||||
await client.verifyChallenge(authz, challenge);
|
await client.verifyChallenge(authz, challenge);
|
||||||
}
|
}
|
||||||
@@ -250,7 +234,7 @@ module.exports = async (client, userOpts) => {
|
|||||||
i += 1;
|
i += 1;
|
||||||
log(`开始第${i}组`);
|
log(`开始第${i}组`);
|
||||||
if (opts.signal && opts.signal.aborted) {
|
if (opts.signal && opts.signal.aborted) {
|
||||||
throw new Error('用户取消');
|
throw new CancelError('用户取消');
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* Axios instance
|
* Axios instance
|
||||||
*/
|
*/
|
||||||
const axios = require('axios');
|
import axios from 'axios';
|
||||||
const { parseRetryAfterHeader } = require('./util');
|
import { parseRetryAfterHeader } from './util.js';
|
||||||
const { log } = require('./logger');
|
import { log } from './logger.js';
|
||||||
const pkg = require('./../package.json');
|
|
||||||
const Agents = require('./agents');
|
|
||||||
|
|
||||||
const { AxiosError } = axios;
|
const { AxiosError } = axios;
|
||||||
|
import {getGlobalAgents, HttpError} from '@certd/basic'
|
||||||
/**
|
/**
|
||||||
* Defaults
|
* Defaults
|
||||||
*/
|
*/
|
||||||
@@ -16,7 +13,7 @@ const { AxiosError } = axios;
|
|||||||
const instance = axios.create();
|
const instance = axios.create();
|
||||||
|
|
||||||
/* Default User-Agent */
|
/* Default User-Agent */
|
||||||
instance.defaults.headers.common['User-Agent'] = `node-${pkg.name}/${pkg.version}`;
|
instance.defaults.headers.common['User-Agent'] = `@certd/acme-client`;
|
||||||
|
|
||||||
/* Default ACME settings */
|
/* Default ACME settings */
|
||||||
instance.defaults.acmeSettings = {
|
instance.defaults.acmeSettings = {
|
||||||
@@ -75,7 +72,7 @@ function validateStatus(response) {
|
|||||||
response,
|
response,
|
||||||
);
|
);
|
||||||
|
|
||||||
throw new Agents.HttpError(err);
|
throw new HttpError(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pass all responses through the error interceptor */
|
/* Pass all responses through the error interceptor */
|
||||||
@@ -85,7 +82,7 @@ instance.interceptors.request.use((config) => {
|
|||||||
}
|
}
|
||||||
config.validateStatus = () => false;
|
config.validateStatus = () => false;
|
||||||
|
|
||||||
const agents = Agents.getGlobalAgents();
|
const agents = getGlobalAgents();
|
||||||
// if (config.skipSslVerify) {
|
// if (config.skipSslVerify) {
|
||||||
// logger.info('跳过SSL验证');
|
// logger.info('跳过SSL验证');
|
||||||
// agents = createAgent({ rejectUnauthorized: false } as any);
|
// agents = createAgent({ rejectUnauthorized: false } as any);
|
||||||
@@ -102,7 +99,7 @@ instance.interceptors.response.use(null, async (error) => {
|
|||||||
const { config, response } = error;
|
const { config, response } = error;
|
||||||
|
|
||||||
if (!config) {
|
if (!config) {
|
||||||
return Promise.reject(new Agents.HttpError(error));
|
return Promise.reject(new HttpError(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pick up errors we want to retry */
|
/* Pick up errors we want to retry */
|
||||||
@@ -114,17 +111,19 @@ instance.interceptors.response.use(null, async (error) => {
|
|||||||
const code = response ? `HTTP ${response.status}` : error.code;
|
const code = response ? `HTTP ${response.status}` : error.code;
|
||||||
log(`Caught ${code}, retry attempt ${config.retryAttempt}/${retryMaxAttempts} to URL ${config.url}`);
|
log(`Caught ${code}, retry attempt ${config.retryAttempt}/${retryMaxAttempts} to URL ${config.url}`);
|
||||||
|
|
||||||
|
const retryAfter = (retryDefaultDelay * config.retryAttempt);
|
||||||
/* Attempt to parse Retry-After header, fallback to default delay */
|
/* Attempt to parse Retry-After header, fallback to default delay */
|
||||||
let retryAfter = response ? parseRetryAfterHeader(response.headers['retry-after']) : 0;
|
const headerRetryAfter = response ? parseRetryAfterHeader(response.headers['retry-after']) : 0;
|
||||||
|
|
||||||
if (retryAfter > 0) {
|
if (headerRetryAfter > 0) {
|
||||||
log(`Found retry-after response header with value: ${response.headers['retry-after']}, waiting ${retryAfter} seconds`);
|
const waitMinutes = (headerRetryAfter / 60).toFixed(1);
|
||||||
}
|
log(`Found retry-after response header with value: ${response.headers['retry-after']}, waiting ${waitMinutes} minutes`);
|
||||||
else {
|
log(JSON.stringify(response.data));
|
||||||
retryAfter = (retryDefaultDelay * config.retryAttempt);
|
return Promise.reject(new HttpError(error));
|
||||||
log(`Unable to locate or parse retry-after response header, waiting ${retryAfter} seconds`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log(`waiting ${retryAfter} seconds`);
|
||||||
|
|
||||||
/* Wait and retry the request */
|
/* Wait and retry the request */
|
||||||
await new Promise((resolve) => { setTimeout(resolve, (retryAfter * 1000)); });
|
await new Promise((resolve) => { setTimeout(resolve, (retryAfter * 1000)); });
|
||||||
return instance(config);
|
return instance(config);
|
||||||
@@ -132,7 +131,7 @@ instance.interceptors.response.use(null, async (error) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!response) {
|
if (!response) {
|
||||||
return Promise.reject(new Agents.HttpError(error));
|
return Promise.reject(new HttpError(error));
|
||||||
}
|
}
|
||||||
/* Validate and return response */
|
/* Validate and return response */
|
||||||
return validateStatus(response);
|
return validateStatus(response);
|
||||||
@@ -142,4 +141,4 @@ instance.interceptors.response.use(null, async (error) => {
|
|||||||
* Export instance
|
* Export instance
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = instance;
|
export default instance;
|
||||||
|
|||||||
@@ -3,15 +3,17 @@
|
|||||||
*
|
*
|
||||||
* @namespace Client
|
* @namespace Client
|
||||||
*/
|
*/
|
||||||
|
import { createHash } from 'crypto';
|
||||||
|
import { getPemBodyAsB64u } from './crypto/index.js';
|
||||||
|
import { log } from './logger.js';
|
||||||
|
import HttpClient from './http.js';
|
||||||
|
import AcmeApi from './api.js';
|
||||||
|
import verify from './verify.js';
|
||||||
|
import * as util from './util.js';
|
||||||
|
import auto from './auto.js';
|
||||||
|
import { CancelError } from './error.js';
|
||||||
|
|
||||||
|
|
||||||
const { createHash } = require('crypto');
|
|
||||||
const { getPemBodyAsB64u } = require('./crypto');
|
|
||||||
const { log } = require('./logger');
|
|
||||||
const HttpClient = require('./http');
|
|
||||||
const AcmeApi = require('./api');
|
|
||||||
const verify = require('./verify');
|
|
||||||
const util = require('./util');
|
|
||||||
const auto = require('./auto');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ACME states
|
* ACME states
|
||||||
@@ -490,9 +492,10 @@ class AcmeClient {
|
|||||||
|
|
||||||
const keyAuthorization = await this.getChallengeKeyAuthorization(challenge);
|
const keyAuthorization = await this.getChallengeKeyAuthorization(challenge);
|
||||||
|
|
||||||
const verifyFn = async () => {
|
const verifyFn = async (abort) => {
|
||||||
if (this.opts.signal && this.opts.signal.aborted) {
|
if (this.opts.signal && this.opts.signal.aborted) {
|
||||||
throw new Error('用户取消');
|
abort();
|
||||||
|
throw new CancelError('用户取消');
|
||||||
}
|
}
|
||||||
await verify[challenge.type](authz, challenge, keyAuthorization);
|
await verify[challenge.type](authz, challenge, keyAuthorization);
|
||||||
};
|
};
|
||||||
@@ -518,7 +521,7 @@ class AcmeClient {
|
|||||||
|
|
||||||
async completeChallenge(challenge) {
|
async completeChallenge(challenge) {
|
||||||
if (this.opts.signal && this.opts.signal.aborted) {
|
if (this.opts.signal && this.opts.signal.aborted) {
|
||||||
throw new Error('用户取消');
|
throw new CancelError('用户取消');
|
||||||
}
|
}
|
||||||
const resp = await this.api.completeChallenge(challenge.url, {});
|
const resp = await this.api.completeChallenge(challenge.url, {});
|
||||||
return resp.data;
|
return resp.data;
|
||||||
@@ -559,7 +562,7 @@ class AcmeClient {
|
|||||||
const verifyFn = async (abort) => {
|
const verifyFn = async (abort) => {
|
||||||
if (this.opts.signal && this.opts.signal.aborted) {
|
if (this.opts.signal && this.opts.signal.aborted) {
|
||||||
abort();
|
abort();
|
||||||
throw new Error('用户取消');
|
throw new CancelError('用户取消');
|
||||||
}
|
}
|
||||||
|
|
||||||
const resp = await this.api.apiRequest(item.url, null, [200]);
|
const resp = await this.api.apiRequest(item.url, null, [200]);
|
||||||
@@ -717,4 +720,4 @@ class AcmeClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Export client */
|
/* Export client */
|
||||||
module.exports = AcmeClient;
|
export default AcmeClient;
|
||||||
|
|||||||
@@ -6,11 +6,10 @@
|
|||||||
*
|
*
|
||||||
* @namespace forge
|
* @namespace forge
|
||||||
*/
|
*/
|
||||||
|
import net from 'net';
|
||||||
const net = require('net');
|
import { promisify } from 'util';
|
||||||
const { promisify } = require('util');
|
import forge from 'node-forge';
|
||||||
const forge = require('node-forge');
|
import { createPrivateEcdsaKey } from './index.js';
|
||||||
const { createPrivateEcdsaKey, getPublicKey } = require('./index');
|
|
||||||
|
|
||||||
const generateKeyPair = promisify(forge.pki.rsa.generateKeyPair);
|
const generateKeyPair = promisify(forge.pki.rsa.generateKeyPair);
|
||||||
|
|
||||||
@@ -113,13 +112,12 @@ function parseDomains(obj) {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
async function createPrivateKey(size = 2048) {
|
export async function createPrivateKey(size = 2048) {
|
||||||
const keyPair = await generateKeyPair({ bits: size });
|
const keyPair = await generateKeyPair({ bits: size });
|
||||||
const pemKey = forge.pki.privateKeyToPem(keyPair.privateKey);
|
const pemKey = forge.pki.privateKeyToPem(keyPair.privateKey);
|
||||||
return Buffer.from(pemKey);
|
return Buffer.from(pemKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.createPrivateKey = createPrivateKey;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create public key from a private RSA key
|
* Create public key from a private RSA key
|
||||||
@@ -133,7 +131,7 @@ exports.createPrivateKey = createPrivateKey;
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.createPublicKey = async (key) => {
|
export const createPublicKey = async (key) => {
|
||||||
const privateKey = forge.pki.privateKeyFromPem(key);
|
const privateKey = forge.pki.privateKeyFromPem(key);
|
||||||
const publicKey = forge.pki.rsa.setPublicKey(privateKey.n, privateKey.e);
|
const publicKey = forge.pki.rsa.setPublicKey(privateKey.n, privateKey.e);
|
||||||
const pemKey = forge.pki.publicKeyToPem(publicKey);
|
const pemKey = forge.pki.publicKeyToPem(publicKey);
|
||||||
@@ -148,7 +146,7 @@ exports.createPublicKey = async (key) => {
|
|||||||
* @returns {string} PEM body
|
* @returns {string} PEM body
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.getPemBody = (str) => {
|
export const getPemBody = (str) => {
|
||||||
const msg = forge.pem.decode(str)[0];
|
const msg = forge.pem.decode(str)[0];
|
||||||
return forge.util.encode64(msg.body);
|
return forge.util.encode64(msg.body);
|
||||||
};
|
};
|
||||||
@@ -160,7 +158,7 @@ exports.getPemBody = (str) => {
|
|||||||
* @returns {string[]} Array of PEM bodies
|
* @returns {string[]} Array of PEM bodies
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.splitPemChain = (str) => forge.pem.decode(str).map(forge.pem.encode);
|
export const splitPemChain = (str) => forge.pem.decode(str).map(forge.pem.encode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get modulus
|
* Get modulus
|
||||||
@@ -176,7 +174,7 @@ exports.splitPemChain = (str) => forge.pem.decode(str).map(forge.pem.encode);
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.getModulus = async (input) => {
|
export const getModulus = async (input) => {
|
||||||
if (!Buffer.isBuffer(input)) {
|
if (!Buffer.isBuffer(input)) {
|
||||||
input = Buffer.from(input);
|
input = Buffer.from(input);
|
||||||
}
|
}
|
||||||
@@ -199,7 +197,7 @@ exports.getModulus = async (input) => {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.getPublicExponent = async (input) => {
|
export const getPublicExponent = async (input) => {
|
||||||
if (!Buffer.isBuffer(input)) {
|
if (!Buffer.isBuffer(input)) {
|
||||||
input = Buffer.from(input);
|
input = Buffer.from(input);
|
||||||
}
|
}
|
||||||
@@ -223,7 +221,7 @@ exports.getPublicExponent = async (input) => {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.readCsrDomains = async (csr) => {
|
export const readCsrDomains = async (csr) => {
|
||||||
if (!Buffer.isBuffer(csr)) {
|
if (!Buffer.isBuffer(csr)) {
|
||||||
csr = Buffer.from(csr);
|
csr = Buffer.from(csr);
|
||||||
}
|
}
|
||||||
@@ -251,7 +249,7 @@ exports.readCsrDomains = async (csr) => {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.readCertificateInfo = async (cert) => {
|
export const readCertificateInfo = async (cert) => {
|
||||||
if (!Buffer.isBuffer(cert)) {
|
if (!Buffer.isBuffer(cert)) {
|
||||||
cert = Buffer.from(cert);
|
cert = Buffer.from(cert);
|
||||||
}
|
}
|
||||||
@@ -379,7 +377,7 @@ function formatCsrAltNames(altNames) {
|
|||||||
* }, certificateKey);
|
* }, certificateKey);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.createCsr = async (data, keyType = null) => {
|
export const createCsr = async (data, keyType = null) => {
|
||||||
let key = null;
|
let key = null;
|
||||||
if (keyType === 'ec') {
|
if (keyType === 'ec') {
|
||||||
key = await createPrivateEcdsaKey();
|
key = await createPrivateEcdsaKey();
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
*
|
*
|
||||||
* @namespace crypto
|
* @namespace crypto
|
||||||
*/
|
*/
|
||||||
|
import net from 'net';
|
||||||
|
import { promisify } from 'util';
|
||||||
|
import crypto from 'crypto';
|
||||||
|
import asn1js from 'asn1js';
|
||||||
|
import x509 from '@peculiar/x509';
|
||||||
|
|
||||||
const net = require('net');
|
|
||||||
const { promisify } = require('util');
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const asn1js = require('asn1js');
|
|
||||||
const x509 = require('@peculiar/x509');
|
|
||||||
|
|
||||||
const randomInt = promisify(crypto.randomInt);
|
const randomInt = promisify(crypto.randomInt);
|
||||||
const generateKeyPair = promisify(crypto.generateKeyPair);
|
const generateKeyPair = promisify(crypto.generateKeyPair);
|
||||||
@@ -67,7 +67,7 @@ function getKeyInfo(keyPem) {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
async function createPrivateRsaKey(modulusLength = 2048, encodingType = 'pkcs8') {
|
export async function createPrivateRsaKey(modulusLength = 2048, encodingType = 'pkcs8') {
|
||||||
const pair = await generateKeyPair('rsa', {
|
const pair = await generateKeyPair('rsa', {
|
||||||
modulusLength,
|
modulusLength,
|
||||||
privateKeyEncoding: {
|
privateKeyEncoding: {
|
||||||
@@ -79,7 +79,6 @@ async function createPrivateRsaKey(modulusLength = 2048, encodingType = 'pkcs8')
|
|||||||
return Buffer.from(pair.privateKey);
|
return Buffer.from(pair.privateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.createPrivateRsaKey = createPrivateRsaKey;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alias of `createPrivateRsaKey()`
|
* Alias of `createPrivateRsaKey()`
|
||||||
@@ -87,7 +86,7 @@ exports.createPrivateRsaKey = createPrivateRsaKey;
|
|||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.createPrivateKey = createPrivateRsaKey;
|
export const createPrivateKey = createPrivateRsaKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a private ECDSA key
|
* Generate a private ECDSA key
|
||||||
@@ -106,7 +105,7 @@ exports.createPrivateKey = createPrivateRsaKey;
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.createPrivateEcdsaKey = async (namedCurve = 'P-256', encodingType = 'pkcs8') => {
|
export const createPrivateEcdsaKey = async (namedCurve = 'P-256', encodingType = 'pkcs8') => {
|
||||||
const pair = await generateKeyPair('ec', {
|
const pair = await generateKeyPair('ec', {
|
||||||
namedCurve,
|
namedCurve,
|
||||||
privateKeyEncoding: {
|
privateKeyEncoding: {
|
||||||
@@ -130,7 +129,7 @@ exports.createPrivateEcdsaKey = async (namedCurve = 'P-256', encodingType = 'pkc
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.getPublicKey = (keyPem) => {
|
export const getPublicKey = (keyPem) => {
|
||||||
const info = getKeyInfo(keyPem);
|
const info = getKeyInfo(keyPem);
|
||||||
|
|
||||||
const publicKey = info.publicKey.export({
|
const publicKey = info.publicKey.export({
|
||||||
@@ -155,7 +154,7 @@ exports.getPublicKey = (keyPem) => {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function getJwk(keyPem) {
|
export function getJwk(keyPem) {
|
||||||
const jwk = crypto.createPublicKey(keyPem).export({
|
const jwk = crypto.createPublicKey(keyPem).export({
|
||||||
format: 'jwk',
|
format: 'jwk',
|
||||||
});
|
});
|
||||||
@@ -167,7 +166,6 @@ function getJwk(keyPem) {
|
|||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getJwk = getJwk;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce CryptoKeyPair and signing algorithm from a PEM encoded private key
|
* Produce CryptoKeyPair and signing algorithm from a PEM encoded private key
|
||||||
@@ -215,7 +213,7 @@ async function getWebCryptoKeyPair(keyPem) {
|
|||||||
* @returns {string[]} Array of PEM objects including headers
|
* @returns {string[]} Array of PEM objects including headers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function splitPemChain(chainPem) {
|
export function splitPemChain(chainPem) {
|
||||||
if (Buffer.isBuffer(chainPem)) {
|
if (Buffer.isBuffer(chainPem)) {
|
||||||
chainPem = chainPem.toString();
|
chainPem = chainPem.toString();
|
||||||
}
|
}
|
||||||
@@ -225,7 +223,6 @@ function splitPemChain(chainPem) {
|
|||||||
.map((params) => x509.PemConverter.encode([params]));
|
.map((params) => x509.PemConverter.encode([params]));
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.splitPemChain = splitPemChain;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse body of PEM encoded object and return a Base64URL string
|
* Parse body of PEM encoded object and return a Base64URL string
|
||||||
@@ -235,7 +232,7 @@ exports.splitPemChain = splitPemChain;
|
|||||||
* @returns {string} Base64URL-encoded body
|
* @returns {string} Base64URL-encoded body
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.getPemBodyAsB64u = (pem) => {
|
export const getPemBodyAsB64u = (pem) => {
|
||||||
const chain = splitPemChain(pem);
|
const chain = splitPemChain(pem);
|
||||||
|
|
||||||
if (!chain.length) {
|
if (!chain.length) {
|
||||||
@@ -286,7 +283,7 @@ function parseDomains(input) {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.readCsrDomains = (csrPem) => {
|
export const readCsrDomains = (csrPem) => {
|
||||||
if (Buffer.isBuffer(csrPem)) {
|
if (Buffer.isBuffer(csrPem)) {
|
||||||
csrPem = csrPem.toString();
|
csrPem = csrPem.toString();
|
||||||
}
|
}
|
||||||
@@ -315,7 +312,7 @@ exports.readCsrDomains = (csrPem) => {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.readCertificateInfo = (certPem) => {
|
export const readCertificateInfo = (certPem) => {
|
||||||
if (Buffer.isBuffer(certPem)) {
|
if (Buffer.isBuffer(certPem)) {
|
||||||
certPem = certPem.toString();
|
certPem = certPem.toString();
|
||||||
}
|
}
|
||||||
@@ -449,7 +446,7 @@ function createSubjectAltNameExtension(altNames) {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.createCsr = async (data, keyPem = null) => {
|
export const createCsr = async (data, keyPem = null) => {
|
||||||
if (!keyPem) {
|
if (!keyPem) {
|
||||||
keyPem = await createPrivateRsaKey(data.keySize);
|
keyPem = await createPrivateRsaKey(data.keySize);
|
||||||
}
|
}
|
||||||
@@ -520,7 +517,7 @@ exports.createCsr = async (data, keyPem = null) => {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.createAlpnCertificate = async (authz, keyAuthorization, keyPem = null) => {
|
export const createAlpnCertificate = async (authz, keyAuthorization, keyPem = null) => {
|
||||||
if (!keyPem) {
|
if (!keyPem) {
|
||||||
keyPem = await createPrivateRsaKey();
|
keyPem = await createPrivateRsaKey();
|
||||||
}
|
}
|
||||||
@@ -583,7 +580,7 @@ exports.createAlpnCertificate = async (authz, keyAuthorization, keyPem = null) =
|
|||||||
* @returns {boolean} True when valid
|
* @returns {boolean} True when valid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.isAlpnCertificateAuthorizationValid = (certPem, keyAuthorization) => {
|
export const isAlpnCertificateAuthorizationValid = (certPem, keyAuthorization) => {
|
||||||
const expected = crypto.createHash('sha256').update(keyAuthorization).digest('hex');
|
const expected = crypto.createHash('sha256').update(keyAuthorization).digest('hex');
|
||||||
|
|
||||||
/* Attempt to locate ALPN extension */
|
/* Attempt to locate ALPN extension */
|
||||||
|
|||||||
9
packages/core/acme-client/src/error.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export class CancelError extends Error {
|
||||||
|
constructor(message) {
|
||||||
|
super(message);
|
||||||
|
this.name = 'CancelError';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* ACME HTTP client
|
* ACME HTTP client
|
||||||
*/
|
*/
|
||||||
|
import { createHmac, createSign, constants } from 'crypto';
|
||||||
const { createHmac, createSign, constants: { RSA_PKCS1_PADDING } } = require('crypto');
|
const { RSA_PKCS1_PADDING } = constants;
|
||||||
const { getJwk } = require('./crypto');
|
import axios from './axios.js';
|
||||||
const { log } = require('./logger');
|
import { log } from './logger.js';
|
||||||
const axios = require('./axios');
|
import { getJwk } from './crypto/index.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ACME HTTP client
|
* ACME HTTP client
|
||||||
@@ -324,4 +324,4 @@ class HttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Export client */
|
/* Export client */
|
||||||
module.exports = HttpClient;
|
export default HttpClient;
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
/**
|
/**
|
||||||
* acme-client
|
* acme-client
|
||||||
*/
|
*/
|
||||||
|
import AcmeClinet from './client.js'
|
||||||
exports.Client = require('./client');
|
export const Client = AcmeClinet
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Directory URLs
|
* Directory URLs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.directory = {
|
export const directory = {
|
||||||
buypass: {
|
buypass: {
|
||||||
staging: 'https://api.test4.buypass.no/acme/directory',
|
staging: 'https://api.test4.buypass.no/acme/directory',
|
||||||
production: 'https://api.buypass.com/acme/directory',
|
production: 'https://api.buypass.com/acme/directory',
|
||||||
@@ -31,20 +31,18 @@ exports.directory = {
|
|||||||
* Crypto
|
* Crypto
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.crypto = require('./crypto');
|
export * as crypto from './crypto/index.js'
|
||||||
exports.forge = require('./crypto/forge');
|
export * as forge from './crypto/forge.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Axios
|
* Axios
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.axios = require('./axios');
|
export * from './axios.js'
|
||||||
exports.agents = require('./agents');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logger
|
* Logger
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.setLogger = require('./logger').setLogger;
|
export * from './logger.js'
|
||||||
|
export * from './verify.js'
|
||||||
exports.walkTxtRecord = require('./verify').walkTxtRecord;
|
export * from './error.js'
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
* ACME logger
|
* ACME logger
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const debug = require('debug')('acme-client');
|
import debugg from 'debug'
|
||||||
|
const debug = debugg('acme-client');
|
||||||
|
|
||||||
let logger = () => {};
|
let logger = () => {};
|
||||||
|
|
||||||
@@ -12,7 +13,7 @@ let logger = () => {};
|
|||||||
* @param {function} fn Logger function
|
* @param {function} fn Logger function
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.setLogger = (fn) => {
|
export const setLogger = (fn) => {
|
||||||
logger = fn;
|
logger = fn;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ exports.setLogger = (fn) => {
|
|||||||
* @param {string} msg Message
|
* @param {string} msg Message
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.log = (...msg) => {
|
export const log = (...msg) => {
|
||||||
debug(...msg);
|
debug(...msg);
|
||||||
logger(...msg);
|
logger(...msg);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
* Utility methods
|
* Utility methods
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const tls = require('tls');
|
import tls from 'tls';
|
||||||
const dns = require('dns').promises;
|
import dnsSdk from 'dns';
|
||||||
const { readCertificateInfo, splitPemChain } = require('./crypto');
|
import { readCertificateInfo, splitPemChain }from './crypto/index.js'
|
||||||
const { log } = require('./logger');
|
import { log } from './logger.js'
|
||||||
|
|
||||||
|
const dns = dnsSdk.promises;
|
||||||
/**
|
/**
|
||||||
* Exponential backoff
|
* Exponential backoff
|
||||||
*
|
*
|
||||||
@@ -329,7 +330,7 @@ async function retrieveTlsAlpnCertificate(host, port, timeout = 30000) {
|
|||||||
* Export utils
|
* Export utils
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = {
|
export {
|
||||||
retry,
|
retry,
|
||||||
parseLinkHeader,
|
parseLinkHeader,
|
||||||
parseRetryAfterHeader,
|
parseRetryAfterHeader,
|
||||||
@@ -338,3 +339,4 @@ module.exports = {
|
|||||||
getAuthoritativeDnsResolver,
|
getAuthoritativeDnsResolver,
|
||||||
retrieveTlsAlpnCertificate,
|
retrieveTlsAlpnCertificate,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,15 @@
|
|||||||
* ACME challenge verification
|
* ACME challenge verification
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const dns = require('dns').promises;
|
import dnsSdk from "dns"
|
||||||
const https = require('https');
|
import https from 'https'
|
||||||
const { log } = require('./logger');
|
import {log} from './logger.js'
|
||||||
const axios = require('./axios');
|
import axios from './axios.js'
|
||||||
const util = require('./util');
|
import * as util from './util.js'
|
||||||
const { isAlpnCertificateAuthorizationValid } = require('./crypto');
|
import {isAlpnCertificateAuthorizationValid} from './crypto/index.js'
|
||||||
|
|
||||||
|
|
||||||
|
const dns = dnsSdk.promises
|
||||||
/**
|
/**
|
||||||
* Verify ACME HTTP challenge
|
* Verify ACME HTTP challenge
|
||||||
*
|
*
|
||||||
@@ -79,7 +81,7 @@ async function walkDnsChallengeRecord(recordName, resolver = dns) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function walkTxtRecord(recordName) {
|
export async function walkTxtRecord(recordName) {
|
||||||
try {
|
try {
|
||||||
/* Default DNS resolver first */
|
/* Default DNS resolver first */
|
||||||
log('Attempting to resolve TXT with default DNS resolver first');
|
log('Attempting to resolve TXT with default DNS resolver first');
|
||||||
@@ -153,9 +155,8 @@ async function verifyTlsAlpnChallenge(authz, challenge, keyAuthorization) {
|
|||||||
* Export API
|
* Export API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = {
|
export default {
|
||||||
'http-01': verifyHttpChallenge,
|
'http-01': verifyHttpChallenge,
|
||||||
'dns-01': verifyDnsChallenge,
|
'dns-01': verifyDnsChallenge,
|
||||||
'tls-alpn-01': verifyTlsAlpnChallenge,
|
'tls-alpn-01': verifyTlsAlpnChallenge,
|
||||||
walkTxtRecord,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
async function wait(ms) {
|
export async function wait(ms) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
setTimeout(resolve, ms);
|
setTimeout(resolve, ms);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
wait
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"compileOnSave": false,
|
|
||||||
"compilerOptions": {
|
|
||||||
"module": "commonjs",
|
|
||||||
"lib": ["es6"],
|
|
||||||
"strict": true,
|
|
||||||
"noEmit": false,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"baseUrl": ".",
|
|
||||||
"composite": true,
|
|
||||||
"paths": { "acme-client": ["."] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
8
packages/core/acme-client/types/index.d.ts
vendored
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
import { AxiosInstance } from 'axios';
|
import { AxiosInstance } from 'axios';
|
||||||
import * as rfc8555 from './rfc8555';
|
import * as rfc8555 from './rfc8555';
|
||||||
|
import {CancelError} from '../src/error.js'
|
||||||
|
export * from '../src/error.js'
|
||||||
|
|
||||||
export type PrivateKeyBuffer = Buffer;
|
export type PrivateKeyBuffer = Buffer;
|
||||||
export type PublicKeyBuffer = Buffer;
|
export type PublicKeyBuffer = Buffer;
|
||||||
@@ -56,7 +58,7 @@ export interface ClientExternalAccountBindingOptions {
|
|||||||
|
|
||||||
export interface ClientAutoOptions {
|
export interface ClientAutoOptions {
|
||||||
csr: CsrBuffer | CsrString;
|
csr: CsrBuffer | CsrString;
|
||||||
challengeCreateFn: (authz: Authorization, challenge: rfc8555.Challenge, keyAuthorization: string) => Promise<{recordReq:any,recordRes:any,dnsProvider:any}>;
|
challengeCreateFn: (authz: Authorization, keyAuthorization: (challenge:rfc8555.Challenge)=>Promise<string>) => Promise<{recordReq?:any,recordRes?:any,dnsProvider?:any,challenge: rfc8555.Challenge,keyAuthorization:string}>;
|
||||||
challengeRemoveFn: (authz: Authorization, challenge: rfc8555.Challenge, keyAuthorization: string,recordReq:any, recordRes:any,dnsProvider:any) => Promise<any>;
|
challengeRemoveFn: (authz: Authorization, challenge: rfc8555.Challenge, keyAuthorization: string,recordReq:any, recordRes:any,dnsProvider:any) => Promise<any>;
|
||||||
email?: string;
|
email?: string;
|
||||||
termsOfServiceAgreed?: boolean;
|
termsOfServiceAgreed?: boolean;
|
||||||
@@ -198,6 +200,8 @@ export const agents: any;
|
|||||||
* Logger
|
* Logger
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function setLogger(fn: (msg: string) => void): void;
|
export function setLogger(fn: (message: any, ...args: any[]) => void): void;
|
||||||
|
|
||||||
export function walkTxtRecord(record: any): Promise<string[]>;
|
export function walkTxtRecord(record: any): Promise<string[]>;
|
||||||
|
|
||||||
|
export const CancelError: typeof CancelError;
|
||||||
137
packages/core/acme-client/types/index.test-d.js
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
"use strict";
|
||||||
|
/**
|
||||||
|
* acme-client type definition tests
|
||||||
|
*/
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||||
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||||
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||||
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||||
|
function step(op) {
|
||||||
|
if (f) throw new TypeError("Generator is already executing.");
|
||||||
|
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
||||||
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||||
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||||
|
switch (op[0]) {
|
||||||
|
case 0: case 1: t = op; break;
|
||||||
|
case 4: _.label++; return { value: op[1], done: false };
|
||||||
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||||
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||||
|
default:
|
||||||
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||||
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||||
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||||
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||||
|
if (t[2]) _.ops.pop();
|
||||||
|
_.trys.pop(); continue;
|
||||||
|
}
|
||||||
|
op = body.call(thisArg, _);
|
||||||
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||||
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
var acme = require("acme-client");
|
||||||
|
(function () { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var accountKey, client, order, authorizations, authorization, challenge, _a, certKey, certCsr;
|
||||||
|
return __generator(this, function (_b) {
|
||||||
|
switch (_b.label) {
|
||||||
|
case 0: return [4 /*yield*/, acme.crypto.createPrivateKey()];
|
||||||
|
case 1:
|
||||||
|
accountKey = _b.sent();
|
||||||
|
client = new acme.Client({
|
||||||
|
accountKey: accountKey,
|
||||||
|
directoryUrl: acme.directory.letsencrypt.staging
|
||||||
|
});
|
||||||
|
/* Account */
|
||||||
|
return [4 /*yield*/, client.createAccount({
|
||||||
|
termsOfServiceAgreed: true,
|
||||||
|
contact: ['mailto:test@example.com']
|
||||||
|
})];
|
||||||
|
case 2:
|
||||||
|
/* Account */
|
||||||
|
_b.sent();
|
||||||
|
return [4 /*yield*/, client.createOrder({
|
||||||
|
identifiers: [
|
||||||
|
{ type: 'dns', value: 'example.com' },
|
||||||
|
{ type: 'dns', value: '*.example.com' },
|
||||||
|
]
|
||||||
|
})];
|
||||||
|
case 3:
|
||||||
|
order = _b.sent();
|
||||||
|
return [4 /*yield*/, client.getOrder(order)];
|
||||||
|
case 4:
|
||||||
|
_b.sent();
|
||||||
|
return [4 /*yield*/, client.getAuthorizations(order)];
|
||||||
|
case 5:
|
||||||
|
authorizations = _b.sent();
|
||||||
|
authorization = authorizations[0];
|
||||||
|
challenge = authorization.challenges[0];
|
||||||
|
return [4 /*yield*/, client.getChallengeKeyAuthorization(challenge)];
|
||||||
|
case 6:
|
||||||
|
_b.sent();
|
||||||
|
return [4 /*yield*/, client.verifyChallenge(authorization, challenge)];
|
||||||
|
case 7:
|
||||||
|
_b.sent();
|
||||||
|
return [4 /*yield*/, client.completeChallenge(challenge)];
|
||||||
|
case 8:
|
||||||
|
_b.sent();
|
||||||
|
return [4 /*yield*/, client.waitForValidStatus(challenge)];
|
||||||
|
case 9:
|
||||||
|
_b.sent();
|
||||||
|
return [4 /*yield*/, acme.crypto.createCsr({
|
||||||
|
commonName: 'example.com',
|
||||||
|
altNames: ['example.com', '*.example.com']
|
||||||
|
})];
|
||||||
|
case 10:
|
||||||
|
_a = _b.sent(), certKey = _a[0], certCsr = _a[1];
|
||||||
|
return [4 /*yield*/, client.finalizeOrder(order, certCsr)];
|
||||||
|
case 11:
|
||||||
|
_b.sent();
|
||||||
|
return [4 /*yield*/, client.getCertificate(order)];
|
||||||
|
case 12:
|
||||||
|
_b.sent();
|
||||||
|
return [4 /*yield*/, client.getCertificate(order, 'DST Root CA X3')];
|
||||||
|
case 13:
|
||||||
|
_b.sent();
|
||||||
|
/* Auto */
|
||||||
|
return [4 /*yield*/, client.auto({
|
||||||
|
csr: certCsr,
|
||||||
|
challengeCreateFn: function (authz, challenge, keyAuthorization) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
||||||
|
return [2 /*return*/];
|
||||||
|
}); }); },
|
||||||
|
challengeRemoveFn: function (authz, challenge, keyAuthorization) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
||||||
|
return [2 /*return*/];
|
||||||
|
}); }); }
|
||||||
|
})];
|
||||||
|
case 14:
|
||||||
|
/* Auto */
|
||||||
|
_b.sent();
|
||||||
|
return [4 /*yield*/, client.auto({
|
||||||
|
csr: certCsr,
|
||||||
|
email: 'test@example.com',
|
||||||
|
termsOfServiceAgreed: false,
|
||||||
|
skipChallengeVerification: false,
|
||||||
|
challengePriority: ['http-01', 'dns-01'],
|
||||||
|
preferredChain: 'DST Root CA X3',
|
||||||
|
challengeCreateFn: function (authz, challenge, keyAuthorization) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
||||||
|
return [2 /*return*/];
|
||||||
|
}); }); },
|
||||||
|
challengeRemoveFn: function (authz, challenge, keyAuthorization) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
||||||
|
return [2 /*return*/];
|
||||||
|
}); }); }
|
||||||
|
})];
|
||||||
|
case 15:
|
||||||
|
_b.sent();
|
||||||
|
return [2 /*return*/];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}); })();
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
link-workspace-packages=true
|
link-workspace-packages=deep
|
||||||
prefer-workspace-packages=true
|
prefer-workspace-packages=true
|
||||||
|
|||||||
@@ -3,6 +3,123 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.29.3](https://github.com/certd/certd/compare/v1.29.2...v1.29.3) (2025-01-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.29.2](https://github.com/certd/certd/compare/v1.29.1...v1.29.2) (2024-12-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.29.1](https://github.com/certd/certd/compare/v1.29.0...v1.29.1) (2024-12-25)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复某处金额转换丢失精度的bug ([d2d6f12](https://github.com/certd/certd/commit/d2d6f12218cbe7bd55f4ae082b93084be85f0a7b))
|
||||||
|
|
||||||
|
# [1.29.0](https://github.com/certd/certd/compare/v1.28.4...v1.29.0) (2024-12-24)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 用户套餐,用户支付功能 ([a019956](https://github.com/certd/certd/commit/a019956698acaf2c4beb620b5ad8c18918ead6a1))
|
||||||
|
* 支持微信支付 ([45d6347](https://github.com/certd/certd/commit/45d6347f5b6199493b11aabdd74177f6dca2cea4))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 站点证书监控通知发送,每天定时检查 ([bb4910f](https://github.com/certd/certd/commit/bb4910f4e57234e42b44505f4620ae7af66025c5))
|
||||||
|
* 支持plesk网站证书部署 ([eda45c1](https://github.com/certd/certd/commit/eda45c1528199648b3970505e87f492d398226cd))
|
||||||
|
|
||||||
|
## [1.28.4](https://github.com/certd/certd/compare/v1.28.3...v1.28.4) (2024-12-12)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.28.3](https://github.com/certd/certd/compare/v1.28.2...v1.28.3) (2024-12-12)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.28.2](https://github.com/certd/certd/compare/v1.28.1...v1.28.2) (2024-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.28.1](https://github.com/certd/certd/compare/v1.28.0...v1.28.1) (2024-12-08)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 通知选择器优化 ([2c0cbdd](https://github.com/certd/certd/commit/2c0cbdd29ecb74cc939b2ae7ee86b8d40f70ba31))
|
||||||
|
|
||||||
|
# [1.28.0](https://github.com/certd/certd/compare/v1.27.9...v1.28.0) (2024-11-30)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 优化证书申请成功通知发送方式 ([8002a56](https://github.com/certd/certd/commit/8002a56efc5998aa03db5711ae87f9eb4bc9e160))
|
||||||
|
* 支持短信验证码登录 ([387bcc5](https://github.com/certd/certd/commit/387bcc5fa418cdeea81a06da5e3f8cd6b43cd082))
|
||||||
|
|
||||||
|
## [1.27.9](https://github.com/certd/certd/compare/v1.27.8...v1.27.9) (2024-11-26)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.27.8](https://github.com/certd/certd/compare/v1.27.7...v1.27.8) (2024-11-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.27.7](https://github.com/certd/certd/compare/v1.27.6...v1.27.7) (2024-11-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.27.6](https://github.com/certd/certd/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.27.5](https://github.com/certd/certd/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 系统设置中的代理设置优化为可全局生效,环境变量中的https_proxy设置将无效 ([381a37f](https://github.com/certd/certd/commit/381a37fbaa6b61c887eda743897ae00afb825bdf))
|
||||||
|
* 新手导航在非编辑模式下不显示 ([18bfcc2](https://github.com/certd/certd/commit/18bfcc24ad0bde57bb04db8a4209861ec6b8ff1d))
|
||||||
|
* 优化腾讯云 cloudflare 重复解析记录时的返回值 ([90d1b68](https://github.com/certd/certd/commit/90d1b68bd6cf232fbe085234efe07d29b7690044))
|
||||||
|
|
||||||
|
## [1.27.4](https://github.com/certd/certd/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.27.3](https://github.com/certd/certd/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复ipv6未开启情况下,请求带有ipv6地址域名报ETIMEDOUT的bug ([a9a0967](https://github.com/certd/certd/commit/a9a0967a6f1d0bd27e69f3ec52c31d90d470bc23))
|
||||||
|
|
||||||
|
## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 支持公共cname服务 ([3c919ee](https://github.com/certd/certd/commit/3c919ee5d1aef5d26cf3620a7c49d920786bc941))
|
||||||
|
|
||||||
|
## [1.27.1](https://github.com/certd/certd/compare/v1.27.0...v1.27.1) (2024-11-04)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* cname 域名映射记录可读性优化 ([b1117ed](https://github.com/certd/certd/commit/b1117ed54a3ef015752999324ff72b821ef5e4b9))
|
||||||
|
|
||||||
|
# [1.27.0](https://github.com/certd/certd/compare/v1.26.16...v1.27.0) (2024-10-31)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.26.16](https://github.com/certd/certd/compare/v1.26.15...v1.26.16) (2024-10-30)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 支持华为云cdn ([81a3fdb](https://github.com/certd/certd/commit/81a3fdbc29b71f380762008cc151493ec97458f9))
|
||||||
|
|
||||||
|
## [1.26.15](https://github.com/certd/certd/compare/v1.26.14...v1.26.15) (2024-10-28)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.26.14](https://github.com/certd/certd/compare/v1.26.13...v1.26.14) (2024-10-26)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复启动时自签证书无法保存的bug ([526c484](https://github.com/certd/certd/commit/526c48450bcd37b3ccded9b448f17de8140bdc6e))
|
||||||
|
|
||||||
## [1.26.13](https://github.com/certd/certd/compare/v1.26.12...v1.26.13) (2024-10-26)
|
## [1.26.13](https://github.com/certd/certd/compare/v1.26.12...v1.26.13) (2024-10-26)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/basic
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
20:27
|
01:09
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/basic",
|
"name": "@certd/basic",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.26.13",
|
"version": "1.29.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.js",
|
"module": "./dist/index.js",
|
||||||
@@ -17,52 +17,32 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"fix-path": "^4.0.0",
|
|
||||||
"http-proxy-agent": "^7.0.2",
|
"http-proxy-agent": "^7.0.2",
|
||||||
"https-proxy-agent": "^7.0.5",
|
"https-proxy-agent": "^7.0.5",
|
||||||
|
"iconv-lite": "^0.6.3",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
|
"log4js": "^6.9.1",
|
||||||
"lru-cache": "^10.0.0",
|
"lru-cache": "^10.0.0",
|
||||||
|
"mitt": "^3.0.1",
|
||||||
"nanoid": "^5.0.7",
|
"nanoid": "^5.0.7",
|
||||||
"node-forge": "^1.3.1",
|
"node-forge": "^1.3.1",
|
||||||
"nodemailer": "^6.9.3",
|
"nodemailer": "^6.9.3"
|
||||||
"proxy-agent": "^6.4.0",
|
|
||||||
"qs": "^6.11.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-commonjs": "^23.0.4",
|
|
||||||
"@rollup/plugin-json": "^6.0.0",
|
|
||||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
||||||
"@rollup/plugin-terser": "^0.4.3",
|
|
||||||
"@rollup/plugin-typescript": "^11.0.0",
|
|
||||||
"@types/chai": "^4.3.10",
|
"@types/chai": "^4.3.10",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/mocha": "^10.0.1",
|
"@types/mocha": "^10.0.1",
|
||||||
"@types/node-forge": "^1.3.2",
|
"@types/node-forge": "^1.3.2",
|
||||||
"@types/uuid": "^9.0.2",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.59.7",
|
"@typescript-eslint/eslint-plugin": "^5.59.7",
|
||||||
"@typescript-eslint/parser": "^5.59.7",
|
"@typescript-eslint/parser": "^5.59.7",
|
||||||
"chai": "4.3.10",
|
"chai": "4.3.10",
|
||||||
"dayjs": "^1.11.7",
|
|
||||||
"eslint": "^8.41.0",
|
"eslint": "^8.41.0",
|
||||||
"eslint-config-prettier": "^8.8.0",
|
"eslint-config-prettier": "^8.8.0",
|
||||||
"eslint-plugin-import": "^2.27.5",
|
|
||||||
"eslint-plugin-node": "^11.1.0",
|
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"iconv-lite": "^0.6.3",
|
|
||||||
"log4js": "^6.9.1",
|
|
||||||
"mocha": "^10.2.0",
|
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
"reflect-metadata": "^0.1.13",
|
|
||||||
"rimraf": "^5.0.5",
|
"rimraf": "^5.0.5",
|
||||||
"rollup": "^3.7.4",
|
"tslib": "^2.8.1",
|
||||||
"rollup-plugin-typescript2": "^0.34.1",
|
"typescript": "^5.4.2"
|
||||||
"rollup-plugin-visualizer": "^5.8.2",
|
|
||||||
"ts-node": "^10.9.1",
|
|
||||||
"tsc-esm-fix": "^3.0.0",
|
|
||||||
"tslib": "^2.5.2",
|
|
||||||
"typescript": "^5.4.2",
|
|
||||||
"vite": "^4.3.8",
|
|
||||||
"vue-tsc": "^1.6.5"
|
|
||||||
},
|
},
|
||||||
"gitHead": "11d0daa59ae409c229037189066414f29b787de0"
|
"gitHead": "ed5634ff83405ad0eb13a8456f59270ed4218734"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
export * from './utils/index.js';
|
export * from './utils/index.js';
|
||||||
|
export * from './utils/util.id.js';
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export * from './util.request.js';
|
export * from './util.request.js';
|
||||||
|
export * from './util.env.js';
|
||||||
export * from './util.log.js';
|
export * from './util.log.js';
|
||||||
export * from './util.file.js';
|
export * from './util.file.js';
|
||||||
export * from './util.sp.js';
|
export * from './util.sp.js';
|
||||||
@@ -6,9 +7,16 @@ export * from './util.promise.js';
|
|||||||
export * from './util.hash.js';
|
export * from './util.hash.js';
|
||||||
export * from './util.merge.js';
|
export * from './util.merge.js';
|
||||||
export * from './util.cache.js';
|
export * from './util.cache.js';
|
||||||
|
export * from './util.string.js';
|
||||||
|
export * from './util.lock.js';
|
||||||
|
export * from './util.mitter.js';
|
||||||
|
export * from './util.id.js';
|
||||||
|
export * from './util.domain.js';
|
||||||
|
export * from './util.amount.js';
|
||||||
|
import { stringUtils } from './util.string.js';
|
||||||
import sleep from './util.sleep.js';
|
import sleep from './util.sleep.js';
|
||||||
import { http } from './util.request.js';
|
import { http, download } from './util.request.js';
|
||||||
import { nanoid } from 'nanoid';
|
|
||||||
import { mergeUtils } from './util.merge.js';
|
import { mergeUtils } from './util.merge.js';
|
||||||
import { sp } from './util.sp.js';
|
import { sp } from './util.sp.js';
|
||||||
import { hashUtils } from './util.hash.js';
|
import { hashUtils } from './util.hash.js';
|
||||||
@@ -19,10 +27,15 @@ import { cache } from './util.cache.js';
|
|||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { domainUtils } from './util.domain.js';
|
import { domainUtils } from './util.domain.js';
|
||||||
import { optionsUtils } from './util.options.js';
|
import { optionsUtils } from './util.options.js';
|
||||||
|
import { amountUtils } from './util.amount.js';
|
||||||
|
import { nanoid } from 'nanoid';
|
||||||
|
import * as id from './util.id.js';
|
||||||
|
import { locker } from './util.lock.js';
|
||||||
|
import { mitter } from './util.mitter.js';
|
||||||
export const utils = {
|
export const utils = {
|
||||||
sleep,
|
sleep,
|
||||||
http,
|
http,
|
||||||
|
download,
|
||||||
sp,
|
sp,
|
||||||
hash: hashUtils,
|
hash: hashUtils,
|
||||||
promises,
|
promises,
|
||||||
@@ -31,7 +44,12 @@ export const utils = {
|
|||||||
mergeUtils,
|
mergeUtils,
|
||||||
cache,
|
cache,
|
||||||
nanoid,
|
nanoid,
|
||||||
|
id,
|
||||||
dayjs,
|
dayjs,
|
||||||
domain: domainUtils,
|
domain: domainUtils,
|
||||||
options: optionsUtils,
|
options: optionsUtils,
|
||||||
|
string: stringUtils,
|
||||||
|
locker,
|
||||||
|
mitter,
|
||||||
|
amount: amountUtils,
|
||||||
};
|
};
|
||||||
|
|||||||
9
packages/core/basic/src/utils/util.amount.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export const amountUtils = {
|
||||||
|
toCent(amount: number): number {
|
||||||
|
return parseInt((amount * 100).toFixed(0));
|
||||||
|
},
|
||||||
|
|
||||||
|
toYuan(amount: number): number {
|
||||||
|
return parseFloat((amount / 100).toFixed(2));
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// LRUCache
|
// LRUCache
|
||||||
|
|
||||||
import { LRUCache } from "lru-cache";
|
import { LRUCache } from 'lru-cache';
|
||||||
|
|
||||||
export const cache = new LRUCache<string, any>({
|
export const cache = new LRUCache<string, any>({
|
||||||
max: 1000,
|
max: 1000,
|
||||||
|
|||||||
4
packages/core/basic/src/utils/util.env.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export function isDev() {
|
||||||
|
const nodeEnv = process.env.NODE_ENV || '';
|
||||||
|
return nodeEnv === 'development' || nodeEnv.includes('local') || nodeEnv.startsWith('dev');
|
||||||
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
import crypto from "crypto";
|
import crypto from 'crypto';
|
||||||
|
|
||||||
function md5(data: string) {
|
function md5(data: string) {
|
||||||
return crypto.createHash("md5").update(data).digest("hex");
|
return crypto.createHash('md5').update(data).digest('hex');
|
||||||
|
}
|
||||||
|
function sha256(data: string) {
|
||||||
|
return crypto.createHash('sha256').update(data).digest('hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
export const hashUtils = {
|
export const hashUtils = {
|
||||||
md5,
|
md5,
|
||||||
|
sha256,
|
||||||
};
|
};
|
||||||
|
|||||||
4
packages/core/basic/src/utils/util.id.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { customAlphabet } from 'nanoid';
|
||||||
|
|
||||||
|
export const randomNumber = customAlphabet('1234567890', 4);
|
||||||
|
export const simpleNanoId = customAlphabet('1234567890abcdefghijklmopqrstuvwxyz', 12);
|
||||||
47
packages/core/basic/src/utils/util.lock.ts
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import { logger, utils } from './index.js';
|
||||||
|
|
||||||
|
export class Locker {
|
||||||
|
locked: Record<string, any> = {};
|
||||||
|
|
||||||
|
async execute(lockStr: string, callback: any) {
|
||||||
|
await this.lock(lockStr);
|
||||||
|
const timeoutId = setTimeout(() => {
|
||||||
|
logger.warn('Lock timeout,自动解锁', lockStr);
|
||||||
|
this.unlock(lockStr);
|
||||||
|
}, 20000);
|
||||||
|
try {
|
||||||
|
return await callback();
|
||||||
|
} finally {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
this.unlock(lockStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async lock(str: string) {
|
||||||
|
const isLocked = this.isLocked(str);
|
||||||
|
if (isLocked) {
|
||||||
|
let count = 0;
|
||||||
|
while (true) {
|
||||||
|
await utils.sleep(100);
|
||||||
|
if (!this.isLocked(str)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
if (count > 20) {
|
||||||
|
throw new Error('Lock timeout');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.locked[str] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock(str: string) {
|
||||||
|
delete this.locked[str];
|
||||||
|
}
|
||||||
|
|
||||||
|
isLocked(str: string) {
|
||||||
|
return this.locked[str] ?? false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const locker = new Locker();
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import log4js, { LoggingEvent, Logger } from "log4js";
|
import log4js, { LoggingEvent, Logger } from 'log4js';
|
||||||
|
|
||||||
const OutputAppender = {
|
const OutputAppender = {
|
||||||
configure: (config: any, layouts: any, findAppender: any, levels: any) => {
|
configure: (config: any, layouts: any, findAppender: any, levels: any) => {
|
||||||
@@ -18,18 +18,22 @@ const OutputAppender = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// @ts-ignore
|
export function resetLogConfigure() {
|
||||||
log4js.configure({
|
// @ts-ignore
|
||||||
appenders: { std: { type: "stdout" }, output: { type: OutputAppender } },
|
log4js.configure({
|
||||||
categories: { default: { appenders: ["std"], level: "info" }, pipeline: { appenders: ["std", "output"], level: "info" } },
|
appenders: { std: { type: 'stdout' }, output: { type: OutputAppender } },
|
||||||
});
|
categories: { default: { appenders: ['std'], level: 'info' }, pipeline: { appenders: ['std', 'output'], level: 'info' } },
|
||||||
export const logger = log4js.getLogger("default");
|
});
|
||||||
|
}
|
||||||
|
resetLogConfigure();
|
||||||
|
export const logger = log4js.getLogger('default');
|
||||||
|
|
||||||
export function buildLogger(write: (text: string) => void) {
|
export function buildLogger(write: (text: string) => void) {
|
||||||
const logger = log4js.getLogger("pipeline");
|
const logger = log4js.getLogger('pipeline');
|
||||||
logger.addContext("outputHandler", {
|
logger.addContext('outputHandler', {
|
||||||
write,
|
write,
|
||||||
});
|
});
|
||||||
return logger;
|
return logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ILogger = Logger;
|
export type ILogger = Logger;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import _ from "lodash-es";
|
import * as _ from 'lodash-es';
|
||||||
function isUnMergeable(srcValue: any) {
|
function isUnMergeable(srcValue: any) {
|
||||||
return srcValue != null && srcValue instanceof UnMergeable;
|
return srcValue != null && srcValue instanceof UnMergeable;
|
||||||
}
|
}
|
||||||
|
|||||||
2
packages/core/basic/src/utils/util.mitter.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
import mitt from 'mitt';
|
||||||
|
export const mitter = mitt();
|
||||||
@@ -19,7 +19,7 @@ function groupByDomain(options: any[], inDomains: string[]) {
|
|||||||
function buildGroupOptions(options: any[], inDomains: string[]) {
|
function buildGroupOptions(options: any[], inDomains: string[]) {
|
||||||
const grouped = groupByDomain(options, inDomains);
|
const grouped = groupByDomain(options, inDomains);
|
||||||
const groupOptions = [];
|
const groupOptions = [];
|
||||||
groupOptions.push({ value: '', disabled: true, label: '----已匹配----' });
|
groupOptions.push({ value: 'matched', disabled: true, label: '----已匹配----' });
|
||||||
if (grouped.matched.length === 0) {
|
if (grouped.matched.length === 0) {
|
||||||
options.push({ value: '', disabled: true, label: '没有可以匹配的域名' });
|
options.push({ value: '', disabled: true, label: '没有可以匹配的域名' });
|
||||||
} else {
|
} else {
|
||||||
@@ -28,7 +28,7 @@ function buildGroupOptions(options: any[], inDomains: string[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (grouped.notMatched.length > 0) {
|
if (grouped.notMatched.length > 0) {
|
||||||
groupOptions.push({ value: '', disabled: true, label: '----未匹配----' });
|
groupOptions.push({ value: 'unmatched', disabled: true, label: '----未匹配----' });
|
||||||
for (const notMatched of grouped.notMatched) {
|
for (const notMatched of grouped.notMatched) {
|
||||||
groupOptions.push(notMatched);
|
groupOptions.push(notMatched);
|
||||||
}
|
}
|
||||||
@@ -37,6 +37,8 @@ function buildGroupOptions(options: any[], inDomains: string[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const optionsUtils = {
|
export const optionsUtils = {
|
||||||
|
//获取分组
|
||||||
groupByDomain,
|
groupByDomain,
|
||||||
|
//构建分组后的选项列表,常用
|
||||||
buildGroupOptions,
|
buildGroupOptions,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,34 +1,43 @@
|
|||||||
import axios, { AxiosRequestConfig } from 'axios';
|
import axios, { AxiosHeaders, AxiosRequestConfig } from 'axios';
|
||||||
import { logger } from './util.log.js';
|
import { ILogger, logger } from './util.log.js';
|
||||||
import { Logger } from 'log4js';
|
import { Logger } from 'log4js';
|
||||||
import { HttpProxyAgent } from 'http-proxy-agent';
|
import { HttpProxyAgent } from 'http-proxy-agent';
|
||||||
import { HttpsProxyAgent } from 'https-proxy-agent';
|
import { HttpsProxyAgent } from 'https-proxy-agent';
|
||||||
import nodeHttp from 'http';
|
import nodeHttp from 'http';
|
||||||
import * as https from 'node:https';
|
import * as https from 'node:https';
|
||||||
import { merge } from 'lodash-es';
|
import { merge } from 'lodash-es';
|
||||||
|
import { safePromise } from './util.promise.js';
|
||||||
|
import fs from 'fs';
|
||||||
export class HttpError extends Error {
|
export class HttpError extends Error {
|
||||||
status?: number;
|
status?: number;
|
||||||
statusText?: string;
|
statusText?: string;
|
||||||
code?: string;
|
code?: string;
|
||||||
request?: { baseURL: string; url: string; method: string; params?: any; data?: any };
|
request?: { baseURL: string; url: string; method: string; params?: any; data?: any };
|
||||||
response?: { data: any };
|
response?: { data: any; headers: AxiosHeaders };
|
||||||
cause?: any;
|
cause?: any;
|
||||||
constructor(error: any) {
|
constructor(error: any) {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
super(error.message);
|
super(error.message || error.response?.statusText);
|
||||||
|
|
||||||
if (error?.message?.indexOf('ssl3_get_record:wrong version number') >= 0) {
|
const message = error?.message;
|
||||||
this.message = 'http协议错误,服务端要求http协议,请检查是否使用了https请求';
|
if (message && typeof message === 'string') {
|
||||||
|
if (message.indexOf && message.indexOf('ssl3_get_record:wrong version number') >= 0) {
|
||||||
|
this.message = `${message}(http协议错误,服务端要求http协议,请检查是否使用了https请求)`;
|
||||||
|
} else if (message.indexOf('getaddrinfo EAI_AGAIN') >= 0) {
|
||||||
|
this.message = `${message}(无法解析域名,请检查网络连接或dns配置,更换docker-compose.yaml中dns配置)`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.name = error.name;
|
this.name = error.name;
|
||||||
this.code = error.code;
|
this.code = error.code;
|
||||||
this.cause = error.cause;
|
|
||||||
|
|
||||||
this.status = error.response?.status;
|
this.status = error.response?.status;
|
||||||
this.statusText = error.response?.statusText;
|
this.statusText = error.response?.statusText || error.code;
|
||||||
|
if (!this.message) {
|
||||||
|
this.message = error.code;
|
||||||
|
}
|
||||||
this.request = {
|
this.request = {
|
||||||
baseURL: error.config?.baseURL,
|
baseURL: error.config?.baseURL,
|
||||||
url: error.config?.url,
|
url: error.config?.url,
|
||||||
@@ -38,16 +47,20 @@ export class HttpError extends Error {
|
|||||||
};
|
};
|
||||||
let url = error.config?.url;
|
let url = error.config?.url;
|
||||||
if (error.config?.baseURL) {
|
if (error.config?.baseURL) {
|
||||||
url = error.config?.baseURL + url;
|
url = (error.config?.baseURL || '') + url;
|
||||||
}
|
}
|
||||||
if (url) {
|
if (url) {
|
||||||
this.message = `${this.message} : url=${url}`;
|
this.message = `${this.message} 【${url}】`;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.response = {
|
this.response = {
|
||||||
data: error.response?.data,
|
data: error.response?.data,
|
||||||
|
headers: error.response?.headers,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { stack, cause } = error;
|
||||||
|
this.cause = cause;
|
||||||
|
this.stack = stack;
|
||||||
delete error.response;
|
delete error.response;
|
||||||
delete error.config;
|
delete error.config;
|
||||||
delete error.request;
|
delete error.request;
|
||||||
@@ -61,14 +74,7 @@ let defaultAgents = createAgent();
|
|||||||
|
|
||||||
export function setGlobalProxy(opts: { httpProxy?: string; httpsProxy?: string }) {
|
export function setGlobalProxy(opts: { httpProxy?: string; httpsProxy?: string }) {
|
||||||
logger.info('setGlobalProxy:', opts);
|
logger.info('setGlobalProxy:', opts);
|
||||||
if (opts.httpProxy) {
|
defaultAgents = createAgent(opts);
|
||||||
process.env.HTTP_PROXY = opts.httpProxy;
|
|
||||||
}
|
|
||||||
if (opts.httpsProxy) {
|
|
||||||
process.env.HTTPS_PROXY = opts.httpsProxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultAgents = createAgent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getGlobalAgents() {
|
export function getGlobalAgents() {
|
||||||
@@ -93,10 +99,22 @@ export function createAxiosService({ logger }: { logger: Logger }) {
|
|||||||
config.timeout = 15000;
|
config.timeout = 15000;
|
||||||
}
|
}
|
||||||
let agents = defaultAgents;
|
let agents = defaultAgents;
|
||||||
if (config.skipSslVerify) {
|
if (config.skipSslVerify || config.httpProxy) {
|
||||||
logger.info('跳过SSL验证');
|
let rejectUnauthorized = true;
|
||||||
agents = createAgent({ rejectUnauthorized: false } as any);
|
if (config.skipSslVerify) {
|
||||||
|
logger.info('跳过SSL验证');
|
||||||
|
rejectUnauthorized = false;
|
||||||
|
}
|
||||||
|
const proxy: any = {};
|
||||||
|
if (config.httpProxy) {
|
||||||
|
logger.info('使用自定义http代理:', config.httpProxy);
|
||||||
|
proxy.httpProxy = config.httpProxy;
|
||||||
|
proxy.httpsProxy = config.httpProxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
agents = createAgent({ rejectUnauthorized, ...proxy } as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete config.skipSslVerify;
|
delete config.skipSslVerify;
|
||||||
config.httpsAgent = agents.httpsAgent;
|
config.httpsAgent = agents.httpsAgent;
|
||||||
config.httpAgent = agents.httpAgent;
|
config.httpAgent = agents.httpAgent;
|
||||||
@@ -118,10 +136,18 @@ export function createAxiosService({ logger }: { logger: Logger }) {
|
|||||||
service.interceptors.response.use(
|
service.interceptors.response.use(
|
||||||
(response: any) => {
|
(response: any) => {
|
||||||
if (response?.config?.logRes !== false) {
|
if (response?.config?.logRes !== false) {
|
||||||
logger.info(`http response : status=${response?.status},data=${JSON.stringify(response?.data)}`);
|
let resData = response?.data;
|
||||||
|
try {
|
||||||
|
resData = JSON.stringify(response?.data);
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
logger.info(`http response : status=${response?.status},data=${resData}`);
|
||||||
} else {
|
} else {
|
||||||
logger.info('http response status:', response?.status);
|
logger.info('http response status:', response?.status);
|
||||||
}
|
}
|
||||||
|
if (response?.config?.returnResponse) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
(error: any) => {
|
(error: any) => {
|
||||||
@@ -131,13 +157,13 @@ export function createAxiosService({ logger }: { logger: Logger }) {
|
|||||||
error.message = '请求错误';
|
error.message = '请求错误';
|
||||||
break;
|
break;
|
||||||
case 401:
|
case 401:
|
||||||
error.message = '未授权,请登录';
|
error.message = '认证/登录失败';
|
||||||
break;
|
break;
|
||||||
case 403:
|
case 403:
|
||||||
error.message = '拒绝访问';
|
error.message = '拒绝访问';
|
||||||
break;
|
break;
|
||||||
case 404:
|
case 404:
|
||||||
error.message = `请求地址出错: ${error.response.config.url}`;
|
error.message = `请求地址出错`;
|
||||||
break;
|
break;
|
||||||
case 408:
|
case 408:
|
||||||
error.message = '请求超时';
|
error.message = '请求超时';
|
||||||
@@ -168,7 +194,10 @@ export function createAxiosService({ logger }: { logger: Logger }) {
|
|||||||
);
|
);
|
||||||
logger.error('返回数据:', JSON.stringify(error.response?.data));
|
logger.error('返回数据:', JSON.stringify(error.response?.data));
|
||||||
if (error.response?.data) {
|
if (error.response?.data) {
|
||||||
error.message = error.response.data.message || error.response.data.msg || error.response.data.error || error.response.data;
|
const message = error.response.data.message || error.response.data.msg || error.response.data.error;
|
||||||
|
if (typeof message === 'string') {
|
||||||
|
error.message = message;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (error instanceof AggregateError) {
|
if (error instanceof AggregateError) {
|
||||||
logger.error('AggregateError', error);
|
logger.error('AggregateError', error);
|
||||||
@@ -187,27 +216,52 @@ export type HttpRequestConfig<D = any> = {
|
|||||||
skipCheckRes?: boolean;
|
skipCheckRes?: boolean;
|
||||||
logParams?: boolean;
|
logParams?: boolean;
|
||||||
logRes?: boolean;
|
logRes?: boolean;
|
||||||
|
httpProxy?: string;
|
||||||
|
returnResponse?: boolean;
|
||||||
} & AxiosRequestConfig<D>;
|
} & AxiosRequestConfig<D>;
|
||||||
export type HttpClient = {
|
export type HttpClient = {
|
||||||
request<D = any, R = any>(config: HttpRequestConfig<D>): Promise<HttpClientResponse<R>>;
|
request<D = any, R = any>(config: HttpRequestConfig<D>): Promise<HttpClientResponse<R>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function createAgent(opts: nodeHttp.AgentOptions = {}) {
|
// const http_proxy_backup = process.env.HTTP_PROXY || process.env.http_proxy;
|
||||||
|
// const https_proxy_backup = process.env.HTTPS_PROXY || process.env.https_proxy;
|
||||||
|
|
||||||
|
export type CreateAgentOptions = {
|
||||||
|
httpProxy?: string;
|
||||||
|
httpsProxy?: string;
|
||||||
|
} & nodeHttp.AgentOptions;
|
||||||
|
export function createAgent(opts: CreateAgentOptions = {}) {
|
||||||
|
opts = merge(
|
||||||
|
{
|
||||||
|
autoSelectFamily: true,
|
||||||
|
autoSelectFamilyAttemptTimeout: 1000,
|
||||||
|
},
|
||||||
|
opts
|
||||||
|
);
|
||||||
|
|
||||||
let httpAgent, httpsAgent;
|
let httpAgent, httpsAgent;
|
||||||
const httpProxy = process.env.HTTP_PROXY || process.env.http_proxy;
|
const httpProxy = opts.httpProxy;
|
||||||
if (httpProxy) {
|
if (httpProxy) {
|
||||||
|
process.env.HTTP_PROXY = httpProxy;
|
||||||
|
process.env.http_proxy = httpProxy;
|
||||||
logger.info('use httpProxy:', httpProxy);
|
logger.info('use httpProxy:', httpProxy);
|
||||||
httpAgent = new HttpProxyAgent(httpProxy, opts as any);
|
httpAgent = new HttpProxyAgent(httpProxy, opts as any);
|
||||||
merge(httpAgent.options, opts);
|
merge(httpAgent.options, opts);
|
||||||
} else {
|
} else {
|
||||||
|
process.env.HTTP_PROXY = '';
|
||||||
|
process.env.http_proxy = '';
|
||||||
httpAgent = new nodeHttp.Agent(opts);
|
httpAgent = new nodeHttp.Agent(opts);
|
||||||
}
|
}
|
||||||
const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy;
|
const httpsProxy = opts.httpsProxy;
|
||||||
if (httpsProxy) {
|
if (httpsProxy) {
|
||||||
|
process.env.HTTPS_PROXY = httpsProxy;
|
||||||
|
process.env.https_proxy = httpsProxy;
|
||||||
logger.info('use httpsProxy:', httpsProxy);
|
logger.info('use httpsProxy:', httpsProxy);
|
||||||
httpsAgent = new HttpsProxyAgent(httpsProxy, opts as any);
|
httpsAgent = new HttpsProxyAgent(httpsProxy, opts as any);
|
||||||
merge(httpsAgent.options, opts);
|
merge(httpsAgent.options, opts);
|
||||||
} else {
|
} else {
|
||||||
|
process.env.HTTPS_PROXY = '';
|
||||||
|
process.env.https_proxy = '';
|
||||||
httpsAgent = new https.Agent(opts);
|
httpsAgent = new https.Agent(opts);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -215,3 +269,44 @@ export function createAgent(opts: nodeHttp.AgentOptions = {}) {
|
|||||||
httpsAgent,
|
httpsAgent,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function download(req: { http: HttpClient; config: HttpRequestConfig; savePath: string; logger: ILogger }) {
|
||||||
|
const { http, config, savePath, logger } = req;
|
||||||
|
return safePromise((resolve, reject) => {
|
||||||
|
http
|
||||||
|
.request({
|
||||||
|
logRes: false,
|
||||||
|
responseType: 'stream',
|
||||||
|
...config,
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
const writer = fs.createWriteStream(savePath);
|
||||||
|
res.pipe(writer);
|
||||||
|
writer.on('close', () => {
|
||||||
|
logger.info('文件下载成功');
|
||||||
|
resolve(true);
|
||||||
|
});
|
||||||
|
//error
|
||||||
|
writer.on('error', err => {
|
||||||
|
logger.error('下载失败', err);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
//进度条打印
|
||||||
|
const totalLength = res.headers['content-length'];
|
||||||
|
let currentLength = 0;
|
||||||
|
// 每5%打印一次
|
||||||
|
const step = (totalLength / 100) * 5;
|
||||||
|
res.on('data', (chunk: any) => {
|
||||||
|
currentLength += chunk.length;
|
||||||
|
if (currentLength % step < chunk.length) {
|
||||||
|
const percent = ((currentLength / totalLength) * 100).toFixed(2);
|
||||||
|
logger.info(`下载进度:${percent}%`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
logger.info('下载失败', err);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
//转换为import
|
//转换为import
|
||||||
import childProcess from "child_process";
|
import childProcess from 'child_process';
|
||||||
import { safePromise } from "./util.promise.js";
|
import { safePromise } from './util.promise.js';
|
||||||
import { ILogger, logger } from "./util.log.js";
|
import { ILogger, logger } from './util.log.js';
|
||||||
|
import iconv from 'iconv-lite';
|
||||||
export type ExecOption = {
|
export type ExecOption = {
|
||||||
cmd: string | string[];
|
cmd: string | string[];
|
||||||
env: any;
|
env: any;
|
||||||
@@ -11,12 +11,12 @@ export type ExecOption = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
async function exec(opts: ExecOption): Promise<string> {
|
async function exec(opts: ExecOption): Promise<string> {
|
||||||
let cmd = "";
|
let cmd = '';
|
||||||
const log = opts.logger || logger;
|
const log = opts.logger || logger;
|
||||||
if (opts.cmd instanceof Array) {
|
if (opts.cmd instanceof Array) {
|
||||||
for (const item of opts.cmd) {
|
for (const item of opts.cmd) {
|
||||||
if (cmd) {
|
if (cmd) {
|
||||||
cmd += " && " + item;
|
cmd += ' && ' + item;
|
||||||
} else {
|
} else {
|
||||||
cmd = item;
|
cmd = item;
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,7 @@ async function exec(opts: ExecOption): Promise<string> {
|
|||||||
log.error(`exec error: ${error}`);
|
log.error(`exec error: ${error}`);
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
const res = stdout.toString("utf-8");
|
const res = stdout.toString('utf-8');
|
||||||
log.info(`stdout: ${res}`);
|
log.info(`stdout: ${res}`);
|
||||||
resolve(res);
|
resolve(res);
|
||||||
}
|
}
|
||||||
@@ -55,13 +55,31 @@ export type SpawnOption = {
|
|||||||
logger?: ILogger;
|
logger?: ILogger;
|
||||||
options?: any;
|
options?: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function isWindows() {
|
||||||
|
return process.platform === 'win32';
|
||||||
|
}
|
||||||
|
function convert(buffer: any) {
|
||||||
|
if (isWindows()) {
|
||||||
|
const decoded = iconv.decode(buffer, 'GBK');
|
||||||
|
// 检查是否有有效字符
|
||||||
|
return decoded && decoded.trim().length > 0 ? decoded : buffer.toString();
|
||||||
|
} else {
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// function convert(buffer: any) {
|
||||||
|
// return buffer;
|
||||||
|
// }
|
||||||
|
|
||||||
async function spawn(opts: SpawnOption): Promise<string> {
|
async function spawn(opts: SpawnOption): Promise<string> {
|
||||||
let cmd = "";
|
let cmd = '';
|
||||||
const log = opts.logger || logger;
|
const log = opts.logger || logger;
|
||||||
if (opts.cmd instanceof Array) {
|
if (opts.cmd instanceof Array) {
|
||||||
for (const item of opts.cmd) {
|
for (const item of opts.cmd) {
|
||||||
if (cmd) {
|
if (cmd) {
|
||||||
cmd += " && " + item;
|
cmd += ' && ' + item;
|
||||||
} else {
|
} else {
|
||||||
cmd = item;
|
cmd = item;
|
||||||
}
|
}
|
||||||
@@ -70,8 +88,8 @@ async function spawn(opts: SpawnOption): Promise<string> {
|
|||||||
cmd = opts.cmd;
|
cmd = opts.cmd;
|
||||||
}
|
}
|
||||||
log.info(`执行命令: ${cmd}`);
|
log.info(`执行命令: ${cmd}`);
|
||||||
let stdout = "";
|
let stdout = '';
|
||||||
let stderr = "";
|
let stderr = '';
|
||||||
return safePromise((resolve, reject) => {
|
return safePromise((resolve, reject) => {
|
||||||
const ls = childProcess.spawn(cmd, {
|
const ls = childProcess.spawn(cmd, {
|
||||||
shell: true,
|
shell: true,
|
||||||
@@ -81,21 +99,23 @@ async function spawn(opts: SpawnOption): Promise<string> {
|
|||||||
},
|
},
|
||||||
...opts.options,
|
...opts.options,
|
||||||
});
|
});
|
||||||
ls.stdout.on("data", (data) => {
|
ls.stdout.on('data', data => {
|
||||||
|
data = convert(data);
|
||||||
log.info(`stdout: ${data}`);
|
log.info(`stdout: ${data}`);
|
||||||
stdout += data;
|
stdout += data;
|
||||||
});
|
});
|
||||||
|
|
||||||
ls.stderr.on("data", (data) => {
|
ls.stderr.on('data', data => {
|
||||||
log.error(`stderr: ${data}`);
|
data = convert(data);
|
||||||
|
log.warn(`stderr: ${data}`);
|
||||||
stderr += data;
|
stderr += data;
|
||||||
});
|
});
|
||||||
ls.on("error", (error) => {
|
ls.on('error', error => {
|
||||||
log.error(`child process error: ${error}`);
|
log.error(`child process error: ${error}`);
|
||||||
reject(error);
|
reject(error);
|
||||||
});
|
});
|
||||||
|
|
||||||
ls.on("close", (code: number) => {
|
ls.on('close', (code: number) => {
|
||||||
if (code !== 0) {
|
if (code !== 0) {
|
||||||
log.error(`child process exited with code ${code}`);
|
log.error(`child process exited with code ${code}`);
|
||||||
reject(new Error(stderr));
|
reject(new Error(stderr));
|
||||||
|
|||||||
8
packages/core/basic/src/utils/util.string.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export const stringUtils = {
|
||||||
|
maxLength(str?: string, length = 100) {
|
||||||
|
if (str) {
|
||||||
|
return str.length > length ? str.slice(0, length) + '...' : str;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -7,28 +7,27 @@
|
|||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"inlineSourceMap":true,
|
|
||||||
"noImplicitThis": true,
|
"noImplicitThis": true,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"stripInternal": true,
|
"stripInternal": true,
|
||||||
|
"importHelpers": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"pretty": true,
|
"pretty": true,
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"typeRoots": [ "./typings", "./node_modules/@types"],
|
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"rootDir": "src",
|
"rootDir": "src",
|
||||||
"composite": true,
|
"composite": false,
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
// "sourceMap": true,
|
"typeRoots": [ "./typings", "./node_modules/@types"],
|
||||||
|
"inlineSourceMap": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": false,
|
"isolatedModules": false,
|
||||||
"lib": ["ESNext", "DOM"],
|
"lib": ["ESNext", "DOM"],
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*.ts",
|
"src/**/*.ts",
|
||||||
"src/**/*.d.ts",
|
|
||||||
"src/**/*.json"
|
"src/**/*.json"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
link-workspace-packages=true
|
link-workspace-packages=deep
|
||||||
prefer-workspace-packages=true
|
prefer-workspace-packages=true
|
||||||
|
|||||||
@@ -3,6 +3,142 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.29.3](https://github.com/certd/certd/compare/v1.29.2...v1.29.3) (2025-01-04)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 支持http校验方式申请证书 ([405591c](https://github.com/certd/certd/commit/405591c5d08fa1a3b228ee3980199e7731cfec4a))
|
||||||
|
|
||||||
|
## [1.29.2](https://github.com/certd/certd/compare/v1.29.1...v1.29.2) (2024-12-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.29.1](https://github.com/certd/certd/compare/v1.29.0...v1.29.1) (2024-12-25)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 用户创建证书流水线没有购买套餐或者超限时提前报错 ([472f06c](https://github.com/certd/certd/commit/472f06c2d190d0ae48e8b53c18bc278437656a1c))
|
||||||
|
|
||||||
|
# [1.29.0](https://github.com/certd/certd/compare/v1.28.4...v1.29.0) (2024-12-24)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 套餐购买支持易支付、支付宝支付 ([faa28f8](https://github.com/certd/certd/commit/faa28f88f954cba4c1dd29125562e5acd2fd99af))
|
||||||
|
* 支持微信支付 ([45d6347](https://github.com/certd/certd/commit/45d6347f5b6199493b11aabdd74177f6dca2cea4))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 同一时间只允许一个套餐生效 ([8ebf95a](https://github.com/certd/certd/commit/8ebf95a222a900d1707716c7b1f3b39f8a6d8f94))
|
||||||
|
* 优化证书申请跳过的状态显示,成功通知现在在跳过时不会发送 ([67d762b](https://github.com/certd/certd/commit/67d762b6a520f1fa24719a124e5ae975a81f5f82))
|
||||||
|
* 支持plesk网站证书部署 ([eda45c1](https://github.com/certd/certd/commit/eda45c1528199648b3970505e87f492d398226cd))
|
||||||
|
|
||||||
|
## [1.28.4](https://github.com/certd/certd/compare/v1.28.3...v1.28.4) (2024-12-12)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复证书成功通知发送失败的bug ([0f5c690](https://github.com/certd/certd/commit/0f5c69040ba77340c909813220a26bc7ddada3ea))
|
||||||
|
|
||||||
|
## [1.28.3](https://github.com/certd/certd/compare/v1.28.2...v1.28.3) (2024-12-12)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 通知标题优化 ([ff083ce](https://github.com/certd/certd/commit/ff083ce6848a8bee3c8248e4b881086ae1517c28))
|
||||||
|
* 支持aws cloudfront ([0ae39f1](https://github.com/certd/certd/commit/0ae39f160a7c6b6696b3bf513d68aa28905810ad))
|
||||||
|
|
||||||
|
## [1.28.2](https://github.com/certd/certd/compare/v1.28.1...v1.28.2) (2024-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.28.1](https://github.com/certd/certd/compare/v1.28.0...v1.28.1) (2024-12-08)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 通知选择器优化 ([2c0cbdd](https://github.com/certd/certd/commit/2c0cbdd29ecb74cc939b2ae7ee86b8d40f70ba31))
|
||||||
|
* 新增七牛云插件分组 ([49e7dc5](https://github.com/certd/certd/commit/49e7dc56e1a95fbdea3e30cdeb945b48415b69e3))
|
||||||
|
|
||||||
|
# [1.28.0](https://github.com/certd/certd/compare/v1.27.9...v1.28.0) (2024-11-30)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 手机号登录、邮箱验证码注册 ([7b55337](https://github.com/certd/certd/commit/7b55337c5edb470cca7aa62201eda8d274784004))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 首页新增修改密码提示 ([0772d3b](https://github.com/certd/certd/commit/0772d3b3fd24afdde4086d9f09ef19d037b431b4))
|
||||||
|
* 选项显示图标 ([aedc462](https://github.com/certd/certd/commit/aedc46213571a3bd93809b7af7fa17a08d546237))
|
||||||
|
* 优化证书申请成功通知发送方式 ([8002a56](https://github.com/certd/certd/commit/8002a56efc5998aa03db5711ae87f9eb4bc9e160))
|
||||||
|
* 支持短信验证码登录 ([387bcc5](https://github.com/certd/certd/commit/387bcc5fa418cdeea81a06da5e3f8cd6b43cd082))
|
||||||
|
|
||||||
|
## [1.27.9](https://github.com/certd/certd/compare/v1.27.8...v1.27.9) (2024-11-26)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 通知支持自定义webhook、anpush、iyuu、server酱 ([cbccd9e](https://github.com/certd/certd/commit/cbccd9e3d0a4c24aba772af62734666d40b22c57))
|
||||||
|
* 通知支持vocechat、bark、telegram、discord、slack ([642f57f](https://github.com/certd/certd/commit/642f57ff6d7152a9e14f59c7fc0e32a6b1751fb7))
|
||||||
|
|
||||||
|
## [1.27.8](https://github.com/certd/certd/compare/v1.27.7...v1.27.8) (2024-11-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.27.7](https://github.com/certd/certd/compare/v1.27.6...v1.27.7) (2024-11-25)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 通知管理 ([d9a00ee](https://github.com/certd/certd/commit/d9a00eeaf72735ced67c59d7983d84e3c730064a))
|
||||||
|
* 通知渠道支持测试按钮 ([b54ae27](https://github.com/certd/certd/commit/b54ae272ebc2d31b32b049d44e2299a6be7f153c))
|
||||||
|
* 优化插件开发,dnsProvider无需写http logger 变量 ([fcbb5e4](https://github.com/certd/certd/commit/fcbb5e46a112174150a62648319b8224fce3b7ed))
|
||||||
|
* 支持企业微信群聊机器人通知 ([b805a29](https://github.com/certd/certd/commit/b805a2925984144a31575b8aaa622f0c30d41b56))
|
||||||
|
|
||||||
|
## [1.27.6](https://github.com/certd/certd/compare/v1.27.5...v1.27.6) (2024-11-19)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.27.5](https://github.com/certd/certd/compare/v1.27.4...v1.27.5) (2024-11-18)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 新手导航在非编辑模式下不显示 ([18bfcc2](https://github.com/certd/certd/commit/18bfcc24ad0bde57bb04db8a4209861ec6b8ff1d))
|
||||||
|
|
||||||
|
## [1.27.4](https://github.com/certd/certd/compare/v1.27.3...v1.27.4) (2024-11-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.27.3](https://github.com/certd/certd/compare/v1.27.2...v1.27.3) (2024-11-13)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.27.2](https://github.com/certd/certd/compare/v1.27.1...v1.27.2) (2024-11-08)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 支持公共cname服务 ([3c919ee](https://github.com/certd/certd/commit/3c919ee5d1aef5d26cf3620a7c49d920786bc941))
|
||||||
|
|
||||||
|
## [1.27.1](https://github.com/certd/certd/compare/v1.27.0...v1.27.1) (2024-11-04)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 优化时间选择器,自动填写分钟和秒钟 ([396dc34](https://github.com/certd/certd/commit/396dc34a841c7d016b033736afdba8366fb2d211))
|
||||||
|
|
||||||
|
# [1.27.0](https://github.com/certd/certd/compare/v1.26.16...v1.27.0) (2024-10-31)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.26.16](https://github.com/certd/certd/compare/v1.26.15...v1.26.16) (2024-10-30)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 支持白山云cdn部署 ([b1b2cd0](https://github.com/certd/certd/commit/b1b2cd088b684eda764962abd61754c26a204d1c))
|
||||||
|
|
||||||
|
## [1.26.15](https://github.com/certd/certd/compare/v1.26.14...v1.26.15) (2024-10-28)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 默认证书更新时间设置为35天,增加腾讯云删除过期证书插件,可以避免腾讯云过期证书邮件 ([51b6fed](https://github.com/certd/certd/commit/51b6fed468eaa6f28ce4497ce303ace1a52abb96))
|
||||||
|
|
||||||
|
## [1.26.14](https://github.com/certd/certd/compare/v1.26.13...v1.26.14) (2024-10-26)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
## [1.26.13](https://github.com/certd/certd/compare/v1.26.12...v1.26.13) (2024-10-26)
|
## [1.26.13](https://github.com/certd/certd/compare/v1.26.12...v1.26.13) (2024-10-26)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/pipeline
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/pipeline",
|
"name": "@certd/pipeline",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.26.13",
|
"version": "1.29.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
|
"module": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -15,20 +16,11 @@
|
|||||||
"test": "mocha --loader=ts-node/esm"
|
"test": "mocha --loader=ts-node/esm"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/basic": "^1.26.13",
|
"@certd/basic": "^1.29.3",
|
||||||
"@certd/plus-core": "^1.26.13",
|
"@certd/plus-core": "^1.29.3",
|
||||||
"axios": "^1.7.2",
|
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"fix-path": "^4.0.0",
|
|
||||||
"http-proxy-agent": "^7.0.2",
|
|
||||||
"https-proxy-agent": "^7.0.5",
|
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"lru-cache": "^10.0.0",
|
"reflect-metadata": "^0.1.13"
|
||||||
"nanoid": "^5.0.7",
|
|
||||||
"node-forge": "^1.3.1",
|
|
||||||
"nodemailer": "^6.9.3",
|
|
||||||
"proxy-agent": "^6.4.0",
|
|
||||||
"qs": "^6.11.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-commonjs": "^23.0.4",
|
"@rollup/plugin-commonjs": "^23.0.4",
|
||||||
@@ -39,32 +31,17 @@
|
|||||||
"@types/chai": "^4.3.10",
|
"@types/chai": "^4.3.10",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/mocha": "^10.0.1",
|
"@types/mocha": "^10.0.1",
|
||||||
"@types/node-forge": "^1.3.2",
|
|
||||||
"@types/uuid": "^9.0.2",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.59.7",
|
"@typescript-eslint/eslint-plugin": "^5.59.7",
|
||||||
"@typescript-eslint/parser": "^5.59.7",
|
"@typescript-eslint/parser": "^5.59.7",
|
||||||
"chai": "4.3.10",
|
"chai": "4.3.10",
|
||||||
"dayjs": "^1.11.7",
|
|
||||||
"eslint": "^8.41.0",
|
"eslint": "^8.41.0",
|
||||||
"eslint-config-prettier": "^8.8.0",
|
"eslint-config-prettier": "^8.8.0",
|
||||||
"eslint-plugin-import": "^2.27.5",
|
|
||||||
"eslint-plugin-node": "^11.1.0",
|
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"iconv-lite": "^0.6.3",
|
|
||||||
"log4js": "^6.9.1",
|
|
||||||
"mocha": "^10.2.0",
|
"mocha": "^10.2.0",
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
"reflect-metadata": "^0.1.13",
|
|
||||||
"rimraf": "^5.0.5",
|
"rimraf": "^5.0.5",
|
||||||
"rollup": "^3.7.4",
|
"tslib": "^2.8.1",
|
||||||
"rollup-plugin-typescript2": "^0.34.1",
|
"typescript": "^5.4.2"
|
||||||
"rollup-plugin-visualizer": "^5.8.2",
|
|
||||||
"ts-node": "^10.9.1",
|
|
||||||
"tsc-esm-fix": "^3.0.0",
|
|
||||||
"tslib": "^2.5.2",
|
|
||||||
"typescript": "^5.4.2",
|
|
||||||
"vite": "^4.3.8",
|
|
||||||
"vue-tsc": "^1.6.5"
|
|
||||||
},
|
},
|
||||||
"gitHead": "11d0daa59ae409c229037189066414f29b787de0"
|
"gitHead": "ed5634ff83405ad0eb13a8456f59270ed4218734"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
import { Registrable } from "../registry/index.js";
|
import { Registrable } from "../registry/index.js";
|
||||||
import { FormItemProps } from "../dt/index.js";
|
import { FormItemProps } from "../dt/index.js";
|
||||||
import { HttpClient, ILogger, utils } from "../utils/index.js";
|
import { HttpClient, ILogger, utils } from "@certd/basic";
|
||||||
import _ from "lodash-es";
|
import * as _ from "lodash-es";
|
||||||
import { AccessRequestHandleReq } from "../core";
|
import { PluginRequestHandleReq } from "../plugin/index.js";
|
||||||
|
|
||||||
|
export type AccessRequestHandleReqInput<T = any> = {
|
||||||
|
id?: number;
|
||||||
|
title?: string;
|
||||||
|
access: T;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AccessRequestHandleReq<T = any> = PluginRequestHandleReq<AccessRequestHandleReqInput<T>>;
|
||||||
|
|
||||||
export type AccessInputDefine = FormItemProps & {
|
export type AccessInputDefine = FormItemProps & {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -10,6 +18,7 @@ export type AccessInputDefine = FormItemProps & {
|
|||||||
encrypt?: boolean;
|
encrypt?: boolean;
|
||||||
};
|
};
|
||||||
export type AccessDefine = Registrable & {
|
export type AccessDefine = Registrable & {
|
||||||
|
icon?: string;
|
||||||
input?: {
|
input?: {
|
||||||
[key: string]: AccessInputDefine;
|
[key: string]: AccessInputDefine;
|
||||||
};
|
};
|
||||||
@@ -33,6 +42,10 @@ export type AccessContext = {
|
|||||||
export abstract class BaseAccess implements IAccess {
|
export abstract class BaseAccess implements IAccess {
|
||||||
ctx!: AccessContext;
|
ctx!: AccessContext;
|
||||||
|
|
||||||
|
setCtx(ctx: AccessContext) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
async onRequest(req: AccessRequestHandleReq) {
|
async onRequest(req: AccessRequestHandleReq) {
|
||||||
if (!req.action) {
|
if (!req.action) {
|
||||||
throw new Error("action is required");
|
throw new Error("action is required");
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// src/decorator/memoryCache.decorator.ts
|
// src/decorator/memoryCache.decorator.ts
|
||||||
import { AccessContext, AccessDefine, AccessInputDefine } from "./api.js";
|
import { AccessContext, AccessDefine, AccessInputDefine } from "./api.js";
|
||||||
import { Decorator } from "../decorator/index.js";
|
import { Decorator } from "../decorator/index.js";
|
||||||
import _ from "lodash-es";
|
import * as _ from "lodash-es";
|
||||||
import { accessRegistry } from "./registry.js";
|
import { accessRegistry } from "./registry.js";
|
||||||
import { http, logger, utils } from "../utils/index.js";
|
import { http, logger, utils } from "@certd/basic";
|
||||||
|
|
||||||
// 提供一个唯一 key
|
// 提供一个唯一 key
|
||||||
export const ACCESS_CLASS_KEY = "pipeline:access";
|
export const ACCESS_CLASS_KEY = "pipeline:access";
|
||||||
@@ -56,6 +56,6 @@ export function newAccess(type: string, input: any, ctx?: AccessContext) {
|
|||||||
utils,
|
utils,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
access.ctx = ctx;
|
access.setCtx(ctx);
|
||||||
return access;
|
return access;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Registry } from "../registry/index.js";
|
import { createRegistry } from "../registry/index.js";
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export const accessRegistry = new Registry("access");
|
export const accessRegistry = createRegistry("access");
|
||||||
|
|||||||
5
packages/core/pipeline/src/core/exceptions.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export class CancelError extends Error {
|
||||||
|
constructor(message: string) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,14 +3,19 @@ import { RunHistory, RunnableCollection } from "./run-history.js";
|
|||||||
import { AbstractTaskPlugin, PluginDefine, pluginRegistry, TaskInstanceContext, UserInfo } from "../plugin/index.js";
|
import { AbstractTaskPlugin, PluginDefine, pluginRegistry, TaskInstanceContext, UserInfo } from "../plugin/index.js";
|
||||||
import { ContextFactory, IContext } from "./context.js";
|
import { ContextFactory, IContext } from "./context.js";
|
||||||
import { IStorage } from "./storage.js";
|
import { IStorage } from "./storage.js";
|
||||||
import { createAxiosService, hashUtils, logger, utils } from "../utils/index.js";
|
import { createAxiosService, hashUtils, HttpRequestConfig, ILogger, logger, utils } from "@certd/basic";
|
||||||
import { Logger } from "log4js";
|
|
||||||
import { IAccessService } from "../access/index.js";
|
import { IAccessService } from "../access/index.js";
|
||||||
import { RegistryItem } from "../registry/index.js";
|
import { RegistryItem } from "../registry/index.js";
|
||||||
import { Decorator } from "../decorator/index.js";
|
import { Decorator } from "../decorator/index.js";
|
||||||
import { ICnameProxyService, IEmailService, IPluginConfigService } from "../service/index.js";
|
import { ICnameProxyService, IEmailService, IPluginConfigService, IUrlService } from "../service/index.js";
|
||||||
import { FileStore } from "./file-store.js";
|
import { FileStore } from "./file-store.js";
|
||||||
import { cloneDeep, forEach, merge } from "lodash-es";
|
import { cloneDeep, forEach, merge } from "lodash-es";
|
||||||
|
import { INotificationService } from "../notification/index.js";
|
||||||
|
|
||||||
|
export type SysInfo = {
|
||||||
|
//系统标题
|
||||||
|
title?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type ExecutorOptions = {
|
export type ExecutorOptions = {
|
||||||
pipeline: Pipeline;
|
pipeline: Pipeline;
|
||||||
@@ -18,17 +23,21 @@ export type ExecutorOptions = {
|
|||||||
onChanged: (history: RunHistory) => Promise<void>;
|
onChanged: (history: RunHistory) => Promise<void>;
|
||||||
accessService: IAccessService;
|
accessService: IAccessService;
|
||||||
emailService: IEmailService;
|
emailService: IEmailService;
|
||||||
|
notificationService: INotificationService;
|
||||||
cnameProxyService: ICnameProxyService;
|
cnameProxyService: ICnameProxyService;
|
||||||
pluginConfigService: IPluginConfigService;
|
pluginConfigService: IPluginConfigService;
|
||||||
|
urlService: IUrlService;
|
||||||
fileRootDir?: string;
|
fileRootDir?: string;
|
||||||
user: UserInfo;
|
user: UserInfo;
|
||||||
|
baseURL?: string;
|
||||||
|
sysInfo?: SysInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Executor {
|
export class Executor {
|
||||||
pipeline: Pipeline;
|
pipeline: Pipeline;
|
||||||
runtime!: RunHistory;
|
runtime!: RunHistory;
|
||||||
contextFactory: ContextFactory;
|
contextFactory: ContextFactory;
|
||||||
logger: Logger;
|
logger: ILogger;
|
||||||
pipelineContext!: IContext;
|
pipelineContext!: IContext;
|
||||||
currentStatusMap!: RunnableCollection;
|
currentStatusMap!: RunnableCollection;
|
||||||
lastStatusMap!: RunnableCollection;
|
lastStatusMap!: RunnableCollection;
|
||||||
@@ -83,20 +92,30 @@ export class Executor {
|
|||||||
await this.onChanged(this.runtime);
|
await this.onChanged(this.runtime);
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
|
||||||
await this.runWithHistory(this.pipeline, "pipeline", async () => {
|
const result = await this.runWithHistory(this.pipeline, "pipeline", async () => {
|
||||||
return await this.runStages(this.pipeline);
|
return await this.runStages(this.pipeline);
|
||||||
});
|
});
|
||||||
if (this.lastRuntime && this.lastRuntime.pipeline.status?.status === ResultType.error) {
|
if (result === ResultType.success) {
|
||||||
await this.notification("turnToSuccess");
|
if (this.lastRuntime && this.lastRuntime.pipeline.status?.status === ResultType.error) {
|
||||||
|
await this.notification("turnToSuccess");
|
||||||
|
} else {
|
||||||
|
await this.notification("success");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await this.notification("success");
|
return result;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
await this.notification("error", e);
|
await this.notification("error", e);
|
||||||
this.logger.error("pipeline 执行失败", e);
|
this.logger.error("pipeline 执行失败", e);
|
||||||
} finally {
|
} finally {
|
||||||
clearInterval(intervalFlushLogId);
|
clearInterval(intervalFlushLogId);
|
||||||
await this.onChanged(this.runtime);
|
await this.onChanged(this.runtime);
|
||||||
await this.pipelineContext.setObj("lastRuntime", this.runtime);
|
//保存之前移除logs
|
||||||
|
const lastRuntime: any = {
|
||||||
|
...this.runtime,
|
||||||
|
};
|
||||||
|
delete lastRuntime.logs;
|
||||||
|
delete lastRuntime._loggers;
|
||||||
|
await this.pipelineContext.setObj("lastRuntime", lastRuntime);
|
||||||
this.logger.info(`pipeline.${this.pipeline.id} end`);
|
this.logger.info(`pipeline.${this.pipeline.id} end`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,7 +154,12 @@ export class Executor {
|
|||||||
this.runtime.success(runnable);
|
this.runtime.success(runnable);
|
||||||
return ResultType.success;
|
return ResultType.success;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.runtime.error(runnable, e);
|
if (e.name === "CancelError" || this.abort.signal.aborted) {
|
||||||
|
this.runtime.cancel(runnable);
|
||||||
|
return ResultType.canceled;
|
||||||
|
} else {
|
||||||
|
this.runtime.error(runnable, e);
|
||||||
|
}
|
||||||
throw e;
|
throw e;
|
||||||
} finally {
|
} finally {
|
||||||
this.runtime.finally(runnable);
|
this.runtime.finally(runnable);
|
||||||
@@ -285,17 +309,29 @@ export class Executor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const http = createAxiosService({ logger: currentLogger });
|
const http = createAxiosService({ logger: currentLogger });
|
||||||
|
const download = async (config: HttpRequestConfig, savePath: string) => {
|
||||||
|
await utils.download({
|
||||||
|
http,
|
||||||
|
logger: currentLogger,
|
||||||
|
config,
|
||||||
|
savePath,
|
||||||
|
});
|
||||||
|
};
|
||||||
const taskCtx: TaskInstanceContext = {
|
const taskCtx: TaskInstanceContext = {
|
||||||
pipeline: this.pipeline,
|
pipeline: this.pipeline,
|
||||||
|
runtime: this.runtime,
|
||||||
step,
|
step,
|
||||||
lastStatus,
|
lastStatus,
|
||||||
http,
|
http,
|
||||||
|
download,
|
||||||
logger: currentLogger,
|
logger: currentLogger,
|
||||||
inputChanged,
|
inputChanged,
|
||||||
accessService: this.options.accessService,
|
accessService: this.options.accessService,
|
||||||
emailService: this.options.emailService,
|
emailService: this.options.emailService,
|
||||||
cnameProxyService: this.options.cnameProxyService,
|
cnameProxyService: this.options.cnameProxyService,
|
||||||
pluginConfigService: this.options.pluginConfigService,
|
pluginConfigService: this.options.pluginConfigService,
|
||||||
|
notificationService: this.options.notificationService,
|
||||||
|
urlService: this.options.urlService,
|
||||||
pipelineContext: this.pipelineContext,
|
pipelineContext: this.pipelineContext,
|
||||||
userContext: this.contextFactory.getContext("user", this.options.user.id),
|
userContext: this.contextFactory.getContext("user", this.options.user.id),
|
||||||
fileStore: new FileStore({
|
fileStore: new FileStore({
|
||||||
@@ -310,7 +346,7 @@ export class Executor {
|
|||||||
instance.setCtx(taskCtx);
|
instance.setCtx(taskCtx);
|
||||||
|
|
||||||
await instance.onInstance();
|
await instance.onInstance();
|
||||||
await instance.execute();
|
const result = await instance.execute();
|
||||||
//执行结果处理
|
//执行结果处理
|
||||||
if (instance._result.clearLastStatus) {
|
if (instance._result.clearLastStatus) {
|
||||||
//是否需要清除所有状态
|
//是否需要清除所有状态
|
||||||
@@ -338,26 +374,30 @@ export class Executor {
|
|||||||
merge(vars, instance._result.pipelinePrivateVars);
|
merge(vars, instance._result.pipelinePrivateVars);
|
||||||
await this.pipelineContext.setObj("privateVars", vars);
|
await this.pipelineContext.setObj("privateVars", vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
async notification(when: NotificationWhen, error?: any) {
|
async notification(when: NotificationWhen, error?: any) {
|
||||||
if (!this.pipeline.notifications) {
|
if (!this.pipeline.notifications) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const url = await this.options.urlService.getPipelineDetailUrl(this.pipeline.id, this.runtime.id);
|
||||||
let subject = "";
|
let subject = "";
|
||||||
let content = "";
|
let content = "";
|
||||||
|
const errorMessage = error?.message;
|
||||||
if (when === "start") {
|
if (when === "start") {
|
||||||
subject = `【CertD】开始执行,【${this.pipeline.id}】${this.pipeline.title}`;
|
subject = `开始执行,${this.pipeline.title}【${this.pipeline.id}】`;
|
||||||
content = `buildId:${this.runtime.id}`;
|
content = `流水线ID:${this.pipeline.id},运行ID:${this.runtime.id}`;
|
||||||
} else if (when === "success") {
|
} else if (when === "success") {
|
||||||
subject = `【CertD】执行成功,【${this.pipeline.id}】${this.pipeline.title}`;
|
subject = `执行成功,${this.pipeline.title}【${this.pipeline.id}】`;
|
||||||
content = `buildId:${this.runtime.id}`;
|
content = `流水线ID:${this.pipeline.id},运行ID:${this.runtime.id}`;
|
||||||
} else if (when === "turnToSuccess") {
|
} else if (when === "turnToSuccess") {
|
||||||
subject = `【CertD】执行成功(错误转成功),【${this.pipeline.id}】${this.pipeline.title}`;
|
subject = `执行成功(失败转成功),${this.pipeline.title}【${this.pipeline.id}】`;
|
||||||
content = `buildId:${this.runtime.id}`;
|
content = `流水线ID:${this.pipeline.id},运行ID:${this.runtime.id}`;
|
||||||
} else if (when === "error") {
|
} else if (when === "error") {
|
||||||
subject = `【CertD】执行失败,【${this.pipeline.id}】${this.pipeline.title}`;
|
subject = `执行失败,${this.pipeline.title}【${this.pipeline.id}】`;
|
||||||
content = `buildId:${this.runtime.id}\nerror:${error.message}`;
|
content = `流水线ID:${this.pipeline.id},运行ID:${this.runtime.id}\n\n${this.currentStatusMap?.currentStep?.title} 执行失败\n\n错误详情:${error.message}`;
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -366,10 +406,10 @@ export class Executor {
|
|||||||
if (!notification.when.includes(when)) {
|
if (!notification.when.includes(when)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notification.type === "email") {
|
if (notification.type === "email") {
|
||||||
try {
|
try {
|
||||||
await this.options.emailService?.send({
|
await this.options.emailService?.send({
|
||||||
userId: this.pipeline.userId,
|
|
||||||
subject,
|
subject,
|
||||||
content,
|
content,
|
||||||
receivers: notification.options.receivers,
|
receivers: notification.options.receivers,
|
||||||
@@ -377,6 +417,29 @@ export class Executor {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error("send email error", e);
|
logger.error("send email error", e);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
//发送通知
|
||||||
|
await this.options.notificationService.send({
|
||||||
|
id: notification.notificationId,
|
||||||
|
useDefault: true,
|
||||||
|
useEmail: false,
|
||||||
|
logger: this.logger,
|
||||||
|
body: {
|
||||||
|
title: subject,
|
||||||
|
content,
|
||||||
|
userId: this.pipeline.userId,
|
||||||
|
pipeline: this.pipeline,
|
||||||
|
result: this.lastRuntime.pipeline.status,
|
||||||
|
pipelineId: this.pipeline.id,
|
||||||
|
historyId: this.runtime.id,
|
||||||
|
errorMessage,
|
||||||
|
url,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
logger.error("send notification error", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { fileUtils } from "../utils/index.js";
|
import { fileUtils } from "@certd/basic";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { logger } from "../utils/index.js";
|
import { logger } from "@certd/basic";
|
||||||
|
|
||||||
export type FileStoreOptions = {
|
export type FileStoreOptions = {
|
||||||
rootDir?: string;
|
rootDir?: string;
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
import { HttpClient, ILogger, utils } from "../utils/index.js";
|
|
||||||
|
|
||||||
export type PluginRequestHandleReq<T = any> = {
|
|
||||||
typeName: string;
|
|
||||||
action: string;
|
|
||||||
input: T;
|
|
||||||
data: any;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type AccessRequestHandleReqInput<T = any> = {
|
|
||||||
id?: number;
|
|
||||||
title?: string;
|
|
||||||
access: T;
|
|
||||||
};
|
|
||||||
export type AccessRequestHandleContext = {
|
|
||||||
http: HttpClient;
|
|
||||||
logger: ILogger;
|
|
||||||
utils: typeof utils;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type AccessRequestHandleReq<T = any> = PluginRequestHandleReq<AccessRequestHandleReqInput<T>>;
|
|
||||||