mirror of
https://github.com/acmesh-official/acme.sh
synced 2025-11-05 22:45:52 +08:00
Compare commits
971 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc7f86104e | ||
|
|
d057a9bb6d | ||
|
|
167aba6f26 | ||
|
|
9ecd84080b | ||
|
|
22d260f4e6 | ||
|
|
ea94477cd4 | ||
|
|
522c953860 | ||
|
|
f86ee84457 | ||
|
|
2d282597ca | ||
|
|
8635d89cc8 | ||
|
|
dc341ef9c1 | ||
|
|
beb31ab2fa | ||
|
|
e0214a2c2a | ||
|
|
5275daa66c | ||
|
|
fb27261568 | ||
|
|
5a20ce81e3 | ||
|
|
1454b85671 | ||
|
|
fc4dba4468 | ||
|
|
adff28dade | ||
|
|
c345ecae63 | ||
|
|
e6461380c6 | ||
|
|
deb2a3e415 | ||
|
|
c71dcd7611 | ||
|
|
c1e05664ed | ||
|
|
0f1e5f4fa4 | ||
|
|
0fa20da990 | ||
|
|
02fb40c507 | ||
|
|
dc6ea97877 | ||
|
|
031d53b04f | ||
|
|
3006c90fb8 | ||
|
|
9cec2688ed | ||
|
|
65c3dc21f4 | ||
|
|
cefa7d940a | ||
|
|
fab292d2de | ||
|
|
00bbe68f78 | ||
|
|
fa3591f4f2 | ||
|
|
10cfc6838d | ||
|
|
42e78f9a3e | ||
|
|
0122eabd44 | ||
|
|
435bb3f1d3 | ||
|
|
1d59d43286 | ||
|
|
fe30bf7d09 | ||
|
|
5f68ad4e19 | ||
|
|
3fc39aad33 | ||
|
|
a94653ba77 | ||
|
|
d8637b2c0f | ||
|
|
f1b6016157 | ||
|
|
de99d6d9fc | ||
|
|
bb8386ab85 | ||
|
|
ca6226359b | ||
|
|
adfafe5c54 | ||
|
|
a8d8fefceb | ||
|
|
3bb5943b20 | ||
|
|
57da04b5ec | ||
|
|
e711d168df | ||
|
|
1700f064b3 | ||
|
|
de902166a8 | ||
|
|
2f08bd1965 | ||
|
|
13c68cd799 | ||
|
|
c7d78f4594 | ||
|
|
2f1ca949f0 | ||
|
|
a6488ff9ac | ||
|
|
cb5eae888d | ||
|
|
b6f7710621 | ||
|
|
3e36f05a8c | ||
|
|
bcb7e5f2c8 | ||
|
|
3cefcd8204 | ||
|
|
4cd1871816 | ||
|
|
7aaa9583fa | ||
|
|
dd582c0306 | ||
|
|
5cded5b53e | ||
|
|
0a64567822 | ||
|
|
7ca861805d | ||
|
|
6b6faa8129 | ||
|
|
f84577bcda | ||
|
|
37f9fd3498 | ||
|
|
11aef82993 | ||
|
|
9861e2d724 | ||
|
|
7ae0d0caa3 | ||
|
|
93d2c9a3f0 | ||
|
|
60569fdd83 | ||
|
|
0f61e9c15e | ||
|
|
d81fc155cb | ||
|
|
60f7750d77 | ||
|
|
9bdfd8f4fe | ||
|
|
945b7de76f | ||
|
|
3c35eadbc4 | ||
|
|
ab86e056a2 | ||
|
|
a2bc79ddd5 | ||
|
|
5789e80d74 | ||
|
|
65868ab8a7 | ||
|
|
89586530a5 | ||
|
|
0d93145834 | ||
|
|
fe4113d623 | ||
|
|
9a0e15cced | ||
|
|
e0c63d58b2 | ||
|
|
f7f8ea9b97 | ||
|
|
58cad98cd8 | ||
|
|
74ffbb2172 | ||
|
|
cc9c85cc1a | ||
|
|
a8f252e45d | ||
|
|
f7e09af5c9 | ||
|
|
304cb56337 | ||
|
|
6b7b5caf54 | ||
|
|
fd461fe015 | ||
|
|
2797d2c535 | ||
|
|
f440656572 | ||
|
|
b1d019146a | ||
|
|
1dbc58d4e0 | ||
|
|
47ccb28482 | ||
|
|
744dea00ca | ||
|
|
373c2b379c | ||
|
|
957bbab440 | ||
|
|
bd48c99383 | ||
|
|
52d1d421a3 | ||
|
|
c3cc13595d | ||
|
|
adc8031e34 | ||
|
|
0974c74a89 | ||
|
|
c64aae6f39 | ||
|
|
b7b1714637 | ||
|
|
d8525493a1 | ||
|
|
30d0945855 | ||
|
|
ffde1f8343 | ||
|
|
96c35b41ed | ||
|
|
dc2979926f | ||
|
|
ff357dd3fb | ||
|
|
f35e15204d | ||
|
|
3ae4ba3300 | ||
|
|
0d8a314bcf | ||
|
|
e7cfde1904 | ||
|
|
aa41df4e7d | ||
|
|
d73953af3d | ||
|
|
54eec82311 | ||
|
|
dab244ad25 | ||
|
|
dbe7cb8dbb | ||
|
|
e814cccc44 | ||
|
|
1078fdc157 | ||
|
|
4bf4259dda | ||
|
|
03b53cbb60 | ||
|
|
7ef1340e2a | ||
|
|
c0b87adee5 | ||
|
|
4a8c2251e0 | ||
|
|
d1df5f3021 | ||
|
|
e1acea52f8 | ||
|
|
2e9f159225 | ||
|
|
2fcda9a73a | ||
|
|
78ba205f4d | ||
|
|
f44dec2c8d | ||
|
|
8c07af6fc7 | ||
|
|
cd01104de9 | ||
|
|
28f438a6bd | ||
|
|
9ff89b570f | ||
|
|
bc90376489 | ||
|
|
43b5ea801f | ||
|
|
9863e7ea6e | ||
|
|
ebaa39b03f | ||
|
|
fa3d7ad14b | ||
|
|
c51104f956 | ||
|
|
84795ff4d9 | ||
|
|
cc5c722e29 | ||
|
|
4fcddd1893 | ||
|
|
c8604255e4 | ||
|
|
492826a7f2 | ||
|
|
5e64781d65 | ||
|
|
2d4b900e33 | ||
|
|
d2481f5790 | ||
|
|
49f6104f03 | ||
|
|
2728d2aa6e | ||
|
|
0588fc6b7c | ||
|
|
e3cd52cab4 | ||
|
|
b2c6b9a320 | ||
|
|
39fa40ab12 | ||
|
|
0bf87bf4af | ||
|
|
92d37f6eaf | ||
|
|
d3b022fe17 | ||
|
|
79640f6b7d | ||
|
|
2cbdf274b1 | ||
|
|
6af5293315 | ||
|
|
bd3a2b1bb5 | ||
|
|
ff090d2f74 | ||
|
|
68e3a12a91 | ||
|
|
50eda6b678 | ||
|
|
192ec598a3 | ||
|
|
5b449999a5 | ||
|
|
afed62f6de | ||
|
|
59d1e16f9c | ||
|
|
dbe0d477d6 | ||
|
|
7248560169 | ||
|
|
f840f7d75b | ||
|
|
6e14a073ff | ||
|
|
cf3839ecec | ||
|
|
aa8cf76fb1 | ||
|
|
10b4bb598a | ||
|
|
de14d59bb3 | ||
|
|
d76272f0ea | ||
|
|
e04093efe2 | ||
|
|
bd6bbba948 | ||
|
|
37e4f35c93 | ||
|
|
0084cb7403 | ||
|
|
99e5c159a7 | ||
|
|
802121d54a | ||
|
|
160b2e95c9 | ||
|
|
7ec692cdef | ||
|
|
3dca67112d | ||
|
|
f8dac5905c | ||
|
|
48e4e41e05 | ||
|
|
22374b81de | ||
|
|
b9157e29cb | ||
|
|
bd247c35f2 | ||
|
|
7da9a45c61 | ||
|
|
122dfa12ac | ||
|
|
1905830b20 | ||
|
|
bfb41ce123 | ||
|
|
85e3ecfe0b | ||
|
|
9e073c954d | ||
|
|
b79c3f5cc4 | ||
|
|
ad5acb80fe | ||
|
|
7b7c834b08 | ||
|
|
42827be7c3 | ||
|
|
7022d27b8e | ||
|
|
ab911f1ce9 | ||
|
|
a6a1de50c8 | ||
|
|
97723fbbc9 | ||
|
|
2e58cf1168 | ||
|
|
3ca97d7258 | ||
|
|
9786dccdee | ||
|
|
a3612f53dd | ||
|
|
112257c49e | ||
|
|
d8e2b96bce | ||
|
|
6992659ba9 | ||
|
|
05696d443a | ||
|
|
f59a925897 | ||
|
|
afacdfcb95 | ||
|
|
8cb1b6b5d5 | ||
|
|
f7d9d53ad2 | ||
|
|
f4315e2c6f | ||
|
|
f0ac566c93 | ||
|
|
50f6a459cf | ||
|
|
179c80ae6d | ||
|
|
6e72f161a6 | ||
|
|
f71d8d7348 | ||
|
|
a12a3640a7 | ||
|
|
3b7bc5a56a | ||
|
|
e09d45c844 | ||
|
|
36fc321096 | ||
|
|
98a7a01dbb | ||
|
|
0f7be90500 | ||
|
|
7aaf4432d4 | ||
|
|
884a8995b4 | ||
|
|
bb42595275 | ||
|
|
a4bd89c938 | ||
|
|
f364d4fbef | ||
|
|
f899d0d8ed | ||
|
|
074cf00a7c | ||
|
|
15d10eeebc | ||
|
|
bea71f3411 | ||
|
|
eb99803b53 | ||
|
|
a60d0c4108 | ||
|
|
1cc3a13c49 | ||
|
|
feffbba6de | ||
|
|
6ea09444ec | ||
|
|
f1f486dacf | ||
|
|
fec4af3194 | ||
|
|
5342c7c82b | ||
|
|
8454ffa331 | ||
|
|
199977be6a | ||
|
|
00dbc3881f | ||
|
|
d93a5b2d20 | ||
|
|
8ca5ca6594 | ||
|
|
fe890c62f4 | ||
|
|
e15513bfdd | ||
|
|
dbe569c0d9 | ||
|
|
f2e1b589b5 | ||
|
|
377a37e4c9 | ||
|
|
6e163208b4 | ||
|
|
87a7bde618 | ||
|
|
37b0498699 | ||
|
|
59f976dc48 | ||
|
|
8565a853a8 | ||
|
|
dfd49e46ad | ||
|
|
73bbaced62 | ||
|
|
0c8870cb7f | ||
|
|
1a90f66f73 | ||
|
|
558e706bde | ||
|
|
1a08be0a3f | ||
|
|
29b2960805 | ||
|
|
f7f3a0bf0d | ||
|
|
ae4c186f55 | ||
|
|
af534a73fc | ||
|
|
772bbdc862 | ||
|
|
86521ec443 | ||
|
|
e3c4c9265d | ||
|
|
b3f8612e61 | ||
|
|
27b1dd04c4 | ||
|
|
46a876445f | ||
|
|
9bb58e47a7 | ||
|
|
b8447fcab8 | ||
|
|
3abcfd8fa9 | ||
|
|
f4ff2d5d2e | ||
|
|
09b41aa667 | ||
|
|
87dc4fe388 | ||
|
|
eed8a7f078 | ||
|
|
c18364c755 | ||
|
|
04946e992e | ||
|
|
5533782152 | ||
|
|
3f42487f0a | ||
|
|
8bdcd22486 | ||
|
|
b32d22731b | ||
|
|
b788cc24d1 | ||
|
|
94948f6d34 | ||
|
|
e5b76ed4c4 | ||
|
|
29a2920a2c | ||
|
|
089d35708b | ||
|
|
9b0b5bce9f | ||
|
|
ef20a0128f | ||
|
|
3039e4eb6d | ||
|
|
9143cd1485 | ||
|
|
13d31ecb7f | ||
|
|
a936b2f1f6 | ||
|
|
8d00f489cd | ||
|
|
b793dbf977 | ||
|
|
d52b38777a | ||
|
|
56cf93dff2 | ||
|
|
67d84cadad | ||
|
|
b384a24c0e | ||
|
|
66a68edbe6 | ||
|
|
dcf3d7234e | ||
|
|
0da839cce3 | ||
|
|
b6f62ac446 | ||
|
|
15ee036db1 | ||
|
|
6db8ae451a | ||
|
|
a7f3d413ef | ||
|
|
3b7be478aa | ||
|
|
7f39cdc856 | ||
|
|
80006f4730 | ||
|
|
a51025fe8f | ||
|
|
c42ed9c693 | ||
|
|
c48c8d07de | ||
|
|
4d4b6edbc2 | ||
|
|
2014ca9feb | ||
|
|
a9f631f404 | ||
|
|
ba468bb5e4 | ||
|
|
cf86d57a9f | ||
|
|
9e958f4e32 | ||
|
|
c7f6f20c9d | ||
|
|
1984f44ffe | ||
|
|
02de281e40 | ||
|
|
ae035deb92 | ||
|
|
edd1b60c3d | ||
|
|
55a3709bd1 | ||
|
|
d1fc01a407 | ||
|
|
65293f81d9 | ||
|
|
0afb0f7958 | ||
|
|
dd958872a8 | ||
|
|
62a2ce1d35 | ||
|
|
b556908cab | ||
|
|
e69a19db5c | ||
|
|
d86414febb | ||
|
|
832318fab1 | ||
|
|
80ad62ff56 | ||
|
|
ee50f254df | ||
|
|
cc0be6cd90 | ||
|
|
a7455d7edd | ||
|
|
b7c370fff7 | ||
|
|
8fd3a64e35 | ||
|
|
3761fb4377 | ||
|
|
0472f5da6a | ||
|
|
09041fb81d | ||
|
|
299a157409 | ||
|
|
53ede7b0d8 | ||
|
|
cd13aee3e7 | ||
|
|
8b3acb719e | ||
|
|
2961a90e7f | ||
|
|
db8a2d0c65 | ||
|
|
a6b5f0c9d4 | ||
|
|
8d136c6a25 | ||
|
|
4d94270cde | ||
|
|
e0d96bcb39 | ||
|
|
0d7b831661 | ||
|
|
0c9e4f67a8 | ||
|
|
da2c386b60 | ||
|
|
4770364d42 | ||
|
|
db3f131dfc | ||
|
|
d7f58c64f8 | ||
|
|
41b6aebe7c | ||
|
|
7d50332246 | ||
|
|
0d0478245f | ||
|
|
f680ede980 | ||
|
|
b7caf7a016 | ||
|
|
891198e4f3 | ||
|
|
38c5910be4 | ||
|
|
327e2fb0a4 | ||
|
|
c20c219990 | ||
|
|
4c30250782 | ||
|
|
caf23f9a04 | ||
|
|
beab808b76 | ||
|
|
6c8920f63e | ||
|
|
d108072bfb | ||
|
|
8cc7c5349a | ||
|
|
fb33ea2a0b | ||
|
|
63fca33b04 | ||
|
|
0548ad2fc6 | ||
|
|
623d615cd7 | ||
|
|
126df9647b | ||
|
|
2e2e7cd054 | ||
|
|
0ebc9f7a44 | ||
|
|
a8fba65cbd | ||
|
|
0b0476e196 | ||
|
|
f99d6dac08 | ||
|
|
cd2b7cd943 | ||
|
|
af759f2330 | ||
|
|
51be15f66d | ||
|
|
110e25e784 | ||
|
|
8414100d0b | ||
|
|
a3f4cb154e | ||
|
|
e6e22a1ca1 | ||
|
|
bb5f3cc326 | ||
|
|
7623025b90 | ||
|
|
56c98e9295 | ||
|
|
b937665b90 | ||
|
|
a7bc2293c0 | ||
|
|
0d25f7612b | ||
|
|
84e4181ed7 | ||
|
|
f66a29d1c3 | ||
|
|
dbd3881cea | ||
|
|
df753e2619 | ||
|
|
7eb6bbe65f | ||
|
|
a570fda1cb | ||
|
|
3b06fa6523 | ||
|
|
dcdbe2fbb8 | ||
|
|
dc1f36da43 | ||
|
|
cbb7082afd | ||
|
|
6ee72e119c | ||
|
|
05dbd395e6 | ||
|
|
69e7360cc3 | ||
|
|
7ef2533b98 | ||
|
|
97f87c4229 | ||
|
|
42a5cd961d | ||
|
|
bf00d3157f | ||
|
|
cf3ff4c136 | ||
|
|
7fe06adcfd | ||
|
|
ae3e5dbf2c | ||
|
|
20304590b4 | ||
|
|
2d8c0c0131 | ||
|
|
70f4cad2ca | ||
|
|
1f777a94a7 | ||
|
|
7560c64f46 | ||
|
|
bddde60522 | ||
|
|
e9366f8c76 | ||
|
|
4dba84d09e | ||
|
|
0cce2d6098 | ||
|
|
acbd8bce21 | ||
|
|
dea8a08b64 | ||
|
|
dde1bab1a8 | ||
|
|
799e402077 | ||
|
|
ce629e8e70 | ||
|
|
20cfc4ac66 | ||
|
|
132d5e8253 | ||
|
|
cb8b341fb4 | ||
|
|
982c54b605 | ||
|
|
67f543332a | ||
|
|
88ac4086c2 | ||
|
|
15f96b7239 | ||
|
|
0ea84ad799 | ||
|
|
1522b713da | ||
|
|
fe6b27bb59 | ||
|
|
df14b15397 | ||
|
|
7dd12044de | ||
|
|
06e12a30e7 | ||
|
|
d3fefd223d | ||
|
|
c0639c6608 | ||
|
|
05a2eb3df4 | ||
|
|
d4befeb536 | ||
|
|
f7f1168aad | ||
|
|
d6cf15368a | ||
|
|
a5fbf3fb80 | ||
|
|
3cf8f78745 | ||
|
|
59dab6eac7 | ||
|
|
553d861b8a | ||
|
|
7b5d94d062 | ||
|
|
cb021efaee | ||
|
|
c2344f3717 | ||
|
|
f537c606f7 | ||
|
|
c8f48a4a90 | ||
|
|
c2ad1b4e46 | ||
|
|
ba9d146d6c | ||
|
|
a5b04a0328 | ||
|
|
01249d0cb9 | ||
|
|
71c273fbcb | ||
|
|
aa9cbf7c55 | ||
|
|
429b18ed48 | ||
|
|
2690c05781 | ||
|
|
e3b688c9d8 | ||
|
|
41b6f18a5d | ||
|
|
5a59c39036 | ||
|
|
a02dd18ad7 | ||
|
|
16bdc7d0a3 | ||
|
|
40002e8040 | ||
|
|
6748c55c04 | ||
|
|
deb63b4adf | ||
|
|
015a9b9271 | ||
|
|
ab2305e259 | ||
|
|
b99c998057 | ||
|
|
6c0a7144f6 | ||
|
|
bf50fce5bd | ||
|
|
8718b156c4 | ||
|
|
7bbdd1f839 | ||
|
|
ffed1a4afa | ||
|
|
1bfd3642e8 | ||
|
|
577f4e0cc3 | ||
|
|
e2f05f3fc9 | ||
|
|
27f30631ed | ||
|
|
1ccfa96c2e | ||
|
|
a2c64e79ff | ||
|
|
7b623f85cd | ||
|
|
ed63eb6833 | ||
|
|
b8d0d3c242 | ||
|
|
fe1bfe9ae1 | ||
|
|
7154c9ee5d | ||
|
|
057c95bd1c | ||
|
|
0cafc00c4f | ||
|
|
75d2898efd | ||
|
|
764a4c99fa | ||
|
|
160513c671 | ||
|
|
a2af26635f | ||
|
|
63869deeb2 | ||
|
|
91e387e8b9 | ||
|
|
7d13146859 | ||
|
|
699d2b7e7e | ||
|
|
257de15c73 | ||
|
|
5a0225d033 | ||
|
|
bd2d0e6ad3 | ||
|
|
0c0d1d4e52 | ||
|
|
eab9603921 | ||
|
|
c07db3aa14 | ||
|
|
a19f7481b2 | ||
|
|
2905edce35 | ||
|
|
04a5d794ac | ||
|
|
264b9819ff | ||
|
|
4610204c83 | ||
|
|
ecf1f17cf4 | ||
|
|
9f942a6b65 | ||
|
|
f4ed1b32b8 | ||
|
|
ec0e871592 | ||
|
|
7a756ebc4d | ||
|
|
16dc21afff | ||
|
|
3a1c6d84f0 | ||
|
|
e684abdacd | ||
|
|
e275cb1efd | ||
|
|
60315e5b91 | ||
|
|
43b1a4bf5a | ||
|
|
cdb238e41c | ||
|
|
3871e44d9c | ||
|
|
5a51454d13 | ||
|
|
d102943a32 | ||
|
|
a0b27ddbd8 | ||
|
|
b950b04e89 | ||
|
|
c9a55f395b | ||
|
|
424da01878 | ||
|
|
3c933158c8 | ||
|
|
7221d488e5 | ||
|
|
1c16931e26 | ||
|
|
0a4b70dbd2 | ||
|
|
666c716bda | ||
|
|
be477d7ae3 | ||
|
|
6c8a623b88 | ||
|
|
ff8de34415 | ||
|
|
f8ca6d9833 | ||
|
|
dbab519004 | ||
|
|
e888c96591 | ||
|
|
59519f0493 | ||
|
|
e02f07d356 | ||
|
|
2c90d220b8 | ||
|
|
9feeba8d4b | ||
|
|
45090fc897 | ||
|
|
d761bdc1b1 | ||
|
|
287a8c76b5 | ||
|
|
a7dd86de71 | ||
|
|
c541a2e5de | ||
|
|
41dbf1ddac | ||
|
|
70ed6b96d1 | ||
|
|
ef26075a1c | ||
|
|
91c87446be | ||
|
|
dd207e1f02 | ||
|
|
e947870da9 | ||
|
|
f0b5f592dc | ||
|
|
773a2a6cfe | ||
|
|
c2a7e384ba | ||
|
|
4a8b35ef5f | ||
|
|
5cd0db32df | ||
|
|
ef01de6149 | ||
|
|
4e9749f655 | ||
|
|
abb7a1fd47 | ||
|
|
60bcee8c1d | ||
|
|
8ded524236 | ||
|
|
0a47f48191 | ||
|
|
8601267b90 | ||
|
|
6767e0c52d | ||
|
|
5141d1775d | ||
|
|
374af996d9 | ||
|
|
dcc9624c15 | ||
|
|
b3df1a2bf8 | ||
|
|
3fc3c02a4f | ||
|
|
874ddf9a32 | ||
|
|
69aeb70cc3 | ||
|
|
47e60cefe3 | ||
|
|
4ea7f3cda5 | ||
|
|
03288b521a | ||
|
|
4b0a7a6e1f | ||
|
|
383287adcd | ||
|
|
5c00afc6fe | ||
|
|
025e0e8093 | ||
|
|
35fb1f8585 | ||
|
|
9fb14eef0e | ||
|
|
5d6d0c6176 | ||
|
|
dd707242ef | ||
|
|
4f32f1285a | ||
|
|
a6ecdbae29 | ||
|
|
4904d100ff | ||
|
|
7a1f94bc20 | ||
|
|
f9320fff8f | ||
|
|
3dde83d8a0 | ||
|
|
f3e77a989c | ||
|
|
f3539b0354 | ||
|
|
4e5d4b9695 | ||
|
|
864315f6d1 | ||
|
|
713b7338ea | ||
|
|
53117b2f4c | ||
|
|
90623142e1 | ||
|
|
43503a20e5 | ||
|
|
ec53b27dfe | ||
|
|
238ecfc539 | ||
|
|
b888792940 | ||
|
|
e3d1ab52f8 | ||
|
|
f9c2874c35 | ||
|
|
2304f005e3 | ||
|
|
b95f836256 | ||
|
|
c94f9f21af | ||
|
|
fc336e3733 | ||
|
|
fc1df9f9a5 | ||
|
|
5a604bfdee | ||
|
|
281951a86b | ||
|
|
35ec3adadc | ||
|
|
b9256a1ba7 | ||
|
|
734c9a1aa5 | ||
|
|
6502a71083 | ||
|
|
f2634b44cd | ||
|
|
dcf9c467c3 | ||
|
|
3dcacc1f8d | ||
|
|
7cb81b0f35 | ||
|
|
8155ba5224 | ||
|
|
7169060425 | ||
|
|
ddb9dd4e45 | ||
|
|
2a05f24cb6 | ||
|
|
039e4c662d | ||
|
|
70351677a1 | ||
|
|
33cadfb97d | ||
|
|
5fbaeda217 | ||
|
|
b44ba0d21a | ||
|
|
b42532afe9 | ||
|
|
da6a335b87 | ||
|
|
0e8fef73bb | ||
|
|
7122a960fa | ||
|
|
d5b649a1a4 | ||
|
|
233c724b2d | ||
|
|
e1eb001872 | ||
|
|
5899d7034f | ||
|
|
23c3e9482f | ||
|
|
dd980d9dca | ||
|
|
d4ed50a915 | ||
|
|
d986c7d126 | ||
|
|
67a2a4f249 | ||
|
|
a6e87e7e08 | ||
|
|
33da8a7f62 | ||
|
|
68c533f777 | ||
|
|
671eecf203 | ||
|
|
2454ac8ef1 | ||
|
|
20f097faa4 | ||
|
|
5dba8b493d | ||
|
|
eb27013fba | ||
|
|
4f8d1c5c9d | ||
|
|
74168c3e05 | ||
|
|
cece848801 | ||
|
|
7ddbeaa078 | ||
|
|
2d4aa7ff8b | ||
|
|
79e044ac31 | ||
|
|
15ae5a5135 | ||
|
|
5684b7c329 | ||
|
|
7e96120353 | ||
|
|
cc36421fe5 | ||
|
|
683aa727d5 | ||
|
|
ea07b495ac | ||
|
|
8d211c3524 | ||
|
|
ab8df82563 | ||
|
|
8ba9c4ab97 | ||
|
|
2f70b8682e | ||
|
|
86dd4ea480 | ||
|
|
204e5f4418 | ||
|
|
044a9bb6d3 | ||
|
|
a31143328e | ||
|
|
2bb29a105c | ||
|
|
0013d98d04 | ||
|
|
916743f44b | ||
|
|
edebe65d95 | ||
|
|
c43fcd0af6 | ||
|
|
9a5c2b88dc | ||
|
|
aaee0414c8 | ||
|
|
d0c2fb9761 | ||
|
|
4f076c6924 | ||
|
|
51d4d1451a | ||
|
|
7b9d76dc65 | ||
|
|
f91aeea91c | ||
|
|
4cabf84be9 | ||
|
|
8a1f038a80 | ||
|
|
c9cab9ab74 | ||
|
|
bd78120bd5 | ||
|
|
0de3bf0ac7 | ||
|
|
2d144a8b43 | ||
|
|
1a140a5515 | ||
|
|
1ea8cfbfb0 | ||
|
|
64fda95186 | ||
|
|
7843c0c1b0 | ||
|
|
a3784854a7 | ||
|
|
8b7c000f47 | ||
|
|
5b8d7a3f29 | ||
|
|
328dbd57d4 | ||
|
|
a8c448f4cb | ||
|
|
de0419228f | ||
|
|
d8a4e47a13 | ||
|
|
bc920949cb | ||
|
|
0717f8591c | ||
|
|
affb65219e | ||
|
|
3e628f2678 | ||
|
|
ddabc38e3f | ||
|
|
c0097497be | ||
|
|
78198bfdaf | ||
|
|
2fb9c923f4 | ||
|
|
c485011ed1 | ||
|
|
0b8ae68213 | ||
|
|
0e73128f40 | ||
|
|
927c003d22 | ||
|
|
bd73823828 | ||
|
|
11582bc7d3 | ||
|
|
20ed4f96ba | ||
|
|
19790e9011 | ||
|
|
3a29e03458 | ||
|
|
e2eb685d76 | ||
|
|
86cb28fe34 | ||
|
|
bcc9679339 | ||
|
|
e5aeff50dc | ||
|
|
5f44c195e9 | ||
|
|
e4387e4aad | ||
|
|
b1b336804d | ||
|
|
9985c43817 | ||
|
|
190cac394c | ||
|
|
ae71a5abf6 | ||
|
|
df199c5788 | ||
|
|
c1ba4f1b55 | ||
|
|
afc0097b12 | ||
|
|
4e9f971c91 | ||
|
|
b1cc28bbda | ||
|
|
80d30bdd30 | ||
|
|
f27566669b | ||
|
|
29f12ddaf4 | ||
|
|
ed15ff0515 | ||
|
|
a8f71f79fe | ||
|
|
68c2478e0e | ||
|
|
be07fe9e9f | ||
|
|
4d8b661d51 | ||
|
|
ca0981645f | ||
|
|
bc7e02b47a | ||
|
|
55a55e9f74 | ||
|
|
b41d40da40 | ||
|
|
ba3e088b23 | ||
|
|
1b59b0b739 | ||
|
|
093cfcdf42 | ||
|
|
41801a60ad | ||
|
|
5ff0957861 | ||
|
|
6913b8beb5 | ||
|
|
c8d17bc363 | ||
|
|
2cbf1259a8 | ||
|
|
59dc513ac3 | ||
|
|
87b110bb86 | ||
|
|
1b3e1a7abe | ||
|
|
0afabc60ae | ||
|
|
2d4ea720eb | ||
|
|
9c757bbe6e | ||
|
|
40e0d72105 | ||
|
|
eba788e8c9 | ||
|
|
444b111a62 | ||
|
|
a364ab4ea7 | ||
|
|
be7840c827 | ||
|
|
a46e51e8db | ||
|
|
789ebb8990 | ||
|
|
e3cd96bf19 | ||
|
|
7746042adc | ||
|
|
dfe80556d3 | ||
|
|
b3529dc748 | ||
|
|
543c4423a2 | ||
|
|
3bd4d32b8d | ||
|
|
56a686d3e0 | ||
|
|
2f97c789dd | ||
|
|
04ca808e80 | ||
|
|
9b79743c5d | ||
|
|
a386826808 | ||
|
|
668894fc4d | ||
|
|
dc882e6279 | ||
|
|
d6eebf82be | ||
|
|
799f509ba9 | ||
|
|
688a234127 | ||
|
|
095697900b | ||
|
|
6ccf617d62 | ||
|
|
b3b4811b2c | ||
|
|
966e4246e5 | ||
|
|
9377c4f3ad | ||
|
|
b876128635 | ||
|
|
c0da801580 | ||
|
|
149310e1ec | ||
|
|
4e625c18dc | ||
|
|
a5d5113be3 | ||
|
|
7900c493af | ||
|
|
76fe5d8831 | ||
|
|
37031721dd | ||
|
|
3cc283cbee | ||
|
|
35cf98fff2 | ||
|
|
ca41ea2d5c | ||
|
|
daffc4e6a4 | ||
|
|
5f3cb9019b | ||
|
|
13c7182948 | ||
|
|
4951b58b21 | ||
|
|
7be7586971 | ||
|
|
edc76795d4 | ||
|
|
6d64098288 | ||
|
|
4351110082 | ||
|
|
6652138d3e | ||
|
|
c8d0d475e4 | ||
|
|
39b25029fc | ||
|
|
b5cabd6d8e | ||
|
|
b169a5c707 | ||
|
|
4f816c06b0 | ||
|
|
b5f49d9563 | ||
|
|
274fd5ab8b | ||
|
|
e48d7de763 | ||
|
|
f426940bd2 | ||
|
|
6c11dd12d7 | ||
|
|
c2b14d3075 | ||
|
|
8a144ebfee | ||
|
|
5440fcdf54 | ||
|
|
66b2d496af | ||
|
|
444a0282d7 | ||
|
|
f897ab4eb8 | ||
|
|
993c187e37 | ||
|
|
3ce67b282f | ||
|
|
606e59a5d0 | ||
|
|
0f26b1eafb | ||
|
|
d2a9d731ed | ||
|
|
80e6b1fc01 | ||
|
|
58a89edad7 | ||
|
|
bfe47eb152 | ||
|
|
32adc38e94 | ||
|
|
1584971908 | ||
|
|
025bebb3e2 | ||
|
|
4047adcc35 | ||
|
|
d4cf03c9fd | ||
|
|
5ba2068fc2 | ||
|
|
3ce7d410c8 | ||
|
|
74f28021e7 | ||
|
|
f90cbb636a | ||
|
|
c8929ca0cb | ||
|
|
9fb5bb620d | ||
|
|
ed58f32052 | ||
|
|
6d5743c506 | ||
|
|
a551619de6 | ||
|
|
873b113cb3 | ||
|
|
2280e66d73 | ||
|
|
2133897bbe | ||
|
|
bee5cb55a1 | ||
|
|
0a0838b616 | ||
|
|
b376dfa1e6 | ||
|
|
7ac0577b34 | ||
|
|
f16e060e87 | ||
|
|
9aaae24583 | ||
|
|
915ced7b92 | ||
|
|
5a36b9075f | ||
|
|
b5a7f46ecc | ||
|
|
4381657c5e | ||
|
|
d440b2f2b2 | ||
|
|
5b42aea9e7 | ||
|
|
e1d7a6b9ac | ||
|
|
38778f8adc | ||
|
|
8b7a86bd17 | ||
|
|
619bae745b | ||
|
|
2cf72bad30 | ||
|
|
c4df8090e2 | ||
|
|
fe3523f47a | ||
|
|
199d846acb | ||
|
|
b07e479840 | ||
|
|
9bf37fde02 | ||
|
|
1054325b2d | ||
|
|
ef8cb11707 | ||
|
|
c23c40df8a | ||
|
|
77d606df34 | ||
|
|
e717c9dba2 | ||
|
|
3d312e2140 | ||
|
|
18de21f723 | ||
|
|
6aebaf6f47 | ||
|
|
a092a2fa43 | ||
|
|
227eac10f1 | ||
|
|
1cbd5485e7 | ||
|
|
610c3cf681 | ||
|
|
96d45cc341 | ||
|
|
d6c68f1a84 | ||
|
|
6d2ab4d270 | ||
|
|
a6b58bc88d | ||
|
|
ea3c37d754 | ||
|
|
b37bf06de8 | ||
|
|
27bbf0ccaf | ||
|
|
ed56d52af3 | ||
|
|
fb457968ec | ||
|
|
0bea2e2b94 | ||
|
|
72d02f442e | ||
|
|
bcf63b5d27 | ||
|
|
ac0dd90c37 | ||
|
|
9470850258 | ||
|
|
2982e9943e | ||
|
|
80e13bc24a | ||
|
|
62dad721fc | ||
|
|
cc5cfc7525 | ||
|
|
795dee85ef | ||
|
|
dbd5bef038 | ||
|
|
dd2a420578 | ||
|
|
eeee30ca03 | ||
|
|
82e8792737 | ||
|
|
6b18b3df34 | ||
|
|
fcebed19b9 | ||
|
|
af5f6176b5 | ||
|
|
424cc46db0 | ||
|
|
ce47ccecc4 | ||
|
|
d940f17390 | ||
|
|
6351b5d0dc | ||
|
|
9c4ac24a66 | ||
|
|
bf66df2a29 | ||
|
|
962ce380cd | ||
|
|
9769afb944 | ||
|
|
052b45a510 | ||
|
|
84a96e862e | ||
|
|
3105235a7a | ||
|
|
71a32477e4 | ||
|
|
342bce2168 | ||
|
|
86d8cbc4d2 | ||
|
|
6b63bd6a44 | ||
|
|
225707c877 | ||
|
|
66da6f18e3 | ||
|
|
bdf8bf391c | ||
|
|
f66d9e1a22 | ||
|
|
ccd3d96942 | ||
|
|
00b6c6a437 | ||
|
|
21ef3b0ecf | ||
|
|
08d60fcbf2 | ||
|
|
4cda54774a | ||
|
|
613475ac26 | ||
|
|
20d23fcb92 | ||
|
|
92dbe6cdf8 | ||
|
|
0781e8cf12 | ||
|
|
b71a088da7 | ||
|
|
d76fb566a2 | ||
|
|
24a40af103 | ||
|
|
4a60292f82 | ||
|
|
7eea866869 | ||
|
|
4ab5456a98 | ||
|
|
8881a9f40e |
351
.github/workflows/DNS.yml
vendored
351
.github/workflows/DNS.yml
vendored
@@ -1,5 +1,6 @@
|
||||
name: DNS
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- 'dnsapi/*.sh'
|
||||
@@ -11,6 +12,9 @@ on:
|
||||
- 'dnsapi/*.sh'
|
||||
- '.github/workflows/DNS.yml'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
CheckToken:
|
||||
@@ -53,11 +57,18 @@ jobs:
|
||||
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
|
||||
CASE: le_test_dnsapi
|
||||
TEST_LOCAL: 1
|
||||
DEBUG: 1
|
||||
DEBUG: ${{ secrets.DEBUG }}
|
||||
http_proxy: ${{ secrets.http_proxy }}
|
||||
https_proxy: ${{ secrets.https_proxy }}
|
||||
TokenName1: ${{ secrets.TokenName1}}
|
||||
TokenName2: ${{ secrets.TokenName2}}
|
||||
TokenName3: ${{ secrets.TokenName3}}
|
||||
TokenName4: ${{ secrets.TokenName4}}
|
||||
TokenName5: ${{ secrets.TokenName5}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- name: Set env file
|
||||
run: |
|
||||
cd ../acmetest
|
||||
@@ -76,11 +87,13 @@ jobs:
|
||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||
echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> docker.env
|
||||
fi
|
||||
echo "TEST_DNS_NO_WILDCARD" >> docker.env
|
||||
echo "TEST_DNS_SLEEP" >> docker.env
|
||||
|
||||
- name: Run acmetest
|
||||
run: cd ../acmetest && ./rundocker.sh testall
|
||||
|
||||
|
||||
|
||||
|
||||
MacOS:
|
||||
runs-on: macos-latest
|
||||
needs: Docker
|
||||
@@ -92,33 +105,43 @@ jobs:
|
||||
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
|
||||
CASE: le_test_dnsapi
|
||||
TEST_LOCAL: 1
|
||||
DEBUG: 1
|
||||
DEBUG: ${{ secrets.DEBUG }}
|
||||
http_proxy: ${{ secrets.http_proxy }}
|
||||
https_proxy: ${{ secrets.https_proxy }}
|
||||
TokenName1: ${{ secrets.TokenName1}}
|
||||
TokenName2: ${{ secrets.TokenName2}}
|
||||
TokenName3: ${{ secrets.TokenName3}}
|
||||
TokenName4: ${{ secrets.TokenName4}}
|
||||
TokenName5: ${{ secrets.TokenName5}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install tools
|
||||
run: brew install socat
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- name: Run acmetest
|
||||
run: |
|
||||
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}
|
||||
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}
|
||||
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}
|
||||
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}
|
||||
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}
|
||||
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||
fi
|
||||
cd ../acmetest
|
||||
./letest.sh
|
||||
|
||||
|
||||
|
||||
|
||||
Windows:
|
||||
runs-on: windows-latest
|
||||
needs: MacOS
|
||||
@@ -130,12 +153,19 @@ jobs:
|
||||
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
|
||||
CASE: le_test_dnsapi
|
||||
TEST_LOCAL: 1
|
||||
DEBUG: 1
|
||||
DEBUG: ${{ secrets.DEBUG }}
|
||||
http_proxy: ${{ secrets.http_proxy }}
|
||||
https_proxy: ${{ secrets.https_proxy }}
|
||||
TokenName1: ${{ secrets.TokenName1}}
|
||||
TokenName2: ${{ secrets.TokenName2}}
|
||||
TokenName3: ${{ secrets.TokenName3}}
|
||||
TokenName4: ${{ secrets.TokenName4}}
|
||||
TokenName5: ${{ secrets.TokenName5}}
|
||||
steps:
|
||||
- name: Set git to use LF
|
||||
run: |
|
||||
git config --global core.autocrlf false
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install cygwin base packages with chocolatey
|
||||
run: |
|
||||
choco config get cacheLocation
|
||||
@@ -143,37 +173,39 @@ jobs:
|
||||
shell: cmd
|
||||
- name: Install cygwin additional packages
|
||||
run: |
|
||||
C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s http://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git
|
||||
C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s https://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git
|
||||
shell: cmd
|
||||
- name: Set ENV
|
||||
shell: cmd
|
||||
run: |
|
||||
echo PATH=C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin >> %GITHUB_ENV%
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- name: Run acmetest
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}
|
||||
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}
|
||||
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}
|
||||
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}
|
||||
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}
|
||||
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||
fi
|
||||
cd ../acmetest
|
||||
./letest.sh
|
||||
|
||||
|
||||
|
||||
FreeBSD:
|
||||
runs-on: macos-10.15
|
||||
runs-on: ubuntu-latest
|
||||
needs: Windows
|
||||
env:
|
||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||
@@ -183,37 +215,48 @@ jobs:
|
||||
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
|
||||
CASE: le_test_dnsapi
|
||||
TEST_LOCAL: 1
|
||||
DEBUG: 1
|
||||
DEBUG: ${{ secrets.DEBUG }}
|
||||
http_proxy: ${{ secrets.http_proxy }}
|
||||
https_proxy: ${{ secrets.https_proxy }}
|
||||
TokenName1: ${{ secrets.TokenName1}}
|
||||
TokenName2: ${{ secrets.TokenName2}}
|
||||
TokenName3: ${{ secrets.TokenName3}}
|
||||
TokenName4: ${{ secrets.TokenName4}}
|
||||
TokenName5: ${{ secrets.TokenName5}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/freebsd-vm@v0.1.4
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/freebsd-vm@v1
|
||||
with:
|
||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||
prepare: pkg install -y socat curl
|
||||
usesh: true
|
||||
copyback: false
|
||||
run: |
|
||||
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}
|
||||
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}
|
||||
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}
|
||||
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}
|
||||
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}
|
||||
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||
fi
|
||||
cd ../acmetest
|
||||
./letest.sh
|
||||
|
||||
Solaris:
|
||||
runs-on: macos-10.15
|
||||
|
||||
|
||||
|
||||
OpenBSD:
|
||||
runs-on: ubuntu-latest
|
||||
needs: FreeBSD
|
||||
env:
|
||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||
@@ -223,32 +266,250 @@ jobs:
|
||||
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
|
||||
CASE: le_test_dnsapi
|
||||
TEST_LOCAL: 1
|
||||
DEBUG: 1
|
||||
DEBUG: ${{ secrets.DEBUG }}
|
||||
http_proxy: ${{ secrets.http_proxy }}
|
||||
https_proxy: ${{ secrets.https_proxy }}
|
||||
TokenName1: ${{ secrets.TokenName1}}
|
||||
TokenName2: ${{ secrets.TokenName2}}
|
||||
TokenName3: ${{ secrets.TokenName3}}
|
||||
TokenName4: ${{ secrets.TokenName4}}
|
||||
TokenName5: ${{ secrets.TokenName5}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/solaris-vm@v0.0.5
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/openbsd-vm@v1
|
||||
with:
|
||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||
prepare: pkg_add socat curl
|
||||
usesh: true
|
||||
copyback: false
|
||||
run: |
|
||||
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||
fi
|
||||
cd ../acmetest
|
||||
./letest.sh
|
||||
|
||||
|
||||
|
||||
|
||||
NetBSD:
|
||||
runs-on: ubuntu-latest
|
||||
needs: OpenBSD
|
||||
env:
|
||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||
TestingDomain: ${{ secrets.TestingDomain }}
|
||||
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
|
||||
TEST_DNS_NO_SUBDOMAIN: ${{ secrets.TEST_DNS_NO_SUBDOMAIN }}
|
||||
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
|
||||
CASE: le_test_dnsapi
|
||||
TEST_LOCAL: 1
|
||||
DEBUG: ${{ secrets.DEBUG }}
|
||||
http_proxy: ${{ secrets.http_proxy }}
|
||||
https_proxy: ${{ secrets.https_proxy }}
|
||||
TokenName1: ${{ secrets.TokenName1}}
|
||||
TokenName2: ${{ secrets.TokenName2}}
|
||||
TokenName3: ${{ secrets.TokenName3}}
|
||||
TokenName4: ${{ secrets.TokenName4}}
|
||||
TokenName5: ${{ secrets.TokenName5}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/netbsd-vm@v1
|
||||
with:
|
||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||
prepare: |
|
||||
/usr/sbin/pkg_add curl socat
|
||||
usesh: true
|
||||
copyback: false
|
||||
run: |
|
||||
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||
fi
|
||||
cd ../acmetest
|
||||
./letest.sh
|
||||
|
||||
|
||||
|
||||
|
||||
DragonFlyBSD:
|
||||
runs-on: ubuntu-latest
|
||||
needs: NetBSD
|
||||
env:
|
||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||
TestingDomain: ${{ secrets.TestingDomain }}
|
||||
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
|
||||
TEST_DNS_NO_SUBDOMAIN: ${{ secrets.TEST_DNS_NO_SUBDOMAIN }}
|
||||
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
|
||||
CASE: le_test_dnsapi
|
||||
TEST_LOCAL: 1
|
||||
DEBUG: ${{ secrets.DEBUG }}
|
||||
http_proxy: ${{ secrets.http_proxy }}
|
||||
https_proxy: ${{ secrets.https_proxy }}
|
||||
TokenName1: ${{ secrets.TokenName1}}
|
||||
TokenName2: ${{ secrets.TokenName2}}
|
||||
TokenName3: ${{ secrets.TokenName3}}
|
||||
TokenName4: ${{ secrets.TokenName4}}
|
||||
TokenName5: ${{ secrets.TokenName5}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/dragonflybsd-vm@v1
|
||||
with:
|
||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||
prepare: |
|
||||
pkg install -y curl socat libnghttp2
|
||||
usesh: true
|
||||
copyback: false
|
||||
run: |
|
||||
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||
fi
|
||||
cd ../acmetest
|
||||
./letest.sh
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Solaris:
|
||||
runs-on: ubuntu-latest
|
||||
needs: DragonFlyBSD
|
||||
env:
|
||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||
TestingDomain: ${{ secrets.TestingDomain }}
|
||||
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
|
||||
TEST_DNS_NO_SUBDOMAIN: ${{ secrets.TEST_DNS_NO_SUBDOMAIN }}
|
||||
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
|
||||
CASE: le_test_dnsapi
|
||||
TEST_LOCAL: 1
|
||||
DEBUG: ${{ secrets.DEBUG }}
|
||||
http_proxy: ${{ secrets.http_proxy }}
|
||||
https_proxy: ${{ secrets.https_proxy }}
|
||||
HTTPS_INSECURE: 1 # always set to 1 to ignore https error, since Solaris doesn't accept the expired ISRG X1 root
|
||||
TokenName1: ${{ secrets.TokenName1}}
|
||||
TokenName2: ${{ secrets.TokenName2}}
|
||||
TokenName3: ${{ secrets.TokenName3}}
|
||||
TokenName4: ${{ secrets.TokenName4}}
|
||||
TokenName5: ${{ secrets.TokenName5}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/solaris-vm@v1
|
||||
with:
|
||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy HTTPS_INSECURE TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||
copyback: false
|
||||
prepare: pkgutil -y -i socat
|
||||
run: |
|
||||
pkg set-mediator -v -I default@1.1 openssl
|
||||
export PATH=/usr/gnu/bin:$PATH
|
||||
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}
|
||||
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}
|
||||
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}
|
||||
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}
|
||||
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}
|
||||
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||
fi
|
||||
cd ../acmetest
|
||||
./letest.sh
|
||||
|
||||
|
||||
Omnios:
|
||||
runs-on: ubuntu-latest
|
||||
needs: Solaris
|
||||
env:
|
||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||
TestingDomain: ${{ secrets.TestingDomain }}
|
||||
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
|
||||
TEST_DNS_NO_SUBDOMAIN: ${{ secrets.TEST_DNS_NO_SUBDOMAIN }}
|
||||
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
|
||||
CASE: le_test_dnsapi
|
||||
TEST_LOCAL: 1
|
||||
DEBUG: ${{ secrets.DEBUG }}
|
||||
http_proxy: ${{ secrets.http_proxy }}
|
||||
https_proxy: ${{ secrets.https_proxy }}
|
||||
HTTPS_INSECURE: 1 # always set to 1 to ignore https error, since Omnios doesn't accept the expired ISRG X1 root
|
||||
TokenName1: ${{ secrets.TokenName1}}
|
||||
TokenName2: ${{ secrets.TokenName2}}
|
||||
TokenName3: ${{ secrets.TokenName3}}
|
||||
TokenName4: ${{ secrets.TokenName4}}
|
||||
TokenName5: ${{ secrets.TokenName5}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/omnios-vm@v1
|
||||
with:
|
||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy HTTPS_INSECURE TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||
copyback: false
|
||||
prepare: pkg install socat
|
||||
run: |
|
||||
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||
fi
|
||||
cd ../acmetest
|
||||
./letest.sh
|
||||
|
||||
|
||||
|
||||
71
.github/workflows/DragonFlyBSD.yml
vendored
Normal file
71
.github/workflows/DragonFlyBSD.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
name: DragonFlyBSD
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
paths:
|
||||
- '*.sh'
|
||||
- '.github/workflows/DragonFlyBSD.yml'
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
paths:
|
||||
- '*.sh'
|
||||
- '.github/workflows/DragonFlyBSD.yml'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
|
||||
jobs:
|
||||
DragonFlyBSD:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- TEST_ACME_Server: "LetsEncrypt.org_test"
|
||||
CA_ECDSA: ""
|
||||
CA: ""
|
||||
CA_EMAIL: ""
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
#- TEST_ACME_Server: "ZeroSSL.com"
|
||||
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
||||
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||
# CA_EMAIL: "githubtest@acme.sh"
|
||||
# TEST_PREFERRED_CHAIN: ""
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TEST_LOCAL: 1
|
||||
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
||||
CA_ECDSA: ${{ matrix.CA_ECDSA }}
|
||||
CA: ${{ matrix.CA }}
|
||||
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
||||
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: vmactions/cf-tunnel@v0
|
||||
id: tunnel
|
||||
with:
|
||||
protocol: http
|
||||
port: 8080
|
||||
- name: Set envs
|
||||
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/dragonflybsd-vm@v1
|
||||
with:
|
||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
|
||||
nat: |
|
||||
"8080": "80"
|
||||
prepare: |
|
||||
pkg install -y curl socat libnghttp2
|
||||
usesh: true
|
||||
copyback: false
|
||||
run: |
|
||||
cd ../acmetest \
|
||||
&& ./letest.sh
|
||||
|
||||
|
||||
29
.github/workflows/FreeBSD.yml
vendored
29
.github/workflows/FreeBSD.yml
vendored
@@ -14,6 +14,11 @@ on:
|
||||
- '*.sh'
|
||||
- '.github/workflows/FreeBSD.yml'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
|
||||
jobs:
|
||||
FreeBSD:
|
||||
@@ -24,13 +29,19 @@ jobs:
|
||||
CA_ECDSA: ""
|
||||
CA: ""
|
||||
CA_EMAIL: ""
|
||||
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
- TEST_ACME_Server: "LetsEncrypt.org_test"
|
||||
CA_ECDSA: ""
|
||||
CA: ""
|
||||
CA_EMAIL: ""
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
ACME_USE_WGET: 1
|
||||
#- TEST_ACME_Server: "ZeroSSL.com"
|
||||
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
||||
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||
# CA_EMAIL: "githubtest@acme.sh"
|
||||
# TEST_PREFERRED_CHAIN: ""
|
||||
runs-on: macos-10.15
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TEST_LOCAL: 1
|
||||
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
||||
@@ -38,9 +49,10 @@ jobs:
|
||||
CA: ${{ matrix.CA }}
|
||||
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
||||
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: vmactions/cf-tunnel@v0.0.3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: vmactions/cf-tunnel@v0
|
||||
id: tunnel
|
||||
with:
|
||||
protocol: http
|
||||
@@ -48,14 +60,15 @@ jobs:
|
||||
- name: Set envs
|
||||
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/freebsd-vm@v0.1.5
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/freebsd-vm@v1
|
||||
with:
|
||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN'
|
||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
|
||||
nat: |
|
||||
"8080": "80"
|
||||
prepare: pkg install -y socat curl
|
||||
prepare: pkg install -y socat curl wget
|
||||
usesh: true
|
||||
copyback: false
|
||||
run: |
|
||||
cd ../acmetest \
|
||||
&& ./letest.sh
|
||||
|
||||
15
.github/workflows/Linux.yml
vendored
15
.github/workflows/Linux.yml
vendored
@@ -15,22 +15,29 @@ on:
|
||||
- '.github/workflows/Linux.yml'
|
||||
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
|
||||
|
||||
jobs:
|
||||
Linux:
|
||||
strategy:
|
||||
matrix:
|
||||
os: ["ubuntu:latest", "debian:latest", "almalinux:latest", "fedora:latest", "centos:7", "opensuse/leap:latest", "alpine:latest", "oraclelinux:8", "kalilinux/kali", "archlinux:latest", "mageia", "gentoo/stage3"]
|
||||
os: ["ubuntu:latest", "debian:latest", "almalinux:latest", "fedora:latest", "opensuse/leap:latest", "alpine:latest", "oraclelinux:8", "kalilinux/kali", "archlinux:latest", "mageia", "gentoo/stage3"]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TEST_LOCAL: 1
|
||||
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
TEST_ACME_Server: "LetsEncrypt.org_test"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Clone acmetest
|
||||
run: |
|
||||
cd .. \
|
||||
&& git clone https://github.com/acmesh-official/acmetest.git \
|
||||
&& git clone --depth=1 https://github.com/acmesh-official/acmetest.git \
|
||||
&& cp -r acme.sh acmetest/
|
||||
- name: Run acmetest
|
||||
run: |
|
||||
|
||||
11
.github/workflows/MacOS.yml
vendored
11
.github/workflows/MacOS.yml
vendored
@@ -14,6 +14,11 @@ on:
|
||||
- '*.sh'
|
||||
- '.github/workflows/MacOS.yml'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
|
||||
jobs:
|
||||
MacOS:
|
||||
@@ -24,7 +29,7 @@ jobs:
|
||||
CA_ECDSA: ""
|
||||
CA: ""
|
||||
CA_EMAIL: ""
|
||||
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
#- TEST_ACME_Server: "ZeroSSL.com"
|
||||
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
||||
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||
@@ -39,13 +44,13 @@ jobs:
|
||||
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
||||
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install tools
|
||||
run: brew install socat
|
||||
- name: Clone acmetest
|
||||
run: |
|
||||
cd .. \
|
||||
&& git clone https://github.com/acmesh-official/acmetest.git \
|
||||
&& git clone --depth=1 https://github.com/acmesh-official/acmetest.git \
|
||||
&& cp -r acme.sh acmetest/
|
||||
- name: Run acmetest
|
||||
run: |
|
||||
|
||||
71
.github/workflows/NetBSD.yml
vendored
Normal file
71
.github/workflows/NetBSD.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
name: NetBSD
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
paths:
|
||||
- '*.sh'
|
||||
- '.github/workflows/NetBSD.yml'
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
paths:
|
||||
- '*.sh'
|
||||
- '.github/workflows/NetBSD.yml'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
|
||||
jobs:
|
||||
NetBSD:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- TEST_ACME_Server: "LetsEncrypt.org_test"
|
||||
CA_ECDSA: ""
|
||||
CA: ""
|
||||
CA_EMAIL: ""
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
#- TEST_ACME_Server: "ZeroSSL.com"
|
||||
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
||||
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||
# CA_EMAIL: "githubtest@acme.sh"
|
||||
# TEST_PREFERRED_CHAIN: ""
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TEST_LOCAL: 1
|
||||
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
||||
CA_ECDSA: ${{ matrix.CA_ECDSA }}
|
||||
CA: ${{ matrix.CA }}
|
||||
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
||||
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: vmactions/cf-tunnel@v0
|
||||
id: tunnel
|
||||
with:
|
||||
protocol: http
|
||||
port: 8080
|
||||
- name: Set envs
|
||||
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/netbsd-vm@v1
|
||||
with:
|
||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
|
||||
nat: |
|
||||
"8080": "80"
|
||||
prepare: |
|
||||
/usr/sbin/pkg_add curl socat
|
||||
usesh: true
|
||||
copyback: false
|
||||
run: |
|
||||
cd ../acmetest \
|
||||
&& ./letest.sh
|
||||
|
||||
|
||||
75
.github/workflows/Omnios.yml
vendored
Normal file
75
.github/workflows/Omnios.yml
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
name: Omnios
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
paths:
|
||||
- '*.sh'
|
||||
- '.github/workflows/Omnios.yml'
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
paths:
|
||||
- '*.sh'
|
||||
- '.github/workflows/Omnios.yml'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
|
||||
jobs:
|
||||
Omnios:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- TEST_ACME_Server: "LetsEncrypt.org_test"
|
||||
CA_ECDSA: ""
|
||||
CA: ""
|
||||
CA_EMAIL: ""
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
- TEST_ACME_Server: "LetsEncrypt.org_test"
|
||||
CA_ECDSA: ""
|
||||
CA: ""
|
||||
CA_EMAIL: ""
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
ACME_USE_WGET: 1
|
||||
#- TEST_ACME_Server: "ZeroSSL.com"
|
||||
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
||||
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||
# CA_EMAIL: "githubtest@acme.sh"
|
||||
# TEST_PREFERRED_CHAIN: ""
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TEST_LOCAL: 1
|
||||
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
||||
CA_ECDSA: ${{ matrix.CA_ECDSA }}
|
||||
CA: ${{ matrix.CA }}
|
||||
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
||||
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: vmactions/cf-tunnel@v0
|
||||
id: tunnel
|
||||
with:
|
||||
protocol: http
|
||||
port: 8080
|
||||
- name: Set envs
|
||||
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/omnios-vm@v1
|
||||
with:
|
||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
|
||||
nat: |
|
||||
"8080": "80"
|
||||
prepare: pkg install socat wget
|
||||
copyback: false
|
||||
run: |
|
||||
cd ../acmetest \
|
||||
&& ./letest.sh
|
||||
|
||||
|
||||
76
.github/workflows/OpenBSD.yml
vendored
Normal file
76
.github/workflows/OpenBSD.yml
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
name: OpenBSD
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
paths:
|
||||
- '*.sh'
|
||||
- '.github/workflows/OpenBSD.yml'
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
paths:
|
||||
- '*.sh'
|
||||
- '.github/workflows/OpenBSD.yml'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
|
||||
jobs:
|
||||
OpenBSD:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- TEST_ACME_Server: "LetsEncrypt.org_test"
|
||||
CA_ECDSA: ""
|
||||
CA: ""
|
||||
CA_EMAIL: ""
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
- TEST_ACME_Server: "LetsEncrypt.org_test"
|
||||
CA_ECDSA: ""
|
||||
CA: ""
|
||||
CA_EMAIL: ""
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
ACME_USE_WGET: 1
|
||||
#- TEST_ACME_Server: "ZeroSSL.com"
|
||||
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
||||
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||
# CA_EMAIL: "githubtest@acme.sh"
|
||||
# TEST_PREFERRED_CHAIN: ""
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TEST_LOCAL: 1
|
||||
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
||||
CA_ECDSA: ${{ matrix.CA_ECDSA }}
|
||||
CA: ${{ matrix.CA }}
|
||||
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
||||
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: vmactions/cf-tunnel@v0
|
||||
id: tunnel
|
||||
with:
|
||||
protocol: http
|
||||
port: 8080
|
||||
- name: Set envs
|
||||
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/openbsd-vm@v1
|
||||
with:
|
||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
|
||||
nat: |
|
||||
"8080": "80"
|
||||
prepare: pkg_add socat curl wget libnghttp2
|
||||
usesh: true
|
||||
copyback: false
|
||||
run: |
|
||||
cd ../acmetest \
|
||||
&& ./letest.sh
|
||||
|
||||
|
||||
26
.github/workflows/PebbleStrict.yml
vendored
26
.github/workflows/PebbleStrict.yml
vendored
@@ -13,6 +13,13 @@ on:
|
||||
- '*.sh'
|
||||
- '.github/workflows/PebbleStrict.yml'
|
||||
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
|
||||
jobs:
|
||||
PebbleStrict:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -26,23 +33,23 @@ jobs:
|
||||
TEST_CA: "Pebble Intermediate CA"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install tools
|
||||
run: sudo apt-get install -y socat
|
||||
- name: Run Pebble
|
||||
run: cd .. && curl https://raw.githubusercontent.com/letsencrypt/pebble/master/docker-compose.yml >docker-compose.yml && docker-compose up -d
|
||||
run: cd .. && curl https://raw.githubusercontent.com/letsencrypt/pebble/master/docker-compose.yml >docker-compose.yml && docker compose up -d
|
||||
- name: Set up Pebble
|
||||
run: curl --request POST --data '{"ip":"10.30.50.1"}' http://localhost:8055/set-default-ipv4
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- name: Run acmetest
|
||||
run: cd ../acmetest && ./letest.sh
|
||||
|
||||
PebbleStrict_IPCert:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TestingDomain: 10.30.50.1
|
||||
ACME_DIRECTORY: https://localhost:14000/dir
|
||||
TestingDomain: 1.23.45.67
|
||||
TEST_ACME_Server: https://localhost:14000/dir
|
||||
HTTPS_INSECURE: 1
|
||||
Le_HTTPPort: 5002
|
||||
Le_TLSPort: 5001
|
||||
@@ -51,12 +58,15 @@ jobs:
|
||||
TEST_IPCERT: 1
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install tools
|
||||
run: sudo apt-get install -y socat
|
||||
- name: Run Pebble
|
||||
run: cd .. && curl https://raw.githubusercontent.com/letsencrypt/pebble/master/docker-compose.yml >docker-compose.yml && docker-compose up -d
|
||||
run: |
|
||||
docker run --rm -itd --name=pebble \
|
||||
-e PEBBLE_VA_ALWAYS_VALID=1 \
|
||||
-p 14000:14000 -p 15000:15000 letsencrypt/pebble:latest pebble -config /test/config/pebble-config.json -strict
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- name: Run acmetest
|
||||
run: cd ../acmetest && ./letest.sh
|
||||
30
.github/workflows/Solaris.yml
vendored
30
.github/workflows/Solaris.yml
vendored
@@ -14,6 +14,11 @@ on:
|
||||
- '*.sh'
|
||||
- '.github/workflows/Solaris.yml'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
|
||||
jobs:
|
||||
Solaris:
|
||||
@@ -24,13 +29,19 @@ jobs:
|
||||
CA_ECDSA: ""
|
||||
CA: ""
|
||||
CA_EMAIL: ""
|
||||
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
- TEST_ACME_Server: "LetsEncrypt.org_test"
|
||||
CA_ECDSA: ""
|
||||
CA: ""
|
||||
CA_EMAIL: ""
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
ACME_USE_WGET: 1
|
||||
#- TEST_ACME_Server: "ZeroSSL.com"
|
||||
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
||||
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||
# CA_EMAIL: "githubtest@acme.sh"
|
||||
# TEST_PREFERRED_CHAIN: ""
|
||||
runs-on: macos-10.15
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TEST_LOCAL: 1
|
||||
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
||||
@@ -38,9 +49,10 @@ jobs:
|
||||
CA: ${{ matrix.CA }}
|
||||
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
||||
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: vmactions/cf-tunnel@v0.0.3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: vmactions/cf-tunnel@v0
|
||||
id: tunnel
|
||||
with:
|
||||
protocol: http
|
||||
@@ -48,14 +60,16 @@ jobs:
|
||||
- name: Set envs
|
||||
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/solaris-vm@v0.0.5
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/solaris-vm@v1
|
||||
with:
|
||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN'
|
||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
|
||||
nat: |
|
||||
"8080": "80"
|
||||
prepare: pkgutil -y -i socat curl
|
||||
prepare: pkgutil -y -i socat curl wget
|
||||
copyback: false
|
||||
run: |
|
||||
cd ../acmetest \
|
||||
&& ./letest.sh
|
||||
|
||||
|
||||
|
||||
29
.github/workflows/Ubuntu.yml
vendored
29
.github/workflows/Ubuntu.yml
vendored
@@ -14,6 +14,11 @@ on:
|
||||
- '*.sh'
|
||||
- '.github/workflows/Ubuntu.yml'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
|
||||
jobs:
|
||||
Ubuntu:
|
||||
@@ -24,7 +29,13 @@ jobs:
|
||||
CA_ECDSA: ""
|
||||
CA: ""
|
||||
CA_EMAIL: ""
|
||||
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
- TEST_ACME_Server: "LetsEncrypt.org_test"
|
||||
CA_ECDSA: ""
|
||||
CA: ""
|
||||
CA_EMAIL: ""
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
ACME_USE_WGET: 1
|
||||
- TEST_ACME_Server: "ZeroSSL.com"
|
||||
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
||||
CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||
@@ -57,10 +68,11 @@ jobs:
|
||||
NO_REVOKE: ${{ matrix.NO_REVOKE }}
|
||||
TEST_IPCERT: ${{ matrix.TEST_IPCERT }}
|
||||
TestingDomain: ${{ matrix.TestingDomain }}
|
||||
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install tools
|
||||
run: sudo apt-get install -y socat
|
||||
run: sudo apt-get install -y socat wget
|
||||
- name: Start StepCA
|
||||
if: ${{ matrix.TEST_ACME_Server=='https://localhost:9000/acme/acme/directory' }}
|
||||
run: |
|
||||
@@ -68,15 +80,20 @@ jobs:
|
||||
-p 9000:9000 \
|
||||
-e "DOCKER_STEPCA_INIT_NAME=Smallstep" \
|
||||
-e "DOCKER_STEPCA_INIT_DNS_NAMES=localhost,$(hostname -f)" \
|
||||
-e "DOCKER_STEPCA_INIT_REMOTE_MANAGEMENT=true" \
|
||||
-e "DOCKER_STEPCA_INIT_PASSWORD=test" \
|
||||
--name stepca \
|
||||
smallstep/step-ca \
|
||||
&& sleep 5 && docker exec stepca step ca provisioner add acme --type ACME \
|
||||
smallstep/step-ca:0.23.1
|
||||
|
||||
sleep 5
|
||||
docker exec stepca bash -c "echo test >test" \
|
||||
&& docker exec stepca step ca provisioner add acme --type ACME --admin-subject step --admin-password-file=/home/step/test \
|
||||
&& docker exec stepca kill -1 1 \
|
||||
&& docker exec stepca cat /home/step/certs/root_ca.crt | sudo bash -c "cat - >>/etc/ssl/certs/ca-certificates.crt"
|
||||
- name: Clone acmetest
|
||||
run: |
|
||||
cd .. \
|
||||
&& git clone https://github.com/acmesh-official/acmetest.git \
|
||||
&& git clone --depth=1 https://github.com/acmesh-official/acmetest.git \
|
||||
&& cp -r acme.sh acmetest/
|
||||
- name: Run acmetest
|
||||
run: |
|
||||
|
||||
13
.github/workflows/Windows.yml
vendored
13
.github/workflows/Windows.yml
vendored
@@ -15,6 +15,11 @@ on:
|
||||
- '.github/workflows/Windows.yml'
|
||||
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
jobs:
|
||||
Windows:
|
||||
strategy:
|
||||
@@ -24,7 +29,7 @@ jobs:
|
||||
CA_ECDSA: ""
|
||||
CA: ""
|
||||
CA_EMAIL: ""
|
||||
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
#- TEST_ACME_Server: "ZeroSSL.com"
|
||||
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
||||
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||
@@ -44,7 +49,7 @@ jobs:
|
||||
- name: Set git to use LF
|
||||
run: |
|
||||
git config --global core.autocrlf false
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install cygwin base packages with chocolatey
|
||||
run: |
|
||||
choco config get cacheLocation
|
||||
@@ -52,7 +57,7 @@ jobs:
|
||||
shell: cmd
|
||||
- name: Install cygwin additional packages
|
||||
run: |
|
||||
C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s http://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git,xxd
|
||||
C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s https://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git,xxd
|
||||
shell: cmd
|
||||
- name: Set ENV
|
||||
shell: cmd
|
||||
@@ -64,7 +69,7 @@ jobs:
|
||||
echo "PATH=%PATH%"
|
||||
- name: Clone acmetest
|
||||
shell: cmd
|
||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- name: Run acmetest
|
||||
shell: cmd
|
||||
run: cd ../acmetest && bash.exe -c ./letest.sh
|
||||
|
||||
14
.github/workflows/dockerhub.yml
vendored
14
.github/workflows/dockerhub.yml
vendored
@@ -11,6 +11,10 @@ on:
|
||||
- "Dockerfile"
|
||||
- '.github/workflows/dockerhub.yml'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
jobs:
|
||||
CheckToken:
|
||||
@@ -24,9 +28,9 @@ jobs:
|
||||
id: step_one
|
||||
run: |
|
||||
if [ "$DOCKER_PASSWORD" ] ; then
|
||||
echo "::set-output name=hasToken::true"
|
||||
echo "hasToken=true" >>$GITHUB_OUTPUT
|
||||
else
|
||||
echo "::set-output name=hasToken::false"
|
||||
echo "hasToken=false" >>$GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Check the value
|
||||
run: echo ${{ steps.step_one.outputs.hasToken }}
|
||||
@@ -37,11 +41,11 @@ jobs:
|
||||
if: "contains(needs.CheckToken.outputs.hasToken, 'true')"
|
||||
steps:
|
||||
- name: checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: login to docker hub
|
||||
run: |
|
||||
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
|
||||
|
||||
19
.github/workflows/issue.yml
vendored
Normal file
19
.github/workflows/issue.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
name: "Update issues"
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: "Please upgrade to the latest code and try again first. Maybe it's already fixed. ```acme.sh --upgrade``` If it's still not working, please provide the log with `--debug 2`, otherwise, nobody can help you."
|
||||
|
||||
})
|
||||
30
.github/workflows/pr_dns.yml
vendored
Normal file
30
.github/workflows/pr_dns.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: Check dns api
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
paths:
|
||||
- 'dnsapi/*.sh'
|
||||
|
||||
|
||||
jobs:
|
||||
welcome:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
await github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: `**Welcome**
|
||||
First thing: don't send PR to the master branch, please send to the dev branch instead.
|
||||
Please make sure you've read our [DNS API Dev Guide](../wiki/DNS-API-Dev-Guide) and [DNS-API-Test](../wiki/DNS-API-Test).
|
||||
Then reply on this message, otherwise, your code will not be reviewed or merged.
|
||||
We look forward to reviewing your Pull request shortly ✨
|
||||
注意: 必须通过了 [DNS-API-Test](../wiki/DNS-API-Test) 才会被 review. 无论是修改, 还是新加的 dns api, 都必须确保通过这个测试.
|
||||
`
|
||||
})
|
||||
|
||||
30
.github/workflows/pr_notify.yml
vendored
Normal file
30
.github/workflows/pr_notify.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: Check dns api
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
branches:
|
||||
- 'dev'
|
||||
paths:
|
||||
- 'notify/*.sh'
|
||||
|
||||
|
||||
jobs:
|
||||
welcome:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
await github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: `**Welcome**
|
||||
Please make sure you've read our [Code-of-conduct](../wiki/Code-of-conduct) and add the usage here: [notify](../wiki/notify).
|
||||
Then reply on this message, otherwise, your code will not be reviewed or merged.
|
||||
We look forward to reviewing your Pull request shortly ✨
|
||||
`
|
||||
})
|
||||
|
||||
11
.github/workflows/shellcheck.yml
vendored
11
.github/workflows/shellcheck.yml
vendored
@@ -13,20 +13,25 @@ on:
|
||||
- '**.sh'
|
||||
- '.github/workflows/shellcheck.yml'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
jobs:
|
||||
ShellCheck:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Shellcheck
|
||||
run: sudo apt-get install -y shellcheck
|
||||
- name: DoShellcheck
|
||||
run: shellcheck -V && shellcheck -e SC2181 **/*.sh && echo "shellcheck OK"
|
||||
run: shellcheck -V && shellcheck -e SC2181 -e SC2089 **/*.sh && echo "shellcheck OK"
|
||||
|
||||
shfmt:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install shfmt
|
||||
run: curl -sSL https://github.com/mvdan/sh/releases/download/v3.1.2/shfmt_v3.1.2_linux_amd64 -o ~/shfmt && chmod +x ~/shfmt
|
||||
- name: shfmt
|
||||
|
||||
13
Dockerfile
13
Dockerfile
@@ -1,4 +1,4 @@
|
||||
FROM alpine:3.15
|
||||
FROM alpine:3.17
|
||||
|
||||
RUN apk --no-cache add -f \
|
||||
openssl \
|
||||
@@ -12,7 +12,8 @@ RUN apk --no-cache add -f \
|
||||
oath-toolkit-oathtool \
|
||||
tar \
|
||||
libidn \
|
||||
jq
|
||||
jq \
|
||||
cronie
|
||||
|
||||
ENV LE_CONFIG_HOME /acme.sh
|
||||
|
||||
@@ -25,7 +26,7 @@ COPY ./ /install_acme.sh/
|
||||
RUN cd /install_acme.sh && ([ -f /install_acme.sh/acme.sh ] && /install_acme.sh/acme.sh --install || curl https://get.acme.sh | sh) && rm -rf /install_acme.sh/
|
||||
|
||||
|
||||
RUN ln -s /root/.acme.sh/acme.sh /usr/local/bin/acme.sh && crontab -l | grep acme.sh | sed 's#> /dev/null##' | crontab -
|
||||
RUN ln -s /root/.acme.sh/acme.sh /usr/local/bin/acme.sh && crontab -l | grep acme.sh | sed 's#> /dev/null#> /proc/1/fd/1 2>/proc/1/fd/2#' | crontab -
|
||||
|
||||
RUN for verb in help \
|
||||
version \
|
||||
@@ -64,12 +65,10 @@ RUN for verb in help \
|
||||
|
||||
RUN printf "%b" '#!'"/usr/bin/env sh\n \
|
||||
if [ \"\$1\" = \"daemon\" ]; then \n \
|
||||
trap \"echo stop && killall crond && exit 0\" SIGTERM SIGINT \n \
|
||||
crond && sleep infinity &\n \
|
||||
wait \n \
|
||||
exec crond -n -s -m off \n \
|
||||
else \n \
|
||||
exec -- \"\$@\"\n \
|
||||
fi" >/entry.sh && chmod +x /entry.sh
|
||||
fi\n" >/entry.sh && chmod +x /entry.sh
|
||||
|
||||
VOLUME /acme.sh
|
||||
|
||||
|
||||
53
README.md
53
README.md
@@ -1,10 +1,14 @@
|
||||
# An ACME Shell script: acme.sh
|
||||
|
||||
[](https://github.com/acmesh-official/acme.sh/actions/workflows/FreeBSD.yml)
|
||||
[](https://github.com/acmesh-official/acme.sh/actions/workflows/OpenBSD.yml)
|
||||
[](https://github.com/acmesh-official/acme.sh/actions/workflows/NetBSD.yml)
|
||||
[](https://github.com/acmesh-official/acme.sh/actions/workflows/MacOS.yml)
|
||||
[](https://github.com/acmesh-official/acme.sh/actions/workflows/Ubuntu.yml)
|
||||
[](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml)
|
||||
[](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml)
|
||||
[](https://github.com/acmesh-official/acme.sh/actions/workflows/DragonFlyBSD.yml)
|
||||
[](https://github.com/acmesh-official/acme.sh/actions/workflows/Omnios.yml)
|
||||
|
||||

|
||||

|
||||
@@ -47,14 +51,12 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
|
||||
- [ruby-china.org](https://ruby-china.org/topics/31983)
|
||||
- [Proxmox](https://pve.proxmox.com/wiki/Certificate_Management)
|
||||
- [pfsense](https://github.com/pfsense/FreeBSD-ports/pull/89)
|
||||
- [webfaction](https://community.webfaction.com/questions/19988/using-letsencrypt)
|
||||
- [Loadbalancer.org](https://www.loadbalancer.org/blog/loadbalancer-org-with-lets-encrypt-quick-and-dirty)
|
||||
- [discourse.org](https://meta.discourse.org/t/setting-up-lets-encrypt/40709)
|
||||
- [Centminmod](https://centminmod.com/letsencrypt-acmetool-https.html)
|
||||
- [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297)
|
||||
- [archlinux](https://www.archlinux.org/packages/community/any/acme.sh)
|
||||
- [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient)
|
||||
- [CentOS Web Panel](http://centos-webpanel.com/)
|
||||
- [CentOS Web Panel](https://control-webpanel.com)
|
||||
- [lnmp.org](https://lnmp.org/)
|
||||
- [more...](https://github.com/acmesh-official/acme.sh/wiki/Blogs-and-tutorials)
|
||||
|
||||
@@ -68,21 +70,24 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
|
||||
|4|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml)|Solaris
|
||||
|5|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Ubuntu.yml)| Ubuntu
|
||||
|6|NA|pfsense
|
||||
|7|NA|OpenBSD
|
||||
|8|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)| Debian
|
||||
|9|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|CentOS
|
||||
|10|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|openSUSE
|
||||
|11|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Alpine Linux (with curl)
|
||||
|12|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Archlinux
|
||||
|13|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|fedora
|
||||
|14|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Kali Linux
|
||||
|15|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Oracle Linux
|
||||
|16|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Mageia
|
||||
|17|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Gentoo Linux
|
||||
|18|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|ClearLinux
|
||||
|19|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111
|
||||
|20|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT)
|
||||
|21|[](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management)
|
||||
|7|[](https://github.com/acmesh-official/acme.sh/actions/workflows/OpenBSD.yml)|OpenBSD
|
||||
|8|[](https://github.com/acmesh-official/acme.sh/actions/workflows/NetBSD.yml)|NetBSD
|
||||
|9|[](https://github.com/acmesh-official/acme.sh/actions/workflows/DragonFlyBSD.yml)|DragonFlyBSD
|
||||
|10|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Omnios.yml)|Omnios
|
||||
|11|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)| Debian
|
||||
|12|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|CentOS
|
||||
|13|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|openSUSE
|
||||
|14|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Alpine Linux (with curl)
|
||||
|15|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Archlinux
|
||||
|16|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|fedora
|
||||
|17|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Kali Linux
|
||||
|18|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Oracle Linux
|
||||
|19|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Mageia
|
||||
|10|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Gentoo Linux
|
||||
|11|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|ClearLinux
|
||||
|22|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111
|
||||
|23|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT)
|
||||
|24|[](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management)
|
||||
|
||||
|
||||
Check our [testing project](https://github.com/acmesh-official/acmetest):
|
||||
@@ -355,10 +360,6 @@ Ok, it's done.
|
||||
|
||||
# 10. Issue ECC certificates
|
||||
|
||||
`Let's Encrypt` can now issue **ECDSA** certificates.
|
||||
|
||||
And we support them too!
|
||||
|
||||
Just set the `keylength` parameter with a prefix `ec-`.
|
||||
|
||||
For example:
|
||||
@@ -379,10 +380,12 @@ Please look at the `keylength` parameter above.
|
||||
|
||||
Valid values are:
|
||||
|
||||
1. **ec-256 (prime256v1, "ECDSA P-256")**
|
||||
1. **ec-256 (prime256v1, "ECDSA P-256", which is the default key type)**
|
||||
2. **ec-384 (secp384r1, "ECDSA P-384")**
|
||||
3. **ec-521 (secp521r1, "ECDSA P-521", which is not supported by Let's Encrypt yet.)**
|
||||
|
||||
4. **2048 (RSA2048)**
|
||||
5. **3072 (RSA3072)**
|
||||
6. **4096 (RSA4096)**
|
||||
|
||||
|
||||
# 11. Issue Wildcard certificates
|
||||
@@ -503,6 +506,8 @@ Support this project with your organization. Your logo will show up here with a
|
||||
<a href="https://opencollective.com/acmesh/organization/8/website"><img src="https://opencollective.com/acmesh/organization/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/acmesh/organization/9/website"><img src="https://opencollective.com/acmesh/organization/9/avatar.svg"></a>
|
||||
|
||||
|
||||
|
||||
# 19. License & Others
|
||||
|
||||
License is GPLv3
|
||||
|
||||
157
deploy/ali_cdn.sh
Normal file
157
deploy/ali_cdn.sh
Normal file
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Script to create certificate to Alibaba Cloud CDN
|
||||
#
|
||||
# This deployment required following variables
|
||||
# export Ali_Key="ALIACCESSKEY"
|
||||
# export Ali_Secret="ALISECRETKEY"
|
||||
# export DEPLOY_ALI_CDN_DOMAIN="cdn.example.com"
|
||||
# If you have more than one domain, just
|
||||
# export DEPLOY_ALI_CDN_DOMAIN="cdn1.example.com cdn2.example.com"
|
||||
#
|
||||
# The credentials are shared with all domains, also shared with dns_ali api
|
||||
|
||||
Ali_API="https://cdn.aliyuncs.com/"
|
||||
|
||||
ali_cdn_deploy() {
|
||||
_cdomain="$1"
|
||||
_ckey="$2"
|
||||
_ccert="$3"
|
||||
_cca="$4"
|
||||
_cfullchain="$5"
|
||||
|
||||
_debug _cdomain "$_cdomain"
|
||||
_debug _ckey "$_ckey"
|
||||
_debug _ccert "$_ccert"
|
||||
_debug _cca "$_cca"
|
||||
_debug _cfullchain "$_cfullchain"
|
||||
|
||||
Ali_Key="${Ali_Key:-$(_readaccountconf_mutable Ali_Key)}"
|
||||
Ali_Secret="${Ali_Secret:-$(_readaccountconf_mutable Ali_Secret)}"
|
||||
if [ -z "$Ali_Key" ] || [ -z "$Ali_Secret" ]; then
|
||||
Ali_Key=""
|
||||
Ali_Secret=""
|
||||
_err "You don't specify aliyun api key and secret yet."
|
||||
return 1
|
||||
fi
|
||||
|
||||
#save the api key and secret to the account conf file.
|
||||
_saveaccountconf_mutable Ali_Key "$Ali_Key"
|
||||
_saveaccountconf_mutable Ali_Secret "$Ali_Secret"
|
||||
|
||||
_getdeployconf DEPLOY_ALI_CDN_DOMAIN
|
||||
if [ "$DEPLOY_ALI_CDN_DOMAIN" ]; then
|
||||
_savedeployconf DEPLOY_ALI_CDN_DOMAIN "$DEPLOY_ALI_CDN_DOMAIN"
|
||||
else
|
||||
DEPLOY_ALI_CDN_DOMAIN="$_cdomain"
|
||||
fi
|
||||
|
||||
# read cert and key files and urlencode both
|
||||
_cert=$(_url_encode_upper <"$_cfullchain")
|
||||
_key=$(_url_encode_upper <"$_ckey")
|
||||
|
||||
_debug2 _cert "$_cert"
|
||||
_debug2 _key "$_key"
|
||||
|
||||
## update domain ssl config
|
||||
for domain in $DEPLOY_ALI_CDN_DOMAIN; do
|
||||
_set_cdn_domain_ssl_certificate_query "$domain" "$_cert" "$_key"
|
||||
if _ali_rest "Set CDN domain SSL certificate for $domain" "" POST; then
|
||||
_info "Domain $domain certificate has been deployed successfully"
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
|
||||
# act ign mtd
|
||||
_ali_rest() {
|
||||
act="$1"
|
||||
ign="$2"
|
||||
mtd="$3"
|
||||
|
||||
signature=$(printf "%s" "$mtd&%2F&$(_ali_urlencode "$query")" | _hmac "sha1" "$(printf "%s" "$Ali_Secret&" | _hex_dump | tr -d " ")" | _base64)
|
||||
signature=$(_ali_urlencode "$signature")
|
||||
url="$Ali_API?$query&Signature=$signature"
|
||||
|
||||
if [ "$mtd" = "GET" ]; then
|
||||
response="$(_get "$url")"
|
||||
else
|
||||
# post payload is not supported yet because of signature
|
||||
response="$(_post "" "$url")"
|
||||
fi
|
||||
|
||||
_ret="$?"
|
||||
_debug2 response "$response"
|
||||
if [ "$_ret" != "0" ]; then
|
||||
_err "Error <$act>"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$ign" ]; then
|
||||
message="$(echo "$response" | _egrep_o "\"Message\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")"
|
||||
if [ "$message" ]; then
|
||||
_err "$message"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_ali_urlencode() {
|
||||
_str="$1"
|
||||
_str_len=${#_str}
|
||||
_u_i=1
|
||||
while [ "$_u_i" -le "$_str_len" ]; do
|
||||
_str_c="$(printf "%s" "$_str" | cut -c "$_u_i")"
|
||||
case $_str_c in [a-zA-Z0-9.~_-])
|
||||
printf "%s" "$_str_c"
|
||||
;;
|
||||
*)
|
||||
printf "%%%02X" "'$_str_c"
|
||||
;;
|
||||
esac
|
||||
_u_i="$(_math "$_u_i" + 1)"
|
||||
done
|
||||
}
|
||||
|
||||
_ali_nonce() {
|
||||
#_head_n 1 </dev/urandom | _digest "sha256" hex | cut -c 1-31
|
||||
#Not so good...
|
||||
date +"%s%N" | sed 's/%N//g'
|
||||
}
|
||||
|
||||
_timestamp() {
|
||||
date -u +"%Y-%m-%dT%H%%3A%M%%3A%SZ"
|
||||
}
|
||||
|
||||
# stdin stdout
|
||||
_url_encode_upper() {
|
||||
encoded=$(_url_encode)
|
||||
|
||||
for match in $(echo "$encoded" | _egrep_o '%..' | sort -u); do
|
||||
upper=$(echo "$match" | _upper_case)
|
||||
encoded=$(echo "$encoded" | sed "s/$match/$upper/g")
|
||||
done
|
||||
|
||||
echo "$encoded"
|
||||
}
|
||||
|
||||
# domain pub pri
|
||||
_set_cdn_domain_ssl_certificate_query() {
|
||||
query=''
|
||||
query=$query'AccessKeyId='$Ali_Key
|
||||
query=$query'&Action=SetCdnDomainSSLCertificate'
|
||||
query=$query'&CertType=upload'
|
||||
query=$query'&DomainName='$1
|
||||
query=$query'&Format=json'
|
||||
query=$query'&SSLPri='$3
|
||||
query=$query'&SSLProtocol=on'
|
||||
query=$query'&SSLPub='$2
|
||||
query=$query'&SignatureMethod=HMAC-SHA1'
|
||||
query=$query"&SignatureNonce=$(_ali_nonce)"
|
||||
query=$query'&SignatureVersion=1.0'
|
||||
query=$query'&Timestamp='$(_timestamp)
|
||||
query=$query'&Version=2018-05-10'
|
||||
}
|
||||
@@ -3,18 +3,29 @@
|
||||
# Uses command line uapi. --user option is needed only if run as root.
|
||||
# Returns 0 when success.
|
||||
#
|
||||
# Configure DEPLOY_CPANEL_AUTO_<...> options to enable or restrict automatic
|
||||
# detection of deployment targets through UAPI (if not set, defaults below are used.)
|
||||
# - ENABLED : 'true' for multi-site / wildcard capability; otherwise single-site mode.
|
||||
# - NOMATCH : 'true' to allow deployment to sites that do not match the certificate.
|
||||
# - INCLUDE : Comma-separated list - sites must match this field.
|
||||
# - EXCLUDE : Comma-separated list - sites must NOT match this field.
|
||||
# INCLUDE/EXCLUDE both support non-lexical, glob-style matches using '*'
|
||||
#
|
||||
# Please note that I am no longer using Github. If you want to report an issue
|
||||
# or contact me, visit https://forum.webseodesigners.com/web-design-seo-and-hosting-f16/
|
||||
#
|
||||
# Written by Santeri Kannisto <santeri.kannisto@webseodesigners.com>
|
||||
# Public domain, 2017-2018
|
||||
|
||||
#
|
||||
# export DEPLOY_CPANEL_USER=myusername
|
||||
# export DEPLOY_CPANEL_AUTO_ENABLED='true'
|
||||
# export DEPLOY_CPANEL_AUTO_NOMATCH='false'
|
||||
# export DEPLOY_CPANEL_AUTO_INCLUDE='*'
|
||||
# export DEPLOY_CPANEL_AUTO_EXCLUDE=''
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#domain keyfile certfile cafile fullchain
|
||||
|
||||
cpanel_uapi_deploy() {
|
||||
_cdomain="$1"
|
||||
_ckey="$2"
|
||||
@@ -22,6 +33,9 @@ cpanel_uapi_deploy() {
|
||||
_cca="$4"
|
||||
_cfullchain="$5"
|
||||
|
||||
# re-declare vars inherited from acme.sh but not passed to make ShellCheck happy
|
||||
: "${Le_Alt:=""}"
|
||||
|
||||
_debug _cdomain "$_cdomain"
|
||||
_debug _ckey "$_ckey"
|
||||
_debug _ccert "$_ccert"
|
||||
@@ -32,25 +46,120 @@ cpanel_uapi_deploy() {
|
||||
_err "The command uapi is not found."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# declare useful constants
|
||||
uapi_error_response='status: 0'
|
||||
|
||||
# read cert and key files and urlencode both
|
||||
_cert=$(_url_encode <"$_ccert")
|
||||
_key=$(_url_encode <"$_ckey")
|
||||
|
||||
_debug _cert "$_cert"
|
||||
_debug _key "$_key"
|
||||
_debug2 _cert "$_cert"
|
||||
_debug2 _key "$_key"
|
||||
|
||||
if [ "$(id -u)" = 0 ]; then
|
||||
if [ -z "$DEPLOY_CPANEL_USER" ]; then
|
||||
_getdeployconf DEPLOY_CPANEL_USER
|
||||
# fallback to _readdomainconf for old installs
|
||||
if [ -z "${DEPLOY_CPANEL_USER:=$(_readdomainconf DEPLOY_CPANEL_USER)}" ]; then
|
||||
_err "It seems that you are root, please define the target user name: export DEPLOY_CPANEL_USER=username"
|
||||
return 1
|
||||
fi
|
||||
_savedomainconf DEPLOY_CPANEL_USER "$DEPLOY_CPANEL_USER"
|
||||
_response=$(uapi --user="$DEPLOY_CPANEL_USER" SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key")
|
||||
_debug DEPLOY_CPANEL_USER "$DEPLOY_CPANEL_USER"
|
||||
_savedeployconf DEPLOY_CPANEL_USER "$DEPLOY_CPANEL_USER"
|
||||
|
||||
_uapi_user="$DEPLOY_CPANEL_USER"
|
||||
fi
|
||||
|
||||
# Load all AUTO envars and set defaults - see above for usage
|
||||
__cpanel_initautoparam ENABLED 'true'
|
||||
__cpanel_initautoparam NOMATCH 'false'
|
||||
__cpanel_initautoparam INCLUDE '*'
|
||||
__cpanel_initautoparam EXCLUDE ''
|
||||
|
||||
# Auto mode
|
||||
if [ "$DEPLOY_CPANEL_AUTO_ENABLED" = "true" ]; then
|
||||
# call API for site config
|
||||
_response=$(uapi DomainInfo list_domains)
|
||||
# exit if error in response
|
||||
if [ -z "$_response" ] || [ "${_response#*"$uapi_error_response"}" != "$_response" ]; then
|
||||
_err "Error in deploying certificate - cannot retrieve sitelist:"
|
||||
_err "\n$_response"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# parse response to create site list
|
||||
sitelist=$(__cpanel_parse_response "$_response")
|
||||
_debug "UAPI sites found: $sitelist"
|
||||
|
||||
# filter sitelist using configured domains
|
||||
# skip if NOMATCH is "true"
|
||||
if [ "$DEPLOY_CPANEL_AUTO_NOMATCH" = "true" ]; then
|
||||
_debug "DEPLOY_CPANEL_AUTO_NOMATCH is true"
|
||||
_info "UAPI nomatch mode is enabled - Will not validate sites are valid for the certificate"
|
||||
else
|
||||
_debug "DEPLOY_CPANEL_AUTO_NOMATCH is false"
|
||||
d="$(echo "${Le_Alt}," | sed -e "s/^$_cdomain,//" -e "s/,$_cdomain,/,/")"
|
||||
d="$(echo "$_cdomain,$d" | tr ',' '\n' | sed -e 's/\./\\./g' -e 's/\*/\[\^\.\]\*/g')"
|
||||
sitelist="$(echo "$sitelist" | grep -ix "$d")"
|
||||
_debug2 "Matched UAPI sites: $sitelist"
|
||||
fi
|
||||
|
||||
# filter sites that do not match $DEPLOY_CPANEL_AUTO_INCLUDE
|
||||
_info "Applying sitelist filter DEPLOY_CPANEL_AUTO_INCLUDE: $DEPLOY_CPANEL_AUTO_INCLUDE"
|
||||
sitelist="$(echo "$sitelist" | grep -ix "$(echo "$DEPLOY_CPANEL_AUTO_INCLUDE" | tr ',' '\n' | sed -e 's/\./\\./g' -e 's/\*/\.\*/g')")"
|
||||
_debug2 "Remaining sites: $sitelist"
|
||||
|
||||
# filter sites that match $DEPLOY_CPANEL_AUTO_EXCLUDE
|
||||
_info "Applying sitelist filter DEPLOY_CPANEL_AUTO_EXCLUDE: $DEPLOY_CPANEL_AUTO_EXCLUDE"
|
||||
sitelist="$(echo "$sitelist" | grep -vix "$(echo "$DEPLOY_CPANEL_AUTO_EXCLUDE" | tr ',' '\n' | sed -e 's/\./\\./g' -e 's/\*/\.\*/g')")"
|
||||
_debug2 "Remaining sites: $sitelist"
|
||||
|
||||
# counter for success / failure check
|
||||
successes=0
|
||||
if [ -n "$sitelist" ]; then
|
||||
sitetotal="$(echo "$sitelist" | wc -l)"
|
||||
_debug "$sitetotal sites to deploy"
|
||||
else
|
||||
sitetotal=0
|
||||
_debug "No sites to deploy"
|
||||
fi
|
||||
|
||||
# for each site: call uapi to publish cert and log result. Only return failure if all fail
|
||||
for site in $sitelist; do
|
||||
# call uapi to publish cert, check response for errors and log them.
|
||||
if [ -n "$_uapi_user" ]; then
|
||||
_response=$(uapi --user="$_uapi_user" SSL install_ssl domain="$site" cert="$_cert" key="$_key")
|
||||
else
|
||||
_response=$(uapi SSL install_ssl domain="$site" cert="$_cert" key="$_key")
|
||||
fi
|
||||
if [ "${_response#*"$uapi_error_response"}" != "$_response" ]; then
|
||||
_err "Error in deploying certificate to $site:"
|
||||
_err "$_response"
|
||||
else
|
||||
successes=$((successes + 1))
|
||||
_debug "$_response"
|
||||
_info "Succcessfully deployed to $site"
|
||||
fi
|
||||
done
|
||||
|
||||
# Raise error if all updates fail
|
||||
if [ "$sitetotal" -gt 0 ] && [ "$successes" -eq 0 ]; then
|
||||
_err "Could not deploy to any of $sitetotal sites via UAPI"
|
||||
_debug "successes: $successes, sitetotal: $sitetotal"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_info "Successfully deployed certificate to $successes of $sitetotal sites via UAPI"
|
||||
return 0
|
||||
else
|
||||
# "classic" mode - will only try to deploy to the primary domain; will not check UAPI first
|
||||
if [ -n "$_uapi_user" ]; then
|
||||
_response=$(uapi --user="$_uapi_user" SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key")
|
||||
else
|
||||
_response=$(uapi SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key")
|
||||
fi
|
||||
error_response="status: 0"
|
||||
if test "${_response#*$error_response}" != "$_response"; then
|
||||
|
||||
if [ "${_response#*"$uapi_error_response"}" != "$_response" ]; then
|
||||
_err "Error in deploying certificate:"
|
||||
_err "$_response"
|
||||
return 1
|
||||
@@ -59,4 +168,44 @@ cpanel_uapi_deploy() {
|
||||
_debug response "$_response"
|
||||
_info "Certificate successfully deployed"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
######## Private functions #####################
|
||||
|
||||
# Internal utility to process YML from UAPI - looks at main_domain, sub_domains, addon domains and parked domains
|
||||
#[response]
|
||||
__cpanel_parse_response() {
|
||||
if [ $# -gt 0 ]; then resp="$*"; else resp="$(cat)"; fi
|
||||
|
||||
echo "$resp" |
|
||||
sed -En \
|
||||
-e 's/\r$//' \
|
||||
-e 's/^( *)([_.[:alnum:]]+) *: *(.*)/\1,\2,\3/p' \
|
||||
-e 's/^( *)- (.*)/\1,-,\2/p' |
|
||||
awk -F, '{
|
||||
level = length($1)/2;
|
||||
section[level] = $2;
|
||||
for (i in section) {if (i > level) {delete section[i]}}
|
||||
if (length($3) > 0) {
|
||||
prefix="";
|
||||
for (i=0; i < level; i++)
|
||||
{ prefix = (prefix)(section[i])("/") }
|
||||
printf("%s%s=%s\n", prefix, $2, $3);
|
||||
}
|
||||
}' |
|
||||
sed -En -e 's/^result\/data\/(main_domain|sub_domains\/-|addon_domains\/-|parked_domains\/-)=(.*)$/\2/p'
|
||||
}
|
||||
|
||||
# Load parameter by prefix+name - fallback to default if not set, and save to config
|
||||
#pname pdefault
|
||||
__cpanel_initautoparam() {
|
||||
pname="$1"
|
||||
pdefault="$2"
|
||||
pkey="DEPLOY_CPANEL_AUTO_$pname"
|
||||
|
||||
_getdeployconf "$pkey"
|
||||
[ -n "$(eval echo "\"\$$pkey\"")" ] || eval "$pkey=\"$pdefault\""
|
||||
_debug2 "$pkey" "$(eval echo "\"\$$pkey\"")"
|
||||
_savedeployconf "$pkey" "$(eval echo "\"\$$pkey\"")"
|
||||
}
|
||||
|
||||
@@ -273,16 +273,27 @@ _check_curl_version() {
|
||||
_minor="$(_getfield "$_cversion" 2 '.')"
|
||||
_debug2 "_minor" "$_minor"
|
||||
|
||||
if [ "$_major$_minor" -lt "740" ]; then
|
||||
if [ "$_major" -ge "8" ]; then
|
||||
#ok
|
||||
return 0
|
||||
fi
|
||||
if [ "$_major" = "7" ]; then
|
||||
if [ "$_minor" -lt "40" ]; then
|
||||
_err "curl v$_cversion doesn't support unit socket"
|
||||
_err "Please upgrade to curl 7.40 or later."
|
||||
return 1
|
||||
fi
|
||||
if [ "$_major$_minor" -lt "750" ]; then
|
||||
if [ "$_minor" -lt "50" ]; then
|
||||
_debug "Use short host name"
|
||||
export _CURL_NO_HOST=1
|
||||
else
|
||||
export _CURL_NO_HOST=
|
||||
fi
|
||||
return 0
|
||||
else
|
||||
_err "curl v$_cversion doesn't support unit socket"
|
||||
_err "Please upgrade to curl 7.40 or later."
|
||||
return 1
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Here is the script to deploy the cert to G-Core CDN service (https://gcorelabs.com/ru/) using the G-Core Labs API (https://docs.gcorelabs.com/cdn/).
|
||||
# Here is the script to deploy the cert to G-Core CDN service (https://gcore.com/) using the G-Core Labs API (https://apidocs.gcore.com/cdn).
|
||||
# Returns 0 when success.
|
||||
#
|
||||
# Written by temoffey <temofffey@gmail.com>
|
||||
# Public domain, 2019
|
||||
# Update by DreamOfIce <admin@dreamofice.cn> in 2023
|
||||
|
||||
#export DEPLOY_GCORE_CDN_USERNAME=myusername
|
||||
#export DEPLOY_GCORE_CDN_PASSWORD=mypassword
|
||||
@@ -56,7 +57,7 @@ gcore_cdn_deploy() {
|
||||
_request="{\"username\":\"$Le_Deploy_gcore_cdn_username\",\"password\":\"$Le_Deploy_gcore_cdn_password\"}"
|
||||
_debug _request "$_request"
|
||||
export _H1="Content-Type:application/json"
|
||||
_response=$(_post "$_request" "https://api.gcdn.co/auth/jwt/login")
|
||||
_response=$(_post "$_request" "https://api.gcore.com/auth/jwt/login")
|
||||
_debug _response "$_response"
|
||||
_regex=".*\"access\":\"\([-._0-9A-Za-z]*\)\".*$"
|
||||
_debug _regex "$_regex"
|
||||
@@ -69,8 +70,8 @@ gcore_cdn_deploy() {
|
||||
fi
|
||||
|
||||
_info "Find CDN resource with cname $_cdomain"
|
||||
export _H2="Authorization:Token $_token"
|
||||
_response=$(_get "https://api.gcdn.co/resources")
|
||||
export _H2="Authorization:Bearer $_token"
|
||||
_response=$(_get "https://api.gcore.com/cdn/resources")
|
||||
_debug _response "$_response"
|
||||
_regex="\"primary_resource\":null},"
|
||||
_debug _regex "$_regex"
|
||||
@@ -102,7 +103,7 @@ gcore_cdn_deploy() {
|
||||
_date=$(date "+%d.%m.%Y %H:%M:%S")
|
||||
_request="{\"name\":\"$_cdomain ($_date)\",\"sslCertificate\":\"$_fullchain\",\"sslPrivateKey\":\"$_key\"}"
|
||||
_debug _request "$_request"
|
||||
_response=$(_post "$_request" "https://api.gcdn.co/sslData")
|
||||
_response=$(_post "$_request" "https://api.gcore.com/cdn/sslData")
|
||||
_debug _response "$_response"
|
||||
_regex=".*\"id\":\([0-9]*\).*$"
|
||||
_debug _regex "$_regex"
|
||||
@@ -117,7 +118,7 @@ gcore_cdn_deploy() {
|
||||
_info "Update CDN resource"
|
||||
_request="{\"originGroup\":$_originGroup,\"sslData\":$_sslDataAdd}"
|
||||
_debug _request "$_request"
|
||||
_response=$(_post "$_request" "https://api.gcdn.co/resources/$_resourceId" '' "PUT")
|
||||
_response=$(_post "$_request" "https://api.gcore.com/cdn/resources/$_resourceId" '' "PUT")
|
||||
_debug _response "$_response"
|
||||
_regex=".*\"sslData\":\([0-9]*\).*$"
|
||||
_debug _regex "$_regex"
|
||||
@@ -133,7 +134,7 @@ gcore_cdn_deploy() {
|
||||
_info "Not found old SSL certificate"
|
||||
else
|
||||
_info "Delete old SSL certificate"
|
||||
_response=$(_post '' "https://api.gcdn.co/sslData/$_sslDataOld" '' "DELETE")
|
||||
_response=$(_post '' "https://api.gcore.com/cdn/sslData/$_sslDataOld" '' "DELETE")
|
||||
_debug _response "$_response"
|
||||
fi
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ gitlab_deploy() {
|
||||
|
||||
error_response="error"
|
||||
|
||||
if test "${_response#*$error_response}" != "$_response"; then
|
||||
if test "${_response#*"$error_response"}" != "$_response"; then
|
||||
_err "Error in deploying certificate:"
|
||||
_err "$_response"
|
||||
return 1
|
||||
|
||||
@@ -36,6 +36,19 @@
|
||||
# Note: This functionality requires HAProxy was compiled against
|
||||
# a version of OpenSSL that supports this.
|
||||
#
|
||||
# export DEPLOY_HAPROXY_HOT_UPDATE="yes"
|
||||
# export DEPLOY_HAPROXY_STATS_SOCKET="UNIX:/run/haproxy/admin.sock"
|
||||
#
|
||||
# OPTIONAL: Deploy the certificate over the HAProxy stats socket without
|
||||
# needing to reload HAProxy. Default is "no".
|
||||
#
|
||||
# Require the socat binary. DEPLOY_HAPROXY_STATS_SOCKET variable uses the socat
|
||||
# address format.
|
||||
#
|
||||
# export DEPLOY_HAPROXY_MASTER_CLI="UNIX:/run/haproxy-master.sock"
|
||||
#
|
||||
# OPTIONAL: To use the master CLI with DEPLOY_HAPROXY_HOT_UPDATE="yes" instead
|
||||
# of a stats socket, use this variable.
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
@@ -46,6 +59,7 @@ haproxy_deploy() {
|
||||
_ccert="$3"
|
||||
_cca="$4"
|
||||
_cfullchain="$5"
|
||||
_cmdpfx=""
|
||||
|
||||
# Some defaults
|
||||
DEPLOY_HAPROXY_PEM_PATH_DEFAULT="/etc/haproxy"
|
||||
@@ -53,6 +67,8 @@ haproxy_deploy() {
|
||||
DEPLOY_HAPROXY_BUNDLE_DEFAULT="no"
|
||||
DEPLOY_HAPROXY_ISSUER_DEFAULT="no"
|
||||
DEPLOY_HAPROXY_RELOAD_DEFAULT="true"
|
||||
DEPLOY_HAPROXY_HOT_UPDATE_DEFAULT="no"
|
||||
DEPLOY_HAPROXY_STATS_SOCKET_DEFAULT="UNIX:/run/haproxy/admin.sock"
|
||||
|
||||
_debug _cdomain "${_cdomain}"
|
||||
_debug _ckey "${_ckey}"
|
||||
@@ -86,6 +102,11 @@ haproxy_deploy() {
|
||||
_savedomainconf Le_Deploy_haproxy_pem_name "${Le_Deploy_haproxy_pem_name}"
|
||||
elif [ -z "${Le_Deploy_haproxy_pem_name}" ]; then
|
||||
Le_Deploy_haproxy_pem_name="${DEPLOY_HAPROXY_PEM_NAME_DEFAULT}"
|
||||
# We better not have '*' as the first character
|
||||
if [ "${Le_Deploy_haproxy_pem_name%%"${Le_Deploy_haproxy_pem_name#?}"}" = '*' ]; then
|
||||
# removes the first characters and add a _ instead
|
||||
Le_Deploy_haproxy_pem_name="_${Le_Deploy_haproxy_pem_name#?}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# BUNDLE is optional. If not provided then assume "${DEPLOY_HAPROXY_BUNDLE_DEFAULT}"
|
||||
@@ -118,6 +139,36 @@ haproxy_deploy() {
|
||||
Le_Deploy_haproxy_reload="${DEPLOY_HAPROXY_RELOAD_DEFAULT}"
|
||||
fi
|
||||
|
||||
# HOT_UPDATE is optional. If not provided then assume "${DEPLOY_HAPROXY_HOT_UPDATE_DEFAULT}"
|
||||
_getdeployconf DEPLOY_HAPROXY_HOT_UPDATE
|
||||
_debug2 DEPLOY_HAPROXY_HOT_UPDATE "${DEPLOY_HAPROXY_HOT_UPDATE}"
|
||||
if [ -n "${DEPLOY_HAPROXY_HOT_UPDATE}" ]; then
|
||||
Le_Deploy_haproxy_hot_update="${DEPLOY_HAPROXY_HOT_UPDATE}"
|
||||
_savedomainconf Le_Deploy_haproxy_hot_update "${Le_Deploy_haproxy_hot_update}"
|
||||
elif [ -z "${Le_Deploy_haproxy_hot_update}" ]; then
|
||||
Le_Deploy_haproxy_hot_update="${DEPLOY_HAPROXY_HOT_UPDATE_DEFAULT}"
|
||||
fi
|
||||
|
||||
# STATS_SOCKET is optional. If not provided then assume "${DEPLOY_HAPROXY_STATS_SOCKET_DEFAULT}"
|
||||
_getdeployconf DEPLOY_HAPROXY_STATS_SOCKET
|
||||
_debug2 DEPLOY_HAPROXY_STATS_SOCKET "${DEPLOY_HAPROXY_STATS_SOCKET}"
|
||||
if [ -n "${DEPLOY_HAPROXY_STATS_SOCKET}" ]; then
|
||||
Le_Deploy_haproxy_stats_socket="${DEPLOY_HAPROXY_STATS_SOCKET}"
|
||||
_savedomainconf Le_Deploy_haproxy_stats_socket "${Le_Deploy_haproxy_stats_socket}"
|
||||
elif [ -z "${Le_Deploy_haproxy_stats_socket}" ]; then
|
||||
Le_Deploy_haproxy_stats_socket="${DEPLOY_HAPROXY_STATS_SOCKET_DEFAULT}"
|
||||
fi
|
||||
|
||||
# MASTER_CLI is optional. No defaults are used. When the master CLI is used,
|
||||
# all commands are sent with a prefix.
|
||||
_getdeployconf DEPLOY_HAPROXY_MASTER_CLI
|
||||
_debug2 DEPLOY_HAPROXY_MASTER_CLI "${DEPLOY_HAPROXY_MASTER_CLI}"
|
||||
if [ -n "${DEPLOY_HAPROXY_MASTER_CLI}" ]; then
|
||||
Le_Deploy_haproxy_stats_socket="${DEPLOY_HAPROXY_MASTER_CLI}"
|
||||
_savedomainconf Le_Deploy_haproxy_stats_socket "${Le_Deploy_haproxy_stats_socket}"
|
||||
_cmdpfx="@1 " # command prefix used for master CLI only.
|
||||
fi
|
||||
|
||||
# Set the suffix depending if we are creating a bundle or not
|
||||
if [ "${Le_Deploy_haproxy_bundle}" = "yes" ]; then
|
||||
_info "Bundle creation requested"
|
||||
@@ -142,12 +193,13 @@ haproxy_deploy() {
|
||||
_issuer="${_pem}.issuer"
|
||||
_ocsp="${_pem}.ocsp"
|
||||
_reload="${Le_Deploy_haproxy_reload}"
|
||||
_statssock="${Le_Deploy_haproxy_stats_socket}"
|
||||
|
||||
_info "Deploying PEM file"
|
||||
# Create a temporary PEM file
|
||||
_temppem="$(_mktemp)"
|
||||
_debug _temppem "${_temppem}"
|
||||
cat "${_ckey}" "${_ccert}" "${_cca}" >"${_temppem}"
|
||||
cat "${_ccert}" "${_cca}" "${_ckey}" | grep . >"${_temppem}"
|
||||
_ret="$?"
|
||||
|
||||
# Check that we could create the temporary file
|
||||
@@ -265,6 +317,76 @@ haproxy_deploy() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${Le_Deploy_haproxy_hot_update}" = "yes" ]; then
|
||||
# set the socket name for messages
|
||||
if [ -n "${_cmdpfx}" ]; then
|
||||
_socketname="master CLI"
|
||||
else
|
||||
_socketname="stats socket"
|
||||
fi
|
||||
|
||||
# Update certificate over HAProxy stats socket or master CLI.
|
||||
if _exists socat; then
|
||||
# look for the certificate on the stats socket, to chose between updating or creating one
|
||||
_socat_cert_cmd="echo '${_cmdpfx}show ssl cert' | socat '${_statssock}' - | grep -q '^${_pem}$'"
|
||||
_debug _socat_cert_cmd "${_socat_cert_cmd}"
|
||||
eval "${_socat_cert_cmd}"
|
||||
_ret=$?
|
||||
if [ "${_ret}" != "0" ]; then
|
||||
_newcert="1"
|
||||
_info "Creating new certificate '${_pem}' over HAProxy ${_socketname}."
|
||||
# certificate wasn't found, it's a new one. We should check if the crt-list exists and creates/inserts the certificate.
|
||||
_socat_crtlist_show_cmd="echo '${_cmdpfx}show ssl crt-list' | socat '${_statssock}' - | grep -q '^${Le_Deploy_haproxy_pem_path}$'"
|
||||
_debug _socat_crtlist_show_cmd "${_socat_crtlist_show_cmd}"
|
||||
eval "${_socat_crtlist_show_cmd}"
|
||||
_ret=$?
|
||||
if [ "${_ret}" != "0" ]; then
|
||||
_err "Couldn't find '${Le_Deploy_haproxy_pem_path}' in haproxy 'show ssl crt-list'"
|
||||
return "${_ret}"
|
||||
fi
|
||||
# create a new certificate
|
||||
_socat_new_cmd="echo '${_cmdpfx}new ssl cert ${_pem}' | socat '${_statssock}' - | grep -q 'New empty'"
|
||||
_debug _socat_new_cmd "${_socat_new_cmd}"
|
||||
eval "${_socat_new_cmd}"
|
||||
_ret=$?
|
||||
if [ "${_ret}" != "0" ]; then
|
||||
_err "Couldn't create '${_pem}' in haproxy"
|
||||
return "${_ret}"
|
||||
fi
|
||||
else
|
||||
_info "Update existing certificate '${_pem}' over HAProxy ${_socketname}."
|
||||
fi
|
||||
_socat_cert_set_cmd="echo -e '${_cmdpfx}set ssl cert ${_pem} <<\n$(cat "${_pem}")\n' | socat '${_statssock}' - | grep -q 'Transaction created'"
|
||||
_debug _socat_cert_set_cmd "${_socat_cert_set_cmd}"
|
||||
eval "${_socat_cert_set_cmd}"
|
||||
_ret=$?
|
||||
if [ "${_ret}" != "0" ]; then
|
||||
_err "Can't update '${_pem}' in haproxy"
|
||||
return "${_ret}"
|
||||
fi
|
||||
_socat_cert_commit_cmd="echo '${_cmdpfx}commit ssl cert ${_pem}' | socat '${_statssock}' - | grep -q '^Success!$'"
|
||||
_debug _socat_cert_commit_cmd "${_socat_cert_commit_cmd}"
|
||||
eval "${_socat_cert_commit_cmd}"
|
||||
_ret=$?
|
||||
if [ "${_ret}" != "0" ]; then
|
||||
_err "Can't commit '${_pem}' in haproxy"
|
||||
return ${_ret}
|
||||
fi
|
||||
if [ "${_newcert}" = "1" ]; then
|
||||
# if this is a new certificate, it needs to be inserted into the crt-list`
|
||||
_socat_cert_add_cmd="echo '${_cmdpfx}add ssl crt-list ${Le_Deploy_haproxy_pem_path} ${_pem}' | socat '${_statssock}' - | grep -q 'Success!'"
|
||||
_debug _socat_cert_add_cmd "${_socat_cert_add_cmd}"
|
||||
eval "${_socat_cert_add_cmd}"
|
||||
_ret=$?
|
||||
if [ "${_ret}" != "0" ]; then
|
||||
_err "Can't update '${_pem}' in haproxy"
|
||||
return "${_ret}"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
_err "'socat' is not available, couldn't update over ${_socketname}"
|
||||
fi
|
||||
else
|
||||
# Reload HAProxy
|
||||
_debug _reload "${_reload}"
|
||||
eval "${_reload}"
|
||||
@@ -275,6 +397,7 @@ haproxy_deploy() {
|
||||
else
|
||||
_info "Reload successful"
|
||||
fi
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -44,30 +44,20 @@ mailcow_deploy() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
# ECC or RSA
|
||||
length=$(_readdomainconf Le_Keylength)
|
||||
if _isEccKey "$length"; then
|
||||
_info "ECC key type detected"
|
||||
_cert_name_prefix="ecdsa-"
|
||||
else
|
||||
_info "RSA key type detected"
|
||||
_cert_name_prefix=""
|
||||
fi
|
||||
|
||||
_info "Copying key and cert"
|
||||
_real_key="$_ssl_path/${_cert_name_prefix}key.pem"
|
||||
_real_key="$_ssl_path/key.pem"
|
||||
if ! cat "$_ckey" >"$_real_key"; then
|
||||
_err "Error: write key file to: $_real_key"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_real_fullchain="$_ssl_path/${_cert_name_prefix}cert.pem"
|
||||
_real_fullchain="$_ssl_path/cert.pem"
|
||||
if ! cat "$_cfullchain" >"$_real_fullchain"; then
|
||||
_err "Error: write cert file to: $_real_fullchain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
DEFAULT_MAILCOW_RELOAD="docker restart \$(docker ps --quiet --filter name=nginx-mailcow --filter name=dovecot-mailcow)"
|
||||
DEFAULT_MAILCOW_RELOAD="docker restart \$(docker ps --quiet --filter name=nginx-mailcow --filter name=dovecot-mailcow --filter name=postfix-mailcow)"
|
||||
_reload="${DEPLOY_MAILCOW_RELOAD:-$DEFAULT_MAILCOW_RELOAD}"
|
||||
|
||||
_info "Run reload: $_reload"
|
||||
|
||||
179
deploy/panos.sh
179
deploy/panos.sh
@@ -7,11 +7,18 @@
|
||||
#
|
||||
# Firewall admin with superuser and IP address is required.
|
||||
#
|
||||
# export PANOS_USER="" # required
|
||||
# export PANOS_PASS="" # required
|
||||
# export PANOS_HOST="" # required
|
||||
# REQURED:
|
||||
# export PANOS_HOST=""
|
||||
# export PANOS_USER="" #User *MUST* have Commit and Import Permissions in XML API for Admin Role
|
||||
# export PANOS_PASS=""
|
||||
#
|
||||
# OPTIONAL
|
||||
# export PANOS_TEMPLATE="" #Template Name of panorama managed devices
|
||||
#
|
||||
# The script will automatically generate a new API key if
|
||||
# no key is found, or if a saved key has expired or is invalid.
|
||||
|
||||
# This function is to parse the XML
|
||||
# This function is to parse the XML response from the firewall
|
||||
parse_response() {
|
||||
type=$2
|
||||
if [ "$type" = 'keygen' ]; then
|
||||
@@ -23,25 +30,46 @@ parse_response() {
|
||||
message="PAN-OS Key could not be set."
|
||||
fi
|
||||
else
|
||||
status=$(echo "$1" | sed 's/^.*"\([a-z]*\)".*/\1/g')
|
||||
message=$(echo "$1" | sed 's/^.*<result>\(.*\)<\/result.*/\1/g')
|
||||
status=$(echo "$1" | tr -d '\n' | sed 's/^.*"\([a-z]*\)".*/\1/g')
|
||||
message=$(echo "$1" | tr -d '\n' | sed 's/.*\(<result>\|<msg>\|<line>\)\([^<]*\).*/\2/g')
|
||||
_debug "Firewall message: $message"
|
||||
if [ "$type" = 'keytest' ] && [ "$status" != "success" ]; then
|
||||
_debug "**** API Key has EXPIRED or is INVALID ****"
|
||||
unset _panos_key
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
#This function is used to deploy to the firewall
|
||||
deployer() {
|
||||
content=""
|
||||
type=$1 # Types are keygen, cert, key, commit
|
||||
_debug "**** Deploying $type *****"
|
||||
type=$1 # Types are keytest, keygen, cert, key, commit
|
||||
panos_url="https://$_panos_host/api/"
|
||||
|
||||
#Test API Key by performing a lookup
|
||||
if [ "$type" = 'keytest' ]; then
|
||||
_debug "**** Testing saved API Key ****"
|
||||
_H1="Content-Type: application/x-www-form-urlencoded"
|
||||
# Get Version Info to test key
|
||||
content="type=version&key=$_panos_key"
|
||||
## Exclude all scopes for the empty commit
|
||||
#_exclude_scope="<policy-and-objects>exclude</policy-and-objects><device-and-network>exclude</device-and-network><shared-object>exclude</shared-object>"
|
||||
#content="type=commit&action=partial&key=$_panos_key&cmd=<commit><partial>$_exclude_scope<admin><member>acmekeytest</member></admin></partial></commit>"
|
||||
fi
|
||||
|
||||
# Generate API Key
|
||||
if [ "$type" = 'keygen' ]; then
|
||||
_debug "**** Generating new API Key ****"
|
||||
_H1="Content-Type: application/x-www-form-urlencoded"
|
||||
content="type=keygen&user=$_panos_user&password=$_panos_pass"
|
||||
# content="$content${nl}--$delim${nl}Content-Disposition: form-data; type=\"keygen\"; user=\"$_panos_user\"; password=\"$_panos_pass\"${nl}Content-Type: application/octet-stream${nl}${nl}"
|
||||
fi
|
||||
|
||||
# Deploy Cert or Key
|
||||
if [ "$type" = 'cert' ] || [ "$type" = 'key' ]; then
|
||||
#Generate DEIM
|
||||
_debug "**** Deploying $type ****"
|
||||
#Generate DELIM
|
||||
delim="-----MultipartDelimiter$(date "+%s%N")"
|
||||
nl="\015\012"
|
||||
#Set Header
|
||||
@@ -53,6 +81,9 @@ deployer() {
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n$_panos_key"
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\npem"
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")"
|
||||
if [ "$_panos_template" ]; then
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"target-tpl\"\r\n\r\n$_panos_template"
|
||||
fi
|
||||
fi
|
||||
if [ "$type" = 'key' ]; then
|
||||
panos_url="${panos_url}?type=import"
|
||||
@@ -61,7 +92,10 @@ deployer() {
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n$_panos_key"
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\npem"
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"passphrase\"\r\n\r\n123456"
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")"
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_cdomain.key")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")"
|
||||
if [ "$_panos_template" ]; then
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"target-tpl\"\r\n\r\n$_panos_template"
|
||||
fi
|
||||
fi
|
||||
#Close multipart
|
||||
content="$content${nl}--$delim--${nl}${nl}"
|
||||
@@ -69,16 +103,25 @@ deployer() {
|
||||
content=$(printf %b "$content")
|
||||
fi
|
||||
|
||||
# Commit changes
|
||||
if [ "$type" = 'commit' ]; then
|
||||
_debug "**** Committing changes ****"
|
||||
export _H1="Content-Type: application/x-www-form-urlencoded"
|
||||
cmd=$(printf "%s" "<commit><partial><$_panos_user></$_panos_user></partial></commit>" | _url_encode)
|
||||
content="type=commit&key=$_panos_key&cmd=$cmd"
|
||||
#Check for force commit - will commit ALL uncommited changes to the firewall. Use with caution!
|
||||
if [ "$FORCE" ]; then
|
||||
_debug "Force switch detected. Committing ALL changes to the firewall."
|
||||
cmd=$(printf "%s" "<commit><partial><force><admin><member>$_panos_user</member></admin></force></partial></commit>" | _url_encode)
|
||||
else
|
||||
_exclude_scope="<policy-and-objects>exclude</policy-and-objects><device-and-network>exclude</device-and-network>"
|
||||
cmd=$(printf "%s" "<commit><partial>$_exclude_scope<admin><member>$_panos_user</member></admin></partial></commit>" | _url_encode)
|
||||
fi
|
||||
content="type=commit&action=partial&key=$_panos_key&cmd=$cmd"
|
||||
fi
|
||||
|
||||
response=$(_post "$content" "$panos_url" "" "POST")
|
||||
parse_response "$response" "$type"
|
||||
# Saving response to variables
|
||||
response_status=$status
|
||||
#DEBUG
|
||||
_debug response_status "$response_status"
|
||||
if [ "$response_status" = "success" ]; then
|
||||
_debug "Successfully deployed $type"
|
||||
@@ -92,43 +135,95 @@ deployer() {
|
||||
|
||||
# This is the main function that will call the other functions to deploy everything.
|
||||
panos_deploy() {
|
||||
_cdomain="$1"
|
||||
_cdomain=$(echo "$1" | sed 's/*/WILDCARD_/g') #Wildcard Safe Filename
|
||||
_ckey="$2"
|
||||
_cfullchain="$5"
|
||||
# PANOS ENV VAR check
|
||||
if [ -z "$PANOS_USER" ] || [ -z "$PANOS_PASS" ] || [ -z "$PANOS_HOST" ]; then
|
||||
_debug "No ENV variables found lets check for saved variables"
|
||||
_getdeployconf PANOS_USER
|
||||
_getdeployconf PANOS_PASS
|
||||
|
||||
# VALID FILE CHECK
|
||||
if [ ! -f "$_ckey" ] || [ ! -f "$_cfullchain" ]; then
|
||||
_err "Unable to find a valid key and/or cert. If this is an ECDSA/ECC cert, use the --ecc flag when deploying."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# PANOS_HOST
|
||||
if [ "$PANOS_HOST" ]; then
|
||||
_debug "Detected ENV variable PANOS_HOST. Saving to file."
|
||||
_savedeployconf PANOS_HOST "$PANOS_HOST" 1
|
||||
else
|
||||
_debug "Attempting to load variable PANOS_HOST from file."
|
||||
_getdeployconf PANOS_HOST
|
||||
fi
|
||||
|
||||
# PANOS USER
|
||||
if [ "$PANOS_USER" ]; then
|
||||
_debug "Detected ENV variable PANOS_USER. Saving to file."
|
||||
_savedeployconf PANOS_USER "$PANOS_USER" 1
|
||||
else
|
||||
_debug "Attempting to load variable PANOS_USER from file."
|
||||
_getdeployconf PANOS_USER
|
||||
fi
|
||||
|
||||
# PANOS_PASS
|
||||
if [ "$PANOS_PASS" ]; then
|
||||
_debug "Detected ENV variable PANOS_PASS. Saving to file."
|
||||
_savedeployconf PANOS_PASS "$PANOS_PASS" 1
|
||||
else
|
||||
_debug "Attempting to load variable PANOS_PASS from file."
|
||||
_getdeployconf PANOS_PASS
|
||||
fi
|
||||
|
||||
# PANOS_KEY
|
||||
_getdeployconf PANOS_KEY
|
||||
if [ "$PANOS_KEY" ]; then
|
||||
_debug "Detected saved key."
|
||||
_panos_key=$PANOS_KEY
|
||||
else
|
||||
_debug "No key detected"
|
||||
unset _panos_key
|
||||
fi
|
||||
|
||||
# PANOS_TEMPLATE
|
||||
if [ "$PANOS_TEMPLATE" ]; then
|
||||
_debug "Detected ENV variable PANOS_TEMPLATE. Saving to file."
|
||||
_savedeployconf PANOS_TEMPLATE "$PANOS_TEMPLATE" 1
|
||||
else
|
||||
_debug "Attempting to load variable PANOS_TEMPLATE from file."
|
||||
_getdeployconf PANOS_TEMPLATE
|
||||
fi
|
||||
|
||||
#Store variables
|
||||
_panos_host=$PANOS_HOST
|
||||
_panos_user=$PANOS_USER
|
||||
_panos_pass=$PANOS_PASS
|
||||
_panos_host=$PANOS_HOST
|
||||
if [ -z "$_panos_user" ] && [ -z "$_panos_pass" ] && [ -z "$_panos_host" ]; then
|
||||
_err "No host, user and pass found.. If this is the first time deploying please set PANOS_HOST, PANOS_USER and PANOS_PASS in environment variables. Delete them after you have succesfully deployed certs."
|
||||
_panos_template=$PANOS_TEMPLATE
|
||||
|
||||
#Test API Key if found. If the key is invalid, the variable _panos_key will be unset.
|
||||
if [ "$_panos_host" ] && [ "$_panos_key" ]; then
|
||||
_debug "**** Testing API KEY ****"
|
||||
deployer keytest
|
||||
fi
|
||||
|
||||
# Check for valid variables
|
||||
if [ -z "$_panos_host" ]; then
|
||||
_err "No host found. If this is your first time deploying, please set PANOS_HOST in ENV variables. You can delete it after you have successfully deployed the certs."
|
||||
return 1
|
||||
elif [ -z "$_panos_user" ]; then
|
||||
_err "No user found. If this is your first time deploying, please set PANOS_USER in ENV variables. You can delete it after you have successfully deployed the certs."
|
||||
return 1
|
||||
elif [ -z "$_panos_pass" ]; then
|
||||
_err "No password found. If this is your first time deploying, please set PANOS_PASS in ENV variables. You can delete it after you have successfully deployed the certs."
|
||||
return 1
|
||||
else
|
||||
_debug "Using saved env variables."
|
||||
fi
|
||||
else
|
||||
_debug "Detected ENV variables to be saved to the deploy conf."
|
||||
# Encrypt and save user
|
||||
_savedeployconf PANOS_USER "$PANOS_USER" 1
|
||||
_savedeployconf PANOS_PASS "$PANOS_PASS" 1
|
||||
_savedeployconf PANOS_HOST "$PANOS_HOST" 1
|
||||
_panos_user="$PANOS_USER"
|
||||
_panos_pass="$PANOS_PASS"
|
||||
_panos_host="$PANOS_HOST"
|
||||
fi
|
||||
_debug "Let's use username and pass to generate token."
|
||||
if [ -z "$_panos_user" ] || [ -z "$_panos_pass" ] || [ -z "$_panos_host" ]; then
|
||||
_err "Please pass username and password and host as env variables PANOS_USER, PANOS_PASS and PANOS_HOST"
|
||||
return 1
|
||||
else
|
||||
_debug "Getting PANOS KEY"
|
||||
deployer keygen
|
||||
# Generate a new API key if no valid API key is found
|
||||
if [ -z "$_panos_key" ]; then
|
||||
_err "Missing apikey."
|
||||
_debug "**** Generating new PANOS API KEY ****"
|
||||
deployer keygen
|
||||
_savedeployconf PANOS_KEY "$_panos_key" 1
|
||||
fi
|
||||
|
||||
# Confirm that a valid key was generated
|
||||
if [ -z "$_panos_key" ]; then
|
||||
_err "Unable to generate an API key. The user and pass may be invalid or not authorized to generate a new key. Please check the PANOS_USER and PANOS_PASS credentials and try again"
|
||||
return 1
|
||||
else
|
||||
deployer cert
|
||||
|
||||
132
deploy/proxmoxve.sh
Normal file
132
deploy/proxmoxve.sh
Normal file
@@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Deploy certificates to a proxmox virtual environment node using the API.
|
||||
#
|
||||
# Environment variables that can be set are:
|
||||
# `DEPLOY_PROXMOXVE_SERVER`: The hostname of the proxmox ve node. Defaults to
|
||||
# _cdomain.
|
||||
# `DEPLOY_PROXMOXVE_SERVER_PORT`: The port number the management interface is on.
|
||||
# Defaults to 8006.
|
||||
# `DEPLOY_PROXMOXVE_NODE_NAME`: The name of the node we'll be connecting to.
|
||||
# Defaults to the host portion of the server
|
||||
# domain name.
|
||||
# `DEPLOY_PROXMOXVE_USER`: The user we'll connect as. Defaults to root.
|
||||
# `DEPLOY_PROXMOXVE_USER_REALM`: The authentication realm the user authenticates
|
||||
# with. Defaults to pam.
|
||||
# `DEPLOY_PROXMOXVE_API_TOKEN_NAME`: The name of the API token created for the
|
||||
# user account. Defaults to acme.
|
||||
# `DEPLOY_PROXMOXVE_API_TOKEN_KEY`: The API token. Required.
|
||||
|
||||
proxmoxve_deploy() {
|
||||
_cdomain="$1"
|
||||
_ckey="$2"
|
||||
_ccert="$3"
|
||||
_cca="$4"
|
||||
_cfullchain="$5"
|
||||
|
||||
_debug _cdomain "$_cdomain"
|
||||
_debug2 _ckey "$_ckey"
|
||||
_debug _ccert "$_ccert"
|
||||
_debug _cca "$_cca"
|
||||
_debug _cfullchain "$_cfullchain"
|
||||
|
||||
# "Sane" defaults.
|
||||
_getdeployconf DEPLOY_PROXMOXVE_SERVER
|
||||
if [ -z "$DEPLOY_PROXMOXVE_SERVER" ]; then
|
||||
_target_hostname="$_cdomain"
|
||||
else
|
||||
_target_hostname="$DEPLOY_PROXMOXVE_SERVER"
|
||||
_savedeployconf DEPLOY_PROXMOXVE_SERVER "$DEPLOY_PROXMOXVE_SERVER"
|
||||
fi
|
||||
_debug2 DEPLOY_PROXMOXVE_SERVER "$_target_hostname"
|
||||
|
||||
_getdeployconf DEPLOY_PROXMOXVE_SERVER_PORT
|
||||
if [ -z "$DEPLOY_PROXMOXVE_SERVER_PORT" ]; then
|
||||
_target_port="8006"
|
||||
else
|
||||
_target_port="$DEPLOY_PROXMOXVE_SERVER_PORT"
|
||||
_savedeployconf DEPLOY_PROXMOXVE_SERVER_PORT "$DEPLOY_PROXMOXVE_SERVER_PORT"
|
||||
fi
|
||||
_debug2 DEPLOY_PROXMOXVE_SERVER_PORT "$_target_port"
|
||||
|
||||
_getdeployconf DEPLOY_PROXMOXVE_NODE_NAME
|
||||
if [ -z "$DEPLOY_PROXMOXVE_NODE_NAME" ]; then
|
||||
_node_name=$(echo "$_target_hostname" | cut -d. -f1)
|
||||
else
|
||||
_node_name="$DEPLOY_PROXMOXVE_NODE_NAME"
|
||||
_savedeployconf DEPLOY_PROXMOXVE_NODE_NAME "$DEPLOY_PROXMOXVE_NODE_NAME"
|
||||
fi
|
||||
_debug2 DEPLOY_PROXMOXVE_NODE_NAME "$_node_name"
|
||||
|
||||
# Complete URL.
|
||||
_target_url="https://${_target_hostname}:${_target_port}/api2/json/nodes/${_node_name}/certificates/custom"
|
||||
_debug TARGET_URL "$_target_url"
|
||||
|
||||
# More "sane" defaults.
|
||||
_getdeployconf DEPLOY_PROXMOXVE_USER
|
||||
if [ -z "$DEPLOY_PROXMOXVE_USER" ]; then
|
||||
_proxmoxve_user="root"
|
||||
else
|
||||
_proxmoxve_user="$DEPLOY_PROXMOXVE_USER"
|
||||
_savedeployconf DEPLOY_PROXMOXVE_USER "$DEPLOY_PROXMOXVE_USER"
|
||||
fi
|
||||
_debug2 DEPLOY_PROXMOXVE_USER "$_proxmoxve_user"
|
||||
|
||||
_getdeployconf DEPLOY_PROXMOXVE_USER_REALM
|
||||
if [ -z "$DEPLOY_PROXMOXVE_USER_REALM" ]; then
|
||||
_proxmoxve_user_realm="pam"
|
||||
else
|
||||
_proxmoxve_user_realm="$DEPLOY_PROXMOXVE_USER_REALM"
|
||||
_savedeployconf DEPLOY_PROXMOXVE_USER_REALM "$DEPLOY_PROXMOXVE_USER_REALM"
|
||||
fi
|
||||
_debug2 DEPLOY_PROXMOXVE_USER_REALM "$_proxmoxve_user_realm"
|
||||
|
||||
_getdeployconf DEPLOY_PROXMOXVE_API_TOKEN_NAME
|
||||
if [ -z "$DEPLOY_PROXMOXVE_API_TOKEN_NAME" ]; then
|
||||
_proxmoxve_api_token_name="acme"
|
||||
else
|
||||
_proxmoxve_api_token_name="$DEPLOY_PROXMOXVE_API_TOKEN_NAME"
|
||||
_savedeployconf DEPLOY_PROXMOXVE_API_TOKEN_NAME "$DEPLOY_PROXMOXVE_API_TOKEN_NAME"
|
||||
fi
|
||||
_debug2 DEPLOY_PROXMOXVE_API_TOKEN_NAME "$_proxmoxve_api_token_name"
|
||||
|
||||
# This is required.
|
||||
_getdeployconf DEPLOY_PROXMOXVE_API_TOKEN_KEY
|
||||
if [ -z "$DEPLOY_PROXMOXVE_API_TOKEN_KEY" ]; then
|
||||
_err "API key not provided."
|
||||
return 1
|
||||
else
|
||||
_proxmoxve_api_token_key="$DEPLOY_PROXMOXVE_API_TOKEN_KEY"
|
||||
_savedeployconf DEPLOY_PROXMOXVE_API_TOKEN_KEY "$DEPLOY_PROXMOXVE_API_TOKEN_KEY"
|
||||
fi
|
||||
_debug2 DEPLOY_PROXMOXVE_API_TOKEN_KEY "$_proxmoxve_api_token_key"
|
||||
|
||||
# PVE API Token header value. Used in "Authorization: PVEAPIToken".
|
||||
_proxmoxve_header_api_token="${_proxmoxve_user}@${_proxmoxve_user_realm}!${_proxmoxve_api_token_name}=${_proxmoxve_api_token_key}"
|
||||
_debug2 "Auth Header" "$_proxmoxve_header_api_token"
|
||||
|
||||
# Ugly. I hate putting heredocs inside functions because heredocs don't
|
||||
# account for whitespace correctly but it _does_ work and is several times
|
||||
# cleaner than anything else I had here.
|
||||
#
|
||||
# This dumps the json payload to a variable that should be passable to the
|
||||
# _psot function.
|
||||
_json_payload=$(
|
||||
cat <<HEREDOC
|
||||
{
|
||||
"certificates": "$(tr '\n' ':' <"$_cfullchain" | sed 's/:/\\n/g')",
|
||||
"key": "$(tr '\n' ':' <"$_ckey" | sed 's/:/\\n/g')",
|
||||
"node":"$_node_name",
|
||||
"restart":"1",
|
||||
"force":"1"
|
||||
}
|
||||
HEREDOC
|
||||
)
|
||||
_debug2 Payload "$_json_payload"
|
||||
|
||||
_info "Push certificates to server"
|
||||
export HTTPS_INSECURE=1
|
||||
export _H1="Authorization: PVEAPIToken=${_proxmoxve_header_api_token}"
|
||||
_post "$_json_payload" "$_target_url" "" POST "application/json"
|
||||
|
||||
}
|
||||
@@ -53,7 +53,7 @@ qiniu_deploy() {
|
||||
sslcert_access_token="$(_make_access_token "$sslcert_path")"
|
||||
_debug sslcert_access_token "$sslcert_access_token"
|
||||
export _H1="Authorization: QBox $sslcert_access_token"
|
||||
sslcert_response=$(_post "$sslcerl_body" "$QINIU_API_BASE$sslcert_path" 0 "POST" "application/json" | _dbase64 "multiline")
|
||||
sslcert_response=$(_post "$sslcerl_body" "$QINIU_API_BASE$sslcert_path" 0 "POST" "application/json" | _dbase64)
|
||||
|
||||
if ! _contains "$sslcert_response" "certID"; then
|
||||
_err "Error in creating certificate:"
|
||||
@@ -75,7 +75,7 @@ qiniu_deploy() {
|
||||
update_access_token="$(_make_access_token "$update_path")"
|
||||
_debug update_access_token "$update_access_token"
|
||||
export _H1="Authorization: QBox $update_access_token"
|
||||
update_response=$(_post "$update_body" "$QINIU_API_BASE$update_path" 0 "PUT" "application/json" | _dbase64 "multiline")
|
||||
update_response=$(_post "$update_body" "$QINIU_API_BASE$update_path" 0 "PUT" "application/json" | _dbase64)
|
||||
|
||||
if _contains "$update_response" "error"; then
|
||||
_err "Error in updating domain $domain httpsconf:"
|
||||
|
||||
@@ -137,7 +137,8 @@ routeros_deploy() {
|
||||
return $_err_code
|
||||
fi
|
||||
|
||||
DEPLOY_SCRIPT_CMD="/system script add name=\"LE Cert Deploy - $_cdomain\" owner=$ROUTER_OS_USERNAME \
|
||||
DEPLOY_SCRIPT_CMD=":do {/system script remove \"LECertDeploy-$_cdomain\" } on-error={ }; \
|
||||
/system script add name=\"LECertDeploy-$_cdomain\" owner=$ROUTER_OS_USERNAME \
|
||||
comment=\"generated by routeros deploy script in acme.sh\" \
|
||||
source=\"/certificate remove [ find name=$_cdomain.cer_0 ];\
|
||||
\n/certificate remove [ find name=$_cdomain.cer_1 ];\
|
||||
@@ -146,8 +147,8 @@ source=\"/certificate remove [ find name=$_cdomain.cer_0 ];\
|
||||
\n/certificate import file-name=$_cdomain.cer passphrase=\\\"\\\";\
|
||||
\n/certificate import file-name=$_cdomain.key passphrase=\\\"\\\";\
|
||||
\ndelay 1;\
|
||||
\n/file remove $_cdomain.cer;\
|
||||
\n/file remove $_cdomain.key;\
|
||||
\n:do {/file remove $_cdomain.cer; } on-error={ }\
|
||||
\n:do {/file remove $_cdomain.key; } on-error={ }\
|
||||
\ndelay 2;\
|
||||
\n/ip service set www-ssl certificate=$_cdomain.cer_0;\
|
||||
\n$ROUTER_OS_ADDITIONAL_SERVICES;\
|
||||
|
||||
403
deploy/ssh.sh
403
deploy/ssh.sh
@@ -14,7 +14,7 @@
|
||||
# The following examples are for QNAP NAS running QTS 4.2
|
||||
# export DEPLOY_SSH_CMD="" # defaults to "ssh -T"
|
||||
# export DEPLOY_SSH_USER="admin" # required
|
||||
# export DEPLOY_SSH_SERVER="qnap" # defaults to domain name
|
||||
# export DEPLOY_SSH_SERVER="host1 host2:8022 192.168.0.1:9022" # defaults to domain name, support multiple servers with optional port
|
||||
# export DEPLOY_SSH_KEYFILE="/etc/stunnel/stunnel.pem"
|
||||
# export DEPLOY_SSH_CERTFILE="/etc/stunnel/stunnel.pem"
|
||||
# export DEPLOY_SSH_CAFILE="/etc/stunnel/uca.pem"
|
||||
@@ -23,6 +23,8 @@
|
||||
# export DEPLOY_SSH_BACKUP="" # yes or no, default to yes or previously saved value
|
||||
# export DEPLOY_SSH_BACKUP_PATH=".acme_ssh_deploy" # path on remote system. Defaults to .acme_ssh_deploy
|
||||
# export DEPLOY_SSH_MULTI_CALL="" # yes or no, default to no or previously saved value
|
||||
# export DEPLOY_SSH_USE_SCP="" yes or no, default to no
|
||||
# export DEPLOY_SSH_SCP_CMD="" defaults to "scp -q"
|
||||
#
|
||||
######## Public functions #####################
|
||||
|
||||
@@ -42,72 +44,134 @@ ssh_deploy() {
|
||||
_debug _cfullchain "$_cfullchain"
|
||||
|
||||
# USER is required to login by SSH to remote host.
|
||||
_migratedeployconf Le_Deploy_ssh_user DEPLOY_SSH_USER
|
||||
_getdeployconf DEPLOY_SSH_USER
|
||||
_debug2 DEPLOY_SSH_USER "$DEPLOY_SSH_USER"
|
||||
if [ -z "$DEPLOY_SSH_USER" ]; then
|
||||
if [ -z "$Le_Deploy_ssh_user" ]; then
|
||||
_err "DEPLOY_SSH_USER not defined."
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
Le_Deploy_ssh_user="$DEPLOY_SSH_USER"
|
||||
_savedomainconf Le_Deploy_ssh_user "$Le_Deploy_ssh_user"
|
||||
fi
|
||||
_savedeployconf DEPLOY_SSH_USER "$DEPLOY_SSH_USER"
|
||||
|
||||
# SERVER is optional. If not provided then use _cdomain
|
||||
_migratedeployconf Le_Deploy_ssh_server DEPLOY_SSH_SERVER
|
||||
_getdeployconf DEPLOY_SSH_SERVER
|
||||
_debug2 DEPLOY_SSH_SERVER "$DEPLOY_SSH_SERVER"
|
||||
if [ -n "$DEPLOY_SSH_SERVER" ]; then
|
||||
Le_Deploy_ssh_server="$DEPLOY_SSH_SERVER"
|
||||
_savedomainconf Le_Deploy_ssh_server "$Le_Deploy_ssh_server"
|
||||
elif [ -z "$Le_Deploy_ssh_server" ]; then
|
||||
Le_Deploy_ssh_server="$_cdomain"
|
||||
if [ -z "$DEPLOY_SSH_SERVER" ]; then
|
||||
DEPLOY_SSH_SERVER="$_cdomain"
|
||||
fi
|
||||
_savedeployconf DEPLOY_SSH_SERVER "$DEPLOY_SSH_SERVER"
|
||||
|
||||
# CMD is optional. If not provided then use ssh
|
||||
_migratedeployconf Le_Deploy_ssh_cmd DEPLOY_SSH_CMD
|
||||
_getdeployconf DEPLOY_SSH_CMD
|
||||
_debug2 DEPLOY_SSH_CMD "$DEPLOY_SSH_CMD"
|
||||
if [ -n "$DEPLOY_SSH_CMD" ]; then
|
||||
Le_Deploy_ssh_cmd="$DEPLOY_SSH_CMD"
|
||||
_savedomainconf Le_Deploy_ssh_cmd "$Le_Deploy_ssh_cmd"
|
||||
elif [ -z "$Le_Deploy_ssh_cmd" ]; then
|
||||
Le_Deploy_ssh_cmd="ssh -T"
|
||||
if [ -z "$DEPLOY_SSH_CMD" ]; then
|
||||
DEPLOY_SSH_CMD="ssh -T"
|
||||
fi
|
||||
_savedeployconf DEPLOY_SSH_CMD "$DEPLOY_SSH_CMD"
|
||||
|
||||
# BACKUP is optional. If not provided then default to previously saved value or yes.
|
||||
_migratedeployconf Le_Deploy_ssh_backup DEPLOY_SSH_BACKUP
|
||||
_getdeployconf DEPLOY_SSH_BACKUP
|
||||
_debug2 DEPLOY_SSH_BACKUP "$DEPLOY_SSH_BACKUP"
|
||||
if [ "$DEPLOY_SSH_BACKUP" = "no" ]; then
|
||||
Le_Deploy_ssh_backup="no"
|
||||
elif [ -z "$Le_Deploy_ssh_backup" ] || [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then
|
||||
Le_Deploy_ssh_backup="yes"
|
||||
if [ -z "$DEPLOY_SSH_BACKUP" ]; then
|
||||
DEPLOY_SSH_BACKUP="yes"
|
||||
fi
|
||||
_savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup"
|
||||
_savedeployconf DEPLOY_SSH_BACKUP "$DEPLOY_SSH_BACKUP"
|
||||
|
||||
# BACKUP_PATH is optional. If not provided then default to previously saved value or .acme_ssh_deploy
|
||||
_migratedeployconf Le_Deploy_ssh_backup_path DEPLOY_SSH_BACKUP_PATH
|
||||
_getdeployconf DEPLOY_SSH_BACKUP_PATH
|
||||
_debug2 DEPLOY_SSH_BACKUP_PATH "$DEPLOY_SSH_BACKUP_PATH"
|
||||
if [ -n "$DEPLOY_SSH_BACKUP_PATH" ]; then
|
||||
Le_Deploy_ssh_backup_path="$DEPLOY_SSH_BACKUP_PATH"
|
||||
elif [ -z "$Le_Deploy_ssh_backup_path" ]; then
|
||||
Le_Deploy_ssh_backup_path=".acme_ssh_deploy"
|
||||
if [ -z "$DEPLOY_SSH_BACKUP_PATH" ]; then
|
||||
DEPLOY_SSH_BACKUP_PATH=".acme_ssh_deploy"
|
||||
fi
|
||||
_savedomainconf Le_Deploy_ssh_backup_path "$Le_Deploy_ssh_backup_path"
|
||||
_savedeployconf DEPLOY_SSH_BACKUP_PATH "$DEPLOY_SSH_BACKUP_PATH"
|
||||
|
||||
# MULTI_CALL is optional. If not provided then default to previously saved
|
||||
# value (which may be undefined... equivalent to "no").
|
||||
_migratedeployconf Le_Deploy_ssh_multi_call DEPLOY_SSH_MULTI_CALL
|
||||
_getdeployconf DEPLOY_SSH_MULTI_CALL
|
||||
_debug2 DEPLOY_SSH_MULTI_CALL "$DEPLOY_SSH_MULTI_CALL"
|
||||
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||
Le_Deploy_ssh_multi_call="yes"
|
||||
_savedomainconf Le_Deploy_ssh_multi_call "$Le_Deploy_ssh_multi_call"
|
||||
elif [ "$DEPLOY_SSH_MULTI_CALL" = "no" ]; then
|
||||
Le_Deploy_ssh_multi_call=""
|
||||
_cleardomainconf Le_Deploy_ssh_multi_call
|
||||
if [ -z "$DEPLOY_SSH_MULTI_CALL" ]; then
|
||||
DEPLOY_SSH_MULTI_CALL="no"
|
||||
fi
|
||||
_savedeployconf DEPLOY_SSH_MULTI_CALL "$DEPLOY_SSH_MULTI_CALL"
|
||||
|
||||
# KEYFILE is optional.
|
||||
# If provided then private key will be copied to provided filename.
|
||||
_migratedeployconf Le_Deploy_ssh_keyfile DEPLOY_SSH_KEYFILE
|
||||
_getdeployconf DEPLOY_SSH_KEYFILE
|
||||
_debug2 DEPLOY_SSH_KEYFILE "$DEPLOY_SSH_KEYFILE"
|
||||
if [ -n "$DEPLOY_SSH_KEYFILE" ]; then
|
||||
_savedeployconf DEPLOY_SSH_KEYFILE "$DEPLOY_SSH_KEYFILE"
|
||||
fi
|
||||
|
||||
_deploy_ssh_servers=$Le_Deploy_ssh_server
|
||||
for Le_Deploy_ssh_server in $_deploy_ssh_servers; do
|
||||
# CERTFILE is optional.
|
||||
# If provided then certificate will be copied or appended to provided filename.
|
||||
_migratedeployconf Le_Deploy_ssh_certfile DEPLOY_SSH_CERTFILE
|
||||
_getdeployconf DEPLOY_SSH_CERTFILE
|
||||
_debug2 DEPLOY_SSH_CERTFILE "$DEPLOY_SSH_CERTFILE"
|
||||
if [ -n "$DEPLOY_SSH_CERTFILE" ]; then
|
||||
_savedeployconf DEPLOY_SSH_CERTFILE "$DEPLOY_SSH_CERTFILE"
|
||||
fi
|
||||
|
||||
# CAFILE is optional.
|
||||
# If provided then CA intermediate certificate will be copied or appended to provided filename.
|
||||
_migratedeployconf Le_Deploy_ssh_cafile DEPLOY_SSH_CAFILE
|
||||
_getdeployconf DEPLOY_SSH_CAFILE
|
||||
_debug2 DEPLOY_SSH_CAFILE "$DEPLOY_SSH_CAFILE"
|
||||
if [ -n "$DEPLOY_SSH_CAFILE" ]; then
|
||||
_savedeployconf DEPLOY_SSH_CAFILE "$DEPLOY_SSH_CAFILE"
|
||||
fi
|
||||
|
||||
# FULLCHAIN is optional.
|
||||
# If provided then fullchain certificate will be copied or appended to provided filename.
|
||||
_migratedeployconf Le_Deploy_ssh_fullchain DEPLOY_SSH_FULLCHAIN
|
||||
_getdeployconf DEPLOY_SSH_FULLCHAIN
|
||||
_debug2 DEPLOY_SSH_FULLCHAIN "$DEPLOY_SSH_FULLCHAIN"
|
||||
if [ -n "$DEPLOY_SSH_FULLCHAIN" ]; then
|
||||
_savedeployconf DEPLOY_SSH_FULLCHAIN "$DEPLOY_SSH_FULLCHAIN"
|
||||
fi
|
||||
|
||||
# REMOTE_CMD is optional.
|
||||
# If provided then this command will be executed on remote host.
|
||||
_migratedeployconf Le_Deploy_ssh_remote_cmd DEPLOY_SSH_REMOTE_CMD
|
||||
_getdeployconf DEPLOY_SSH_REMOTE_CMD
|
||||
_debug2 DEPLOY_SSH_REMOTE_CMD "$DEPLOY_SSH_REMOTE_CMD"
|
||||
if [ -n "$DEPLOY_SSH_REMOTE_CMD" ]; then
|
||||
_savedeployconf DEPLOY_SSH_REMOTE_CMD "$DEPLOY_SSH_REMOTE_CMD"
|
||||
fi
|
||||
|
||||
# USE_SCP is optional. If not provided then default to previously saved
|
||||
# value (which may be undefined... equivalent to "no").
|
||||
_getdeployconf DEPLOY_SSH_USE_SCP
|
||||
_debug2 DEPLOY_SSH_USE_SCP "$DEPLOY_SSH_USE_SCP"
|
||||
if [ -z "$DEPLOY_SSH_USE_SCP" ]; then
|
||||
DEPLOY_SSH_USE_SCP="no"
|
||||
fi
|
||||
_savedeployconf DEPLOY_SSH_USE_SCP "$DEPLOY_SSH_USE_SCP"
|
||||
|
||||
# SCP_CMD is optional. If not provided then use scp
|
||||
_getdeployconf DEPLOY_SSH_SCP_CMD
|
||||
_debug2 DEPLOY_SSH_SCP_CMD "$DEPLOY_SSH_SCP_CMD"
|
||||
if [ -z "$DEPLOY_SSH_SCP_CMD" ]; then
|
||||
DEPLOY_SSH_SCP_CMD="scp -q"
|
||||
fi
|
||||
_savedeployconf DEPLOY_SSH_SCP_CMD "$DEPLOY_SSH_SCP_CMD"
|
||||
|
||||
if [ "$DEPLOY_SSH_USE_SCP" = "yes" ]; then
|
||||
DEPLOY_SSH_MULTI_CALL="yes"
|
||||
_info "Using scp as alternate method for copying files. Multicall Mode is implicit"
|
||||
elif [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||
_info "Using MULTI_CALL mode... Required commands sent in multiple calls to remote host"
|
||||
else
|
||||
_info "Required commands batched and sent in single call to remote host"
|
||||
fi
|
||||
|
||||
_deploy_ssh_servers="$DEPLOY_SSH_SERVER"
|
||||
for DEPLOY_SSH_SERVER in $_deploy_ssh_servers; do
|
||||
_ssh_deploy
|
||||
done
|
||||
}
|
||||
@@ -117,16 +181,25 @@ _ssh_deploy() {
|
||||
_cmdstr=""
|
||||
_backupprefix=""
|
||||
_backupdir=""
|
||||
_local_cert_file=""
|
||||
_local_ca_file=""
|
||||
_local_full_file=""
|
||||
|
||||
_info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server"
|
||||
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
|
||||
_info "Using MULTI_CALL mode... Required commands sent in multiple calls to remote host"
|
||||
else
|
||||
_info "Required commands batched and sent in single call to remote host"
|
||||
fi
|
||||
case $DEPLOY_SSH_SERVER in
|
||||
*:*)
|
||||
_host=${DEPLOY_SSH_SERVER%:*}
|
||||
_port=${DEPLOY_SSH_SERVER##*:}
|
||||
;;
|
||||
*)
|
||||
_host=$DEPLOY_SSH_SERVER
|
||||
_port=
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$Le_Deploy_ssh_backup" = "yes" ]; then
|
||||
_backupprefix="$Le_Deploy_ssh_backup_path/$_cdomain-backup"
|
||||
_info "Deploy certificates to remote server $DEPLOY_SSH_USER@$_host:$_port"
|
||||
|
||||
if [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then
|
||||
_backupprefix="$DEPLOY_SSH_BACKUP_PATH/$_cdomain-backup"
|
||||
_backupdir="$_backupprefix-$(_utc_date | tr ' ' '-')"
|
||||
# run cleanup on the backup directory, erase all older
|
||||
# than 180 days (15552000 seconds).
|
||||
@@ -138,7 +211,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
|
||||
_cmdstr="mkdir -p $_backupdir; $_cmdstr"
|
||||
_info "Backup of old certificate files will be placed in remote directory $_backupdir"
|
||||
_info "Backup directories erased after 180 days."
|
||||
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
|
||||
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||
return $_err_code
|
||||
fi
|
||||
@@ -146,23 +219,11 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
|
||||
fi
|
||||
fi
|
||||
|
||||
# KEYFILE is optional.
|
||||
# If provided then private key will be copied to provided filename.
|
||||
_getdeployconf DEPLOY_SSH_KEYFILE
|
||||
_debug2 DEPLOY_SSH_KEYFILE "$DEPLOY_SSH_KEYFILE"
|
||||
if [ -n "$DEPLOY_SSH_KEYFILE" ]; then
|
||||
Le_Deploy_ssh_keyfile="$DEPLOY_SSH_KEYFILE"
|
||||
_savedomainconf Le_Deploy_ssh_keyfile "$Le_Deploy_ssh_keyfile"
|
||||
fi
|
||||
if [ -n "$Le_Deploy_ssh_keyfile" ]; then
|
||||
if [ "$Le_Deploy_ssh_backup" = "yes" ]; then
|
||||
if [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then
|
||||
# backup file we are about to overwrite.
|
||||
_cmdstr="$_cmdstr cp $Le_Deploy_ssh_keyfile $_backupdir >/dev/null;"
|
||||
fi
|
||||
# copy new certificate into file.
|
||||
_cmdstr="$_cmdstr echo \"$(cat "$_ckey")\" > $Le_Deploy_ssh_keyfile;"
|
||||
_info "will copy private key to remote file $Le_Deploy_ssh_keyfile"
|
||||
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
|
||||
_cmdstr="$_cmdstr cp $DEPLOY_SSH_KEYFILE $_backupdir >/dev/null;"
|
||||
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||
return $_err_code
|
||||
fi
|
||||
@@ -170,27 +231,34 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
|
||||
fi
|
||||
fi
|
||||
|
||||
# CERTFILE is optional.
|
||||
# If provided then certificate will be copied or appended to provided filename.
|
||||
_getdeployconf DEPLOY_SSH_CERTFILE
|
||||
_debug2 DEPLOY_SSH_CERTFILE "$DEPLOY_SSH_CERTFILE"
|
||||
# copy new key into file.
|
||||
if [ "$DEPLOY_SSH_USE_SCP" = "yes" ]; then
|
||||
# scp the file
|
||||
if ! _scp_remote_cmd "$_ckey" "$DEPLOY_SSH_KEYFILE"; then
|
||||
return $_err_code
|
||||
fi
|
||||
else
|
||||
# ssh echo to the file
|
||||
_cmdstr="$_cmdstr echo \"$(cat "$_ckey")\" > $DEPLOY_SSH_KEYFILE;"
|
||||
_info "will copy private key to remote file $DEPLOY_SSH_KEYFILE"
|
||||
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||
return $_err_code
|
||||
fi
|
||||
_cmdstr=""
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$DEPLOY_SSH_CERTFILE" ]; then
|
||||
Le_Deploy_ssh_certfile="$DEPLOY_SSH_CERTFILE"
|
||||
_savedomainconf Le_Deploy_ssh_certfile "$Le_Deploy_ssh_certfile"
|
||||
fi
|
||||
if [ -n "$Le_Deploy_ssh_certfile" ]; then
|
||||
_pipe=">"
|
||||
if [ "$Le_Deploy_ssh_certfile" = "$Le_Deploy_ssh_keyfile" ]; then
|
||||
if [ "$DEPLOY_SSH_CERTFILE" = "$DEPLOY_SSH_KEYFILE" ]; then
|
||||
# if filename is same as previous file then append.
|
||||
_pipe=">>"
|
||||
elif [ "$Le_Deploy_ssh_backup" = "yes" ]; then
|
||||
elif [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then
|
||||
# backup file we are about to overwrite.
|
||||
_cmdstr="$_cmdstr cp $Le_Deploy_ssh_certfile $_backupdir >/dev/null;"
|
||||
fi
|
||||
# copy new certificate into file.
|
||||
_cmdstr="$_cmdstr echo \"$(cat "$_ccert")\" $_pipe $Le_Deploy_ssh_certfile;"
|
||||
_info "will copy certificate to remote file $Le_Deploy_ssh_certfile"
|
||||
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
|
||||
_cmdstr="$_cmdstr cp $DEPLOY_SSH_CERTFILE $_backupdir >/dev/null;"
|
||||
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||
return $_err_code
|
||||
fi
|
||||
@@ -198,28 +266,40 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
|
||||
fi
|
||||
fi
|
||||
|
||||
# CAFILE is optional.
|
||||
# If provided then CA intermediate certificate will be copied or appended to provided filename.
|
||||
_getdeployconf DEPLOY_SSH_CAFILE
|
||||
_debug2 DEPLOY_SSH_CAFILE "$DEPLOY_SSH_CAFILE"
|
||||
# copy new certificate into file.
|
||||
if [ "$DEPLOY_SSH_USE_SCP" = "yes" ]; then
|
||||
# scp the file
|
||||
_local_cert_file=$(_mktemp)
|
||||
if [ "$DEPLOY_SSH_CERTFILE" = "$DEPLOY_SSH_KEYFILE" ]; then
|
||||
cat "$_ckey" >>"$_local_cert_file"
|
||||
fi
|
||||
cat "$_ccert" >>"$_local_cert_file"
|
||||
if ! _scp_remote_cmd "$_local_cert_file" "$DEPLOY_SSH_CERTFILE"; then
|
||||
return $_err_code
|
||||
fi
|
||||
else
|
||||
# ssh echo to the file
|
||||
_cmdstr="$_cmdstr echo \"$(cat "$_ccert")\" $_pipe $DEPLOY_SSH_CERTFILE;"
|
||||
_info "will copy certificate to remote file $DEPLOY_SSH_CERTFILE"
|
||||
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||
return $_err_code
|
||||
fi
|
||||
_cmdstr=""
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$DEPLOY_SSH_CAFILE" ]; then
|
||||
Le_Deploy_ssh_cafile="$DEPLOY_SSH_CAFILE"
|
||||
_savedomainconf Le_Deploy_ssh_cafile "$Le_Deploy_ssh_cafile"
|
||||
fi
|
||||
if [ -n "$Le_Deploy_ssh_cafile" ]; then
|
||||
_pipe=">"
|
||||
if [ "$Le_Deploy_ssh_cafile" = "$Le_Deploy_ssh_keyfile" ] ||
|
||||
[ "$Le_Deploy_ssh_cafile" = "$Le_Deploy_ssh_certfile" ]; then
|
||||
if [ "$DEPLOY_SSH_CAFILE" = "$DEPLOY_SSH_KEYFILE" ] ||
|
||||
[ "$DEPLOY_SSH_CAFILE" = "$DEPLOY_SSH_CERTFILE" ]; then
|
||||
# if filename is same as previous file then append.
|
||||
_pipe=">>"
|
||||
elif [ "$Le_Deploy_ssh_backup" = "yes" ]; then
|
||||
elif [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then
|
||||
# backup file we are about to overwrite.
|
||||
_cmdstr="$_cmdstr cp $Le_Deploy_ssh_cafile $_backupdir >/dev/null;"
|
||||
fi
|
||||
# copy new certificate into file.
|
||||
_cmdstr="$_cmdstr echo \"$(cat "$_cca")\" $_pipe $Le_Deploy_ssh_cafile;"
|
||||
_info "will copy CA file to remote file $Le_Deploy_ssh_cafile"
|
||||
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
|
||||
_cmdstr="$_cmdstr cp $DEPLOY_SSH_CAFILE $_backupdir >/dev/null;"
|
||||
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||
return $_err_code
|
||||
fi
|
||||
@@ -227,29 +307,44 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
|
||||
fi
|
||||
fi
|
||||
|
||||
# FULLCHAIN is optional.
|
||||
# If provided then fullchain certificate will be copied or appended to provided filename.
|
||||
_getdeployconf DEPLOY_SSH_FULLCHAIN
|
||||
_debug2 DEPLOY_SSH_FULLCHAIN "$DEPLOY_SSH_FULLCHAIN"
|
||||
# copy new certificate into file.
|
||||
if [ "$DEPLOY_SSH_USE_SCP" = "yes" ]; then
|
||||
# scp the file
|
||||
_local_ca_file=$(_mktemp)
|
||||
if [ "$DEPLOY_SSH_CAFILE" = "$DEPLOY_SSH_KEYFILE" ]; then
|
||||
cat "$_ckey" >>"$_local_ca_file"
|
||||
fi
|
||||
if [ "$DEPLOY_SSH_CAFILE" = "$DEPLOY_SSH_CERTFILE" ]; then
|
||||
cat "$_ccert" >>"$_local_ca_file"
|
||||
fi
|
||||
cat "$_cca" >>"$_local_ca_file"
|
||||
if ! _scp_remote_cmd "$_local_ca_file" "$DEPLOY_SSH_CAFILE"; then
|
||||
return $_err_code
|
||||
fi
|
||||
else
|
||||
# ssh echo to the file
|
||||
_cmdstr="$_cmdstr echo \"$(cat "$_cca")\" $_pipe $DEPLOY_SSH_CAFILE;"
|
||||
_info "will copy CA file to remote file $DEPLOY_SSH_CAFILE"
|
||||
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||
return $_err_code
|
||||
fi
|
||||
_cmdstr=""
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$DEPLOY_SSH_FULLCHAIN" ]; then
|
||||
Le_Deploy_ssh_fullchain="$DEPLOY_SSH_FULLCHAIN"
|
||||
_savedomainconf Le_Deploy_ssh_fullchain "$Le_Deploy_ssh_fullchain"
|
||||
fi
|
||||
if [ -n "$Le_Deploy_ssh_fullchain" ]; then
|
||||
_pipe=">"
|
||||
if [ "$Le_Deploy_ssh_fullchain" = "$Le_Deploy_ssh_keyfile" ] ||
|
||||
[ "$Le_Deploy_ssh_fullchain" = "$Le_Deploy_ssh_certfile" ] ||
|
||||
[ "$Le_Deploy_ssh_fullchain" = "$Le_Deploy_ssh_cafile" ]; then
|
||||
if [ "$DEPLOY_SSH_FULLCHAIN" = "$DEPLOY_SSH_KEYFILE" ] ||
|
||||
[ "$DEPLOY_SSH_FULLCHAIN" = "$DEPLOY_SSH_CERTFILE" ] ||
|
||||
[ "$DEPLOY_SSH_FULLCHAIN" = "$DEPLOY_SSH_CAFILE" ]; then
|
||||
# if filename is same as previous file then append.
|
||||
_pipe=">>"
|
||||
elif [ "$Le_Deploy_ssh_backup" = "yes" ]; then
|
||||
elif [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then
|
||||
# backup file we are about to overwrite.
|
||||
_cmdstr="$_cmdstr cp $Le_Deploy_ssh_fullchain $_backupdir >/dev/null;"
|
||||
fi
|
||||
# copy new certificate into file.
|
||||
_cmdstr="$_cmdstr echo \"$(cat "$_cfullchain")\" $_pipe $Le_Deploy_ssh_fullchain;"
|
||||
_info "will copy fullchain to remote file $Le_Deploy_ssh_fullchain"
|
||||
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
|
||||
_cmdstr="$_cmdstr cp $DEPLOY_SSH_FULLCHAIN $_backupdir >/dev/null;"
|
||||
if [ "$DEPLOY_SSH_FULLCHAIN" = "yes" ]; then
|
||||
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||
return $_err_code
|
||||
fi
|
||||
@@ -257,18 +352,51 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
|
||||
fi
|
||||
fi
|
||||
|
||||
# REMOTE_CMD is optional.
|
||||
# If provided then this command will be executed on remote host.
|
||||
_getdeployconf DEPLOY_SSH_REMOTE_CMD
|
||||
_debug2 DEPLOY_SSH_REMOTE_CMD "$DEPLOY_SSH_REMOTE_CMD"
|
||||
if [ -n "$DEPLOY_SSH_REMOTE_CMD" ]; then
|
||||
Le_Deploy_ssh_remote_cmd="$DEPLOY_SSH_REMOTE_CMD"
|
||||
_savedomainconf Le_Deploy_ssh_remote_cmd "$Le_Deploy_ssh_remote_cmd"
|
||||
# copy new certificate into file.
|
||||
if [ "$DEPLOY_SSH_USE_SCP" = "yes" ]; then
|
||||
# scp the file
|
||||
_local_full_file=$(_mktemp)
|
||||
if [ "$DEPLOY_SSH_FULLCHAIN" = "$DEPLOY_SSH_KEYFILE" ]; then
|
||||
cat "$_ckey" >>"$_local_full_file"
|
||||
fi
|
||||
if [ -n "$Le_Deploy_ssh_remote_cmd" ]; then
|
||||
_cmdstr="$_cmdstr $Le_Deploy_ssh_remote_cmd;"
|
||||
_info "Will execute remote command $Le_Deploy_ssh_remote_cmd"
|
||||
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
|
||||
if [ "$DEPLOY_SSH_FULLCHAIN" = "$DEPLOY_SSH_CERTFILE" ]; then
|
||||
cat "$_ccert" >>"$_local_full_file"
|
||||
fi
|
||||
if [ "$DEPLOY_SSH_FULLCHAIN" = "$DEPLOY_SSH_CAFILE" ]; then
|
||||
cat "$_cca" >>"$_local_full_file"
|
||||
fi
|
||||
cat "$_cfullchain" >>"$_local_full_file"
|
||||
if ! _scp_remote_cmd "$_local_full_file" "$DEPLOY_SSH_FULLCHAIN"; then
|
||||
return $_err_code
|
||||
fi
|
||||
else
|
||||
# ssh echo to the file
|
||||
_cmdstr="$_cmdstr echo \"$(cat "$_cfullchain")\" $_pipe $DEPLOY_SSH_FULLCHAIN;"
|
||||
_info "will copy fullchain to remote file $DEPLOY_SSH_FULLCHAIN"
|
||||
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||
return $_err_code
|
||||
fi
|
||||
_cmdstr=""
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# cleanup local files if any
|
||||
if [ -f "$_local_cert_file" ]; then
|
||||
rm -f "$_local_cert_file"
|
||||
fi
|
||||
if [ -f "$_local_ca_file" ]; then
|
||||
rm -f "$_local_ca_file"
|
||||
fi
|
||||
if [ -f "$_local_full_file" ]; then
|
||||
rm -f "$_local_full_file"
|
||||
fi
|
||||
|
||||
if [ -n "$DEPLOY_SSH_REMOTE_CMD" ]; then
|
||||
_cmdstr="$_cmdstr $DEPLOY_SSH_REMOTE_CMD;"
|
||||
_info "Will execute remote command $DEPLOY_SSH_REMOTE_CMD"
|
||||
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||
return $_err_code
|
||||
fi
|
||||
@@ -282,17 +410,25 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
|
||||
return $_err_code
|
||||
fi
|
||||
fi
|
||||
# cleanup in case all is ok
|
||||
return 0
|
||||
}
|
||||
|
||||
#cmd
|
||||
_ssh_remote_cmd() {
|
||||
_cmd="$1"
|
||||
|
||||
_ssh_cmd="$DEPLOY_SSH_CMD"
|
||||
if [ -n "$_port" ]; then
|
||||
_ssh_cmd="$_ssh_cmd -p $_port"
|
||||
fi
|
||||
|
||||
_secure_debug "Remote commands to execute: $_cmd"
|
||||
_info "Submitting sequence of commands to remote server by ssh"
|
||||
_info "Submitting sequence of commands to remote server by $_ssh_cmd"
|
||||
|
||||
# quotations in bash cmd below intended. Squash travis spellcheck error
|
||||
# shellcheck disable=SC2029
|
||||
$Le_Deploy_ssh_cmd "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmd'"
|
||||
$_ssh_cmd "$DEPLOY_SSH_USER@$_host" sh -c "'$_cmd'"
|
||||
_err_code="$?"
|
||||
|
||||
if [ "$_err_code" != "0" ]; then
|
||||
@@ -301,3 +437,26 @@ _ssh_remote_cmd() {
|
||||
|
||||
return $_err_code
|
||||
}
|
||||
|
||||
# cmd scp
|
||||
_scp_remote_cmd() {
|
||||
_src=$1
|
||||
_dest=$2
|
||||
|
||||
_scp_cmd="$DEPLOY_SSH_SCP_CMD"
|
||||
if [ -n "$_port" ]; then
|
||||
_scp_cmd="$_scp_cmd -P $_port"
|
||||
fi
|
||||
|
||||
_secure_debug "Remote copy source $_src to destination $_dest"
|
||||
_info "Submitting secure copy by $_scp_cmd"
|
||||
|
||||
$_scp_cmd "$_src" "$DEPLOY_SSH_USER"@"$_host":"$_dest"
|
||||
_err_code="$?"
|
||||
|
||||
if [ "$_err_code" != "0" ]; then
|
||||
_err "Error code $_err_code returned from scp"
|
||||
fi
|
||||
|
||||
return $_err_code
|
||||
}
|
||||
|
||||
@@ -1,34 +1,53 @@
|
||||
#!/usr/bin/env sh
|
||||
#!/bin/bash
|
||||
|
||||
# Here is a script to deploy cert to Synology DSM
|
||||
#
|
||||
# It requires following environment variables:
|
||||
#
|
||||
# SYNO_Username - Synology Username to login (must be an administrator)
|
||||
# SYNO_Password - Synology Password to login
|
||||
# SYNO_Certificate - Certificate description to target for replacement
|
||||
#
|
||||
# The following environmental variables may be set if you don't like their
|
||||
# default values:
|
||||
#
|
||||
# SYNO_Scheme - defaults to http
|
||||
# SYNO_Hostname - defaults to localhost
|
||||
# SYNO_Port - defaults to 5000
|
||||
# SYNO_DID - device ID to skip OTP - defaults to empty
|
||||
# SYNO_TOTP_SECRET - TOTP secret to generate OTP - defaults to empty
|
||||
#
|
||||
################################################################################
|
||||
# ACME.sh 3rd party deploy plugin for Synology DSM
|
||||
################################################################################
|
||||
# Authors: Brian Hartvigsen (creator), https://github.com/tresni
|
||||
# Martin Arndt (contributor), https://troublezone.net/
|
||||
# Updated: 2023-07-03
|
||||
# Issues: https://github.com/acmesh-official/acme.sh/issues/2727
|
||||
################################################################################
|
||||
# Usage (shown values are the examples):
|
||||
# 1. Set required environment variables:
|
||||
# - use automatically created temp admin user to authenticate
|
||||
# export SYNO_USE_TEMP_ADMIN=1
|
||||
# - or provide your own admin user credential to authenticate
|
||||
# 1. export SYNO_USERNAME="adminUser"
|
||||
# 2. export SYNO_PASSWORD="adminPassword"
|
||||
# 2. Set optional environment variables
|
||||
# - common optional variables
|
||||
# - export SYNO_SCHEME="http" - defaults to "http"
|
||||
# - export SYNO_HOSTNAME="localhost" - defaults to "localhost"
|
||||
# - export SYNO_PORT="5000" - defaults to "5000"
|
||||
# - export SYNO_CREATE=1 - to allow creating the cert if it doesn't exist
|
||||
# - export SYNO_CERTIFICATE="" - to replace a specific cert by its
|
||||
# description
|
||||
# - temp admin optional variables
|
||||
# - export SYNO_LOCAL_HOSTNAME=1 - if set to 1, force to treat hostname is
|
||||
# targeting current local machine (since
|
||||
# this method only locally supported)
|
||||
# - exsiting admin 2FA-OTP optional variables
|
||||
# - export SYNO_OTP_CODE="XXXXXX" - if set, script won't require to
|
||||
# interactive input the OTP code
|
||||
# - export SYNO_DEVICE_NAME="CertRenewal" - if set, script won't require to
|
||||
# interactive input the device name
|
||||
# - export SYNO_DEVICE_ID="" - (deprecated, auth with OTP code instead)
|
||||
# required for omitting 2FA-OTP
|
||||
# 3. Run command:
|
||||
# acme.sh --deploy --deploy-hook synology_dsm -d example.com
|
||||
################################################################################
|
||||
# Dependencies:
|
||||
# -------------
|
||||
# - jq and curl
|
||||
# - oathtool (When using 2 Factor Authentication and SYNO_TOTP_SECRET is set)
|
||||
#
|
||||
#returns 0 means success, otherwise error.
|
||||
|
||||
######## Public functions #####################
|
||||
# - curl
|
||||
# - synouser & synogroup & synosetkeyvalue (Required for SYNO_USE_TEMP_ADMIN=1)
|
||||
################################################################################
|
||||
# Return value:
|
||||
# 0 means success, otherwise error.
|
||||
################################################################################
|
||||
|
||||
########## Public functions ####################################################
|
||||
#domain keyfile certfile cafile fullchain
|
||||
synology_dsm_deploy() {
|
||||
|
||||
_cdomain="$1"
|
||||
_ckey="$2"
|
||||
_ccert="$3"
|
||||
@@ -36,148 +55,391 @@ synology_dsm_deploy() {
|
||||
|
||||
_debug _cdomain "$_cdomain"
|
||||
|
||||
# Get Username and Password, but don't save until we successfully authenticate
|
||||
_getdeployconf SYNO_Username
|
||||
_getdeployconf SYNO_Password
|
||||
_getdeployconf SYNO_Create
|
||||
_getdeployconf SYNO_DID
|
||||
_getdeployconf SYNO_TOTP_SECRET
|
||||
if [ -z "${SYNO_Username:-}" ] || [ -z "${SYNO_Password:-}" ]; then
|
||||
_err "SYNO_Username & SYNO_Password must be set"
|
||||
# Get username and password, but don't save until we authenticated successfully
|
||||
_migratedeployconf SYNO_Username SYNO_USERNAME
|
||||
_migratedeployconf SYNO_Password SYNO_PASSWORD
|
||||
_migratedeployconf SYNO_Device_ID SYNO_DEVICE_ID
|
||||
_migratedeployconf SYNO_Device_Name SYNO_DEVICE_NAME
|
||||
_getdeployconf SYNO_USERNAME
|
||||
_getdeployconf SYNO_PASSWORD
|
||||
_getdeployconf SYNO_DEVICE_ID
|
||||
_getdeployconf SYNO_DEVICE_NAME
|
||||
|
||||
# Prepare to use temp admin if SYNO_USE_TEMP_ADMIN is set
|
||||
_getdeployconf SYNO_USE_TEMP_ADMIN
|
||||
_check2cleardeployconfexp SYNO_USE_TEMP_ADMIN
|
||||
_debug2 SYNO_USE_TEMP_ADMIN "$SYNO_USE_TEMP_ADMIN"
|
||||
|
||||
if [ -n "$SYNO_USE_TEMP_ADMIN" ]; then
|
||||
if ! _exists synouser || ! _exists synogroup || ! _exists synosetkeyvalue; then
|
||||
_err "Missing required tools to creat temp admin user, please set SYNO_USERNAME and SYNO_PASSWORD instead."
|
||||
_err "Notice: temp admin user authorization method only supports local deployment on DSM."
|
||||
return 1
|
||||
fi
|
||||
if synouser --help 2>&1 | grep -q 'Permission denied'; then
|
||||
_err "For creating temp admin user, the deploy script must be run as root."
|
||||
return 1
|
||||
fi
|
||||
_debug2 SYNO_Username "$SYNO_Username"
|
||||
_secure_debug2 SYNO_Password "$SYNO_Password"
|
||||
|
||||
# Optional scheme, hostname, and port for Synology DSM
|
||||
_getdeployconf SYNO_Scheme
|
||||
_getdeployconf SYNO_Hostname
|
||||
_getdeployconf SYNO_Port
|
||||
[ -n "$SYNO_USERNAME" ] || _savedeployconf SYNO_USERNAME ""
|
||||
[ -n "$SYNO_PASSWORD" ] || _savedeployconf SYNO_PASSWORD ""
|
||||
|
||||
# default vaules for scheme, hostname, and port
|
||||
# defaulting to localhost and http because it's localhost...
|
||||
[ -n "${SYNO_Scheme}" ] || SYNO_Scheme="http"
|
||||
[ -n "${SYNO_Hostname}" ] || SYNO_Hostname="localhost"
|
||||
[ -n "${SYNO_Port}" ] || SYNO_Port="5000"
|
||||
_debug "Setting temp admin user credential..."
|
||||
SYNO_USERNAME=sc-acmesh-tmp
|
||||
SYNO_PASSWORD=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16)
|
||||
# Set 2FA-OTP settings to empty consider they won't be needed.
|
||||
SYNO_DEVICE_ID=
|
||||
SYNO_DEVICE_NAME=
|
||||
SYNO_OTP_CODE=
|
||||
else
|
||||
_debug2 SYNO_USERNAME "$SYNO_USERNAME"
|
||||
_secure_debug2 SYNO_PASSWORD "$SYNO_PASSWORD"
|
||||
_debug2 SYNO_DEVICE_NAME "$SYNO_DEVICE_NAME"
|
||||
_secure_debug2 SYNO_DEVICE_ID "$SYNO_DEVICE_ID"
|
||||
fi
|
||||
|
||||
_savedeployconf SYNO_Scheme "$SYNO_Scheme"
|
||||
_savedeployconf SYNO_Hostname "$SYNO_Hostname"
|
||||
_savedeployconf SYNO_Port "$SYNO_Port"
|
||||
if [ -z "$SYNO_USERNAME" ] || [ -z "$SYNO_PASSWORD" ]; then
|
||||
_err "You must set either SYNO_USE_TEMP_ADMIN, or set both SYNO_USERNAME and SYNO_PASSWORD."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug2 SYNO_Scheme "$SYNO_Scheme"
|
||||
_debug2 SYNO_Hostname "$SYNO_Hostname"
|
||||
_debug2 SYNO_Port "$SYNO_Port"
|
||||
# Optional scheme, hostname and port for Synology DSM
|
||||
_migratedeployconf SYNO_Scheme SYNO_SCHEME
|
||||
_migratedeployconf SYNO_Hostname SYNO_HOSTNAME
|
||||
_migratedeployconf SYNO_Port SYNO_PORT
|
||||
_getdeployconf SYNO_SCHEME
|
||||
_getdeployconf SYNO_HOSTNAME
|
||||
_getdeployconf SYNO_PORT
|
||||
|
||||
# Get the certificate description, but don't save it until we verfiy it's real
|
||||
_getdeployconf SYNO_Certificate
|
||||
_debug SYNO_Certificate "${SYNO_Certificate:-}"
|
||||
# Default values for scheme, hostname and port
|
||||
# Defaulting to localhost and http, because it's localhost…
|
||||
[ -n "$SYNO_SCHEME" ] || SYNO_SCHEME=http
|
||||
[ -n "$SYNO_HOSTNAME" ] || SYNO_HOSTNAME=localhost
|
||||
[ -n "$SYNO_PORT" ] || SYNO_PORT=5000
|
||||
_savedeployconf SYNO_SCHEME "$SYNO_SCHEME"
|
||||
_savedeployconf SYNO_HOSTNAME "$SYNO_HOSTNAME"
|
||||
_savedeployconf SYNO_PORT "$SYNO_PORT"
|
||||
_debug2 SYNO_SCHEME "$SYNO_SCHEME"
|
||||
_debug2 SYNO_HOSTNAME "$SYNO_HOSTNAME"
|
||||
_debug2 SYNO_PORT "$SYNO_PORT"
|
||||
|
||||
# Get the certificate description, but don't save it until we verify it's real
|
||||
_migratedeployconf SYNO_Certificate SYNO_CERTIFICATE "base64"
|
||||
_getdeployconf SYNO_CERTIFICATE
|
||||
_check2cleardeployconfexp SYNO_CERTIFICATE
|
||||
_debug SYNO_CERTIFICATE "${SYNO_CERTIFICATE:-}"
|
||||
|
||||
# shellcheck disable=SC1003 # We are not trying to escape a single quote
|
||||
if printf "%s" "$SYNO_Certificate" | grep '\\'; then
|
||||
if printf "%s" "$SYNO_CERTIFICATE" | grep '\\'; then
|
||||
_err "Do not use a backslash (\) in your certificate description"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_base_url="$SYNO_Scheme://$SYNO_Hostname:$SYNO_Port"
|
||||
_debug "Getting API version..."
|
||||
_base_url="$SYNO_SCHEME://$SYNO_HOSTNAME:$SYNO_PORT"
|
||||
_debug _base_url "$_base_url"
|
||||
|
||||
_debug "Getting API version"
|
||||
response=$(_get "$_base_url/webapi/query.cgi?api=SYNO.API.Info&version=1&method=query&query=SYNO.API.Auth")
|
||||
api_path=$(echo "$response" | grep "SYNO.API.Auth" | sed -n 's/.*"path" *: *"\([^"]*\)".*/\1/p')
|
||||
api_version=$(echo "$response" | grep "SYNO.API.Auth" | sed -n 's/.*"maxVersion" *: *\([0-9]*\).*/\1/p')
|
||||
_debug3 response "$response"
|
||||
_debug3 api_path "$api_path"
|
||||
_debug3 api_version "$api_version"
|
||||
|
||||
# Login, get the token from JSON and session id from cookie
|
||||
_info "Logging into $SYNO_Hostname:$SYNO_Port"
|
||||
encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)"
|
||||
encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)"
|
||||
# Login, get the session ID and SynoToken from JSON
|
||||
_info "Logging into $SYNO_HOSTNAME:$SYNO_PORT..."
|
||||
encoded_username="$(printf "%s" "$SYNO_USERNAME" | _url_encode)"
|
||||
encoded_password="$(printf "%s" "$SYNO_PASSWORD" | _url_encode)"
|
||||
|
||||
# ## START ## - DEPRECATED, for backward compatibility
|
||||
_getdeployconf SYNO_TOTP_SECRET
|
||||
|
||||
otp_code=""
|
||||
if [ -n "$SYNO_TOTP_SECRET" ]; then
|
||||
if _exists oathtool; then
|
||||
otp_code="$(oathtool --base32 --totp "${SYNO_TOTP_SECRET}" 2>/dev/null)"
|
||||
else
|
||||
_info "WARNING: Usage of SYNO_TOTP_SECRET is deprecated!"
|
||||
_info " See synology_dsm.sh script or ACME.sh Wiki page for details:"
|
||||
_info " https://github.com/acmesh-official/acme.sh/wiki/Synology-NAS-Guide"
|
||||
if ! _exists oathtool; then
|
||||
_err "oathtool could not be found, install oathtool to use SYNO_TOTP_SECRET"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
DEPRECATED_otp_code="$(oathtool --base32 --totp "$SYNO_TOTP_SECRET" 2>/dev/null)"
|
||||
|
||||
if [ -n "$SYNO_DID" ]; then
|
||||
_H1="Cookie: did=$SYNO_DID"
|
||||
if [ -z "$SYNO_DEVICE_ID" ]; then
|
||||
_getdeployconf SYNO_DID
|
||||
[ -n "$SYNO_DID" ] || SYNO_DEVICE_ID="$SYNO_DID"
|
||||
fi
|
||||
if [ -n "$SYNO_DEVICE_ID" ]; then
|
||||
_H1="Cookie: did=$SYNO_DEVICE_ID"
|
||||
export _H1
|
||||
_debug3 H1 "${_H1}"
|
||||
fi
|
||||
|
||||
response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$otp_code" "$_base_url/webapi/auth.cgi?enable_syno_token=yes")
|
||||
token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p')
|
||||
response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$DEPRECATED_otp_code&device_name=certrenewal&device_id=$SYNO_DEVICE_ID" "$_base_url/webapi/$api_path?enable_syno_token=yes")
|
||||
_debug3 response "$response"
|
||||
_debug token "$token"
|
||||
|
||||
if [ -z "$token" ]; then
|
||||
_err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme."
|
||||
_err "Check your username and password."
|
||||
_err "If two-factor authentication is enabled for the user, set SYNO_TOTP_SECRET."
|
||||
# ## END ## - DEPRECATED, for backward compatibility
|
||||
# If SYNO_DEVICE_ID or SYNO_OTP_CODE is set, we treat current account enabled 2FA-OTP.
|
||||
# Notice that if SYNO_USE_TEMP_ADMIN=1, both variables will be unset
|
||||
else
|
||||
if [ -n "$SYNO_DEVICE_ID" ] || [ -n "$SYNO_OTP_CODE" ]; then
|
||||
response='{"error":{"code":403}}'
|
||||
# Assume the current account disabled 2FA-OTP, try to log in right away.
|
||||
else
|
||||
if [ -n "$SYNO_USE_TEMP_ADMIN" ]; then
|
||||
_getdeployconf SYNO_LOCAL_HOSTNAME
|
||||
_debug SYNO_LOCAL_HOSTNAME "${SYNO_LOCAL_HOSTNAME:-}"
|
||||
if [ "$SYNO_LOCAL_HOSTNAME" != "1" ] && [ "$SYNO_LOCAL_HOSTNAME" == "$SYNO_HOSTNAME" ]; then
|
||||
if [ "$SYNO_HOSTNAME" != "localhost" ] && [ "$SYNO_HOSTNAME" != "127.0.0.1" ]; then
|
||||
_err "SYNO_USE_TEMP_ADMIN=1 only support local deployment, though if you are sure that the hostname $SYNO_HOSTNAME is targeting to your **current local machine**, execute 'export SYNO_LOCAL_HOSTNAME=1' then rerun."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
_debug "Creating temp admin user in Synology DSM..."
|
||||
if synogroup --help | grep -q '\-\-memberadd '; then
|
||||
_temp_admin_create "$SYNO_USERNAME" "$SYNO_PASSWORD"
|
||||
synogroup --memberadd administrators "$SYNO_USERNAME" >/dev/null
|
||||
elif synogroup --help | grep -q '\-\-member '; then
|
||||
# For supporting DSM 6.x which only has `--member` parameter.
|
||||
cur_admins=$(synogroup --get administrators | awk -F '[][]' '/Group Members/,0{if(NF>1)printf "%s ", $2}')
|
||||
if [ -n "$cur_admins" ]; then
|
||||
_temp_admin_create "$SYNO_USERNAME" "$SYNO_PASSWORD"
|
||||
_secure_debug3 admin_users "$cur_admins$SYNO_USERNAME"
|
||||
# shellcheck disable=SC2086
|
||||
synogroup --member administrators $cur_admins $SYNO_USERNAME >/dev/null
|
||||
else
|
||||
_err "The tool synogroup may be broken, please set SYNO_USERNAME and SYNO_PASSWORD instead."
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
_err "Unsupported synogroup tool detected, please set SYNO_USERNAME and SYNO_PASSWORD instead."
|
||||
return 1
|
||||
fi
|
||||
# havig a workaround to temporary disable enforce 2FA-OTP, will restore
|
||||
# it soon (after a single request), though if any accident occurs like
|
||||
# unexpected interruption, this setting can be easily reverted manually.
|
||||
otp_enforce_option=$(synogetkeyvalue /etc/synoinfo.conf otp_enforce_option)
|
||||
if [ -n "$otp_enforce_option" ] && [ "${otp_enforce_option:-"none"}" != "none" ]; then
|
||||
synosetkeyvalue /etc/synoinfo.conf otp_enforce_option none
|
||||
_info "Enforcing 2FA-OTP has been disabled to complete temp admin authentication."
|
||||
_info "Notice: it will be restored soon, if not, you can restore it manually via Control Panel."
|
||||
_info "previous_otp_enforce_option" "$otp_enforce_option"
|
||||
else
|
||||
otp_enforce_option=""
|
||||
fi
|
||||
fi
|
||||
response=$(_get "$_base_url/webapi/$api_path?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&enable_syno_token=yes")
|
||||
if [ -n "$SYNO_USE_TEMP_ADMIN" ] && [ -n "$otp_enforce_option" ]; then
|
||||
synosetkeyvalue /etc/synoinfo.conf otp_enforce_option "$otp_enforce_option"
|
||||
_info "Restored previous enforce 2FA-OTP option."
|
||||
fi
|
||||
_debug3 response "$response"
|
||||
fi
|
||||
fi
|
||||
|
||||
error_code=$(echo "$response" | grep '"error":' | grep -o '"code":[0-9]*' | grep -o '[0-9]*')
|
||||
_debug2 error_code "$error_code"
|
||||
# Account has 2FA-OTP enabled, since error 403 reported.
|
||||
# https://global.download.synology.com/download/Document/Software/DeveloperGuide/Os/DSM/All/enu/DSM_Login_Web_API_Guide_enu.pdf
|
||||
if [ "$error_code" == "403" ]; then
|
||||
if [ -z "$SYNO_DEVICE_NAME" ]; then
|
||||
printf "Enter device name or leave empty for default (CertRenewal): "
|
||||
read -r SYNO_DEVICE_NAME
|
||||
[ -n "$SYNO_DEVICE_NAME" ] || SYNO_DEVICE_NAME="CertRenewal"
|
||||
fi
|
||||
|
||||
if [ -n "$SYNO_DEVICE_ID" ]; then
|
||||
# Omit OTP code with SYNO_DEVICE_ID.
|
||||
response=$(_get "$_base_url/webapi/$api_path?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&enable_syno_token=yes&device_name=$SYNO_DEVICE_NAME&device_id=$SYNO_DEVICE_ID")
|
||||
_secure_debug3 response "$response"
|
||||
else
|
||||
# Require the OTP code if still unset.
|
||||
if [ -z "$SYNO_OTP_CODE" ]; then
|
||||
printf "Enter OTP code for user '%s': " "$SYNO_USERNAME"
|
||||
read -r SYNO_OTP_CODE
|
||||
fi
|
||||
_secure_debug SYNO_OTP_CODE "${SYNO_OTP_CODE:-}"
|
||||
|
||||
if [ -z "$SYNO_OTP_CODE" ]; then
|
||||
response='{"error":{"code":404}}'
|
||||
else
|
||||
response=$(_get "$_base_url/webapi/$api_path?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&enable_syno_token=yes&enable_device_token=yes&device_name=$SYNO_DEVICE_NAME&otp_code=$SYNO_OTP_CODE")
|
||||
_secure_debug3 response "$response"
|
||||
|
||||
id_property='device_id'
|
||||
[ "${api_version}" -gt '6' ] || id_property='did'
|
||||
SYNO_DEVICE_ID=$(echo "$response" | grep "$id_property" | sed -n 's/.*"'$id_property'" *: *"\([^"]*\).*/\1/p')
|
||||
_secure_debug2 SYNO_DEVICE_ID "$SYNO_DEVICE_ID"
|
||||
fi
|
||||
fi
|
||||
error_code=$(echo "$response" | grep '"error":' | grep -o '"code":[0-9]*' | grep -o '[0-9]*')
|
||||
_debug2 error_code "$error_code"
|
||||
fi
|
||||
|
||||
if [ -n "$error_code" ]; then
|
||||
if [ "$error_code" == "403" ] && [ -n "$SYNO_DEVICE_ID" ]; then
|
||||
_cleardeployconf SYNO_DEVICE_ID
|
||||
_err "Failed to authenticate with SYNO_DEVICE_ID (may expired or invalid), please try again in a new terminal window."
|
||||
elif [ "$error_code" == "404" ]; then
|
||||
_err "Failed to authenticate with provided 2FA-OTP code, please try again in a new terminal window."
|
||||
elif [ "$error_code" == "406" ]; then
|
||||
if [ -n "$SYNO_USE_TEMP_ADMIN" ]; then
|
||||
_err "Failed with unexcepted error, please report this by providing full log with '--debug 3'."
|
||||
else
|
||||
_err "Enforce auth with 2FA-OTP enabled, please configure the user to enable 2FA-OTP to continue."
|
||||
fi
|
||||
elif [ "$error_code" == "400" ]; then
|
||||
_err "Failed to authenticate, no such account or incorrect password."
|
||||
elif [ "$error_code" == "401" ]; then
|
||||
_err "Failed to authenticate with a non-existent account."
|
||||
elif [ "$error_code" == "408" ] || [ "$error_code" == "409" ] || [ "$error_code" == "410" ]; then
|
||||
_err "Failed to authenticate, the account password has expired or must be changed."
|
||||
else
|
||||
_err "Failed to authenticate with error: $error_code."
|
||||
fi
|
||||
_temp_admin_cleanup "$SYNO_USE_TEMP_ADMIN" "$SYNO_USERNAME"
|
||||
return 1
|
||||
fi
|
||||
|
||||
sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p')
|
||||
token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p')
|
||||
_debug "Session ID" "$sid"
|
||||
_debug SynoToken "$token"
|
||||
if [ -z "$sid" ] || [ -z "$token" ]; then
|
||||
# Still can't get necessary info even got no errors, may Synology have API updated?
|
||||
_err "Unable to authenticate to $_base_url, you may report this by providing full log with '--debug 3'."
|
||||
_temp_admin_cleanup "$SYNO_USE_TEMP_ADMIN" "$SYNO_USERNAME"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_H1="X-SYNO-TOKEN: $token"
|
||||
export _H1
|
||||
_debug2 H1 "${_H1}"
|
||||
|
||||
# Now that we know the username and password are good, save them
|
||||
_savedeployconf SYNO_Username "$SYNO_Username"
|
||||
_savedeployconf SYNO_Password "$SYNO_Password"
|
||||
_savedeployconf SYNO_DID "$SYNO_DID"
|
||||
_savedeployconf SYNO_TOTP_SECRET "$SYNO_TOTP_SECRET"
|
||||
# Now that we know the username and password are good, save them if not in temp admin mode.
|
||||
if [ -n "$SYNO_USE_TEMP_ADMIN" ]; then
|
||||
_cleardeployconf SYNO_USERNAME
|
||||
_cleardeployconf SYNO_PASSWORD
|
||||
_cleardeployconf SYNO_DEVICE_ID
|
||||
_cleardeployconf SYNO_DEVICE_NAME
|
||||
_savedeployconf SYNO_USE_TEMP_ADMIN "$SYNO_USE_TEMP_ADMIN"
|
||||
_savedeployconf SYNO_LOCAL_HOSTNAME "$SYNO_HOSTNAME"
|
||||
else
|
||||
_savedeployconf SYNO_USERNAME "$SYNO_USERNAME"
|
||||
_savedeployconf SYNO_PASSWORD "$SYNO_PASSWORD"
|
||||
_savedeployconf SYNO_DEVICE_ID "$SYNO_DEVICE_ID"
|
||||
_savedeployconf SYNO_DEVICE_NAME "$SYNO_DEVICE_NAME"
|
||||
fi
|
||||
|
||||
_info "Getting certificates in Synology DSM"
|
||||
_info "Getting certificates in Synology DSM..."
|
||||
response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1&_sid=$sid" "$_base_url/webapi/entry.cgi")
|
||||
_debug3 response "$response"
|
||||
escaped_certificate="$(printf "%s" "$SYNO_Certificate" | sed 's/\([].*^$[]\)/\\\1/g;s/"/\\\\"/g')"
|
||||
escaped_certificate="$(printf "%s" "$SYNO_CERTIFICATE" | sed 's/\([].*^$[]\)/\\\1/g;s/"/\\\\"/g')"
|
||||
_debug escaped_certificate "$escaped_certificate"
|
||||
id=$(echo "$response" | sed -n "s/.*\"desc\":\"$escaped_certificate\",\"id\":\"\([^\"]*\).*/\1/p")
|
||||
_debug2 id "$id"
|
||||
|
||||
if [ -z "$id" ] && [ -z "${SYNO_Create:-}" ]; then
|
||||
_err "Unable to find certificate: $SYNO_Certificate and \$SYNO_Create is not set"
|
||||
error_code=$(echo "$response" | grep '"error":' | grep -o '"code":[0-9]*' | grep -o '[0-9]*')
|
||||
_debug2 error_code "$error_code"
|
||||
if [ -n "$error_code" ]; then
|
||||
if [ "$error_code" -eq 105 ]; then
|
||||
_err "Current user is not administrator and does not have sufficient permission for deploying."
|
||||
else
|
||||
_err "Failed to fetch certificate info: $error_code, please try again or contact Synology to learn more."
|
||||
fi
|
||||
_temp_admin_cleanup "$SYNO_USE_TEMP_ADMIN" "$SYNO_USERNAME"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# we've verified this certificate description is a thing, so save it
|
||||
_savedeployconf SYNO_Certificate "$SYNO_Certificate" "base64"
|
||||
_migratedeployconf SYNO_Create SYNO_CREATE
|
||||
_getdeployconf SYNO_CREATE
|
||||
_debug2 SYNO_CREATE "$SYNO_CREATE"
|
||||
|
||||
_info "Generate form POST request"
|
||||
if [ -z "$id" ] && [ -z "$SYNO_CREATE" ]; then
|
||||
_err "Unable to find certificate: $SYNO_CERTIFICATE and $SYNO_CREATE is not set."
|
||||
_temp_admin_cleanup "$SYNO_USE_TEMP_ADMIN" "$SYNO_USERNAME"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# We've verified this certificate description is a thing, so save it
|
||||
_savedeployconf SYNO_CERTIFICATE "$SYNO_CERTIFICATE" "base64"
|
||||
|
||||
_info "Generating form POST request..."
|
||||
nl="\0015\0012"
|
||||
delim="--------------------------$(_utc_date | tr -d -- '-: ')"
|
||||
content="--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")\0012"
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"cert\"; filename=\"$(basename "$_ccert")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ccert")\0012"
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"inter_cert\"; filename=\"$(basename "$_cca")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cca")\0012"
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"id\"${nl}${nl}$id"
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"desc\"${nl}${nl}${SYNO_Certificate}"
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"desc\"${nl}${nl}${SYNO_CERTIFICATE}"
|
||||
if echo "$response" | sed -n "s/.*\"desc\":\"$escaped_certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then
|
||||
_debug2 default "this is the default certificate"
|
||||
_debug2 default "This is the default certificate"
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"as_default\"${nl}${nl}true"
|
||||
else
|
||||
_debug2 default "this is NOT the default certificate"
|
||||
_debug2 default "This is NOT the default certificate"
|
||||
fi
|
||||
content="$content${nl}--$delim--${nl}"
|
||||
content="$(printf "%b_" "$content")"
|
||||
content="${content%_}" # protect trailing \n
|
||||
|
||||
_info "Upload certificate to the Synology DSM"
|
||||
_info "Upload certificate to the Synology DSM."
|
||||
response=$(_post "$content" "$_base_url/webapi/entry.cgi?api=SYNO.Core.Certificate&method=import&version=1&SynoToken=$token&_sid=$sid" "" "POST" "multipart/form-data; boundary=${delim}")
|
||||
_debug3 response "$response"
|
||||
|
||||
if ! echo "$response" | grep '"error":' >/dev/null; then
|
||||
if echo "$response" | grep '"restart_httpd":true' >/dev/null; then
|
||||
_info "http services were restarted"
|
||||
_info "Restart HTTP services succeeded."
|
||||
else
|
||||
_info "http services were NOT restarted"
|
||||
_info "Restart HTTP services failed."
|
||||
fi
|
||||
_temp_admin_cleanup "$SYNO_USE_TEMP_ADMIN" "$SYNO_USERNAME"
|
||||
_logout
|
||||
return 0
|
||||
else
|
||||
_err "Unable to update certificate, error code $response"
|
||||
_temp_admin_cleanup "$SYNO_USE_TEMP_ADMIN" "$SYNO_USERNAME"
|
||||
_err "Unable to update certificate, got error response: $response."
|
||||
_logout
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
_logout() {
|
||||
# Logout CERT user only to not occupy a permanent session, e.g. in DSM's "Connected Users" widget (based on previous variables)
|
||||
response=$(_get "$_base_url/webapi/$api_path?api=SYNO.API.Auth&version=$api_version&method=logout&_sid=$sid")
|
||||
_debug3 response "$response"
|
||||
}
|
||||
|
||||
_temp_admin_create() {
|
||||
_username="$1"
|
||||
_password="$2"
|
||||
synouser --del "$_username" >/dev/null 2>/dev/null
|
||||
synouser --add "$_username" "$_password" "" 0 "scruelt@hotmail.com" 0 >/dev/null
|
||||
}
|
||||
|
||||
_temp_admin_cleanup() {
|
||||
_flag=$1
|
||||
_username=$2
|
||||
|
||||
if [ -n "${_flag}" ]; then
|
||||
_debug "Cleanuping temp admin info..."
|
||||
synouser --del "$_username" >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
#_cleardeployconf key
|
||||
_cleardeployconf() {
|
||||
_cleardomainconf "SAVED_$1"
|
||||
}
|
||||
|
||||
# key
|
||||
_check2cleardeployconfexp() {
|
||||
_key="$1"
|
||||
_clear_key="CLEAR_$_key"
|
||||
# Clear saved settings if explicitly requested
|
||||
if [ -n "$(eval echo \$"$_clear_key")" ]; then
|
||||
_debug2 "$_key: value cleared from config, exported value will be ignored."
|
||||
_cleardeployconf "$_key"
|
||||
eval "$_key"=
|
||||
export "$_key"=
|
||||
eval SAVED_"$_key"=
|
||||
export SAVED_"$_key"=
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -184,6 +184,27 @@ truenas_deploy() {
|
||||
_info "S3 certificate is not configured or is not the same as TrueNAS web UI"
|
||||
fi
|
||||
|
||||
_info "Checking if any chart release Apps is using the same certificate as TrueNAS web UI. Tool 'jq' is required"
|
||||
if _exists jq; then
|
||||
_info "Query all chart release"
|
||||
_release_list=$(_get "$_api_url/chart/release")
|
||||
_related_name_list=$(printf "%s" "$_release_list" | jq -r "[.[] | {name,certId: .config.ingress?.main.tls[]?.scaleCert} | select(.certId==$_active_cert_id) | .name ] | unique")
|
||||
_release_length=$(printf "%s" "$_related_name_list" | jq -r "length")
|
||||
_info "Found $_release_length related chart release in list: $_related_name_list"
|
||||
for i in $(seq 0 $((_release_length - 1))); do
|
||||
_release_name=$(echo "$_related_name_list" | jq -r ".[$i]")
|
||||
_info "Updating certificate from $_active_cert_id to $_cert_id for chart release: $_release_name"
|
||||
#Read the chart release configuration
|
||||
_chart_config=$(printf "%s" "$_release_list" | jq -r ".[] | select(.name==\"$_release_name\")")
|
||||
#Replace the old certificate id with the new one in path .config.ingress.main.tls[].scaleCert. Then update .config.ingress
|
||||
_updated_chart_config=$(printf "%s" "$_chart_config" | jq "(.config.ingress?.main.tls[]? | select(.scaleCert==$_active_cert_id) | .scaleCert ) |= $_cert_id | .config.ingress ")
|
||||
_update_chart_result="$(_post "{\"values\" : { \"ingress\" : $_updated_chart_config } }" "$_api_url/chart/release/id/$_release_name" "" "PUT" "application/json")"
|
||||
_debug3 _update_chart_result "$_update_chart_result"
|
||||
done
|
||||
else
|
||||
_info "Tool 'jq' does not exists, skip chart release checking"
|
||||
fi
|
||||
|
||||
_info "Deleting old certificate"
|
||||
_delete_result="$(_post "" "$_api_url/certificate/id/$_active_cert_id" "" "DELETE" "application/json")"
|
||||
|
||||
|
||||
@@ -5,6 +5,15 @@
|
||||
# - self-hosted Unifi Controller
|
||||
# - Unifi Cloud Key (Gen1/2/2+)
|
||||
# - Unifi Cloud Key running UnifiOS (v2.0.0+, Gen2/2+ only)
|
||||
# - Unifi Dream Machine
|
||||
# This has not been tested on other "all-in-one" devices such as
|
||||
# UDM Pro or Unifi Express.
|
||||
#
|
||||
# OS Version v2.0.0+
|
||||
# Network Application version 7.0.0+
|
||||
# OS version ~3.1 removed java and keytool from the UnifiOS.
|
||||
# Using PKCS12 format keystore appears to work fine.
|
||||
#
|
||||
# Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3359
|
||||
|
||||
#returns 0 means success, otherwise error.
|
||||
@@ -74,14 +83,16 @@ unifi_deploy() {
|
||||
_reload_cmd=""
|
||||
|
||||
# Unifi Controller environment (self hosted or any Cloud Key) --
|
||||
# auto-detect by file /usr/lib/unifi/data/keystore:
|
||||
# auto-detect by file /usr/lib/unifi/data/keystore
|
||||
_unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-/usr/lib/unifi/data/keystore}"
|
||||
if [ -f "$_unifi_keystore" ]; then
|
||||
_info "Installing certificate for Unifi Controller (Java keystore)"
|
||||
_debug _unifi_keystore "$_unifi_keystore"
|
||||
if ! _exists keytool; then
|
||||
_err "keytool not found"
|
||||
return 1
|
||||
_do_keytool=0
|
||||
_info "Installing certificate for Unifi Controller (PKCS12 keystore)."
|
||||
else
|
||||
_do_keytool=1
|
||||
_info "Installing certificate for Unifi Controller (Java keystore)"
|
||||
fi
|
||||
if [ ! -w "$_unifi_keystore" ]; then
|
||||
_err "The file $_unifi_keystore is not writable, please change the permission."
|
||||
@@ -92,6 +103,7 @@ unifi_deploy() {
|
||||
|
||||
_debug "Generate import pkcs12"
|
||||
_import_pkcs12="$(_mktemp)"
|
||||
_debug "_toPkcs $_import_pkcs12 $_ckey $_ccert $_cca $_unifi_keypass unifi root"
|
||||
_toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root
|
||||
# shellcheck disable=SC2181
|
||||
if [ "$?" != "0" ]; then
|
||||
@@ -99,22 +111,57 @@ unifi_deploy() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Save the existing keystore in case something goes wrong.
|
||||
mv -f "${_unifi_keystore}" "${_unifi_keystore}"_original
|
||||
_info "Previous keystore saved to ${_unifi_keystore}_original."
|
||||
|
||||
if [ "$_do_keytool" -eq 1 ]; then
|
||||
_debug "Import into keystore: $_unifi_keystore"
|
||||
if keytool -importkeystore \
|
||||
-deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \
|
||||
-srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \
|
||||
-alias unifi -noprompt; then
|
||||
_debug "Import keystore success!"
|
||||
rm "$_import_pkcs12"
|
||||
else
|
||||
_err "Error importing into Unifi Java keystore."
|
||||
_err "Please re-run with --debug and report a bug."
|
||||
_info "Restoring original keystore."
|
||||
mv -f "${_unifi_keystore}"_original "${_unifi_keystore}"
|
||||
rm "$_import_pkcs12"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
_debug "Copying new keystore to $_unifi_keystore"
|
||||
cp -f "$_import_pkcs12" "$_unifi_keystore"
|
||||
fi
|
||||
|
||||
# Update unifi service for certificate cipher compatibility
|
||||
if ${ACME_OPENSSL_BIN:-openssl} pkcs12 \
|
||||
-in "$_import_pkcs12" \
|
||||
-password pass:aircontrolenterprise \
|
||||
-nokeys | ${ACME_OPENSSL_BIN:-openssl} x509 -text \
|
||||
-noout | grep -i "signature" | grep -iq ecdsa >/dev/null 2>&1; then
|
||||
cp -f /usr/lib/unifi/data/system.properties /usr/lib/unifi/data/system.properties_original
|
||||
_info "Updating system configuration for cipher compatibility."
|
||||
_info "Saved original system config to /usr/lib/unifi/data/system.properties_original"
|
||||
sed -i '/unifi\.https\.ciphers/d' /usr/lib/unifi/data/system.properties
|
||||
echo "unifi.https.ciphers=ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES128-GCM-SHA256" >>/usr/lib/unifi/data/system.properties
|
||||
sed -i '/unifi\.https\.sslEnabledProtocols/d' /usr/lib/unifi/data/system.properties
|
||||
echo "unifi.https.sslEnabledProtocols=TLSv1.3,TLSv1.2" >>/usr/lib/unifi/data/system.properties
|
||||
_info "System configuration updated."
|
||||
fi
|
||||
|
||||
rm "$_import_pkcs12"
|
||||
|
||||
# Restarting unifi-core will bring up unifi, doing it out of order results in
|
||||
# a certificate error, and breaks wifiman.
|
||||
# Restart if we aren't doing unifi-core, otherwise stop for later restart.
|
||||
if systemctl -q is-active unifi; then
|
||||
_reload_cmd="${_reload_cmd:+$_reload_cmd && }service unifi restart"
|
||||
if [ ! -f "${DEPLOY_UNIFI_CORE_CONFIG:-/data/unifi-core/config}/unifi-core.key" ]; then
|
||||
_reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl restart unifi"
|
||||
else
|
||||
_reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl stop unifi"
|
||||
fi
|
||||
fi
|
||||
_services_updated="${_services_updated} unifi"
|
||||
_info "Install Unifi Controller certificate success!"
|
||||
@@ -165,6 +212,11 @@ unifi_deploy() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Save the existing certs in case something goes wrong.
|
||||
cp -f "${_unifi_core_config}"/unifi-core.crt "${_unifi_core_config}"/unifi-core_original.crt
|
||||
cp -f "${_unifi_core_config}"/unifi-core.key "${_unifi_core_config}"/unifi-core_original.key
|
||||
_info "Previous certificate and key saved to ${_unifi_core_config}/unifi-core_original.crt/key."
|
||||
|
||||
cat "$_cfullchain" >"${_unifi_core_config}/unifi-core.crt"
|
||||
cat "$_ckey" >"${_unifi_core_config}/unifi-core.key"
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#
|
||||
# VAULT_PREFIX - this contains the prefix path in vault
|
||||
# VAULT_ADDR - vault requires this to find your vault server
|
||||
# VAULT_SAVE_TOKEN - set to anything if you want to save the token
|
||||
# VAULT_RENEW_TOKEN - set to anything if you want to renew the token to default TTL before deploying
|
||||
# VAULT_KV_V2 - set to anything if you are using v2 of the kv engine
|
||||
#
|
||||
# additionally, you need to ensure that VAULT_TOKEN is avialable
|
||||
# to access the vault server
|
||||
@@ -45,33 +48,83 @@ vault_deploy() {
|
||||
fi
|
||||
_savedeployconf VAULT_ADDR "$VAULT_ADDR"
|
||||
|
||||
_getdeployconf VAULT_SAVE_TOKEN
|
||||
_savedeployconf VAULT_SAVE_TOKEN "$VAULT_SAVE_TOKEN"
|
||||
|
||||
_getdeployconf VAULT_RENEW_TOKEN
|
||||
_savedeployconf VAULT_RENEW_TOKEN "$VAULT_RENEW_TOKEN"
|
||||
|
||||
_getdeployconf VAULT_KV_V2
|
||||
_savedeployconf VAULT_KV_V2 "$VAULT_KV_V2"
|
||||
|
||||
_getdeployconf VAULT_TOKEN
|
||||
if [ -z "$VAULT_TOKEN" ]; then
|
||||
_err "VAULT_TOKEN needs to be defined"
|
||||
return 1
|
||||
fi
|
||||
if [ -n "$VAULT_SAVE_TOKEN" ]; then
|
||||
_savedeployconf VAULT_TOKEN "$VAULT_TOKEN"
|
||||
fi
|
||||
|
||||
_migratedeployconf FABIO VAULT_FABIO_MODE
|
||||
|
||||
# JSON does not allow multiline strings.
|
||||
# So replacing new-lines with "\n" here
|
||||
_ckey=$(sed -z 's/\n/\\n/g' <"$2")
|
||||
_ccert=$(sed -z 's/\n/\\n/g' <"$3")
|
||||
_cca=$(sed -z 's/\n/\\n/g' <"$4")
|
||||
_cfullchain=$(sed -z 's/\n/\\n/g' <"$5")
|
||||
_ckey=$(sed -e ':a' -e N -e '$ ! ba' -e 's/\n/\\n/g' <"$2")
|
||||
_ccert=$(sed -e ':a' -e N -e '$ ! ba' -e 's/\n/\\n/g' <"$3")
|
||||
_cca=$(sed -e ':a' -e N -e '$ ! ba' -e 's/\n/\\n/g' <"$4")
|
||||
_cfullchain=$(sed -e ':a' -e N -e '$ ! ba' -e 's/\n/\\n/g' <"$5")
|
||||
|
||||
URL="$VAULT_ADDR/v1/$VAULT_PREFIX/$_cdomain"
|
||||
export _H1="X-Vault-Token: $VAULT_TOKEN"
|
||||
|
||||
if [ -n "$FABIO" ]; then
|
||||
if [ -n "$VAULT_RENEW_TOKEN" ]; then
|
||||
URL="$VAULT_ADDR/v1/auth/token/renew-self"
|
||||
_info "Renew the Vault token to default TTL"
|
||||
if ! _post "" "$URL" >/dev/null; then
|
||||
_err "Failed to renew the Vault token"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
URL="$VAULT_ADDR/v1/$VAULT_PREFIX/$_cdomain"
|
||||
|
||||
if [ -n "$VAULT_FABIO_MODE" ]; then
|
||||
_info "Writing certificate and key to $URL in Fabio mode"
|
||||
if [ -n "$VAULT_KV_V2" ]; then
|
||||
_post "{ \"data\": {\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"} }" "$URL"
|
||||
_post "{ \"data\": {\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"} }" "$URL" >/dev/null || return 1
|
||||
else
|
||||
_post "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL"
|
||||
_post "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL" >/dev/null || return 1
|
||||
fi
|
||||
else
|
||||
if [ -n "$VAULT_KV_V2" ]; then
|
||||
_post "{\"data\": {\"value\": \"$_ccert\"}}" "$URL/cert.pem"
|
||||
_post "{\"data\": {\"value\": \"$_ckey\"}}" "$URL/cert.key"
|
||||
_post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/chain.pem"
|
||||
_post "{\"data\": {\"value\": \"$_cfullchain\"}}" "$URL/fullchain.pem"
|
||||
_info "Writing certificate to $URL/cert.pem"
|
||||
_post "{\"data\": {\"value\": \"$_ccert\"}}" "$URL/cert.pem" >/dev/null || return 1
|
||||
_info "Writing key to $URL/cert.key"
|
||||
_post "{\"data\": {\"value\": \"$_ckey\"}}" "$URL/cert.key" >/dev/null || return 1
|
||||
_info "Writing CA certificate to $URL/ca.pem"
|
||||
_post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/ca.pem" >/dev/null || return 1
|
||||
_info "Writing full-chain certificate to $URL/fullchain.pem"
|
||||
_post "{\"data\": {\"value\": \"$_cfullchain\"}}" "$URL/fullchain.pem" >/dev/null || return 1
|
||||
else
|
||||
_post "{\"value\": \"$_ccert\"}" "$URL/cert.pem"
|
||||
_post "{\"value\": \"$_ckey\"}" "$URL/cert.key"
|
||||
_post "{\"value\": \"$_cca\"}" "$URL/chain.pem"
|
||||
_post "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem"
|
||||
_info "Writing certificate to $URL/cert.pem"
|
||||
_post "{\"value\": \"$_ccert\"}" "$URL/cert.pem" >/dev/null || return 1
|
||||
_info "Writing key to $URL/cert.key"
|
||||
_post "{\"value\": \"$_ckey\"}" "$URL/cert.key" >/dev/null || return 1
|
||||
_info "Writing CA certificate to $URL/ca.pem"
|
||||
_post "{\"value\": \"$_cca\"}" "$URL/ca.pem" >/dev/null || return 1
|
||||
_info "Writing full-chain certificate to $URL/fullchain.pem"
|
||||
_post "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem" >/dev/null || return 1
|
||||
fi
|
||||
|
||||
# To make it compatible with the wrong ca path `chain.pem` which was used in former versions
|
||||
if _contains "$(_get "$URL/chain.pem")" "-----BEGIN CERTIFICATE-----"; then
|
||||
_err "The CA certificate has moved from chain.pem to ca.pem, if you don't depend on chain.pem anymore, you can delete it to avoid this warning"
|
||||
_info "Updating CA certificate to $URL/chain.pem for backward compatibility"
|
||||
if [ -n "$VAULT_KV_V2" ]; then
|
||||
_post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/chain.pem" >/dev/null || return 1
|
||||
else
|
||||
_post "{\"value\": \"$_cca\"}" "$URL/chain.pem" >/dev/null || return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#
|
||||
# VAULT_PREFIX - this contains the prefix path in vault
|
||||
# VAULT_ADDR - vault requires this to find your vault server
|
||||
# VAULT_SAVE_TOKEN - set to anything if you want to save the token
|
||||
# VAULT_RENEW_TOKEN - set to anything if you want to renew the token to default TTL before deploying
|
||||
#
|
||||
# additionally, you need to ensure that VAULT_TOKEN is avialable or
|
||||
# `vault auth` has applied the appropriate authorization for the vault binary
|
||||
@@ -33,15 +35,36 @@ vault_cli_deploy() {
|
||||
_debug _cfullchain "$_cfullchain"
|
||||
|
||||
# validate required env vars
|
||||
_getdeployconf VAULT_PREFIX
|
||||
if [ -z "$VAULT_PREFIX" ]; then
|
||||
_err "VAULT_PREFIX needs to be defined (contains prefix path in vault)"
|
||||
return 1
|
||||
fi
|
||||
_savedeployconf VAULT_PREFIX "$VAULT_PREFIX"
|
||||
|
||||
_getdeployconf VAULT_ADDR
|
||||
if [ -z "$VAULT_ADDR" ]; then
|
||||
_err "VAULT_ADDR needs to be defined (contains vault connection address)"
|
||||
return 1
|
||||
fi
|
||||
_savedeployconf VAULT_ADDR "$VAULT_ADDR"
|
||||
|
||||
_getdeployconf VAULT_SAVE_TOKEN
|
||||
_savedeployconf VAULT_SAVE_TOKEN "$VAULT_SAVE_TOKEN"
|
||||
|
||||
_getdeployconf VAULT_RENEW_TOKEN
|
||||
_savedeployconf VAULT_RENEW_TOKEN "$VAULT_RENEW_TOKEN"
|
||||
|
||||
_getdeployconf VAULT_TOKEN
|
||||
if [ -z "$VAULT_TOKEN" ]; then
|
||||
_err "VAULT_TOKEN needs to be defined"
|
||||
return 1
|
||||
fi
|
||||
if [ -n "$VAULT_SAVE_TOKEN" ]; then
|
||||
_savedeployconf VAULT_TOKEN "$VAULT_TOKEN"
|
||||
fi
|
||||
|
||||
_migratedeployconf FABIO VAULT_FABIO_MODE
|
||||
|
||||
VAULT_CMD=$(command -v vault)
|
||||
if [ ! $? ]; then
|
||||
@@ -49,13 +72,33 @@ vault_cli_deploy() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -n "$FABIO" ]; then
|
||||
if [ -n "$VAULT_RENEW_TOKEN" ]; then
|
||||
_info "Renew the Vault token to default TTL"
|
||||
if ! $VAULT_CMD token renew; then
|
||||
_err "Failed to renew the Vault token"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$VAULT_FABIO_MODE" ]; then
|
||||
_info "Writing certificate and key to ${VAULT_PREFIX}/${_cdomain} in Fabio mode"
|
||||
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}" cert=@"$_cfullchain" key=@"$_ckey" || return 1
|
||||
else
|
||||
_info "Writing certificate to ${VAULT_PREFIX}/${_cdomain}/cert.pem"
|
||||
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1
|
||||
_info "Writing key to ${VAULT_PREFIX}/${_cdomain}/cert.key"
|
||||
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1
|
||||
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/chain.pem" value=@"$_cca" || return 1
|
||||
_info "Writing CA certificate to ${VAULT_PREFIX}/${_cdomain}/ca.pem"
|
||||
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/ca.pem" value=@"$_cca" || return 1
|
||||
_info "Writing full-chain certificate to ${VAULT_PREFIX}/${_cdomain}/fullchain.pem"
|
||||
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1
|
||||
|
||||
# To make it compatible with the wrong ca path `chain.pem` which was used in former versions
|
||||
if $VAULT_CMD kv get "${VAULT_PREFIX}/${_cdomain}/chain.pem" >/dev/null; then
|
||||
_err "The CA certificate has moved from chain.pem to ca.pem, if you don't depend on chain.pem anymore, you can delete it to avoid this warning"
|
||||
_info "Updating CA certificate to ${VAULT_PREFIX}/${_cdomain}/chain.pem for backward compatibility"
|
||||
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/chain.pem" value=@"$_cca" || return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
@@ -1,46 +1,42 @@
|
||||
#!/usr/bin/env sh
|
||||
#This file name is "dns_1984hosting.sh"
|
||||
#So, here must be a method dns_1984hosting_add()
|
||||
#Which will be called by acme.sh to add the txt record to your api system.
|
||||
#returns 0 means success, otherwise error.
|
||||
# shellcheck disable=SC2034
|
||||
dns_1984hosting_info='1984.hosting
|
||||
Domains: 1984.is
|
||||
Site: 1984.hosting
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_1984hosting
|
||||
Options:
|
||||
One984HOSTING_Username Username
|
||||
One984HOSTING_Password Password
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2851
|
||||
Author: Adrian Fedoreanu
|
||||
'
|
||||
|
||||
#Author: Adrian Fedoreanu
|
||||
#Report Bugs here: https://github.com/acmesh-official/acme.sh
|
||||
# or here... https://github.com/acmesh-official/acme.sh/issues/2851
|
||||
#
|
||||
######## Public functions #####################
|
||||
|
||||
# Export 1984HOSTING username and password in following variables
|
||||
#
|
||||
# One984HOSTING_Username=username
|
||||
# One984HOSTING_Password=password
|
||||
#
|
||||
# sessionid cookie is saved in ~/.acme.sh/account.conf
|
||||
# username/password need to be set only when changed.
|
||||
|
||||
# Usage: dns_1984hosting_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
# Add a text record.
|
||||
dns_1984hosting_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
_info "Add TXT record using 1984Hosting"
|
||||
_info "Add TXT record using 1984Hosting."
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
if ! _1984hosting_login; then
|
||||
_err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file"
|
||||
_err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug "First detect the root zone"
|
||||
_debug "First detect the root zone."
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain" "$fulldomain"
|
||||
_err "Invalid domain '$fulldomain'."
|
||||
return 1
|
||||
fi
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_debug "Add TXT record $fulldomain with value '$txtvalue'"
|
||||
_debug "Add TXT record $fulldomain with value '$txtvalue'."
|
||||
value="$(printf '%s' "$txtvalue" | _url_encode)"
|
||||
url="https://1984.hosting/domains/entry/"
|
||||
|
||||
@@ -53,21 +49,18 @@ dns_1984hosting_add() {
|
||||
_debug2 postdata "$postdata"
|
||||
|
||||
_authpost "$postdata" "$url"
|
||||
response="$(echo "$_response" | _normalizeJson)"
|
||||
_debug2 response "$response"
|
||||
|
||||
if _contains "$response" '"haserrors": true'; then
|
||||
_err "1984Hosting failed to add TXT record for $_sub_domain bad RC from _post"
|
||||
if _contains "$_response" '"haserrors": true'; then
|
||||
_err "1984Hosting failed to add TXT record for $_sub_domain bad RC from _post."
|
||||
return 1
|
||||
elif _contains "$response" "html>"; then
|
||||
_err "1984Hosting failed to add TXT record for $_sub_domain. Check $HTTP_HEADER file"
|
||||
elif _contains "$_response" "html>"; then
|
||||
_err "1984Hosting failed to add TXT record for $_sub_domain. Check $HTTP_HEADER file."
|
||||
return 1
|
||||
elif _contains "$response" '"auth": false'; then
|
||||
_err "1984Hosting failed to add TXT record for $_sub_domain. Invalid or expired cookie"
|
||||
elif _contains "$_response" '"auth": false'; then
|
||||
_err "1984Hosting failed to add TXT record for $_sub_domain. Invalid or expired cookie."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_info "Added acme challenge TXT record for $fulldomain at 1984Hosting"
|
||||
_info "Added acme challenge TXT record for $fulldomain at 1984Hosting."
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -77,68 +70,75 @@ dns_1984hosting_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
_info "Delete TXT record using 1984Hosting"
|
||||
_info "Delete TXT record using 1984Hosting."
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
if ! _1984hosting_login; then
|
||||
_err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file"
|
||||
_err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug "First detect the root zone"
|
||||
_debug "First detect the root zone."
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain" "$fulldomain"
|
||||
_err "Invalid domain '$fulldomain'."
|
||||
return 1
|
||||
fi
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
_debug "Delete $fulldomain TXT record"
|
||||
_debug "Delete $fulldomain TXT record."
|
||||
|
||||
url="https://1984.hosting/domains"
|
||||
if ! _get_zone_id "$url" "$_domain"; then
|
||||
_err "invalid zone" "$_domain"
|
||||
_err "Invalid zone '$_domain'."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_htmlget "$url/$_zone_id" "$txtvalue"
|
||||
_debug2 _response "$_response"
|
||||
entry_id="$(echo "$_response" | _egrep_o 'entry_[0-9]+' | sed 's/entry_//')"
|
||||
_debug2 entry_id "$entry_id"
|
||||
if [ -z "$entry_id" ]; then
|
||||
_err "Error getting TXT entry_id for $1"
|
||||
_err "Error getting TXT entry_id for $1."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_authpost "entry=$entry_id" "$url/delentry/"
|
||||
response="$(echo "$_response" | _normalizeJson)"
|
||||
_debug2 response "$response"
|
||||
|
||||
if ! _contains "$response" '"ok": true'; then
|
||||
_err "1984Hosting failed to delete TXT record for $entry_id bad RC from _post"
|
||||
if ! _contains "$_response" '"ok": true'; then
|
||||
_err "1984Hosting failed to delete TXT record for $entry_id bad RC from _post."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_info "Deleted acme challenge TXT record for $fulldomain at 1984Hosting"
|
||||
_info "Deleted acme challenge TXT record for $fulldomain at 1984Hosting."
|
||||
return 0
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
|
||||
# usage: _1984hosting_login username password
|
||||
# returns 0 success
|
||||
_1984hosting_login() {
|
||||
if ! _check_credentials; then return 1; fi
|
||||
|
||||
if _check_cookies; then
|
||||
_debug "Already logged in"
|
||||
_debug "Already logged in."
|
||||
return 0
|
||||
fi
|
||||
|
||||
_debug "Login to 1984Hosting as user $One984HOSTING_Username"
|
||||
_debug "Login to 1984Hosting as user $One984HOSTING_Username."
|
||||
username=$(printf '%s' "$One984HOSTING_Username" | _url_encode)
|
||||
password=$(printf '%s' "$One984HOSTING_Password" | _url_encode)
|
||||
url="https://1984.hosting/accounts/checkuserauth/"
|
||||
url="https://1984.hosting/api/auth/"
|
||||
|
||||
_get "https://1984.hosting/accounts/login/" | grep "csrfmiddlewaretoken"
|
||||
csrftoken="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'csrftoken=[^;]*;' | tr -d ';')"
|
||||
sessionid="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'sessionid=[^;]*;' | tr -d ';')"
|
||||
|
||||
if [ -z "$csrftoken" ] || [ -z "$sessionid" ]; then
|
||||
_err "One or more cookies are empty: '$csrftoken', '$sessionid'."
|
||||
return 1
|
||||
fi
|
||||
|
||||
export _H1="Cookie: $csrftoken; $sessionid"
|
||||
export _H2="Referer: https://1984.hosting/accounts/login/"
|
||||
csrf_header=$(echo "$csrftoken" | sed 's/csrftoken=//' | _head_n 1)
|
||||
export _H3="X-CSRFToken: $csrf_header"
|
||||
|
||||
response="$(_post "username=$username&password=$password&otpkey=" $url)"
|
||||
response="$(echo "$response" | _normalizeJson)"
|
||||
@@ -149,6 +149,8 @@ _1984hosting_login() {
|
||||
One984HOSTING_CSRFTOKEN_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'csrftoken=[^;]*;' | tr -d ';')"
|
||||
export One984HOSTING_SESSIONID_COOKIE
|
||||
export One984HOSTING_CSRFTOKEN_COOKIE
|
||||
_saveaccountconf_mutable One984HOSTING_Username "$One984HOSTING_Username"
|
||||
_saveaccountconf_mutable One984HOSTING_Password "$One984HOSTING_Password"
|
||||
_saveaccountconf_mutable One984HOSTING_SESSIONID_COOKIE "$One984HOSTING_SESSIONID_COOKIE"
|
||||
_saveaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE "$One984HOSTING_CSRFTOKEN_COOKIE"
|
||||
return 0
|
||||
@@ -157,9 +159,13 @@ _1984hosting_login() {
|
||||
}
|
||||
|
||||
_check_credentials() {
|
||||
One984HOSTING_Username="${One984HOSTING_Username:-$(_readaccountconf_mutable One984HOSTING_Username)}"
|
||||
One984HOSTING_Password="${One984HOSTING_Password:-$(_readaccountconf_mutable One984HOSTING_Password)}"
|
||||
if [ -z "$One984HOSTING_Username" ] || [ -z "$One984HOSTING_Password" ]; then
|
||||
One984HOSTING_Username=""
|
||||
One984HOSTING_Password=""
|
||||
_clearaccountconf_mutable One984HOSTING_Username
|
||||
_clearaccountconf_mutable One984HOSTING_Password
|
||||
_err "You haven't specified 1984Hosting username or password yet."
|
||||
_err "Please export as One984HOSTING_Username / One984HOSTING_Password and try again."
|
||||
return 1
|
||||
@@ -171,25 +177,26 @@ _check_cookies() {
|
||||
One984HOSTING_SESSIONID_COOKIE="${One984HOSTING_SESSIONID_COOKIE:-$(_readaccountconf_mutable One984HOSTING_SESSIONID_COOKIE)}"
|
||||
One984HOSTING_CSRFTOKEN_COOKIE="${One984HOSTING_CSRFTOKEN_COOKIE:-$(_readaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE)}"
|
||||
if [ -z "$One984HOSTING_SESSIONID_COOKIE" ] || [ -z "$One984HOSTING_CSRFTOKEN_COOKIE" ]; then
|
||||
_debug "No cached cookie(s) found"
|
||||
_debug "No cached cookie(s) found."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_authget "https://1984.hosting/accounts/loginstatus/"
|
||||
if _contains "$response" '"ok": true'; then
|
||||
_debug "Cached cookies still valid"
|
||||
_authget "https://1984.hosting/api/auth/"
|
||||
if _contains "$_response" '"ok": true'; then
|
||||
_debug "Cached cookies still valid."
|
||||
return 0
|
||||
fi
|
||||
_debug "Cached cookies no longer valid"
|
||||
|
||||
_debug "Cached cookies no longer valid. Clearing cookies."
|
||||
One984HOSTING_SESSIONID_COOKIE=""
|
||||
One984HOSTING_CSRFTOKEN_COOKIE=""
|
||||
_saveaccountconf_mutable One984HOSTING_SESSIONID_COOKIE "$One984HOSTING_SESSIONID_COOKIE"
|
||||
_saveaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE "$One984HOSTING_CSRFTOKEN_COOKIE"
|
||||
_clearaccountconf_mutable One984HOSTING_SESSIONID_COOKIE
|
||||
_clearaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE
|
||||
return 1
|
||||
}
|
||||
|
||||
# _acme-challenge.www.domain.com
|
||||
#returns
|
||||
# Returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
# _domain=domain.com
|
||||
_get_root() {
|
||||
@@ -197,16 +204,16 @@ _get_root() {
|
||||
i=1
|
||||
p=1
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
|
||||
|
||||
if [ -z "$h" ]; then
|
||||
# not valid
|
||||
if [ -z "$h" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
_authget "https://1984.hosting/domains/soacheck/?zone=$h&nameserver=ns0.1984.is."
|
||||
if _contains "$_response" "serial" && ! _contains "$_response" "null"; then
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_authget "https://1984.hosting/domains/zonestatus/$h/?cached=no"
|
||||
if _contains "$_response" '"ok": true'; then
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
|
||||
_domain="$h"
|
||||
return 0
|
||||
fi
|
||||
@@ -216,40 +223,39 @@ _get_root() {
|
||||
return 1
|
||||
}
|
||||
|
||||
#usage: _get_zone_id url domain.com
|
||||
#returns zone id for domain.com
|
||||
# Usage: _get_zone_id url domain.com
|
||||
# Returns zone id for domain.com
|
||||
_get_zone_id() {
|
||||
url=$1
|
||||
domain=$2
|
||||
_htmlget "$url" "$domain"
|
||||
_debug2 _response "$_response"
|
||||
_zone_id="$(echo "$_response" | _egrep_o 'zone\/[0-9]+' | _head_n 1)"
|
||||
_debug2 _zone_id "$_zone_id"
|
||||
if [ -z "$_zone_id" ]; then
|
||||
_err "Error getting _zone_id for $2"
|
||||
_err "Error getting _zone_id for $2."
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# add extra headers to request
|
||||
# Add extra headers to request
|
||||
_authget() {
|
||||
export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE"
|
||||
_response=$(_get "$1" | _normalizeJson)
|
||||
_debug2 _response "$_response"
|
||||
}
|
||||
|
||||
# truncate huge HTML response
|
||||
# echo: Argument list too long
|
||||
# Truncate huge HTML response
|
||||
_htmlget() {
|
||||
export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE"
|
||||
_response=$(_get "$1" | grep "$2")
|
||||
if _contains "$_response" "@$2"; then
|
||||
_response=$(echo "$_response" | grep -v "[@]" | _head_n 1)
|
||||
fi
|
||||
_debug2 _response "$_response"
|
||||
}
|
||||
|
||||
# add extra headers to request
|
||||
# Add extra headers to request
|
||||
_authpost() {
|
||||
url="https://1984.hosting/domains"
|
||||
_get_zone_id "$url" "$_domain"
|
||||
@@ -257,5 +263,6 @@ _authpost() {
|
||||
export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE"
|
||||
export _H2="Referer: https://1984.hosting/domains/$_zone_id"
|
||||
export _H3="X-CSRFToken: $csrf_header"
|
||||
_response=$(_post "$1" "$2")
|
||||
_response="$(_post "$1" "$2" | _normalizeJson)"
|
||||
_debug2 _response "$_response"
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#!/usr/bin/env sh
|
||||
#
|
||||
#Author: Wolfgang Ebner
|
||||
#Author: Sven Neubuaer
|
||||
#Report Bugs here: https://github.com/dampfklon/acme.sh
|
||||
#
|
||||
# Usage:
|
||||
# export ACMEDNS_BASE_URL="https://auth.acme-dns.io"
|
||||
#
|
||||
# You can optionally define an already existing account:
|
||||
#
|
||||
# export ACMEDNS_USERNAME="<username>"
|
||||
# export ACMEDNS_PASSWORD="<password>"
|
||||
# export ACMEDNS_SUBDOMAIN="<subdomain>"
|
||||
#
|
||||
# shellcheck disable=SC2034
|
||||
dns_acmedns_info='acme-dns Server API
|
||||
The acme-dns is a limited DNS server with RESTful API to handle ACME DNS challenges.
|
||||
Site: github.com/joohoi/acme-dns
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_acmedns
|
||||
Options:
|
||||
ACMEDNS_USERNAME Username. Optional.
|
||||
ACMEDNS_PASSWORD Password. Optional.
|
||||
ACMEDNS_SUBDOMAIN Subdomain. Optional.
|
||||
ACMEDNS_BASE_URL API endpoint. Default: "https://auth.acme-dns.io".
|
||||
Issues: github.com/dampfklon/acme.sh
|
||||
Author: Wolfgang Ebner, Sven Neubuaer
|
||||
'
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: dns_acmedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
|
||||
18
dnsapi/dns_acmeproxy.sh
Normal file → Executable file
18
dnsapi/dns_acmeproxy.sh
Normal file → Executable file
@@ -1,9 +1,17 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
## Acmeproxy DNS provider to be used with acmeproxy (http://github.com/mdbraber/acmeproxy)
|
||||
## API integration by Maarten den Braber
|
||||
##
|
||||
## Report any bugs via https://github.com/mdbraber/acme.sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_acmeproxy_info='AcmeProxy Server API
|
||||
AcmeProxy can be used to as a single host in your network to request certificates through a DNS API.
|
||||
Clients can connect with the one AcmeProxy host so you do not need to store DNS API credentials on every single host.
|
||||
Site: github.com/mdbraber/acmeproxy
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_acmeproxy
|
||||
Options:
|
||||
ACMEPROXY_ENDPOINT API Endpoint
|
||||
ACMEPROXY_USERNAME Username
|
||||
ACMEPROXY_PASSWORD Password
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2251
|
||||
Author: Maarten den Braber
|
||||
'
|
||||
|
||||
dns_acmeproxy_add() {
|
||||
fulldomain="${1}"
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#ACTIVE24_Token="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
# shellcheck disable=SC2034
|
||||
dns_active24_info='Active24.com
|
||||
Site: Active24.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_active24
|
||||
Options:
|
||||
ACTIVE24_Token API Token
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2059
|
||||
Author: Milan Pála
|
||||
'
|
||||
|
||||
ACTIVE24_Api="https://api.active24.com"
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
#AD_API_KEY="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
|
||||
#This is the Alwaysdata api wrapper for acme.sh
|
||||
#
|
||||
#Author: Paul Koppen
|
||||
#Report Bugs here: https://github.com/wpk-/acme.sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_ad_info='AlwaysData.com
|
||||
Site: AlwaysData.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_ad
|
||||
Options:
|
||||
AD_API_KEY API Key
|
||||
Issues: github.com/acmesh-official/acme.sh/pull/503
|
||||
Author: Paul Koppen
|
||||
'
|
||||
|
||||
AD_API_URL="https://$AD_API_KEY:@api.alwaysdata.com/v1"
|
||||
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_ali_info='AlibabaCloud.com
|
||||
Domains: Aliyun.com
|
||||
Site: AlibabaCloud.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_ali
|
||||
Options:
|
||||
Ali_Key API Key
|
||||
Ali_Secret API Secret
|
||||
'
|
||||
|
||||
Ali_API="https://alidns.aliyuncs.com/"
|
||||
|
||||
#Ali_Key="LTqIA87hOKdjevsf5"
|
||||
#Ali_Secret="0p5EYueFNq501xnCPzKNbx6K51qPH2"
|
||||
|
||||
#Usage: dns_ali_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_ali_add() {
|
||||
fulldomain=$1
|
||||
@@ -117,7 +123,7 @@ _ali_urlencode() {
|
||||
_ali_nonce() {
|
||||
#_head_n 1 </dev/urandom | _digest "sha256" hex | cut -c 1-31
|
||||
#Not so good...
|
||||
date +"%s%N"
|
||||
date +"%s%N" | sed 's/%N//g'
|
||||
}
|
||||
|
||||
_check_exist_query() {
|
||||
|
||||
184
dnsapi/dns_alviy.sh
Normal file
184
dnsapi/dns_alviy.sh
Normal file
@@ -0,0 +1,184 @@
|
||||
#!/usr/bin/env sh
|
||||
# Alviy domain api
|
||||
#
|
||||
# Get API key and secret from https://cloud.alviy.com/token
|
||||
#
|
||||
# Alviy_token="some-secret-key"
|
||||
#
|
||||
# Ex.: acme.sh --issue --staging --dns dns_alviy -d "*.s.example.com" -d "s.example.com"
|
||||
|
||||
Alviy_Api="https://cloud.alviy.com/api/v1"
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: dns_alviy_add _acme-challenge.www.domain.com "content"
|
||||
dns_alviy_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
Alviy_token="${Alviy_token:-$(_readaccountconf_mutable Alviy_token)}"
|
||||
if [ -z "$Alviy_token" ]; then
|
||||
Alviy_token=""
|
||||
_err "Please specify Alviy token."
|
||||
return 1
|
||||
fi
|
||||
|
||||
#save the api key and email to the account conf file.
|
||||
_saveaccountconf_mutable Alviy_token "$Alviy_token"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_debug "Getting existing records"
|
||||
if _alviy_txt_exists "$_domain" "$fulldomain" "$txtvalue"; then
|
||||
_info "This record already exists, skipping"
|
||||
return 0
|
||||
fi
|
||||
|
||||
_add_data="{\"content\":\"$txtvalue\",\"type\":\"TXT\"}"
|
||||
_debug2 _add_data "$_add_data"
|
||||
_info "Adding record"
|
||||
if _alviy_rest POST "zone/$_domain/domain/$fulldomain/" "$_add_data"; then
|
||||
_debug "Checking updated records of '${fulldomain}'"
|
||||
|
||||
if ! _alviy_txt_exists "$_domain" "$fulldomain" "$txtvalue"; then
|
||||
_err "TXT record '${txtvalue}' for '${fulldomain}', value wasn't set!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
else
|
||||
_err "Add txt record error, value '${txtvalue}' for '${fulldomain}' was not set."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_sleep 10
|
||||
_info "Added TXT record '${txtvalue}' for '${fulldomain}'."
|
||||
return 0
|
||||
}
|
||||
|
||||
#fulldomain
|
||||
dns_alviy_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
Alviy_token="${Alviy_token:-$(_readaccountconf_mutable Alviy_token)}"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
if ! _alviy_txt_exists "$_domain" "$fulldomain" "$txtvalue"; then
|
||||
_info "The record does not exist, skip"
|
||||
return 0
|
||||
fi
|
||||
|
||||
_add_data=""
|
||||
uuid=$(echo "$response" | tr "{" "\n" | grep "$txtvalue" | tr "," "\n" | grep uuid | cut -d \" -f4)
|
||||
# delete record
|
||||
_debug "Delete TXT record for '${fulldomain}'"
|
||||
if ! _alviy_rest DELETE "zone/$_domain/record/$uuid" "{\"confirm\":1}"; then
|
||||
_err "Cannot delete empty TXT record for '$fulldomain'"
|
||||
return 1
|
||||
fi
|
||||
_info "The record '$fulldomain'='$txtvalue' deleted"
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
#_acme-challenge.www.domain.com
|
||||
#returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
# _domain=domain.com
|
||||
_get_root() {
|
||||
domain=$1
|
||||
i=3
|
||||
a="init"
|
||||
while [ -n "$a" ]; do
|
||||
a=$(printf "%s" "$domain" | cut -d . -f $i-)
|
||||
i=$((i + 1))
|
||||
done
|
||||
n=$((i - 3))
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $n-)
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
_alviy_rest GET "zone/$domain/"
|
||||
_debug "can't get host from $domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _alviy_rest GET "zone/$h/"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if _contains "$response" '"code":"NOT_FOUND"'; then
|
||||
_debug "$h not found"
|
||||
else
|
||||
s=$((n - 1))
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f -$s)
|
||||
_domain="$h"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
_alviy_txt_exists() {
|
||||
zone=$1
|
||||
domain=$2
|
||||
content_data=$3
|
||||
_debug "Getting existing records"
|
||||
|
||||
if ! _alviy_rest GET "zone/$zone/domain/$domain/TXT/"; then
|
||||
_info "The record does not exist"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _contains "$response" "$3"; then
|
||||
_info "The record has other value"
|
||||
return 1
|
||||
fi
|
||||
# GOOD code return - TRUE function
|
||||
return 0
|
||||
}
|
||||
|
||||
_alviy_rest() {
|
||||
method=$1
|
||||
path="$2"
|
||||
content_data="$3"
|
||||
_debug "$path"
|
||||
|
||||
export _H1="Authorization: Bearer $Alviy_token"
|
||||
export _H2="Content-Type: application/json"
|
||||
|
||||
if [ "$content_data" ] || [ "$method" = "DELETE" ]; then
|
||||
_debug "data ($method): " "$content_data"
|
||||
response="$(_post "$content_data" "$Alviy_Api/$path" "" "$method")"
|
||||
else
|
||||
response="$(_get "$Alviy_Api/$path")"
|
||||
fi
|
||||
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")"
|
||||
if [ "$_code" = "401" ]; then
|
||||
_err "It seems that your api key or secret is not correct."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$_code" != "200" ]; then
|
||||
_err "API call error ($method): $path Response code $_code"
|
||||
fi
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "error on rest call ($method): $path. Response:"
|
||||
_err "$response"
|
||||
return 1
|
||||
fi
|
||||
_debug2 response "$response"
|
||||
return 0
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Anexia CloudDNS acme.sh hook
|
||||
# Author: MA
|
||||
|
||||
#ANX_Token="xxxx"
|
||||
# shellcheck disable=SC2034
|
||||
dns_anx_info='Anexia.com CloudDNS
|
||||
Site: Anexia.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_anx
|
||||
Options:
|
||||
ANX_Token API Token
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/3238
|
||||
'
|
||||
|
||||
ANX_API='https://engine.anexia-it.com/api/clouddns/v1'
|
||||
|
||||
@@ -127,8 +130,6 @@ _get_root() {
|
||||
i=1
|
||||
p=1
|
||||
|
||||
_anx_rest GET "zone.json"
|
||||
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
_debug h "$h"
|
||||
@@ -137,6 +138,7 @@ _get_root() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
_anx_rest GET "zone.json/${h}"
|
||||
if _contains "$response" "\"name\":\"$h\""; then
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_domain=$h
|
||||
|
||||
177
dnsapi/dns_artfiles.sh
Normal file
177
dnsapi/dns_artfiles.sh
Normal file
@@ -0,0 +1,177 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_artfiles_info='ArtFiles.de
|
||||
Site: ArtFiles.de
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_artfiles
|
||||
Options:
|
||||
AF_API_USERNAME API Username
|
||||
AF_API_PASSWORD API Password
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/4718
|
||||
Author: Martin Arndt <https://troublezone.net/>
|
||||
'
|
||||
|
||||
########## API configuration ###################################################
|
||||
|
||||
AF_API_SUCCESS='status":"OK'
|
||||
AF_URL_DCP='https://dcp.c.artfiles.de/api/'
|
||||
AF_URL_DNS=${AF_URL_DCP}'dns/{*}_dns.html?domain='
|
||||
AF_URL_DOMAINS=${AF_URL_DCP}'domain/get_domains.html'
|
||||
|
||||
########## Public functions ####################################################
|
||||
|
||||
# Adds a new TXT record for given ACME challenge value & domain.
|
||||
# Usage: dns_artfiles_add _acme-challenge.www.example.com "ACME challenge value"
|
||||
dns_artfiles_add() {
|
||||
domain="$1"
|
||||
txtValue="$2"
|
||||
_info 'Using ArtFiles.de DNS addition API…'
|
||||
_debug 'Domain' "$domain"
|
||||
_debug 'txtValue' "$txtValue"
|
||||
|
||||
_set_credentials
|
||||
_saveaccountconf_mutable 'AF_API_USERNAME' "$AF_API_USERNAME"
|
||||
_saveaccountconf_mutable 'AF_API_PASSWORD' "$AF_API_PASSWORD"
|
||||
|
||||
_set_headers
|
||||
_get_zone "$domain"
|
||||
_dns 'GET'
|
||||
if ! _contains "$response" 'TXT'; then
|
||||
_err 'Retrieving TXT records failed.'
|
||||
|
||||
return 1
|
||||
fi
|
||||
|
||||
_clean_records
|
||||
_dns 'SET' "$(printf -- '%s\n_acme-challenge "%s"' "$response" "$txtValue")"
|
||||
if ! _contains "$response" "$AF_API_SUCCESS"; then
|
||||
_err 'Adding ACME challenge value failed.'
|
||||
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Removes the existing TXT record for given ACME challenge value & domain.
|
||||
# Usage: dns_artfiles_rm _acme-challenge.www.example.com "ACME challenge value"
|
||||
dns_artfiles_rm() {
|
||||
domain="$1"
|
||||
txtValue="$2"
|
||||
_info 'Using ArtFiles.de DNS removal API…'
|
||||
_debug 'Domain' "$domain"
|
||||
_debug 'txtValue' "$txtValue"
|
||||
|
||||
_set_credentials
|
||||
_set_headers
|
||||
_get_zone "$domain"
|
||||
if ! _dns 'GET'; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _contains "$response" "$txtValue"; then
|
||||
_err 'Retrieved TXT records are missing given ACME challenge value.'
|
||||
|
||||
return 1
|
||||
fi
|
||||
|
||||
_clean_records
|
||||
response="$(printf -- '%s' "$response" | sed '/_acme-challenge "'"$txtValue"'"/d')"
|
||||
_dns 'SET' "$response"
|
||||
if ! _contains "$response" "$AF_API_SUCCESS"; then
|
||||
_err 'Removing ACME challenge value failed.'
|
||||
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
########## Private functions ###################################################
|
||||
|
||||
# Cleans awful TXT records response of ArtFiles's API & pretty prints it.
|
||||
# Usage: _clean_records
|
||||
_clean_records() {
|
||||
_info 'Cleaning TXT records…'
|
||||
# Extract TXT part, strip trailing quote sign (ACME.sh API guidelines forbid
|
||||
# usage of SED's GNU extensions, hence couldn't omit it via regex), strip '\'
|
||||
# from '\"' & turn '\n' into real LF characters.
|
||||
# Yup, awful API to use - but that's all we got to get this working, so… ;)
|
||||
_debug2 'Raw ' "$response"
|
||||
response="$(printf -- '%s' "$response" | sed 's/^.*TXT":"\([^}]*\).*$/\1/;s/,".*$//;s/.$//;s/\\"/"/g;s/\\n/\n/g')"
|
||||
_debug2 'Clean' "$response"
|
||||
}
|
||||
|
||||
# Executes an HTTP GET or POST request for getting or setting DNS records,
|
||||
# containing given payload upon POST.
|
||||
# Usage: _dns [GET | SET] [payload]
|
||||
_dns() {
|
||||
_info 'Executing HTTP request…'
|
||||
action="$1"
|
||||
payload="$(printf -- '%s' "$2" | _url_encode)"
|
||||
url="$(printf -- '%s%s' "$AF_URL_DNS" "$domain" | sed 's/{\*}/'"$(printf -- '%s' "$action" | _lower_case)"'/')"
|
||||
|
||||
if [ "$action" = 'SET' ]; then
|
||||
_debug2 'Payload' "$payload"
|
||||
response="$(_post '' "$url&TXT=$payload" '' 'POST' 'application/x-www-form-urlencoded')"
|
||||
else
|
||||
response="$(_get "$url" '' 10)"
|
||||
fi
|
||||
|
||||
if ! _contains "$response" "$AF_API_SUCCESS"; then
|
||||
_err "DNS API error: $response"
|
||||
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug 'Response' "$response"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Gets the root domain zone for given domain.
|
||||
# Usage: _get_zone _acme-challenge.www.example.com
|
||||
_get_zone() {
|
||||
fqdn="$1"
|
||||
domains="$(_get "$AF_URL_DOMAINS" '' 10)"
|
||||
_info 'Getting domain zone…'
|
||||
_debug2 'FQDN' "$fqdn"
|
||||
_debug2 'Domains' "$domains"
|
||||
|
||||
while _contains "$fqdn" "."; do
|
||||
if _contains "$domains" "$fqdn"; then
|
||||
domain="$fqdn"
|
||||
_info "Found root domain zone: $domain"
|
||||
break
|
||||
else
|
||||
fqdn="${fqdn#*.}"
|
||||
_debug2 'FQDN' "$fqdn"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$domain" = "$fqdn" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
_err 'Couldn'\''t find root domain zone.'
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Sets the credentials for accessing ArtFiles's API
|
||||
# Usage: _set_credentials
|
||||
_set_credentials() {
|
||||
_info 'Setting credentials…'
|
||||
AF_API_USERNAME="${AF_API_USERNAME:-$(_readaccountconf_mutable AF_API_USERNAME)}"
|
||||
AF_API_PASSWORD="${AF_API_PASSWORD:-$(_readaccountconf_mutable AF_API_PASSWORD)}"
|
||||
if [ -z "$AF_API_USERNAME" ] || [ -z "$AF_API_PASSWORD" ]; then
|
||||
_err 'Missing ArtFiles.de username and/or password.'
|
||||
_err 'Please ensure both are set via export command & try again.'
|
||||
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Adds the HTTP Authorization & Content-Type headers to a follow-up request.
|
||||
# Usage: _set_headers
|
||||
_set_headers() {
|
||||
_info 'Setting headers…'
|
||||
encoded="$(printf -- '%s:%s' "$AF_API_USERNAME" "$AF_API_PASSWORD" | _base64)"
|
||||
export _H1="Authorization: Basic $encoded"
|
||||
export _H2='Content-Type: application/json'
|
||||
}
|
||||
@@ -1,11 +1,16 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_arvan_info='ArvanCloud.ir
|
||||
Site: ArvanCloud.ir
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_arvan
|
||||
Options:
|
||||
Arvan_Token API Token
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2796
|
||||
Author: Vahid Fardi
|
||||
'
|
||||
|
||||
#Arvan_Token="Apikey xxxx"
|
||||
ARVAN_API_URL="https://napi.arvancloud.ir/cdn/4.0/domains"
|
||||
|
||||
ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains"
|
||||
#Author: Vahid Fardi
|
||||
#Report Bugs here: https://github.com/Neilpang/acme.sh
|
||||
#
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: dns_arvan_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
@@ -18,7 +23,7 @@ dns_arvan_add() {
|
||||
|
||||
if [ -z "$Arvan_Token" ]; then
|
||||
_err "You didn't specify \"Arvan_Token\" token yet."
|
||||
_err "You can get yours from here https://npanel.arvancloud.com/profile/api-keys"
|
||||
_err "You can get yours from here https://npanel.arvancloud.ir/profile/api-keys"
|
||||
return 1
|
||||
fi
|
||||
#save the api token to the account conf file.
|
||||
@@ -40,7 +45,7 @@ dns_arvan_add() {
|
||||
_info "response id is $response"
|
||||
_info "Added, OK"
|
||||
return 0
|
||||
elif _contains "$response" "Record Data is Duplicated"; then
|
||||
elif _contains "$response" "Record Data is duplicate"; then
|
||||
_info "Already exists, OK"
|
||||
return 0
|
||||
else
|
||||
@@ -141,6 +146,7 @@ _arvan_rest() {
|
||||
response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")"
|
||||
elif [ "$mtd" = "POST" ]; then
|
||||
export _H2="Content-Type: application/json"
|
||||
export _H3="Accept: application/json"
|
||||
_debug data "$data"
|
||||
response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")"
|
||||
else
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
#AURORA_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
#
|
||||
#AURORA_Secret="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
# shellcheck disable=SC2034
|
||||
dns_aurora_info='versio.nl AuroraDNS
|
||||
Domains: pcextreme.nl
|
||||
Site: versio.nl
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_aurora
|
||||
Options:
|
||||
AURORA_Key API Key
|
||||
AURORA_Secret API Secret
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/3459
|
||||
Author: Jasper Zonneveld
|
||||
'
|
||||
|
||||
AURORA_Api="https://api.auroradns.eu"
|
||||
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
#!/usr/bin/env sh
|
||||
# -*- mode: sh; tab-width: 2; indent-tabs-mode: s; coding: utf-8 -*-
|
||||
|
||||
# This is the InternetX autoDNS xml api wrapper for acme.sh
|
||||
# Author: auerswald@gmail.com
|
||||
# Created: 2018-01-14
|
||||
#
|
||||
# export AUTODNS_USER="username"
|
||||
# export AUTODNS_PASSWORD="password"
|
||||
# export AUTODNS_CONTEXT="context"
|
||||
#
|
||||
# Usage:
|
||||
# acme.sh --issue --dns dns_autodns -d example.com
|
||||
# shellcheck disable=SC2034
|
||||
dns_autodns_info='InternetX autoDNS
|
||||
InternetX autoDNS XML API
|
||||
Site: InternetX.com/autodns/
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_autodns
|
||||
Options:
|
||||
AUTODNS_USER Username
|
||||
AUTODNS_PASSWORD Password
|
||||
AUTODNS_CONTEXT Context
|
||||
Author: <auerswald@gmail.com>
|
||||
'
|
||||
|
||||
AUTODNS_API="https://gateway.autodns.com"
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_aws_info='Amazon AWS Route53 domain API
|
||||
Site: docs.aws.amazon.com/route53/
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_aws
|
||||
Options:
|
||||
AWS_ACCESS_KEY_ID API Key ID
|
||||
AWS_SECRET_ACCESS_KEY API Secret
|
||||
'
|
||||
|
||||
#
|
||||
#AWS_ACCESS_KEY_ID="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
#
|
||||
#AWS_SECRET_ACCESS_KEY="xxxxxxx"
|
||||
|
||||
#This is the Amazon Route53 api wrapper for acme.sh
|
||||
# All `_sleep` commands are included to avoid Route53 throttling, see
|
||||
# https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/DNSLimitations.html#limits-api-requests
|
||||
|
||||
@@ -145,41 +147,29 @@ dns_aws_rm() {
|
||||
fi
|
||||
_sleep 1
|
||||
return 1
|
||||
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
|
||||
_get_root() {
|
||||
domain=$1
|
||||
i=2
|
||||
i=1
|
||||
p=1
|
||||
|
||||
if aws_rest GET "2013-04-01/hostedzone"; then
|
||||
# iterate over names (a.b.c.d -> b.c.d -> c.d -> d)
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
_debug2 "Checking domain: $h"
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100 | sed 's/\./\\./g')
|
||||
_debug "Checking domain: $h"
|
||||
if [ -z "$h" ]; then
|
||||
if _contains "$response" "<IsTruncated>true</IsTruncated>" && _contains "$response" "<NextMarker>"; then
|
||||
_debug "IsTruncated"
|
||||
_nextMarker="$(echo "$response" | _egrep_o "<NextMarker>.*</NextMarker>" | cut -d '>' -f 2 | cut -d '<' -f 1)"
|
||||
_debug "NextMarker" "$_nextMarker"
|
||||
if aws_rest GET "2013-04-01/hostedzone" "marker=$_nextMarker"; then
|
||||
_debug "Truncated request OK"
|
||||
i=2
|
||||
p=1
|
||||
continue
|
||||
else
|
||||
_err "Truncated request error."
|
||||
fi
|
||||
fi
|
||||
#not valid
|
||||
_err "Invalid domain"
|
||||
_error "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# iterate over paginated result for list_hosted_zones
|
||||
aws_rest GET "2013-04-01/hostedzone"
|
||||
while true; do
|
||||
if _contains "$response" "<Name>$h.</Name>"; then
|
||||
hostedzone="$(echo "$response" | sed 's/<HostedZone>/#&/g' | tr '#' '\n' | _egrep_o "<HostedZone><Id>[^<]*<.Id><Name>$h.<.Name>.*<PrivateZone>false<.PrivateZone>.*<.HostedZone>")"
|
||||
hostedzone="$(echo "$response" | tr -d '\n' | sed 's/<HostedZone>/#&/g' | tr '#' '\n' | _egrep_o "<HostedZone><Id>[^<]*<.Id><Name>$h.<.Name>.*<PrivateZone>false<.PrivateZone>.*<.HostedZone>")"
|
||||
_debug hostedzone "$hostedzone"
|
||||
if [ "$hostedzone" ]; then
|
||||
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "<Id>.*<.Id>" | head -n 1 | _egrep_o ">.*<" | tr -d "<>")
|
||||
@@ -192,10 +182,19 @@ _get_root() {
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
if _contains "$response" "<IsTruncated>true</IsTruncated>" && _contains "$response" "<NextMarker>"; then
|
||||
_debug "IsTruncated"
|
||||
_nextMarker="$(echo "$response" | _egrep_o "<NextMarker>.*</NextMarker>" | cut -d '>' -f 2 | cut -d '<' -f 1)"
|
||||
_debug "NextMarker" "$_nextMarker"
|
||||
else
|
||||
break
|
||||
fi
|
||||
_debug "Checking domain: $h - Next Page "
|
||||
aws_rest GET "2013-04-01/hostedzone" "marker=$_nextMarker"
|
||||
done
|
||||
p=$i
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -209,24 +208,40 @@ _use_container_role() {
|
||||
}
|
||||
|
||||
_use_instance_role() {
|
||||
_url="http://169.254.169.254/latest/meta-data/iam/security-credentials/"
|
||||
_debug "_url" "$_url"
|
||||
if ! _get "$_url" true 1 | _head_n 1 | grep -Fq 200; then
|
||||
_instance_role_name_url="http://169.254.169.254/latest/meta-data/iam/security-credentials/"
|
||||
|
||||
if _get "$_instance_role_name_url" true 1 | _head_n 1 | grep -Fq 401; then
|
||||
_debug "Using IMDSv2"
|
||||
_token_url="http://169.254.169.254/latest/api/token"
|
||||
export _H1="X-aws-ec2-metadata-token-ttl-seconds: 21600"
|
||||
_token="$(_post "" "$_token_url" "" "PUT")"
|
||||
_secure_debug3 "_token" "$_token"
|
||||
if [ -z "$_token" ]; then
|
||||
_debug "Unable to fetch IMDSv2 token from instance metadata"
|
||||
return 1
|
||||
fi
|
||||
export _H1="X-aws-ec2-metadata-token: $_token"
|
||||
fi
|
||||
|
||||
if ! _get "$_instance_role_name_url" true 1 | _head_n 1 | grep -Fq 200; then
|
||||
_debug "Unable to fetch IAM role from instance metadata"
|
||||
return 1
|
||||
fi
|
||||
_aws_role=$(_get "$_url" "" 1)
|
||||
_debug "_aws_role" "$_aws_role"
|
||||
_use_metadata "$_url$_aws_role"
|
||||
|
||||
_instance_role_name=$(_get "$_instance_role_name_url" "" 1)
|
||||
_debug "_instance_role_name" "$_instance_role_name"
|
||||
_use_metadata "$_instance_role_name_url$_instance_role_name" "$_token"
|
||||
|
||||
}
|
||||
|
||||
_use_metadata() {
|
||||
export _H1="X-aws-ec2-metadata-token: $2"
|
||||
_aws_creds="$(
|
||||
_get "$1" "" 1 |
|
||||
_normalizeJson |
|
||||
tr '{,}' '\n' |
|
||||
while read -r _line; do
|
||||
_key="$(echo "${_line%%:*}" | tr -d '"')"
|
||||
_key="$(echo "${_line%%:*}" | tr -d '\"')"
|
||||
_value="${_line#*:}"
|
||||
_debug3 "_key" "$_key"
|
||||
_secure_debug3 "_value" "$_value"
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
#AZION_Email=""
|
||||
#AZION_Password=""
|
||||
#
|
||||
# shellcheck disable=SC2034
|
||||
dns_azion_info='Azion.om
|
||||
Site: Azion.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_azion
|
||||
Options:
|
||||
AZION_Email Email
|
||||
AZION_Password Password
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/3555
|
||||
'
|
||||
|
||||
AZION_Api="https://api.azionapi.net"
|
||||
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
WIKI="https://github.com/acmesh-official/acme.sh/wiki/How-to-use-Azure-DNS"
|
||||
# shellcheck disable=SC2034
|
||||
dns_azure_info='Azure
|
||||
Site: Azure.microsoft.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_azure
|
||||
Options:
|
||||
AZUREDNS_SUBSCRIPTIONID Subscription ID
|
||||
AZUREDNS_TENANTID Tenant ID
|
||||
AZUREDNS_APPID App ID. App ID of the service principal
|
||||
AZUREDNS_CLIENTSECRET Client Secret. Secret from creating the service principal
|
||||
AZUREDNS_MANAGEDIDENTITY Use Managed Identity. Use Managed Identity assigned to a resource instead of a service principal. "true"/"false"
|
||||
'
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
|
||||
88
dnsapi/dns_bookmyname.sh
Normal file
88
dnsapi/dns_bookmyname.sh
Normal file
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_bookmyname_info='BookMyName.com
|
||||
Site: BookMyName.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_bookmyname
|
||||
Options:
|
||||
BOOKMYNAME_USERNAME Username
|
||||
BOOKMYNAME_PASSWORD Password
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/3209
|
||||
Author: Neilpang
|
||||
'
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
# BookMyName urls:
|
||||
# https://BOOKMYNAME_USERNAME:BOOKMYNAME_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=add&value="XXXXXXXX"'
|
||||
# https://BOOKMYNAME_USERNAME:BOOKMYNAME_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=remove&value="XXXXXXXX"'
|
||||
|
||||
# Output:
|
||||
#good: update done, cid 123456, domain id 456789, type txt, ip XXXXXXXX
|
||||
#good: remove done 1, cid 123456, domain id 456789, ttl 300, type txt, ip XXXXXXXX
|
||||
|
||||
# Be careful, BMN DNS servers can be slow to pick up changes; using dnssleep is thus advised.
|
||||
|
||||
# Usage:
|
||||
# export BOOKMYNAME_USERNAME="ABCDE-FREE"
|
||||
# export BOOKMYNAME_PASSWORD="MyPassword"
|
||||
# /usr/local/ssl/acme.sh/acme.sh --dns dns_bookmyname --dnssleep 600 --issue -d domain.tld
|
||||
|
||||
#Usage: dns_bookmyname_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_bookmyname_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
_info "Using bookmyname"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
BOOKMYNAME_USERNAME="${BOOKMYNAME_USERNAME:-$(_readaccountconf_mutable BOOKMYNAME_USERNAME)}"
|
||||
BOOKMYNAME_PASSWORD="${BOOKMYNAME_PASSWORD:-$(_readaccountconf_mutable BOOKMYNAME_PASSWORD)}"
|
||||
|
||||
if [ -z "$BOOKMYNAME_USERNAME" ] || [ -z "$BOOKMYNAME_PASSWORD" ]; then
|
||||
BOOKMYNAME_USERNAME=""
|
||||
BOOKMYNAME_PASSWORD=""
|
||||
_err "You didn't specify BookMyName username and password yet."
|
||||
_err "Please specify them and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
#save the credentials to the account conf file.
|
||||
_saveaccountconf_mutable BOOKMYNAME_USERNAME "$BOOKMYNAME_USERNAME"
|
||||
_saveaccountconf_mutable BOOKMYNAME_PASSWORD "$BOOKMYNAME_PASSWORD"
|
||||
|
||||
uri="https://${BOOKMYNAME_USERNAME}:${BOOKMYNAME_PASSWORD}@www.bookmyname.com/dyndns/"
|
||||
data="?hostname=${fulldomain}&type=TXT&ttl=300&do=add&value=${txtvalue}"
|
||||
result="$(_get "${uri}${data}")"
|
||||
_debug "Result: $result"
|
||||
|
||||
if ! _startswith "$result" 'good: update done, cid '; then
|
||||
_err "Can't add $fulldomain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
#Usage: fulldomain txtvalue
|
||||
#Remove the txt record after validation.
|
||||
dns_bookmyname_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
_info "Using bookmyname"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
BOOKMYNAME_USERNAME="${BOOKMYNAME_USERNAME:-$(_readaccountconf_mutable BOOKMYNAME_USERNAME)}"
|
||||
BOOKMYNAME_PASSWORD="${BOOKMYNAME_PASSWORD:-$(_readaccountconf_mutable BOOKMYNAME_PASSWORD)}"
|
||||
|
||||
uri="https://${BOOKMYNAME_USERNAME}:${BOOKMYNAME_PASSWORD}@www.bookmyname.com/dyndns/"
|
||||
data="?hostname=${fulldomain}&type=TXT&ttl=300&do=remove&value=${txtvalue}"
|
||||
result="$(_get "${uri}${data}")"
|
||||
_debug "Result: $result"
|
||||
|
||||
if ! _startswith "$result" 'good: remove done 1, cid '; then
|
||||
_info "Can't remove $fulldomain"
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
245
dnsapi/dns_bunny.sh
Normal file
245
dnsapi/dns_bunny.sh
Normal file
@@ -0,0 +1,245 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_bunny_info='Bunny.net
|
||||
Site: Bunny.net/dns/
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_bunny
|
||||
Options:
|
||||
BUNNY_API_KEY API Key
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/4296
|
||||
Author: <nosilver4u@ewww.io>
|
||||
'
|
||||
|
||||
##################### Public functions #####################
|
||||
|
||||
## Create the text record for validation.
|
||||
## Usage: fulldomain txtvalue
|
||||
## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs"
|
||||
dns_bunny_add() {
|
||||
fulldomain="$(echo "$1" | _lower_case)"
|
||||
txtvalue=$2
|
||||
|
||||
BUNNY_API_KEY="${BUNNY_API_KEY:-$(_readaccountconf_mutable BUNNY_API_KEY)}"
|
||||
# Check if API Key is set
|
||||
if [ -z "$BUNNY_API_KEY" ]; then
|
||||
BUNNY_API_KEY=""
|
||||
_err "You did not specify Bunny.net API key."
|
||||
_err "Please export BUNNY_API_KEY and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_info "Using Bunny.net dns validation - add record"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
## save the env vars (key and domain split location) for later automated use
|
||||
_saveaccountconf_mutable BUNNY_API_KEY "$BUNNY_API_KEY"
|
||||
|
||||
## split the domain for Bunny API
|
||||
if ! _get_base_domain "$fulldomain"; then
|
||||
_err "domain not found in your account for addition"
|
||||
return 1
|
||||
fi
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
_debug _domain_id "$_domain_id"
|
||||
|
||||
## Set the header with our post type and auth key
|
||||
export _H1="Accept: application/json"
|
||||
export _H2="AccessKey: $BUNNY_API_KEY"
|
||||
export _H3="Content-Type: application/json"
|
||||
PURL="https://api.bunny.net/dnszone/$_domain_id/records"
|
||||
PBODY='{"Id":'$_domain_id',"Type":3,"Name":"'$_sub_domain'","Value":"'$txtvalue'","ttl":120}'
|
||||
|
||||
_debug PURL "$PURL"
|
||||
_debug PBODY "$PBODY"
|
||||
|
||||
## the create request - POST
|
||||
## args: BODY, URL, [need64, httpmethod]
|
||||
response="$(_post "$PBODY" "$PURL" "" "PUT")"
|
||||
|
||||
## check response
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "error in response: $response"
|
||||
return 1
|
||||
fi
|
||||
_debug2 response "$response"
|
||||
|
||||
## finished correctly
|
||||
return 0
|
||||
}
|
||||
|
||||
## Remove the txt record after validation.
|
||||
## Usage: fulldomain txtvalue
|
||||
## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs"
|
||||
dns_bunny_rm() {
|
||||
fulldomain="$(echo "$1" | _lower_case)"
|
||||
txtvalue=$2
|
||||
|
||||
BUNNY_API_KEY="${BUNNY_API_KEY:-$(_readaccountconf_mutable BUNNY_API_KEY)}"
|
||||
# Check if API Key Exists
|
||||
if [ -z "$BUNNY_API_KEY" ]; then
|
||||
BUNNY_API_KEY=""
|
||||
_err "You did not specify Bunny.net API key."
|
||||
_err "Please export BUNNY_API_KEY and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_info "Using Bunny.net dns validation - remove record"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
## split the domain for Bunny API
|
||||
if ! _get_base_domain "$fulldomain"; then
|
||||
_err "Domain not found in your account for TXT record removal"
|
||||
return 1
|
||||
fi
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
_debug _domain_id "$_domain_id"
|
||||
|
||||
## Set the header with our post type and key auth key
|
||||
export _H1="Accept: application/json"
|
||||
export _H2="AccessKey: $BUNNY_API_KEY"
|
||||
## get URL for the list of DNS records
|
||||
GURL="https://api.bunny.net/dnszone/$_domain_id"
|
||||
|
||||
## 1) Get the domain/zone records
|
||||
## the fetch request - GET
|
||||
## args: URL, [onlyheader, timeout]
|
||||
domain_list="$(_get "$GURL")"
|
||||
|
||||
## check response
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "error in domain_list response: $domain_list"
|
||||
return 1
|
||||
fi
|
||||
_debug2 domain_list "$domain_list"
|
||||
|
||||
## 2) search through records
|
||||
## check for what we are looking for: "Type":3,"Value":"$txtvalue","Name":"$_sub_domain"
|
||||
record="$(echo "$domain_list" | _egrep_o "\"Id\"\s*\:\s*\"*[0-9]+\"*,\s*\"Type\"[^}]*\"Value\"\s*\:\s*\"$txtvalue\"[^}]*\"Name\"\s*\:\s*\"$_sub_domain\"")"
|
||||
|
||||
if [ -n "$record" ]; then
|
||||
|
||||
## We found records
|
||||
rec_ids="$(echo "$record" | _egrep_o "Id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")"
|
||||
_debug rec_ids "$rec_ids"
|
||||
if [ -n "$rec_ids" ]; then
|
||||
echo "$rec_ids" | while IFS= read -r rec_id; do
|
||||
## delete the record
|
||||
## delete URL for removing the one we dont want
|
||||
DURL="https://api.bunny.net/dnszone/$_domain_id/records/$rec_id"
|
||||
|
||||
## the removal request - DELETE
|
||||
## args: BODY, URL, [need64, httpmethod]
|
||||
response="$(_post "" "$DURL" "" "DELETE")"
|
||||
|
||||
## check response (sort of)
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "error in remove response: $response"
|
||||
return 1
|
||||
fi
|
||||
_debug2 response "$response"
|
||||
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
## finished correctly
|
||||
return 0
|
||||
}
|
||||
|
||||
##################### Private functions below #####################
|
||||
|
||||
## Split the domain provided into the "base domain" and the "start prefix".
|
||||
## This function searches for the longest subdomain in your account
|
||||
## for the full domain given and splits it into the base domain (zone)
|
||||
## and the prefix/record to be added/removed
|
||||
## USAGE: fulldomain
|
||||
## EG: "_acme-challenge.two.three.four.domain.com"
|
||||
## returns
|
||||
## _sub_domain="_acme-challenge.two"
|
||||
## _domain="three.four.domain.com" *IF* zone "three.four.domain.com" exists
|
||||
## _domain_id=234
|
||||
## if only "domain.com" exists it will return
|
||||
## _sub_domain="_acme-challenge.two.three.four"
|
||||
## _domain="domain.com"
|
||||
## _domain_id=234
|
||||
_get_base_domain() {
|
||||
# args
|
||||
fulldomain="$(echo "$1" | _lower_case)"
|
||||
_debug fulldomain "$fulldomain"
|
||||
|
||||
# domain max legal length = 253
|
||||
MAX_DOM=255
|
||||
page=1
|
||||
|
||||
## get a list of domains for the account to check thru
|
||||
## Set the headers
|
||||
export _H1="Accept: application/json"
|
||||
export _H2="AccessKey: $BUNNY_API_KEY"
|
||||
_debug BUNNY_API_KEY "$BUNNY_API_KEY"
|
||||
## get URL for the list of domains
|
||||
## may get: "links":{"pages":{"last":".../v2/domains/DOM/records?page=2","next":".../v2/domains/DOM/records?page=2"}}
|
||||
DOMURL="https://api.bunny.net/dnszone"
|
||||
|
||||
## while we dont have a matching domain we keep going
|
||||
while [ -z "$found" ]; do
|
||||
## get the domain list (current page)
|
||||
domain_list="$(_get "$DOMURL")"
|
||||
|
||||
## check response
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "error in domain_list response: $domain_list"
|
||||
return 1
|
||||
fi
|
||||
_debug2 domain_list "$domain_list"
|
||||
|
||||
i=1
|
||||
while [ $i -gt 0 ]; do
|
||||
## get next longest domain
|
||||
_domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM")
|
||||
## check we got something back from our cut (or are we at the end)
|
||||
if [ -z "$_domain" ]; then
|
||||
break
|
||||
fi
|
||||
## we got part of a domain back - grep it out
|
||||
found="$(echo "$domain_list" | _egrep_o "\"Id\"\s*:\s*\"*[0-9]+\"*,\s*\"Domain\"\s*\:\s*\"$_domain\"")"
|
||||
## check if it exists
|
||||
if [ -n "$found" ]; then
|
||||
## exists - exit loop returning the parts
|
||||
sub_point=$(_math $i - 1)
|
||||
_sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$sub_point")
|
||||
_domain_id="$(echo "$found" | _egrep_o "Id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")"
|
||||
_debug _domain_id "$_domain_id"
|
||||
_debug _domain "$_domain"
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
found=""
|
||||
return 0
|
||||
fi
|
||||
## increment cut point $i
|
||||
i=$(_math $i + 1)
|
||||
done
|
||||
|
||||
if [ -z "$found" ]; then
|
||||
page=$(_math $page + 1)
|
||||
nextpage="https://api.bunny.net/dnszone?page=$page"
|
||||
## Find the next page if we don't have a match.
|
||||
hasnextpage="$(echo "$domain_list" | _egrep_o "\"HasMoreItems\"\s*:\s*true")"
|
||||
if [ -z "$hasnextpage" ]; then
|
||||
_err "No record and no nextpage in Bunny.net domain search."
|
||||
found=""
|
||||
return 1
|
||||
fi
|
||||
_debug2 nextpage "$nextpage"
|
||||
DOMURL="$nextpage"
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
## We went through the entire domain zone list and didn't find one that matched.
|
||||
## If we ever get here, something is broken in the code...
|
||||
_err "Domain not found in Bunny.net account, but we should never get here!"
|
||||
found=""
|
||||
return 1
|
||||
}
|
||||
@@ -1,13 +1,16 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
#CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
#
|
||||
#CF_Email="xxxx@sss.com"
|
||||
|
||||
#CF_Token="xxxx"
|
||||
#CF_Account_ID="xxxx"
|
||||
#CF_Zone_ID="xxxx"
|
||||
# shellcheck disable=SC2034
|
||||
dns_cf_info='CloudFlare
|
||||
Site: CloudFlare.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_cf
|
||||
Options:
|
||||
CF_Key API Key
|
||||
CF_Email Your account email
|
||||
OptionsAlt:
|
||||
CF_Token API Token
|
||||
CF_Account_ID Account ID
|
||||
CF_Zone_ID Zone ID. Optional.
|
||||
'
|
||||
|
||||
CF_Api="https://api.cloudflare.com/client/v4"
|
||||
|
||||
@@ -32,7 +35,8 @@ dns_cf_add() {
|
||||
else
|
||||
_saveaccountconf_mutable CF_Token "$CF_Token"
|
||||
_saveaccountconf_mutable CF_Account_ID "$CF_Account_ID"
|
||||
_saveaccountconf_mutable CF_Zone_ID "$CF_Zone_ID"
|
||||
_clearaccountconf_mutable CF_Zone_ID
|
||||
_clearaccountconf CF_Zone_ID
|
||||
fi
|
||||
else
|
||||
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
|
||||
@@ -51,6 +55,14 @@ dns_cf_add() {
|
||||
#save the api key and email to the account conf file.
|
||||
_saveaccountconf_mutable CF_Key "$CF_Key"
|
||||
_saveaccountconf_mutable CF_Email "$CF_Email"
|
||||
|
||||
_clearaccountconf_mutable CF_Token
|
||||
_clearaccountconf_mutable CF_Account_ID
|
||||
_clearaccountconf_mutable CF_Zone_ID
|
||||
_clearaccountconf CF_Token
|
||||
_clearaccountconf CF_Account_ID
|
||||
_clearaccountconf CF_Zone_ID
|
||||
|
||||
fi
|
||||
|
||||
_debug "First detect the root zone"
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Author: Radek Sprta <sprta@vshosting.cz>
|
||||
|
||||
#CLOUDDNS_EMAIL=XXXXX
|
||||
#CLOUDDNS_PASSWORD="YYYYYYYYY"
|
||||
#CLOUDDNS_CLIENT_ID=XXXXX
|
||||
# shellcheck disable=SC2034
|
||||
dns_clouddns_info='vshosting.cz CloudDNS
|
||||
Site: github.com/vshosting/clouddns
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_clouddns
|
||||
Options:
|
||||
CLOUDDNS_EMAIL Email
|
||||
CLOUDDNS_PASSWORD Password
|
||||
CLOUDDNS_CLIENT_ID Client ID
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2699
|
||||
Author: Radek Sprta <sprta@vshosting.cz>
|
||||
'
|
||||
|
||||
CLOUDDNS_API='https://admin.vshosting.cloud/clouddns'
|
||||
CLOUDDNS_LOGIN_API='https://admin.vshosting.cloud/api/public/auth/login'
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_cloudns_info='ClouDNS.net
|
||||
Site: ClouDNS.net
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_cloudns
|
||||
Options:
|
||||
CLOUDNS_AUTH_ID Regular auth ID
|
||||
CLOUDNS_SUB_AUTH_ID Sub auth ID
|
||||
CLOUDNS_AUTH_PASSWORD Auth Password
|
||||
Author: Boyan Peychev <boyan@cloudns.net>
|
||||
'
|
||||
|
||||
# Author: Boyan Peychev <boyan at cloudns dot net>
|
||||
# Repository: https://github.com/ClouDNS/acme.sh/
|
||||
# Editor: I Komang Suryadana
|
||||
|
||||
#CLOUDNS_AUTH_ID=XXXXX
|
||||
#CLOUDNS_SUB_AUTH_ID=XXXXX
|
||||
#CLOUDNS_AUTH_PASSWORD="YYYYYYYYY"
|
||||
CLOUDNS_API="https://api.cloudns.net"
|
||||
DOMAIN_TYPE=
|
||||
DOMAIN_MASTER=
|
||||
@@ -78,7 +81,7 @@ dns_cloudns_rm() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
for i in $(echo "$response" | tr '{' "\n" | grep "$record"); do
|
||||
for i in $(echo "$response" | tr '{' "\n" | grep -- "$record"); do
|
||||
record_id=$(echo "$i" | tr ',' "\n" | grep -E '^"id"' | sed -re 's/^\"id\"\:\"([0-9]+)\"$/\1/g')
|
||||
|
||||
if [ -n "$record_id" ]; then
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# DNS API for acme.sh for Core-Networks (https://beta.api.core-networks.de/doc/).
|
||||
# created by 5ll and francis
|
||||
# shellcheck disable=SC2034
|
||||
dns_cn_info='Core-Networks.de
|
||||
Site: beta.api.Core-Networks.de/doc/
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_cn
|
||||
Options:
|
||||
CN_User User
|
||||
CN_Password Password
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2142
|
||||
Author: 5ll, francis
|
||||
'
|
||||
|
||||
CN_API="https://beta.api.core-networks.de"
|
||||
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_conoha_info='ConoHa.jp
|
||||
Domains: ConoHa.io
|
||||
Site: ConoHa.jp
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_conoha
|
||||
Options:
|
||||
CONOHA_Username Username
|
||||
CONOHA_Password Password
|
||||
CONOHA_TenantId TenantId
|
||||
CONOHA_IdentityServiceApi Identity Service API. E.g. "https://identity.xxxx.conoha.io/v2.0"
|
||||
'
|
||||
|
||||
CONOHA_DNS_EP_PREFIX_REGEXP="https://dns-service\."
|
||||
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Author: Wout Decre <wout@canodus.be>
|
||||
# shellcheck disable=SC2034
|
||||
dns_constellix_info='Constellix.com
|
||||
Site: Constellix.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_constellix
|
||||
Options:
|
||||
CONSTELLIX_Key API Key
|
||||
CONSTELLIX_Secret API Secret
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2724
|
||||
Author: Wout Decre <wout@canodus.be>
|
||||
'
|
||||
|
||||
CONSTELLIX_Api="https://api.dns.constellix.com/v1"
|
||||
#CONSTELLIX_Key="XXX"
|
||||
#CONSTELLIX_Secret="XXX"
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
#!/usr/bin/env sh
|
||||
#
|
||||
#Author: Bjarne Saltbaek
|
||||
#Report Bugs here: https://github.com/acmesh-official/acme.sh/issues/3732
|
||||
#
|
||||
#
|
||||
# shellcheck disable=SC2034
|
||||
dns_cpanel_info='cPanel Server API
|
||||
Manage DNS via cPanel Dashboard.
|
||||
Site: cPanel.net
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_cpanel
|
||||
Options:
|
||||
cPanel_Username Username
|
||||
cPanel_Apitoken API Token
|
||||
cPanel_Hostname Server URL. E.g. "https://hostname:port"
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/3732
|
||||
Author: Bjarne Saltbaek
|
||||
'
|
||||
|
||||
######## Public functions #####################
|
||||
#
|
||||
# Export CPANEL username,api token and hostname in the following variables
|
||||
#
|
||||
# cPanel_Username=username
|
||||
# cPanel_Apitoken=apitoken
|
||||
# cPanel_Hostname=hostname
|
||||
#
|
||||
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
|
||||
# Used to add txt record
|
||||
dns_cpanel_add() {
|
||||
fulldomain=$1
|
||||
@@ -120,7 +121,7 @@ _myget() {
|
||||
|
||||
_get_root() {
|
||||
_myget 'json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=fetchzones'
|
||||
_domains=$(echo "$_result" | sed 's/.*\(zones.*\[\).*/\1/' | cut -d':' -f2 | sed 's/"//g' | sed 's/{//g')
|
||||
_domains=$(echo "$_result" | _egrep_o '"[a-z0-9\.\-]*":\["; cPanel first' | cut -d':' -f1 | sed 's/"//g' | sed 's/{//g')
|
||||
_debug "_result is: $_result"
|
||||
_debug "_domains is: $_domains"
|
||||
if [ -z "$_domains" ]; then
|
||||
@@ -138,15 +139,15 @@ _get_root() {
|
||||
}
|
||||
|
||||
_successful_update() {
|
||||
if (echo "$_result" | grep -q 'newserial'); then return 0; fi
|
||||
return 1
|
||||
if (echo "$_result" | _egrep_o 'data":\[[^]]*]' | grep -q '"newserial":null'); then return 1; fi
|
||||
return 0
|
||||
}
|
||||
|
||||
_findentry() {
|
||||
_debug "In _findentry"
|
||||
#returns id of dns entry, if it exists
|
||||
_myget "json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=fetchzone_records&domain=$_domain"
|
||||
_id=$(echo "$_result" | sed "s/.*\(line.*$fulldomain.*$txtvalue\).*/\1/" | cut -d ':' -f 2 | cut -d ',' -f 1)
|
||||
_id=$(echo "$_result" | sed -e "s/},{/},\n{/g" | grep "$fulldomain" | grep "$txtvalue" | _egrep_o 'line":[0-9]+' | cut -d ':' -f 2)
|
||||
_debug "_result is: $_result"
|
||||
_debug "fulldomain. is $fulldomain."
|
||||
_debug "txtvalue is $txtvalue"
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#Script to use with curanet.dk, scannet.dk, wannafind.dk, dandomain.dk DNS management.
|
||||
#Requires api credentials with scope: dns
|
||||
#Author: Peter L. Hansen <peter@r12.dk>
|
||||
#Version 1.0
|
||||
# shellcheck disable=SC2034
|
||||
dns_curanet_info='Curanet.dk
|
||||
Domains: scannet.dk wannafind.dk dandomain.dk
|
||||
Site: Curanet.dk
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_curanet
|
||||
Options:
|
||||
CURANET_AUTHCLIENTID Auth ClientID. Requires scope dns
|
||||
CURANET_AUTHSECRET Auth Secret
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/3933
|
||||
Author: Peter L. Hansen <peter@r12.dk>
|
||||
'
|
||||
|
||||
CURANET_REST_URL="https://api.curanet.dk/dns/v1/Domains"
|
||||
CURANET_AUTH_URL="https://apiauth.dk.team.blue/auth/realms/Curanet/protocol/openid-connect/token"
|
||||
|
||||
@@ -1,21 +1,15 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
########
|
||||
# Custom cyon.ch DNS API for use with [acme.sh](https://github.com/acmesh-official/acme.sh)
|
||||
#
|
||||
# Usage: acme.sh --issue --dns dns_cyon -d www.domain.com
|
||||
#
|
||||
# Dependencies:
|
||||
# -------------
|
||||
# - oathtool (When using 2 Factor Authentication)
|
||||
#
|
||||
# Issues:
|
||||
# -------
|
||||
# Any issues / questions / suggestions can be posted here:
|
||||
# https://github.com/noplanman/cyon-api/issues
|
||||
#
|
||||
# Author: Armando Lüscher <armando@noplanman.ch>
|
||||
########
|
||||
# shellcheck disable=SC2034
|
||||
dns_cyon_info='cyon.ch
|
||||
Site: cyon.ch
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_cyon
|
||||
Options:
|
||||
CY_Username Username
|
||||
CY_Password API Token
|
||||
CY_OTP_Secret OTP token. Only required if using 2FA
|
||||
Issues: github.com/noplanman/cyon-api/issues
|
||||
Author: Armando Lüscher <armando@noplanman.ch>
|
||||
'
|
||||
|
||||
dns_cyon_add() {
|
||||
_cyon_load_credentials &&
|
||||
@@ -44,7 +38,7 @@ dns_cyon_rm() {
|
||||
_cyon_load_credentials() {
|
||||
# Convert loaded password to/from base64 as needed.
|
||||
if [ "${CY_Password_B64}" ]; then
|
||||
CY_Password="$(printf "%s" "${CY_Password_B64}" | _dbase64 "multiline")"
|
||||
CY_Password="$(printf "%s" "${CY_Password_B64}" | _dbase64)"
|
||||
elif [ "${CY_Password}" ]; then
|
||||
CY_Password_B64="$(printf "%s" "${CY_Password}" | _base64)"
|
||||
fi
|
||||
|
||||
@@ -1,31 +1,14 @@
|
||||
#!/usr/bin/env sh
|
||||
# -*- mode: sh; tab-width: 2; indent-tabs-mode: s; coding: utf-8 -*-
|
||||
# vim: et ts=2 sw=2
|
||||
#
|
||||
# DirectAdmin 1.41.0 API
|
||||
# The DirectAdmin interface has it's own Let's encrypt functionality, but this
|
||||
# script can be used to generate certificates for names which are not hosted on
|
||||
# DirectAdmin
|
||||
#
|
||||
# User must provide login data and URL to DirectAdmin incl. port.
|
||||
# You can create login key, by using the Login Keys function
|
||||
# ( https://da.example.com:8443/CMD_LOGIN_KEYS ), which only has access to
|
||||
# - CMD_API_DNS_CONTROL
|
||||
# - CMD_API_SHOW_DOMAINS
|
||||
#
|
||||
# See also https://www.directadmin.com/api.php and
|
||||
# https://www.directadmin.com/features.php?id=1298
|
||||
#
|
||||
# Report bugs to https://github.com/TigerP/acme.sh/issues
|
||||
#
|
||||
# Values to export:
|
||||
# export DA_Api="https://remoteUser:remotePassword@da.example.com:8443"
|
||||
# export DA_Api_Insecure=1
|
||||
#
|
||||
# Set DA_Api_Insecure to 1 for insecure and 0 for secure -> difference is
|
||||
# whether ssl cert is checked for validity (0) or whether it is just accepted
|
||||
# (1)
|
||||
#
|
||||
# shellcheck disable=SC2034
|
||||
dns_da_info='DirectAdmin Server API
|
||||
Site: DirectAdmin.com/api.php
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_da
|
||||
Options:
|
||||
DA_Api API Server URL. E.g. "https://remoteUser:remotePassword@da.domain.tld:8443"
|
||||
DA_Api_Insecure Insecure TLS. 0: check for cert validity, 1: always accept
|
||||
Issues: github.com/TigerP/acme.sh/issues
|
||||
'
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
# Usage: dns_myapi_add _acme-challenge.www.example.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#Created by RaidenII, to use DuckDNS's API to add/remove text records
|
||||
#modified by helbgd @ 03/13/2018 to support ddnss.de
|
||||
#modified by mod242 @ 04/24/2018 to support different ddnss domains
|
||||
#Please note: the Wildcard Feature must be turned on for the Host record
|
||||
#and the checkbox for TXT needs to be enabled
|
||||
|
||||
# Pass credentials before "acme.sh --issue --dns dns_ddnss ..."
|
||||
# --
|
||||
# export DDNSS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
|
||||
# --
|
||||
#
|
||||
# shellcheck disable=SC2034
|
||||
dns_ddnss_info='DDNSS.de
|
||||
Site: DDNSS.de
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_ddnss
|
||||
Options:
|
||||
DDNSS_Token API Token
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2230
|
||||
Author: RaidenII, helbgd, mod242
|
||||
'
|
||||
|
||||
DDNSS_DNS_API="https://ddnss.de/upd.php"
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#!/usr/bin/env sh
|
||||
#
|
||||
# deSEC.io Domain API
|
||||
#
|
||||
# Author: Zheng Qian
|
||||
#
|
||||
# deSEC API doc
|
||||
# https://desec.readthedocs.io/en/latest/
|
||||
# shellcheck disable=SC2034
|
||||
dns_desec_info='deSEC.io
|
||||
Site: desec.readthedocs.io/en/latest/
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_desec
|
||||
Options:
|
||||
DDNSS_Token API Token
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2180
|
||||
Author: Zheng Qian
|
||||
'
|
||||
|
||||
REST_API="https://desec.io/api/v1/domains"
|
||||
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
########################################################################
|
||||
# https://dyndnsfree.de hook script for acme.sh
|
||||
#
|
||||
# Environment variables:
|
||||
#
|
||||
# - $DF_user (your dyndnsfree.de username)
|
||||
# - $DF_password (your dyndnsfree.de password)
|
||||
#
|
||||
# Author: Thilo Gass <thilo.gass@gmail.com>
|
||||
# Git repo: https://github.com/ThiloGa/acme.sh
|
||||
|
||||
#-- dns_df_add() - Add TXT record --------------------------------------
|
||||
# Usage: dns_df_add _acme-challenge.subdomain.domain.com "XyZ123..."
|
||||
# shellcheck disable=SC2034
|
||||
dns_df_info='DynDnsFree.de
|
||||
Domains: dynup.de
|
||||
Site: DynDnsFree.de
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_df
|
||||
Options:
|
||||
DF_user Username
|
||||
DF_password Password
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2897
|
||||
Author: Thilo Gass <thilo.gass@gmail.com>
|
||||
'
|
||||
|
||||
dyndnsfree_api="https://dynup.de/acme.php"
|
||||
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
## Will be called by acme.sh to add the txt record to your api system.
|
||||
## returns 0 means success, otherwise error.
|
||||
|
||||
## Author: thewer <github at thewer.com>
|
||||
## GitHub: https://github.com/gitwer/acme.sh
|
||||
|
||||
##
|
||||
## Environment Variables Required:
|
||||
##
|
||||
## DO_API_KEY="75310dc4ca779ac39a19f6355db573b49ce92ae126553ebd61ac3a3ae34834cc"
|
||||
##
|
||||
# shellcheck disable=SC2034
|
||||
dns_dgon_info='DigitalOcean.com
|
||||
Site: DigitalOcean.com/help/api/
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_dgon
|
||||
Options:
|
||||
DO_API_KEY API Key
|
||||
Author: <github@thewer.com>
|
||||
'
|
||||
|
||||
##################### Public functions #####################
|
||||
|
||||
@@ -192,6 +188,7 @@ _get_base_domain() {
|
||||
## get URL for the list of domains
|
||||
## may get: "links":{"pages":{"last":".../v2/domains/DOM/records?page=2","next":".../v2/domains/DOM/records?page=2"}}
|
||||
DOMURL="https://api.digitalocean.com/v2/domains"
|
||||
found=""
|
||||
|
||||
## while we dont have a matching domain we keep going
|
||||
while [ -z "$found" ]; do
|
||||
@@ -205,9 +202,7 @@ _get_base_domain() {
|
||||
fi
|
||||
_debug2 domain_list "$domain_list"
|
||||
|
||||
## for each shortening of our $fulldomain, check if it exists in the $domain_list
|
||||
## can never start on 1 (aka whole $fulldomain) as $fulldomain starts with "_acme-challenge"
|
||||
i=2
|
||||
i=1
|
||||
while [ $i -gt 0 ]; do
|
||||
## get next longest domain
|
||||
_domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM")
|
||||
|
||||
188
dnsapi/dns_dnsexit.sh
Normal file
188
dnsapi/dns_dnsexit.sh
Normal file
@@ -0,0 +1,188 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_dnsexit_info='DNSExit.com
|
||||
Site: DNSExit.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_dnsexit
|
||||
Options:
|
||||
DNSEXIT_API_KEY API Key
|
||||
DNSEXIT_AUTH_USER Username
|
||||
DNSEXIT_AUTH_PASS Password
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/4719
|
||||
Author: Samuel Jimenez
|
||||
'
|
||||
|
||||
DNSEXIT_API_URL="https://api.dnsexit.com/dns/"
|
||||
DNSEXIT_HOSTS_URL="https://update.dnsexit.com/ipupdate/hosts.jsp"
|
||||
|
||||
######## Public functions #####################
|
||||
#Usage: dns_dnsexit_add _acme-challenge.*.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_dnsexit_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
_info "Using DNSExit.com"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
_debug 'Load account auth'
|
||||
if ! get_account_info; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug 'First detect the root zone'
|
||||
if ! _get_root "$fulldomain"; then
|
||||
return 1
|
||||
fi
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
if ! _dnsexit_rest "{\"domain\":\"$_domain\",\"add\":{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":0,\"overwrite\":false}}"; then
|
||||
_err "$response"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug2 _response "$response"
|
||||
return 0
|
||||
}
|
||||
|
||||
#Usage: fulldomain txtvalue
|
||||
#Remove the txt record after validation.
|
||||
dns_dnsexit_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
_info "Using DNSExit.com"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
_debug 'Load account auth'
|
||||
if ! get_account_info; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug 'First detect the root zone'
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "$response"
|
||||
return 1
|
||||
fi
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
if ! _dnsexit_rest "{\"domain\":\"$_domain\",\"delete\":{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\"}}"; then
|
||||
_err "$response"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug2 _response "$response"
|
||||
return 0
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
#_acme-challenge.www.domain.com
|
||||
#returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
# _domain=domain.com
|
||||
_get_root() {
|
||||
domain=$1
|
||||
i=1
|
||||
while true; do
|
||||
_domain=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
_debug h "$_domain"
|
||||
if [ -z "$_domain" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug login "$DNSEXIT_AUTH_USER"
|
||||
_debug password "$DNSEXIT_AUTH_PASS"
|
||||
_debug domain "$_domain"
|
||||
|
||||
_dnsexit_http "login=$DNSEXIT_AUTH_USER&password=$DNSEXIT_AUTH_PASS&domain=$_domain"
|
||||
|
||||
if _contains "$response" "0=$_domain"; then
|
||||
_sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")"
|
||||
return 0
|
||||
else
|
||||
_debug "Go to next level of $_domain"
|
||||
fi
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
_dnsexit_rest() {
|
||||
m=POST
|
||||
ep=""
|
||||
data="$1"
|
||||
_debug _dnsexit_rest "$ep"
|
||||
_debug data "$data"
|
||||
|
||||
api_key_trimmed=$(echo "$DNSEXIT_API_KEY" | tr -d '"')
|
||||
|
||||
export _H1="apikey: $api_key_trimmed"
|
||||
export _H2='Content-Type: application/json'
|
||||
|
||||
if [ "$m" != "GET" ]; then
|
||||
_debug data "$data"
|
||||
response="$(_post "$data" "$DNSEXIT_API_URL/$ep" "" "$m")"
|
||||
else
|
||||
response="$(_get "$DNSEXIT_API_URL/$ep")"
|
||||
fi
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "Error $ep"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug2 response "$response"
|
||||
return 0
|
||||
}
|
||||
|
||||
_dnsexit_http() {
|
||||
m=GET
|
||||
param="$1"
|
||||
_debug param "$param"
|
||||
_debug get "$DNSEXIT_HOSTS_URL?$param"
|
||||
|
||||
response="$(_get "$DNSEXIT_HOSTS_URL?$param")"
|
||||
|
||||
_debug response "$response"
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "Error $param"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug2 response "$response"
|
||||
return 0
|
||||
}
|
||||
|
||||
get_account_info() {
|
||||
|
||||
DNSEXIT_API_KEY="${DNSEXIT_API_KEY:-$(_readaccountconf_mutable DNSEXIT_API_KEY)}"
|
||||
if test -z "$DNSEXIT_API_KEY"; then
|
||||
DNSEXIT_API_KEY=''
|
||||
_err 'DNSEXIT_API_KEY was not exported'
|
||||
return 1
|
||||
fi
|
||||
|
||||
_saveaccountconf_mutable DNSEXIT_API_KEY "$DNSEXIT_API_KEY"
|
||||
|
||||
DNSEXIT_AUTH_USER="${DNSEXIT_AUTH_USER:-$(_readaccountconf_mutable DNSEXIT_AUTH_USER)}"
|
||||
if test -z "$DNSEXIT_AUTH_USER"; then
|
||||
DNSEXIT_AUTH_USER=""
|
||||
_err 'DNSEXIT_AUTH_USER was not exported'
|
||||
return 1
|
||||
fi
|
||||
|
||||
_saveaccountconf_mutable DNSEXIT_AUTH_USER "$DNSEXIT_AUTH_USER"
|
||||
|
||||
DNSEXIT_AUTH_PASS="${DNSEXIT_AUTH_PASS:-$(_readaccountconf_mutable DNSEXIT_AUTH_PASS)}"
|
||||
if test -z "$DNSEXIT_AUTH_PASS"; then
|
||||
DNSEXIT_AUTH_PASS=""
|
||||
_err 'DNSEXIT_AUTH_PASS was not exported'
|
||||
return 1
|
||||
fi
|
||||
|
||||
_saveaccountconf_mutable DNSEXIT_AUTH_PASS "$DNSEXIT_AUTH_PASS"
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# dnsHome.de API for acme.sh
|
||||
#
|
||||
# This Script adds the necessary TXT record to a Subdomain
|
||||
#
|
||||
# Author dnsHome.de (https://github.com/dnsHome-de)
|
||||
#
|
||||
# Report Bugs to https://github.com/acmesh-official/acme.sh/issues/3819
|
||||
#
|
||||
# export DNSHOME_Subdomain=""
|
||||
# export DNSHOME_SubdomainPassword=""
|
||||
# shellcheck disable=SC2034
|
||||
dns_dnshome_info='dnsHome.de
|
||||
Site: dnsHome.de
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_dnshome
|
||||
Options:
|
||||
DNSHOME_Subdomain Subdomain
|
||||
DNSHOME_SubdomainPassword Subdomain Password
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/3819
|
||||
Author: dnsHome.de https://github.com/dnsHome-de
|
||||
'
|
||||
|
||||
# Usage: add subdomain.ddnsdomain.tld "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
# Used to add txt record
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# DNSimple domain api
|
||||
# https://github.com/pho3nixf1re/acme.sh/issues
|
||||
#
|
||||
# This is your oauth token which can be acquired on the account page. Please
|
||||
# note that this must be an _account_ token and not a _user_ token.
|
||||
# https://dnsimple.com/a/<your account id>/account/access_tokens
|
||||
# DNSimple_OAUTH_TOKEN="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
# shellcheck disable=SC2034
|
||||
dns_dnsimple_info='DNSimple.com
|
||||
Site: DNSimple.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_dnsimple
|
||||
Options:
|
||||
DNSimple_OAUTH_TOKEN OAuth Token
|
||||
Issues: github.com/pho3nixf1re/acme.sh/issues
|
||||
'
|
||||
|
||||
DNSimple_API="https://api.dnsimple.com/v2"
|
||||
|
||||
|
||||
251
dnsapi/dns_dnsservices.sh
Executable file
251
dnsapi/dns_dnsservices.sh
Executable file
@@ -0,0 +1,251 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_dnsservices_info='DNS.Services
|
||||
Site: DNS.Services
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_dnsservices
|
||||
Options:
|
||||
DnsServices_Username Username
|
||||
DnsServices_Password Password
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/4152
|
||||
Author: Bjarke Bruun <bbruun@gmail.com>
|
||||
'
|
||||
|
||||
DNSServices_API=https://dns.services/api
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: dns_dnsservices_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_dnsservices_add() {
|
||||
fulldomain="$1"
|
||||
txtvalue="$2"
|
||||
|
||||
_info "Using dns.services to create ACME DNS challenge"
|
||||
_debug2 add_fulldomain "$fulldomain"
|
||||
_debug2 add_txtvalue "$txtvalue"
|
||||
|
||||
# Read username/password from environment or .acme.sh/accounts.conf
|
||||
DnsServices_Username="${DnsServices_Username:-$(_readaccountconf_mutable DnsServices_Username)}"
|
||||
DnsServices_Password="${DnsServices_Password:-$(_readaccountconf_mutable DnsServices_Password)}"
|
||||
if [ -z "$DnsServices_Username" ] || [ -z "$DnsServices_Password" ]; then
|
||||
DnsServices_Username=""
|
||||
DnsServices_Password=""
|
||||
_err "You didn't specify dns.services api username and password yet."
|
||||
_err "Set environment variables DnsServices_Username and DnsServices_Password"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Setup GET/POST/DELETE headers
|
||||
_setup_headers
|
||||
|
||||
#save the credentials to the account conf file.
|
||||
_saveaccountconf_mutable DnsServices_Username "$DnsServices_Username"
|
||||
_saveaccountconf_mutable DnsServices_Password "$DnsServices_Password"
|
||||
|
||||
if ! _contains "$DnsServices_Username" "@"; then
|
||||
_err "It seems that the username variable DnsServices_Username has not been set/left blank"
|
||||
_err "or is not a valid email. Please correct and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _get_root "${fulldomain}"; then
|
||||
_err "Invalid domain ${fulldomain}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! createRecord "$fulldomain" "${txtvalue}"; then
|
||||
_err "Error creating TXT record in domain $fulldomain in $rootZoneName"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug2 challenge-created "Created $fulldomain"
|
||||
return 0
|
||||
}
|
||||
|
||||
#Usage: fulldomain txtvalue
|
||||
#Description: Remove the txt record after validation.
|
||||
dns_dnsservices_rm() {
|
||||
fulldomain="$1"
|
||||
txtvalue="$2"
|
||||
|
||||
_info "Using dns.services to remove DNS record $fulldomain TXT $txtvalue"
|
||||
_debug rm_fulldomain "$fulldomain"
|
||||
_debug rm_txtvalue "$txtvalue"
|
||||
|
||||
# Read username/password from environment or .acme.sh/accounts.conf
|
||||
DnsServices_Username="${DnsServices_Username:-$(_readaccountconf_mutable DnsServices_Username)}"
|
||||
DnsServices_Password="${DnsServices_Password:-$(_readaccountconf_mutable DnsServices_Password)}"
|
||||
if [ -z "$DnsServices_Username" ] || [ -z "$DnsServices_Password" ]; then
|
||||
DnsServices_Username=""
|
||||
DnsServices_Password=""
|
||||
_err "You didn't specify dns.services api username and password yet."
|
||||
_err "Set environment variables DnsServices_Username and DnsServices_Password"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Setup GET/POST/DELETE headers
|
||||
_setup_headers
|
||||
|
||||
if ! _get_root "${fulldomain}"; then
|
||||
_err "Invalid domain ${fulldomain}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug2 rm_rootDomainInfo "found root domain $rootZoneName for $fulldomain"
|
||||
|
||||
if ! deleteRecord "${fulldomain}" "${txtvalue}"; then
|
||||
_err "Error removing record: $fulldomain TXT ${txtvalue}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
|
||||
_setup_headers() {
|
||||
# Set up API Headers for _get() and _post()
|
||||
# The <function>_add or <function>_rm must have been called before to work
|
||||
|
||||
if [ -z "$DnsServices_Username" ] || [ -z "$DnsServices_Password" ]; then
|
||||
_err "Could not setup BASIC authentication headers, they are missing"
|
||||
return 1
|
||||
fi
|
||||
|
||||
DnsServiceCredentials="$(printf "%s" "$DnsServices_Username:$DnsServices_Password" | _base64)"
|
||||
export _H1="Authorization: Basic $DnsServiceCredentials"
|
||||
export _H2="Content-Type: application/json"
|
||||
|
||||
# Just return if headers are set
|
||||
return 0
|
||||
}
|
||||
|
||||
_get_root() {
|
||||
domain="$1"
|
||||
_debug2 _get_root "Get the root domain of ${domain} for DNS API"
|
||||
|
||||
# Setup _get() and _post() headers
|
||||
#_setup_headers
|
||||
|
||||
result=$(_H1="$_H1" _H2="$_H2" _get "$DNSServices_API/dns")
|
||||
result2="$(printf "%s\n" "$result" | tr '[' '\n' | grep '"name"')"
|
||||
result3="$(printf "%s\n" "$result2" | tr '}' '\n' | grep '"name"' | sed "s,^\,,,g" | sed "s,$,},g")"
|
||||
useResult=""
|
||||
_debug2 _get_root "Got the following root domain(s) $result"
|
||||
_debug2 _get_root "- JSON: $result"
|
||||
|
||||
if [ "$(printf "%s\n" "$result" | tr '}' '\n' | grep -c '"name"')" -gt "1" ]; then
|
||||
checkMultiZones="true"
|
||||
_debug2 _get_root "- multiple zones found"
|
||||
else
|
||||
checkMultiZones="false"
|
||||
_debug2 _get_root "- single zone found"
|
||||
fi
|
||||
|
||||
# Find/isolate the root zone to work with in createRecord() and deleteRecord()
|
||||
rootZone=""
|
||||
if [ "$checkMultiZones" = "true" ]; then
|
||||
#rootZone=$(for x in $(printf "%s" "${result3}" | tr ',' '\n' | sed -n 's/.*"name":"\(.*\)",.*/\1/p'); do if [ "$(echo "$domain" | grep "$x")" != "" ]; then echo "$x"; fi; done)
|
||||
rootZone=$(for x in $(printf "%s\n" "${result3}" | tr ',' '\n' | grep name | cut -d'"' -f4); do if [ "$(echo "$domain" | grep "$x")" != "" ]; then echo "$x"; fi; done)
|
||||
if [ "$rootZone" != "" ]; then
|
||||
_debug2 _rootZone "- root zone for $domain is $rootZone"
|
||||
else
|
||||
_err "Could not find root zone for $domain, is it correctly typed?"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
rootZone=$(echo "$result" | tr '}' '\n' | _egrep_o '"name":"[^"]*' | cut -d'"' -f4)
|
||||
_debug2 _get_root "- only found 1 domain in API: $rootZone"
|
||||
fi
|
||||
|
||||
if [ -z "$rootZone" ]; then
|
||||
_err "Could not find root domain for $domain - is it correctly typed?"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Make sure we use the correct API zone data
|
||||
useResult="$(printf "%s\n" "${result3}" tr ',' '\n' | grep "$rootZone")"
|
||||
_debug2 _useResult "useResult=$useResult"
|
||||
|
||||
# Setup variables used by other functions to communicate with DNS.Services API
|
||||
#zoneInfo=$(printf "%s\n" "$useResult" | sed -E 's,.*(zones)(.*),\1\2,g' | sed -E 's,^(.*"name":")([^"]*)"(.*)$,\2,g')
|
||||
zoneInfo=$(printf "%s\n" "$useResult" | tr ',' '\n' | grep '"name"' | cut -d'"' -f4)
|
||||
rootZoneName="$rootZone"
|
||||
subDomainName="$(printf "%s\n" "$domain" | sed "s,\.$rootZone,,g")"
|
||||
subDomainNameClean="$(printf "%s\n" "$domain" | sed "s,_acme-challenge.,,g")"
|
||||
rootZoneDomainID=$(printf "%s\n" "$useResult" | tr ',' '\n' | grep domain_id | cut -d'"' -f4)
|
||||
rootZoneServiceID=$(printf "%s\n" "$useResult" | tr ',' '\n' | grep service_id | cut -d'"' -f4)
|
||||
|
||||
_debug2 _zoneInfo "Zone info from API : $zoneInfo"
|
||||
_debug2 _get_root "Root zone name : $rootZoneName"
|
||||
_debug2 _get_root "Root zone domain ID : $rootZoneDomainID"
|
||||
_debug2 _get_root "Root zone service ID: $rootZoneServiceID"
|
||||
_debug2 _get_root "Sub domain : $subDomainName"
|
||||
|
||||
_debug _get_root "Found valid root domain $rootZone for $subDomainNameClean"
|
||||
return 0
|
||||
}
|
||||
|
||||
createRecord() {
|
||||
fulldomain="$1"
|
||||
txtvalue="$2"
|
||||
|
||||
# Get root domain information - needed for DNS.Services API communication
|
||||
if [ -z "$rootZoneName" ] || [ -z "$rootZoneDomainID" ] || [ -z "$rootZoneServiceID" ]; then
|
||||
_get_root "$fulldomain"
|
||||
fi
|
||||
if [ -z "$rootZoneName" ] || [ -z "$rootZoneDomainID" ] || [ -z "$rootZoneServiceID" ]; then
|
||||
_err "Something happend - could not get the API zone information"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug2 createRecord "CNAME TXT value is: $txtvalue"
|
||||
|
||||
# Prepare data to send to API
|
||||
data="{\"name\":\"${fulldomain}\",\"type\":\"TXT\",\"content\":\"${txtvalue}\", \"ttl\":\"10\"}"
|
||||
|
||||
_debug2 createRecord "data to API: $data"
|
||||
result=$(_post "$data" "$DNSServices_API/service/$rootZoneServiceID/dns/$rootZoneDomainID/records" "" "POST")
|
||||
_debug2 createRecord "result from API: $result"
|
||||
|
||||
if [ "$(echo "$result" | _egrep_o "\"success\":true")" = "" ]; then
|
||||
_err "Failed to create TXT record $fulldomain with content $txtvalue in zone $rootZoneName"
|
||||
_err "$result"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_info "Record \"$fulldomain TXT $txtvalue\" has been created"
|
||||
return 0
|
||||
}
|
||||
|
||||
deleteRecord() {
|
||||
fulldomain="$1"
|
||||
txtvalue="$2"
|
||||
|
||||
_log deleteRecord "Deleting $fulldomain TXT $txtvalue record"
|
||||
|
||||
if [ -z "$rootZoneName" ] || [ -z "$rootZoneDomainID" ] || [ -z "$rootZoneServiceID" ]; then
|
||||
_get_root "$fulldomain"
|
||||
fi
|
||||
|
||||
result="$(_H1="$_H1" _H2="$_H2" _get "$DNSServices_API/service/$rootZoneServiceID/dns/$rootZoneDomainID")"
|
||||
#recordInfo="$(echo "$result" | sed -e 's/:{/:{\n/g' -e 's/},/\n},\n/g' | grep "${txtvalue}")"
|
||||
#recordID="$(echo "$recordInfo" | sed -e 's/:{/:{\n/g' -e 's/},/\n},\n/g' | grep "${txtvalue}" | sed -E 's,.*(zones)(.*),\1\2,g' | sed -E 's,^(.*"id":")([^"]*)"(.*)$,\2,g')"
|
||||
recordID="$(printf "%s\n" "$result" | tr '}' '\n' | grep -- "$txtvalue" | tr ',' '\n' | grep '"id"' | cut -d'"' -f4)"
|
||||
_debug2 _recordID "recordID used for deletion of record: $recordID"
|
||||
|
||||
if [ -z "$recordID" ]; then
|
||||
_info "Record $fulldomain TXT $txtvalue not found or already deleted"
|
||||
return 0
|
||||
else
|
||||
_debug2 deleteRecord "Found recordID=$recordID"
|
||||
fi
|
||||
|
||||
_debug2 deleteRecord "DELETE request $DNSServices_API/service/$rootZoneServiceID/dns/$rootZoneDomainID/records/$recordID"
|
||||
_log "curl DELETE request $DNSServices_API/service/$rootZoneServiceID/dns/$rootZoneDomainID/records/$recordID"
|
||||
result="$(_H1="$_H1" _H2="$_H2" _post "" "$DNSServices_API/service/$rootZoneServiceID/dns/$rootZoneDomainID/records/$recordID" "" "DELETE")"
|
||||
_debug2 deleteRecord "API Delete result \"$result\""
|
||||
_log "curl API Delete result \"$result\""
|
||||
|
||||
# Return OK regardless
|
||||
return 0
|
||||
}
|
||||
148
dnsapi/dns_do.sh
148
dnsapi/dns_do.sh
@@ -1,148 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# DNS API for Domain-Offensive / Resellerinterface / Domainrobot
|
||||
|
||||
# Report bugs at https://github.com/seidler2547/acme.sh/issues
|
||||
|
||||
# set these environment variables to match your customer ID and password:
|
||||
# DO_PID="KD-1234567"
|
||||
# DO_PW="cdfkjl3n2"
|
||||
|
||||
DO_URL="https://soap.resellerinterface.de/"
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_do_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
if _dns_do_authenticate; then
|
||||
_info "Adding TXT record to ${_domain} as ${fulldomain}"
|
||||
_dns_do_soap createRR origin "${_domain}" name "${fulldomain}" type TXT data "${txtvalue}" ttl 300
|
||||
if _contains "${response}" '>success<'; then
|
||||
return 0
|
||||
fi
|
||||
_err "Could not create resource record, check logs"
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
#fulldomain
|
||||
dns_do_rm() {
|
||||
fulldomain=$1
|
||||
if _dns_do_authenticate; then
|
||||
if _dns_do_list_rrs; then
|
||||
_dns_do_had_error=0
|
||||
for _rrid in ${_rr_list}; do
|
||||
_info "Deleting resource record $_rrid for $_domain"
|
||||
_dns_do_soap deleteRR origin "${_domain}" rrid "${_rrid}"
|
||||
if ! _contains "${response}" '>success<'; then
|
||||
_dns_do_had_error=1
|
||||
_err "Could not delete resource record for ${_domain}, id ${_rrid}"
|
||||
fi
|
||||
done
|
||||
return $_dns_do_had_error
|
||||
fi
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
_dns_do_authenticate() {
|
||||
_info "Authenticating as ${DO_PID}"
|
||||
_dns_do_soap authPartner partner "${DO_PID}" password "${DO_PW}"
|
||||
if _contains "${response}" '>success<'; then
|
||||
_get_root "$fulldomain"
|
||||
_debug "_domain $_domain"
|
||||
return 0
|
||||
else
|
||||
_err "Authentication failed, are DO_PID and DO_PW set correctly?"
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
_dns_do_list_rrs() {
|
||||
_dns_do_soap getRRList origin "${_domain}"
|
||||
if ! _contains "${response}" 'SOAP-ENC:Array'; then
|
||||
_err "getRRList origin ${_domain} failed"
|
||||
return 1
|
||||
fi
|
||||
_rr_list="$(echo "${response}" |
|
||||
tr -d "\n\r\t" |
|
||||
sed -e 's/<item xsi:type="ns2:Map">/\n/g' |
|
||||
grep ">$(_regexcape "$fulldomain")</value>" |
|
||||
sed -e 's/<\/item>/\n/g' |
|
||||
grep '>id</key><value' |
|
||||
_egrep_o '>[0-9]{1,16}<' |
|
||||
tr -d '><')"
|
||||
[ "${_rr_list}" ]
|
||||
}
|
||||
|
||||
_dns_do_soap() {
|
||||
func="$1"
|
||||
shift
|
||||
# put the parameters to xml
|
||||
body="<tns:${func} xmlns:tns=\"${DO_URL}\">"
|
||||
while [ "$1" ]; do
|
||||
_k="$1"
|
||||
shift
|
||||
_v="$1"
|
||||
shift
|
||||
body="$body<$_k>$_v</$_k>"
|
||||
done
|
||||
body="$body</tns:${func}>"
|
||||
_debug2 "SOAP request ${body}"
|
||||
|
||||
# build SOAP XML
|
||||
_xml='<?xml version="1.0" encoding="UTF-8"?>
|
||||
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
|
||||
<env:Body>'"$body"'</env:Body>
|
||||
</env:Envelope>'
|
||||
|
||||
# set SOAP headers
|
||||
export _H1="SOAPAction: ${DO_URL}#${func}"
|
||||
|
||||
if ! response="$(_post "${_xml}" "${DO_URL}")"; then
|
||||
_err "Error <$1>"
|
||||
return 1
|
||||
fi
|
||||
_debug2 "SOAP response $response"
|
||||
|
||||
# retrieve cookie header
|
||||
_H2="$(_egrep_o 'Cookie: [^;]+' <"$HTTP_HEADER" | _head_n 1)"
|
||||
export _H2
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
_get_root() {
|
||||
domain=$1
|
||||
i=1
|
||||
|
||||
_dns_do_soap getDomainList
|
||||
_all_domains="$(echo "${response}" |
|
||||
tr -d "\n\r\t " |
|
||||
_egrep_o 'domain</key><value[^>]+>[^<]+' |
|
||||
sed -e 's/^domain<\/key><value[^>]*>//g')"
|
||||
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
if [ -z "$h" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if _contains "${_all_domains}" "^$(_regexcape "$h")\$"; then
|
||||
_domain="$h"
|
||||
return 0
|
||||
fi
|
||||
|
||||
i=$(_math $i + 1)
|
||||
done
|
||||
_debug "$domain not found"
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
_regexcape() {
|
||||
echo "$1" | sed -e 's/\([]\.$*^[]\)/\\\1/g'
|
||||
}
|
||||
@@ -1,12 +1,15 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Official Let's Encrypt API for do.de / Domain-Offensive
|
||||
#
|
||||
# This is different from the dns_do adapter, because dns_do is only usable for enterprise customers
|
||||
# This API is also available to private customers/individuals
|
||||
#
|
||||
# Provide the required LetsEncrypt token like this:
|
||||
# DO_LETOKEN="FmD408PdqT1E269gUK57"
|
||||
# shellcheck disable=SC2034
|
||||
dns_doapi_info='Domain-Offensive do.de
|
||||
Official LetsEncrypt API for do.de / Domain-Offensive.
|
||||
This is different from the dns_do adapter, because dns_do is only usable for enterprise customers.
|
||||
This API is also available to private customers/individuals.
|
||||
Site: do.de
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_doapi
|
||||
Options:
|
||||
DO_LETOKEN LetsEncrypt Token
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2057
|
||||
'
|
||||
|
||||
DO_API="https://www.do.de/api/letsencrypt"
|
||||
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_domeneshop_info='DomeneShop.no
|
||||
Site: DomeneShop.no
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_domeneshop
|
||||
Options:
|
||||
DOMENESHOP_Token Token
|
||||
DOMENESHOP_Secret Secret
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2457
|
||||
'
|
||||
|
||||
DOMENESHOP_Api_Endpoint="https://api.domeneshop.no/v0"
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Dnspod.cn Domain api
|
||||
#
|
||||
#DP_Id="1234"
|
||||
#
|
||||
#DP_Key="sADDsdasdgdsf"
|
||||
# shellcheck disable=SC2034
|
||||
dns_dp_info='DNSPod.cn
|
||||
Site: DNSPod.cn
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_dp
|
||||
Options:
|
||||
DP_Id Id
|
||||
DP_Key Key
|
||||
'
|
||||
|
||||
REST_API="https://dnsapi.cn"
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Dnspod.com Domain api
|
||||
#
|
||||
#DPI_Id="1234"
|
||||
#
|
||||
#DPI_Key="sADDsdasdgdsf"
|
||||
# shellcheck disable=SC2034
|
||||
dns_dpi_info='DNSPod.com
|
||||
Site: DNSPod.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_dpi
|
||||
Options:
|
||||
DPI_Id Id
|
||||
DPI_Key Key
|
||||
'
|
||||
|
||||
REST_API="https://api.dnspod.com"
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_dreamhost_info='DreamHost.com
|
||||
Site: DreamHost.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_dreamhost
|
||||
Options:
|
||||
DH_API_KEY API Key
|
||||
Issues: github.com/RhinoLance/acme.sh
|
||||
Author: RhinoLance
|
||||
'
|
||||
|
||||
#Author: RhinoLance
|
||||
#Report Bugs here: https://github.com/RhinoLance/acme.sh
|
||||
#
|
||||
|
||||
#define the api endpoint
|
||||
DH_API_ENDPOINT="https://api.dreamhost.com/"
|
||||
querystring=""
|
||||
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#Created by RaidenII, to use DuckDNS's API to add/remove text records
|
||||
#06/27/2017
|
||||
|
||||
# Pass credentials before "acme.sh --issue --dns dns_duckdns ..."
|
||||
# --
|
||||
# export DuckDNS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
|
||||
# --
|
||||
#
|
||||
# Due to the fact that DuckDNS uses StartSSL as cert provider, --insecure may need to be used with acme.sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_duckdns_info='DuckDNS.org
|
||||
Site: www.DuckDNS.org
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_duckdns
|
||||
Options:
|
||||
DuckDNS_Token API Token
|
||||
Author: RaidenII
|
||||
'
|
||||
|
||||
DuckDNS_API="https://www.duckdns.org/update"
|
||||
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#DD_API_User="xxxxx"
|
||||
#DD_API_Key="xxxxxx"
|
||||
# shellcheck disable=SC2034
|
||||
dns_durabledns_info='DurableDNS.com
|
||||
Site: DurableDNS.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_durabledns
|
||||
Options:
|
||||
DD_API_User API User
|
||||
DD_API_Key API Key
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2281
|
||||
'
|
||||
|
||||
_DD_BASE="https://durabledns.com/services/dns"
|
||||
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
#!/usr/bin/env sh
|
||||
#
|
||||
# Dyn.com Domain API
|
||||
#
|
||||
# Author: Gerd Naschenweng
|
||||
# https://github.com/magicdude4eva
|
||||
#
|
||||
# shellcheck disable=SC2034
|
||||
dns_dyn_info='Dyn.com
|
||||
Domains: dynect.net
|
||||
Site: Dyn.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_dyn
|
||||
Options:
|
||||
DYN_Customer Customer
|
||||
DYN_Username API Username
|
||||
DYN_Password Secret
|
||||
Author: Gerd Naschenweng <https://github.com/magicdude4eva>
|
||||
'
|
||||
|
||||
# Dyn Managed DNS API
|
||||
# https://help.dyn.com/dns-api-knowledge-base/
|
||||
#
|
||||
@@ -20,13 +26,6 @@
|
||||
# ZoneRemoveNode
|
||||
# ZonePublish
|
||||
# --
|
||||
#
|
||||
# Pass credentials before "acme.sh --issue --dns dns_dyn ..."
|
||||
# --
|
||||
# export DYN_Customer="customer"
|
||||
# export DYN_Username="apiuser"
|
||||
# export DYN_Password="secret"
|
||||
# --
|
||||
|
||||
DYN_API="https://api.dynect.net/REST"
|
||||
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_dynu_info='Dynu.com
|
||||
Site: Dynu.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_dynu
|
||||
Options:
|
||||
Dynu_ClientId Client ID
|
||||
Dynu_Secret Secret
|
||||
Issues: github.com/shar0119/acme.sh
|
||||
Author: Dynu Systems Inc
|
||||
'
|
||||
|
||||
#Client ID
|
||||
#Dynu_ClientId="0b71cae7-a099-4f6b-8ddf-94571cdb760d"
|
||||
#
|
||||
#Secret
|
||||
#Dynu_Secret="aCUEY4BDCV45KI8CSIC3sp2LKQ9"
|
||||
#
|
||||
#Token
|
||||
Dynu_Token=""
|
||||
#
|
||||
#Endpoint
|
||||
Dynu_EndPoint="https://api.dynu.com/v2"
|
||||
#
|
||||
#Author: Dynu Systems, Inc.
|
||||
#Report Bugs here: https://github.com/shar0119/acme.sh
|
||||
#
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
#!/usr/bin/env sh
|
||||
#Author StefanAbl
|
||||
#Usage specify a private keyfile to use with dynv6 'export KEY="path/to/keyfile"'
|
||||
#or use the HTTP REST API by by specifying a token 'export DYNV6_TOKEN="value"
|
||||
#if no keyfile is specified, you will be asked if you want to create one in /home/$USER/.ssh/dynv6 and /home/$USER/.ssh/dynv6.pub
|
||||
# shellcheck disable=SC2034
|
||||
dns_dynv6_info='DynV6.com
|
||||
Site: DynV6.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_dynv6
|
||||
Options:
|
||||
DYNV6_TOKEN REST API token. Get from https://DynV6.com/keys
|
||||
OptionsAlt:
|
||||
KEY Path to SSH private key file. E.g. "/root/.ssh/dynv6"
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2702
|
||||
Author: StefanAbl
|
||||
'
|
||||
|
||||
dynv6_api="https://dynv6.com/api/v2"
|
||||
######## Public functions #####################
|
||||
# Please Read this guide first: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide
|
||||
#Usage: dns_dynv6_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_dynv6_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
fulldomain="$(echo "$1" | _lower_case)"
|
||||
txtvalue="$2"
|
||||
_info "Using dynv6 api"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
@@ -43,8 +50,8 @@ dns_dynv6_add() {
|
||||
#Usage: fulldomain txtvalue
|
||||
#Remove the txt record after validation.
|
||||
dns_dynv6_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
fulldomain="$(echo "$1" | _lower_case)"
|
||||
txtvalue="$2"
|
||||
_info "Using dynv6 API"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
@@ -94,8 +101,8 @@ _get_domain() {
|
||||
_your_hosts="$(echo "$_your_hosts" | awk '/\./ {print $1}')"
|
||||
for l in $_your_hosts; do
|
||||
#echo "host: $l"
|
||||
if test "${_full_domain#*$l}" != "$_full_domain"; then
|
||||
_record="${_full_domain%.$l}"
|
||||
if test "${_full_domain#*"$l"}" != "$_full_domain"; then
|
||||
_record=${_full_domain%."$l"}
|
||||
_host=$l
|
||||
_debug "The host is $_host and the record $_record"
|
||||
return 0
|
||||
@@ -143,7 +150,7 @@ _dns_dynv6_add_http() {
|
||||
return 1
|
||||
fi
|
||||
_get_zone_name "$_zone_id"
|
||||
record="${fulldomain%%.$_zone_name}"
|
||||
record=${fulldomain%%."$_zone_name"}
|
||||
_set_record TXT "$record" "$txtvalue"
|
||||
if _contains "$response" "$txtvalue"; then
|
||||
_info "Successfully added record"
|
||||
@@ -161,7 +168,7 @@ _dns_dynv6_rm_http() {
|
||||
return 1
|
||||
fi
|
||||
_get_zone_name "$_zone_id"
|
||||
record="${fulldomain%%.$_zone_name}"
|
||||
record=${fulldomain%%."$_zone_name"}
|
||||
_get_record_id "$_zone_id" "$record" "$txtvalue"
|
||||
_del_record "$_zone_id" "$_record_id"
|
||||
if [ -z "$response" ]; then
|
||||
@@ -199,7 +206,7 @@ _get_zone_id() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
zone_id="$(echo "$response" | tr '}' '\n' | grep "$selected" | tr ',' '\n' | grep id | tr -d '"')"
|
||||
zone_id="$(echo "$response" | tr '}' '\n' | grep "$selected" | tr ',' '\n' | grep '"id":' | tr -d '"')"
|
||||
_zone_id="${zone_id#id:}"
|
||||
_debug "zone id: $_zone_id"
|
||||
}
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_easydns_info='easyDNS.net
|
||||
Site: easyDNS.net
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_easydns
|
||||
Options:
|
||||
EASYDNS_Token API Token
|
||||
EASYDNS_Key API Key
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2647
|
||||
Author: Neilpang, wurzelpanzer <wurzelpanzer@maximolider.net>
|
||||
'
|
||||
|
||||
#######################################################
|
||||
#
|
||||
# easyDNS REST API for acme.sh by Neilpang based on dns_cf.sh
|
||||
#
|
||||
# API Documentation: https://sandbox.rest.easydns.net:3001/
|
||||
#
|
||||
# Author: wurzelpanzer [wurzelpanzer@maximolider.net]
|
||||
# Report Bugs here: https://github.com/acmesh-official/acme.sh/issues/2647
|
||||
#
|
||||
|
||||
#################### Public functions #################
|
||||
|
||||
#EASYDNS_Key="xxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_edgedns_info='Akamai.com Edge DNS
|
||||
Site: techdocs.Akamai.com/edge-dns/reference/edge-dns-api
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_edgedns
|
||||
Options: Specify individual credentials
|
||||
AKAMAI_HOST Host
|
||||
AKAMAI_ACCESS_TOKEN Access token
|
||||
AKAMAI_CLIENT_TOKEN Client token
|
||||
AKAMAI_CLIENT_SECRET Client secret
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/3157
|
||||
'
|
||||
|
||||
# Akamai Edge DNS v2 API
|
||||
# User must provide Open Edgegrid API credentials to the EdgeDNS installation. The remote user in EdgeDNS must have CRUD access to
|
||||
@@ -6,18 +17,10 @@
|
||||
|
||||
# Report bugs to https://control.akamai.com/apps/support-ui/#/contact-support
|
||||
|
||||
# Values to export:
|
||||
# --EITHER--
|
||||
# *** TBD. NOT IMPLEMENTED YET ***
|
||||
# specify Edgegrid credentials file and section
|
||||
# AKAMAI_EDGERC=<full file path>
|
||||
# AKAMAI_EDGERC_SECTION="default"
|
||||
## --OR--
|
||||
# specify indiviual credentials
|
||||
# export AKAMAI_HOST = <host>
|
||||
# export AKAMAI_ACCESS_TOKEN = <access token>
|
||||
# export AKAMAI_CLIENT_TOKEN = <client token>
|
||||
# export AKAMAI_CLIENT_SECRET = <client secret>
|
||||
# Specify Edgegrid credentials file and section.
|
||||
# AKAMAI_EDGERC Edge RC. Full file path
|
||||
# AKAMAI_EDGERC_SECTION Edge RC Section. E.g. "default"
|
||||
|
||||
ACME_EDGEDNS_VERSION="0.1.0"
|
||||
|
||||
@@ -176,6 +179,7 @@ _EDGEDNS_credentials() {
|
||||
_debug "GettingEdge DNS credentials"
|
||||
_log "$(printf "ACME DNSAPI Edge DNS version %s" ${ACME_EDGEDNS_VERSION})"
|
||||
args_missing=0
|
||||
AKAMAI_ACCESS_TOKEN="${AKAMAI_ACCESS_TOKEN:-$(_readaccountconf_mutable AKAMAI_ACCESS_TOKEN)}"
|
||||
if [ -z "$AKAMAI_ACCESS_TOKEN" ]; then
|
||||
AKAMAI_ACCESS_TOKEN=""
|
||||
AKAMAI_CLIENT_TOKEN=""
|
||||
@@ -184,6 +188,7 @@ _EDGEDNS_credentials() {
|
||||
_err "AKAMAI_ACCESS_TOKEN is missing"
|
||||
args_missing=1
|
||||
fi
|
||||
AKAMAI_CLIENT_TOKEN="${AKAMAI_CLIENT_TOKEN:-$(_readaccountconf_mutable AKAMAI_CLIENT_TOKEN)}"
|
||||
if [ -z "$AKAMAI_CLIENT_TOKEN" ]; then
|
||||
AKAMAI_ACCESS_TOKEN=""
|
||||
AKAMAI_CLIENT_TOKEN=""
|
||||
@@ -192,6 +197,7 @@ _EDGEDNS_credentials() {
|
||||
_err "AKAMAI_CLIENT_TOKEN is missing"
|
||||
args_missing=1
|
||||
fi
|
||||
AKAMAI_HOST="${AKAMAI_HOST:-$(_readaccountconf_mutable AKAMAI_HOST)}"
|
||||
if [ -z "$AKAMAI_HOST" ]; then
|
||||
AKAMAI_ACCESS_TOKEN=""
|
||||
AKAMAI_CLIENT_TOKEN=""
|
||||
@@ -200,6 +206,7 @@ _EDGEDNS_credentials() {
|
||||
_err "AKAMAI_HOST is missing"
|
||||
args_missing=1
|
||||
fi
|
||||
AKAMAI_CLIENT_SECRET="${AKAMAI_CLIENT_SECRET:-$(_readaccountconf_mutable AKAMAI_CLIENT_SECRET)}"
|
||||
if [ -z "$AKAMAI_CLIENT_SECRET" ]; then
|
||||
AKAMAI_ACCESS_TOKEN=""
|
||||
AKAMAI_CLIENT_TOKEN=""
|
||||
@@ -414,7 +421,7 @@ _edgedns_make_data_to_sign() {
|
||||
_secure_debug2 "hdr" "$hdr"
|
||||
_edgedns_make_content_hash
|
||||
path="$(echo "$_request_url_path" | tr -d "\n\r" | sed 's/https\?:\/\///')"
|
||||
path="${path#*$AKAMAI_HOST}"
|
||||
path=${path#*"$AKAMAI_HOST"}
|
||||
_debug "hier path" "$path"
|
||||
# dont expose headers to sign so use MT string
|
||||
_mdata="$(printf "%s\thttps\t%s\t%s\t%s\t%s\t%s" "$_request_method" "$AKAMAI_HOST" "$path" "" "$_hash" "$hdr")"
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#This is the euserv.eu api wrapper for acme.sh
|
||||
#
|
||||
#Author: Michael Brueckner
|
||||
#Report Bugs: https://www.github.com/initit/acme.sh or mbr@initit.de
|
||||
|
||||
#
|
||||
#EUSERV_Username="username"
|
||||
#
|
||||
#EUSERV_Password="password"
|
||||
#
|
||||
# Dependencies:
|
||||
# -------------
|
||||
# - none -
|
||||
# shellcheck disable=SC2034
|
||||
dns_euserv_info='EUserv.com
|
||||
Domains: EUserv.eu
|
||||
Site: EUserv.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_euserv
|
||||
Options:
|
||||
EUSERV_Username Username
|
||||
EUSERV_Password Password
|
||||
Author: Michael Brueckner
|
||||
'
|
||||
|
||||
EUSERV_Api="https://api.euserv.net"
|
||||
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_exoscale_info='Exoscale.com
|
||||
Site: Exoscale.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_exoscale
|
||||
Options:
|
||||
EXOSCALE_API_KEY API Key
|
||||
EXOSCALE_SECRET_KEY API Secret key
|
||||
'
|
||||
|
||||
EXOSCALE_API=https://api.exoscale.com/dns/v1
|
||||
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#Author: Timur Umarov <inbox@tumarov.com>
|
||||
# shellcheck disable=SC2034
|
||||
dns_fornex_info='Fornex.com
|
||||
Site: Fornex.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_fornex
|
||||
Options:
|
||||
FORNEX_API_KEY API Key
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/3998
|
||||
Author: Timur Umarov <inbox@tumarov.com>
|
||||
'
|
||||
|
||||
FORNEX_API_URL="https://fornex.com/api/dns/v0.1"
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_freedns_info='FreeDNS
|
||||
Site: FreeDNS.afraid.org
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_freedns
|
||||
Options:
|
||||
FREEDNS_User Username
|
||||
FREEDNS_Password Password
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2305
|
||||
Author: David Kerr <https://github.com/dkerr64>
|
||||
'
|
||||
|
||||
#This file name is "dns_freedns.sh"
|
||||
#So, here must be a method dns_freedns_add()
|
||||
#Which will be called by acme.sh to add the txt record to your api system.
|
||||
#returns 0 means success, otherwise error.
|
||||
#
|
||||
#Author: David Kerr
|
||||
#Report Bugs here: https://github.com/dkerr64/acme.sh
|
||||
#or here... https://github.com/acmesh-official/acme.sh/issues/2305
|
||||
#
|
||||
######## Public functions #####################
|
||||
|
||||
# Export FreeDNS userid and password in following variables...
|
||||
|
||||
@@ -1,31 +1,42 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_gandi_livedns_info='Gandi.net LiveDNS
|
||||
Site: Gandi.net/domain/dns
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_gandi_livedns
|
||||
Options:
|
||||
GANDI_LIVEDNS_KEY API Key
|
||||
Issues: github.com/fcrozat/acme.sh
|
||||
Author: Frédéric Crozat <fcrozat@suse.com>, Dominik Röttsches <drott@google.com>
|
||||
'
|
||||
|
||||
# Gandi LiveDNS v5 API
|
||||
# http://doc.livedns.gandi.net/
|
||||
# https://api.gandi.net/docs/livedns/
|
||||
# https://api.gandi.net/docs/authentication/ for token + apikey (deprecated) authentication
|
||||
# currently under beta
|
||||
#
|
||||
# Requires GANDI API KEY set in GANDI_LIVEDNS_KEY set as environment variable
|
||||
#
|
||||
#Author: Frédéric Crozat <fcrozat@suse.com>
|
||||
# Dominik Röttsches <drott@google.com>
|
||||
#Report Bugs here: https://github.com/fcrozat/acme.sh
|
||||
#
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
GANDI_LIVEDNS_API="https://dns.api.gandi.net/api/v5"
|
||||
GANDI_LIVEDNS_API="https://api.gandi.net/v5/livedns"
|
||||
|
||||
#Usage: dns_gandi_livedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_gandi_livedns_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
if [ -z "$GANDI_LIVEDNS_KEY" ]; then
|
||||
_err "No API key specified for Gandi LiveDNS."
|
||||
_err "Create your key and export it as GANDI_LIVEDNS_KEY"
|
||||
if [ -z "$GANDI_LIVEDNS_KEY" ] && [ -z "$GANDI_LIVEDNS_TOKEN" ]; then
|
||||
_err "No Token or API key (deprecated) specified for Gandi LiveDNS."
|
||||
_err "Create your token or key and export it as GANDI_LIVEDNS_KEY or GANDI_LIVEDNS_TOKEN respectively"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Keep only one secret in configuration
|
||||
if [ -n "$GANDI_LIVEDNS_TOKEN" ]; then
|
||||
_saveaccountconf GANDI_LIVEDNS_TOKEN "$GANDI_LIVEDNS_TOKEN"
|
||||
_clearaccountconf GANDI_LIVEDNS_KEY
|
||||
elif [ -n "$GANDI_LIVEDNS_KEY" ]; then
|
||||
_saveaccountconf GANDI_LIVEDNS_KEY "$GANDI_LIVEDNS_KEY"
|
||||
_clearaccountconf GANDI_LIVEDNS_TOKEN
|
||||
fi
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
@@ -157,7 +168,12 @@ _gandi_livedns_rest() {
|
||||
_debug "$ep"
|
||||
|
||||
export _H1="Content-Type: application/json"
|
||||
export _H2="X-Api-Key: $GANDI_LIVEDNS_KEY"
|
||||
|
||||
if [ -n "$GANDI_LIVEDNS_TOKEN" ]; then
|
||||
export _H2="Authorization: Bearer $GANDI_LIVEDNS_TOKEN"
|
||||
else
|
||||
export _H2="Authorization: Apikey $GANDI_LIVEDNS_KEY"
|
||||
fi
|
||||
|
||||
if [ "$m" = "GET" ]; then
|
||||
response="$(_get "$GANDI_LIVEDNS_API/$ep")"
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Author: Janos Lenart <janos@lenart.io>
|
||||
# shellcheck disable=SC2034
|
||||
dns_gcloud_info='Google Cloud DNS
|
||||
Site: Cloud.Google.com/dns
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_gcloud
|
||||
Options:
|
||||
CLOUDSDK_ACTIVE_CONFIG_NAME Active config name. E.g. "default"
|
||||
Author: Janos Lenart <janos@lenart.io>
|
||||
'
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
@@ -39,10 +45,10 @@ dns_gcloud_rm() {
|
||||
_dns_gcloud_start_tr || return $?
|
||||
_dns_gcloud_get_rrdatas || return $?
|
||||
echo "$rrdatas" | _dns_gcloud_remove_rrs || return $?
|
||||
echo "$rrdatas" | grep -F -v "\"$txtvalue\"" | _dns_gcloud_add_rrs || return $?
|
||||
echo "$rrdatas" | grep -F -v -- "\"$txtvalue\"" | _dns_gcloud_add_rrs || return $?
|
||||
_dns_gcloud_execute_tr || return $?
|
||||
|
||||
_info "$fulldomain record added"
|
||||
_info "$fulldomain record removed"
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
@@ -98,7 +104,7 @@ _dns_gcloud_remove_rrs() {
|
||||
--ttl="$ttl" \
|
||||
--type=TXT \
|
||||
--zone="$managedZone" \
|
||||
--transaction-file="$tr"; then
|
||||
--transaction-file="$tr" --; then
|
||||
_debug tr "$(cat "$tr")"
|
||||
rm -r "$trd"
|
||||
_err "_dns_gcloud_remove_rrs: failed to remove RRs"
|
||||
@@ -113,7 +119,7 @@ _dns_gcloud_add_rrs() {
|
||||
--ttl="$ttl" \
|
||||
--type=TXT \
|
||||
--zone="$managedZone" \
|
||||
--transaction-file="$tr"; then
|
||||
--transaction-file="$tr" --; then
|
||||
_debug tr "$(cat "$tr")"
|
||||
rm -r "$trd"
|
||||
_err "_dns_gcloud_add_rrs: failed to add RRs"
|
||||
|
||||
191
dnsapi/dns_gcore.sh
Executable file
191
dnsapi/dns_gcore.sh
Executable file
@@ -0,0 +1,191 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_gcore_info='Gcore.com
|
||||
Site: Gcore.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_gcore
|
||||
Options:
|
||||
GCORE_Key API Key
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/4460
|
||||
'
|
||||
|
||||
GCORE_Api="https://api.gcore.com/dns/v2"
|
||||
GCORE_Doc="https://api.gcore.com/docs/dns"
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_gcore_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
GCORE_Key="${GCORE_Key:-$(_readaccountconf_mutable GCORE_Key)}"
|
||||
|
||||
if [ -z "$GCORE_Key" ]; then
|
||||
GCORE_Key=""
|
||||
_err "You didn't specify a Gcore api key yet."
|
||||
_err "You can get yours from here $GCORE_Doc"
|
||||
return 1
|
||||
fi
|
||||
|
||||
#save the api key to the account conf file.
|
||||
_saveaccountconf_mutable GCORE_Key "$GCORE_Key"
|
||||
|
||||
_debug "First detect the zone name"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug _zone_name "$_zone_name"
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_debug "Getting txt records"
|
||||
_gcore_rest GET "zones/$_zone_name/$fulldomain/TXT"
|
||||
payload=""
|
||||
|
||||
if echo "$response" | grep "record is not found" >/dev/null; then
|
||||
_info "Record doesn't exists"
|
||||
payload="{\"resource_records\":[{\"content\":[\"$txtvalue\"],\"enabled\":true}],\"ttl\":120}"
|
||||
elif echo "$response" | grep "$txtvalue" >/dev/null; then
|
||||
_info "Already exists, OK"
|
||||
return 0
|
||||
elif echo "$response" | tr -d " " | grep \"name\":\""$fulldomain"\",\"type\":\"TXT\" >/dev/null; then
|
||||
_info "Record with mismatch txtvalue, try update it"
|
||||
payload=$(echo "$response" | tr -d " " | sed 's/"updated_at":[0-9]\+,//g' | sed 's/"meta":{}}]}/"meta":{}},{"content":['\""$txtvalue"\"'],"enabled":true}]}/')
|
||||
fi
|
||||
|
||||
# For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so
|
||||
# we can not use updating anymore.
|
||||
# count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2)
|
||||
# _debug count "$count"
|
||||
# if [ "$count" = "0" ]; then
|
||||
_info "Adding record"
|
||||
if _gcore_rest PUT "zones/$_zone_name/$fulldomain/TXT" "$payload"; then
|
||||
if _contains "$response" "$txtvalue"; then
|
||||
_info "Added, OK"
|
||||
return 0
|
||||
elif _contains "$response" "rrset is already exists"; then
|
||||
_info "Already exists, OK"
|
||||
return 0
|
||||
else
|
||||
_err "Add txt record error."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
_err "Add txt record error."
|
||||
return 1
|
||||
}
|
||||
|
||||
#fulldomain txtvalue
|
||||
dns_gcore_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
GCORE_Key="${GCORE_Key:-$(_readaccountconf_mutable GCORE_Key)}"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug _zone_name "$_zone_name"
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_debug "Getting txt records"
|
||||
_gcore_rest GET "zones/$_zone_name/$fulldomain/TXT"
|
||||
|
||||
if echo "$response" | grep "record is not found" >/dev/null; then
|
||||
_info "No such txt recrod"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! echo "$response" | tr -d " " | grep \"name\":\""$fulldomain"\",\"type\":\"TXT\" >/dev/null; then
|
||||
_err "Error: $response"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! echo "$response" | tr -d " " | grep \""$txtvalue"\" >/dev/null; then
|
||||
_info "No such txt recrod"
|
||||
return 0
|
||||
fi
|
||||
|
||||
count="$(echo "$response" | grep -o "content" | wc -l)"
|
||||
|
||||
if [ "$count" = "1" ]; then
|
||||
if ! _gcore_rest DELETE "zones/$_zone_name/$fulldomain/TXT"; then
|
||||
_err "Delete record error. $response"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
payload="$(echo "$response" | tr -d " " | sed 's/"updated_at":[0-9]\+,//g' | sed 's/{"id":[0-9]\+,"content":\["'"$txtvalue"'"\],"enabled":true,"meta":{}}//' | sed 's/\[,/\[/' | sed 's/,,/,/' | sed 's/,\]/\]/')"
|
||||
if ! _gcore_rest PUT "zones/$_zone_name/$fulldomain/TXT" "$payload"; then
|
||||
_err "Delete record error. $response"
|
||||
fi
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
#_acme-challenge.sub.domain.com
|
||||
#returns
|
||||
# _sub_domain=_acme-challenge.sub or _acme-challenge
|
||||
# _domain=domain.com
|
||||
# _zone_name=domain.com or sub.domain.com
|
||||
_get_root() {
|
||||
domain=$1
|
||||
i=1
|
||||
p=1
|
||||
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
_debug h "$h"
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _gcore_rest GET "zones/$h"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if _contains "$response" "\"name\":\"$h\""; then
|
||||
_zone_name=$h
|
||||
if [ "$_zone_name" ]; then
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_domain=$h
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
p=$i
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
_gcore_rest() {
|
||||
m=$1
|
||||
ep="$2"
|
||||
data="$3"
|
||||
_debug "$ep"
|
||||
|
||||
key_trimmed=$(echo "$GCORE_Key" | tr -d '"')
|
||||
|
||||
export _H1="Content-Type: application/json"
|
||||
export _H2="Authorization: APIKey $key_trimmed"
|
||||
|
||||
if [ "$m" != "GET" ]; then
|
||||
_debug data "$data"
|
||||
response="$(_post "$data" "$GCORE_Api/$ep" "" "$m")"
|
||||
else
|
||||
response="$(_get "$GCORE_Api/$ep")"
|
||||
fi
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "error $ep"
|
||||
return 1
|
||||
fi
|
||||
_debug2 response "$response"
|
||||
return 0
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#Godaddy domain api
|
||||
#
|
||||
#GD_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
#
|
||||
#GD_Secret="asdfsdfsfsdfsdfdfsdf"
|
||||
# shellcheck disable=SC2034
|
||||
dns_gd_info='GoDaddy.com
|
||||
Site: GoDaddy.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_gd
|
||||
Options:
|
||||
GD_Key API Key
|
||||
GD_Secret API Secret
|
||||
'
|
||||
|
||||
GD_Api="https://api.godaddy.com/v1"
|
||||
|
||||
@@ -20,8 +22,8 @@ dns_gd_add() {
|
||||
if [ -z "$GD_Key" ] || [ -z "$GD_Secret" ]; then
|
||||
GD_Key=""
|
||||
GD_Secret=""
|
||||
_err "You don't specify godaddy api key and secret yet."
|
||||
_err "Please create you key and try again."
|
||||
_err "You didn't specify godaddy api key and secret yet."
|
||||
_err "Please create your key and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -44,14 +46,15 @@ dns_gd_add() {
|
||||
fi
|
||||
|
||||
if _contains "$response" "$txtvalue"; then
|
||||
_info "The record is existing, skip"
|
||||
_info "This record already exists, skipping"
|
||||
return 0
|
||||
fi
|
||||
|
||||
_add_data="{\"data\":\"$txtvalue\"}"
|
||||
for t in $(echo "$response" | tr '{' "\n" | grep "\"name\":\"$_sub_domain\"" | tr ',' "\n" | grep '"data"' | cut -d : -f 2); do
|
||||
_debug2 t "$t"
|
||||
if [ "$t" ]; then
|
||||
# ignore empty (previously removed) records, to prevent useless _acme-challenge TXT entries
|
||||
if [ "$t" ] && [ "$t" != '""' ]; then
|
||||
_add_data="$_add_data,{\"data\":$t}"
|
||||
fi
|
||||
done
|
||||
@@ -59,13 +62,25 @@ dns_gd_add() {
|
||||
|
||||
_info "Adding record"
|
||||
if _gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[$_add_data]"; then
|
||||
_info "Added, sleeping 10 seconds"
|
||||
_sleep 10
|
||||
#todo: check if the record takes effect
|
||||
return 0
|
||||
fi
|
||||
_err "Add txt record error."
|
||||
_debug "Checking updated records of '${fulldomain}'"
|
||||
|
||||
if ! _gd_rest GET "domains/$_domain/records/TXT/$_sub_domain"; then
|
||||
_err "Validating TXT record for '${fulldomain}' with rest error [$?]." "$response"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _contains "$response" "$txtvalue"; then
|
||||
_err "TXT record '${txtvalue}' for '${fulldomain}', value wasn't set!"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
_err "Add txt record error, value '${txtvalue}' for '${fulldomain}' was not set."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_sleep 10
|
||||
_info "Added TXT record '${txtvalue}' for '${fulldomain}'."
|
||||
return 0
|
||||
}
|
||||
|
||||
#fulldomain
|
||||
@@ -107,11 +122,20 @@ dns_gd_rm() {
|
||||
fi
|
||||
done
|
||||
if [ -z "$_add_data" ]; then
|
||||
_add_data="{\"data\":\"\"}"
|
||||
# delete empty record
|
||||
_debug "Delete last record for '${fulldomain}'"
|
||||
if ! _gd_rest DELETE "domains/$_domain/records/TXT/$_sub_domain"; then
|
||||
_err "Cannot delete empty TXT record for '$fulldomain'"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
# remove specific TXT value, keeping other entries
|
||||
_debug2 _add_data "$_add_data"
|
||||
|
||||
_gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[$_add_data]"
|
||||
if ! _gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[$_add_data]"; then
|
||||
_err "Cannot update TXT record for '$fulldomain'"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
@@ -156,15 +180,15 @@ _gd_rest() {
|
||||
export _H1="Authorization: sso-key $GD_Key:$GD_Secret"
|
||||
export _H2="Content-Type: application/json"
|
||||
|
||||
if [ "$data" ]; then
|
||||
_debug data "$data"
|
||||
if [ "$data" ] || [ "$m" = "DELETE" ]; then
|
||||
_debug "data ($m): " "$data"
|
||||
response="$(_post "$data" "$GD_Api/$ep" "" "$m")"
|
||||
else
|
||||
response="$(_get "$GD_Api/$ep")"
|
||||
fi
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "error $ep"
|
||||
_err "error on rest call ($m): $ep"
|
||||
return 1
|
||||
fi
|
||||
_debug2 response "$response"
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
########################################################################
|
||||
# Geoscaling hook script for acme.sh
|
||||
#
|
||||
# Environment variables:
|
||||
#
|
||||
# - $GEOSCALING_Username (your Geoscaling username - this is usually NOT an amail address)
|
||||
# - $GEOSCALING_Password (your Geoscaling password)
|
||||
# shellcheck disable=SC2034
|
||||
dns_geoscaling_info='GeoScaling.com
|
||||
Site: GeoScaling.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_geoscaling
|
||||
Options:
|
||||
GEOSCALING_Username Username. This is usually NOT an email address
|
||||
GEOSCALING_Password Password
|
||||
'
|
||||
|
||||
#-- dns_geoscaling_add() - Add TXT record --------------------------------------
|
||||
# Usage: dns_geoscaling_add _acme-challenge.subdomain.domain.com "XyZ123..."
|
||||
|
||||
178
dnsapi/dns_googledomains.sh
Executable file
178
dnsapi/dns_googledomains.sh
Executable file
@@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_googledomains_info='Google Domains
|
||||
Site: Domains.Google.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_googledomains
|
||||
Options:
|
||||
GOOGLEDOMAINS_ACCESS_TOKEN API Access Token
|
||||
GOOGLEDOMAINS_ZONE Zone
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/4545
|
||||
Author: Alex Leigh <leigh@alexleigh.me>
|
||||
'
|
||||
|
||||
GOOGLEDOMAINS_API="https://acmedns.googleapis.com/v1/acmeChallengeSets"
|
||||
|
||||
######## Public functions ########
|
||||
|
||||
#Usage: dns_googledomains_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_googledomains_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
_info "Invoking Google Domains ACME DNS API."
|
||||
|
||||
if ! _dns_googledomains_setup; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
zone="$(_dns_googledomains_get_zone "$fulldomain")"
|
||||
if [ -z "$zone" ]; then
|
||||
_err "Could not find a Google Domains-managed zone containing the requested domain."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug zone "$zone"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
_info "Adding TXT record for $fulldomain."
|
||||
if _dns_googledomains_api "$zone" ":rotateChallenges" "{\"accessToken\":\"$GOOGLEDOMAINS_ACCESS_TOKEN\",\"recordsToAdd\":[{\"fqdn\":\"$fulldomain\",\"digest\":\"$txtvalue\"}],\"keepExpiredRecords\":true}"; then
|
||||
if _contains "$response" "$txtvalue"; then
|
||||
_info "TXT record added."
|
||||
return 0
|
||||
else
|
||||
_err "Error adding TXT record."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
_err "Error adding TXT record."
|
||||
return 1
|
||||
}
|
||||
|
||||
#Usage: dns_googledomains_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_googledomains_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
_info "Invoking Google Domains ACME DNS API."
|
||||
|
||||
if ! _dns_googledomains_setup; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
zone="$(_dns_googledomains_get_zone "$fulldomain")"
|
||||
if [ -z "$zone" ]; then
|
||||
_err "Could not find a Google Domains-managed domain based on request."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug zone "$zone"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
_info "Removing TXT record for $fulldomain."
|
||||
if _dns_googledomains_api "$zone" ":rotateChallenges" "{\"accessToken\":\"$GOOGLEDOMAINS_ACCESS_TOKEN\",\"recordsToRemove\":[{\"fqdn\":\"$fulldomain\",\"digest\":\"$txtvalue\"}],\"keepExpiredRecords\":true}"; then
|
||||
if _contains "$response" "$txtvalue"; then
|
||||
_err "Error removing TXT record."
|
||||
return 1
|
||||
else
|
||||
_info "TXT record removed."
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
_err "Error removing TXT record."
|
||||
return 1
|
||||
}
|
||||
|
||||
######## Private functions ########
|
||||
|
||||
_dns_googledomains_setup() {
|
||||
if [ -n "$GOOGLEDOMAINS_SETUP_COMPLETED" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
GOOGLEDOMAINS_ACCESS_TOKEN="${GOOGLEDOMAINS_ACCESS_TOKEN:-$(_readaccountconf_mutable GOOGLEDOMAINS_ACCESS_TOKEN)}"
|
||||
GOOGLEDOMAINS_ZONE="${GOOGLEDOMAINS_ZONE:-$(_readaccountconf_mutable GOOGLEDOMAINS_ZONE)}"
|
||||
|
||||
if [ -z "$GOOGLEDOMAINS_ACCESS_TOKEN" ]; then
|
||||
GOOGLEDOMAINS_ACCESS_TOKEN=""
|
||||
_err "Google Domains access token was not specified."
|
||||
_err "Please visit Google Domains Security settings to provision an ACME DNS API access token."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$GOOGLEDOMAINS_ZONE" ]; then
|
||||
_savedomainconf GOOGLEDOMAINS_ACCESS_TOKEN "$GOOGLEDOMAINS_ACCESS_TOKEN"
|
||||
_savedomainconf GOOGLEDOMAINS_ZONE "$GOOGLEDOMAINS_ZONE"
|
||||
else
|
||||
_saveaccountconf_mutable GOOGLEDOMAINS_ACCESS_TOKEN "$GOOGLEDOMAINS_ACCESS_TOKEN"
|
||||
_clearaccountconf_mutable GOOGLEDOMAINS_ZONE
|
||||
_clearaccountconf GOOGLEDOMAINS_ZONE
|
||||
fi
|
||||
|
||||
_debug GOOGLEDOMAINS_ACCESS_TOKEN "$GOOGLEDOMAINS_ACCESS_TOKEN"
|
||||
_debug GOOGLEDOMAINS_ZONE "$GOOGLEDOMAINS_ZONE"
|
||||
|
||||
GOOGLEDOMAINS_SETUP_COMPLETED=1
|
||||
return 0
|
||||
}
|
||||
|
||||
_dns_googledomains_get_zone() {
|
||||
domain=$1
|
||||
|
||||
# Use zone directly if provided
|
||||
if [ "$GOOGLEDOMAINS_ZONE" ]; then
|
||||
if ! _dns_googledomains_api "$GOOGLEDOMAINS_ZONE"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "$GOOGLEDOMAINS_ZONE"
|
||||
return 0
|
||||
fi
|
||||
|
||||
i=2
|
||||
while true; do
|
||||
curr=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
_debug curr "$curr"
|
||||
|
||||
if [ -z "$curr" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if _dns_googledomains_api "$curr"; then
|
||||
echo "$curr"
|
||||
return 0
|
||||
fi
|
||||
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
_dns_googledomains_api() {
|
||||
zone=$1
|
||||
apimethod=$2
|
||||
data="$3"
|
||||
|
||||
if [ -z "$data" ]; then
|
||||
response="$(_get "$GOOGLEDOMAINS_API/$zone$apimethod")"
|
||||
else
|
||||
_debug data "$data"
|
||||
export _H1="Content-Type: application/json"
|
||||
response="$(_post "$data" "$GOOGLEDOMAINS_API/$zone$apimethod")"
|
||||
fi
|
||||
|
||||
_debug response "$response"
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "Error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if _contains "$response" "\"error\": {"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
########################################################################
|
||||
# Hurricane Electric hook script for acme.sh
|
||||
#
|
||||
# Environment variables:
|
||||
#
|
||||
# - $HE_Username (your dns.he.net username)
|
||||
# - $HE_Password (your dns.he.net password)
|
||||
#
|
||||
# Author: Ondrej Simek <me@ondrejsimek.com>
|
||||
# Git repo: https://github.com/angel333/acme.sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_he_info='Hurricane Electric HE.net
|
||||
Site: dns.he.net
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_he
|
||||
Options:
|
||||
HE_Username Username
|
||||
HE_Password Password
|
||||
Issues: github.com/angel333/acme.sh/issues/
|
||||
Author: Ondrej Simek <me@ondrejsimek.com>
|
||||
'
|
||||
|
||||
#-- dns_he_add() - Add TXT record --------------------------------------
|
||||
# Usage: dns_he_add _acme-challenge.subdomain.domain.com "XyZ123..."
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
#HETZNER_Token="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
#
|
||||
# shellcheck disable=SC2034
|
||||
dns_hetzner_info='Hetzner.com
|
||||
Site: Hetzner.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_hetzner
|
||||
Options:
|
||||
HETZNER_Token API Token
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2943
|
||||
'
|
||||
|
||||
HETZNER_Api="https://dns.hetzner.com/api/v1"
|
||||
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Hexonet_Login="username!roleId"
|
||||
#
|
||||
# Hexonet_Password="rolePassword"
|
||||
# shellcheck disable=SC2034
|
||||
dns_hexonet_info='Hexonet.com
|
||||
Site: Hexonet.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_hexonet
|
||||
Options:
|
||||
Hexonet_Login Login. E.g. "username!roleId"
|
||||
Hexonet_Password Role Password
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2389
|
||||
'
|
||||
|
||||
Hexonet_Api="https://coreapi.1api.net/api/call.cgi"
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# hosting.de API
|
||||
|
||||
# Values to export:
|
||||
# export HOSTINGDE_ENDPOINT='https://secure.hosting.de'
|
||||
# export HOSTINGDE_APIKEY='xxxxx'
|
||||
# shellcheck disable=SC2034
|
||||
dns_hostingde_info='Hosting.de
|
||||
Site: Hosting.de
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_hostingde
|
||||
Options:
|
||||
HOSTINGDE_ENDPOINT Endpoint. E.g. "https://secure.hosting.de"
|
||||
HOSTINGDE_APIKEY API Key
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2058
|
||||
'
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# HUAWEICLOUD_Username
|
||||
# HUAWEICLOUD_Password
|
||||
# HUAWEICLOUD_ProjectID
|
||||
# shellcheck disable=SC2034
|
||||
dns_huaweicloud_info='HuaweiCloud.com
|
||||
Site: HuaweiCloud.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_huaweicloud
|
||||
Options:
|
||||
HUAWEICLOUD_Username Username
|
||||
HUAWEICLOUD_Password Password
|
||||
HUAWEICLOUD_DomainName DomainName
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/3265
|
||||
'
|
||||
|
||||
iam_api="https://iam.myhuaweicloud.com"
|
||||
dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" # Should work
|
||||
@@ -14,6 +20,8 @@ dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" # Should work
|
||||
#
|
||||
# Ref: https://support.huaweicloud.com/intl/zh-cn/api-dns/zh-cn_topic_0132421999.html
|
||||
#
|
||||
# About "DomainName" parameters see: https://support.huaweicloud.com/api-iam/iam_01_0006.html
|
||||
#
|
||||
|
||||
dns_huaweicloud_add() {
|
||||
fulldomain=$1
|
||||
@@ -21,16 +29,16 @@ dns_huaweicloud_add() {
|
||||
|
||||
HUAWEICLOUD_Username="${HUAWEICLOUD_Username:-$(_readaccountconf_mutable HUAWEICLOUD_Username)}"
|
||||
HUAWEICLOUD_Password="${HUAWEICLOUD_Password:-$(_readaccountconf_mutable HUAWEICLOUD_Password)}"
|
||||
HUAWEICLOUD_ProjectID="${HUAWEICLOUD_ProjectID:-$(_readaccountconf_mutable HUAWEICLOUD_ProjectID)}"
|
||||
HUAWEICLOUD_DomainName="${HUAWEICLOUD_DomainName:-$(_readaccountconf_mutable HUAWEICLOUD_DomainName)}"
|
||||
|
||||
# Check information
|
||||
if [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Password}" ] || [ -z "${HUAWEICLOUD_ProjectID}" ]; then
|
||||
if [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Password}" ] || [ -z "${HUAWEICLOUD_DomainName}" ]; then
|
||||
_err "Not enough information provided to dns_huaweicloud!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
unset token # Clear token
|
||||
token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")"
|
||||
token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_DomainName}")"
|
||||
if [ -z "${token}" ]; then # Check token
|
||||
_err "dns_api(dns_huaweicloud): Error getting token."
|
||||
return 1
|
||||
@@ -56,7 +64,7 @@ dns_huaweicloud_add() {
|
||||
# Do saving work if all succeeded
|
||||
_saveaccountconf_mutable HUAWEICLOUD_Username "${HUAWEICLOUD_Username}"
|
||||
_saveaccountconf_mutable HUAWEICLOUD_Password "${HUAWEICLOUD_Password}"
|
||||
_saveaccountconf_mutable HUAWEICLOUD_ProjectID "${HUAWEICLOUD_ProjectID}"
|
||||
_saveaccountconf_mutable HUAWEICLOUD_DomainName "${HUAWEICLOUD_DomainName}"
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -72,16 +80,16 @@ dns_huaweicloud_rm() {
|
||||
|
||||
HUAWEICLOUD_Username="${HUAWEICLOUD_Username:-$(_readaccountconf_mutable HUAWEICLOUD_Username)}"
|
||||
HUAWEICLOUD_Password="${HUAWEICLOUD_Password:-$(_readaccountconf_mutable HUAWEICLOUD_Password)}"
|
||||
HUAWEICLOUD_ProjectID="${HUAWEICLOUD_ProjectID:-$(_readaccountconf_mutable HUAWEICLOUD_ProjectID)}"
|
||||
HUAWEICLOUD_DomainName="${HUAWEICLOUD_DomainName:-$(_readaccountconf_mutable HUAWEICLOUD_DomainName)}"
|
||||
|
||||
# Check information
|
||||
if [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Password}" ] || [ -z "${HUAWEICLOUD_ProjectID}" ]; then
|
||||
if [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Password}" ] || [ -z "${HUAWEICLOUD_DomainName}" ]; then
|
||||
_err "Not enough information provided to dns_huaweicloud!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
unset token # Clear token
|
||||
token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")"
|
||||
token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_DomainName}")"
|
||||
if [ -z "${token}" ]; then # Check token
|
||||
_err "dns_api(dns_huaweicloud): Error getting token."
|
||||
return 1
|
||||
@@ -96,19 +104,59 @@ dns_huaweicloud_rm() {
|
||||
fi
|
||||
_debug "Zone ID is:" "${zoneid}"
|
||||
|
||||
# Remove all records
|
||||
# Therotically HuaweiCloud does not allow more than one record set
|
||||
# But remove them recurringly to increase robusty
|
||||
while [ "${record_id}" != "0" ]; do
|
||||
_debug "Removing Record"
|
||||
_rm_record "${token}" "${zoneid}" "${record_id}"
|
||||
record_id="$(_get_recordset_id "${token}" "${fulldomain}" "${zoneid}")"
|
||||
done
|
||||
_recursive_rm_record "${token}" "${fulldomain}" "${zoneid}" "${record_id}"
|
||||
ret="$?"
|
||||
if [ "${ret}" != "0" ]; then
|
||||
_err "dns_api(dns_huaweicloud): Error removing record."
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
################### Private functions below ##################################
|
||||
|
||||
# _recursive_rm_record
|
||||
# remove all records from the record set
|
||||
#
|
||||
# _token=$1
|
||||
# _domain=$2
|
||||
# _zoneid=$3
|
||||
# _record_id=$4
|
||||
#
|
||||
# Returns 0 on success
|
||||
_recursive_rm_record() {
|
||||
_token=$1
|
||||
_domain=$2
|
||||
_zoneid=$3
|
||||
_record_id=$4
|
||||
|
||||
# Most likely to have problems will huaweicloud side if more than 50 attempts but still cannot fully remove the record set
|
||||
# Maybe can be removed manually in the dashboard
|
||||
_retry_cnt=50
|
||||
|
||||
# Remove all records
|
||||
# Therotically HuaweiCloud does not allow more than one record set
|
||||
# But remove them recurringly to increase robusty
|
||||
|
||||
while [ "${_record_id}" != "0" ] && [ "${_retry_cnt}" != "0" ]; do
|
||||
_debug "Removing Record"
|
||||
_retry_cnt=$((_retry_cnt - 1))
|
||||
_rm_record "${_token}" "${_zoneid}" "${_record_id}"
|
||||
_record_id="$(_get_recordset_id "${_token}" "${_domain}" "${_zoneid}")"
|
||||
_debug2 "Checking record exists: record_id=${_record_id}"
|
||||
done
|
||||
|
||||
# Check if retry count is reached
|
||||
if [ "${_retry_cnt}" = "0" ]; then
|
||||
_debug "Failed to remove record after 50 attempts, please try removing it manually in the dashboard"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# _get_zoneid
|
||||
#
|
||||
# _token=$1
|
||||
@@ -122,7 +170,7 @@ _get_zoneid() {
|
||||
|
||||
i=1
|
||||
while true; do
|
||||
h=$(printf "%s" "${_domain_string}" | cut -d . -f $i-100)
|
||||
h=$(printf "%s" "${_domain_string}" | cut -d . -f "$i"-100)
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
@@ -133,11 +181,11 @@ _get_zoneid() {
|
||||
if _contains "${response}" '"id"'; then
|
||||
zoneidlist=$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")
|
||||
zonenamelist=$(echo "${response}" | _egrep_o "\"name\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")
|
||||
_debug2 "Return Zone ID(s):" "${zoneidlist}"
|
||||
_debug2 "Return Zone Name(s):" "${zonenamelist}"
|
||||
_debug2 "Returned Zone ID(s):" "${zoneidlist}"
|
||||
_debug2 "Returned Zone Name(s):" "${zonenamelist}"
|
||||
zoneidnum=0
|
||||
zoneidcount=$(echo "${zoneidlist}" | grep -c '^')
|
||||
_debug "Retund Zone ID(s) Count:" "${zoneidcount}"
|
||||
_debug "Returned Zone ID(s) Count:" "${zoneidcount}"
|
||||
while [ "${zoneidnum}" -lt "${zoneidcount}" ]; do
|
||||
zoneidnum=$(_math "$zoneidnum" + 1)
|
||||
_zoneid=$(echo "${zoneidlist}" | sed -n "${zoneidnum}p")
|
||||
@@ -162,7 +210,7 @@ _get_recordset_id() {
|
||||
_zoneid=$3
|
||||
export _H1="X-Auth-Token: ${_token}"
|
||||
|
||||
response=$(_get "${dns_api}/v2/zones/${_zoneid}/recordsets?name=${_domain}")
|
||||
response=$(_get "${dns_api}/v2/zones/${_zoneid}/recordsets?name=${_domain}&status=ACTIVE")
|
||||
if _contains "${response}" '"id"'; then
|
||||
_id="$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")"
|
||||
printf "%s" "${_id}"
|
||||
@@ -179,7 +227,7 @@ _add_record() {
|
||||
|
||||
# Get Existing Records
|
||||
export _H1="X-Auth-Token: ${_token}"
|
||||
response=$(_get "${dns_api}/v2/zones/${zoneid}/recordsets?name=${_domain}")
|
||||
response=$(_get "${dns_api}/v2/zones/${zoneid}/recordsets?name=${_domain}&status=ACTIVE")
|
||||
|
||||
_debug2 "${response}"
|
||||
_exist_record=$(echo "${response}" | _egrep_o '"records":[^]]*' | sed 's/\"records\"\:\[//g')
|
||||
@@ -204,8 +252,7 @@ _add_record() {
|
||||
\"type\": \"TXT\",
|
||||
\"ttl\": 1,
|
||||
\"records\": [
|
||||
${_exist_record},
|
||||
\"\\\"${_txtvalue}\\\"\"
|
||||
${_exist_record},\"\\\"${_txtvalue}\\\"\"
|
||||
]
|
||||
}"
|
||||
fi
|
||||
@@ -213,19 +260,16 @@ _add_record() {
|
||||
_record_id="$(_get_recordset_id "${_token}" "${_domain}" "${zoneid}")"
|
||||
_debug "Record Set ID is:" "${_record_id}"
|
||||
|
||||
# Remove all records
|
||||
while [ "${_record_id}" != "0" ]; do
|
||||
_debug "Removing Record"
|
||||
_rm_record "${_token}" "${zoneid}" "${_record_id}"
|
||||
_record_id="$(_get_recordset_id "${_token}" "${_domain}" "${zoneid}")"
|
||||
done
|
||||
|
||||
# Add brand new records with all old and new records
|
||||
export _H2="Content-Type: application/json"
|
||||
export _H1="X-Auth-Token: ${_token}"
|
||||
|
||||
_debug2 "${_post_body}"
|
||||
if [ -z "${_exist_record}" ]; then
|
||||
_post "${_post_body}" "${dns_api}/v2/zones/${zoneid}/recordsets" >/dev/null
|
||||
else
|
||||
_post "${_post_body}" "${dns_api}/v2/zones/${zoneid}/recordsets/${_record_id}" false "PUT" >/dev/null
|
||||
fi
|
||||
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")"
|
||||
if [ "$_code" != "202" ]; then
|
||||
_err "dns_huaweicloud: http code ${_code}"
|
||||
@@ -253,7 +297,7 @@ _rm_record() {
|
||||
_get_token() {
|
||||
_username=$1
|
||||
_password=$2
|
||||
_project=$3
|
||||
_domain_name=$3
|
||||
|
||||
_debug "Getting Token"
|
||||
body="{
|
||||
@@ -267,14 +311,14 @@ _get_token() {
|
||||
\"name\": \"${_username}\",
|
||||
\"password\": \"${_password}\",
|
||||
\"domain\": {
|
||||
\"name\": \"${_username}\"
|
||||
\"name\": \"${_domain_name}\"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
\"scope\": {
|
||||
\"project\": {
|
||||
\"id\": \"${_project}\"
|
||||
\"name\": \"ap-southeast-1\"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user