mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-07-13 01:31:43 +02:00
Compare commits
51 Commits
Author | SHA1 | Date | |
---|---|---|---|
fe48a9a0c3 | |||
ec973eb3bc | |||
7b69b5fa63 | |||
ce4f46cb50 | |||
3454a9b975 | |||
55bc939a37 | |||
1d63b679dc | |||
3df96350a3 | |||
34fab7b3d0 | |||
46817d0664 | |||
1db2ca61fa | |||
0b601406de | |||
b4c771cdee | |||
a486d42351 | |||
90c2199a1b | |||
161c61fac7 | |||
5ffacb1d06 | |||
75ebd0ffbe | |||
dc069f3c57 | |||
e1b512f78f | |||
8854a38f49 | |||
7583a4628c | |||
73c0ea0896 | |||
7dad7c7305 | |||
faa95b4e21 | |||
cb0e13976d | |||
ccd8dcff56 | |||
750656fd7f | |||
d9f515fdba | |||
176249a7d9 | |||
e2a449a7bc | |||
a9695e969e | |||
7ba997dfc2 | |||
d00117e878 | |||
43a84a3f1c | |||
e24f31bdef | |||
fc9240fbac | |||
e0f5431215 | |||
de658a3c6c | |||
73276b1918 | |||
abdb7d4d75 | |||
72299ace15 | |||
4d6c79f51b | |||
2c045f4f40 | |||
b8cf046ca6 | |||
026dd6b89d | |||
5805fe6ed2 | |||
3c78211800 | |||
8e648a8e1f | |||
a000893dd1 | |||
db88bfb752 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -32,3 +32,5 @@ src/README.md
|
|||||||
docker/ContainerTester.sh
|
docker/ContainerTester.sh
|
||||||
docker/ImagePublisher.sh
|
docker/ImagePublisher.sh
|
||||||
src/mod/acme/test/stackoverflow.pem
|
src/mod/acme/test/stackoverflow.pem
|
||||||
|
/tools/dns_challenge_update/code-gen/acmedns
|
||||||
|
/tools/dns_challenge_update/code-gen/lego
|
||||||
|
40
CHANGELOG.md
40
CHANGELOG.md
@ -1,3 +1,43 @@
|
|||||||
|
# v3.0.3 Apr 30 2024
|
||||||
|
## Breaking Change
|
||||||
|
|
||||||
|
For users using SMTP with older versions, you might need to update the settings by moving the domains (the part after @ in the username and domain setup field) into the username field.
|
||||||
|
|
||||||
|
+ Updated SMTP UI for non email login username [#129](https://github.com/tobychui/zoraxy/issues/129)
|
||||||
|
+ Fixed ACME cert store reload after cert request [#126](https://github.com/tobychui/zoraxy/issues/126)
|
||||||
|
+ Fixed default rule not applying to default site when default site is set to proxy target [#130](https://github.com/tobychui/zoraxy/issues/130)
|
||||||
|
+ Fixed blacklist-ip not working with CIDR bug
|
||||||
|
+ Fixed minor vdir bug in tailing slash detection and redirect logic
|
||||||
|
+ Added custom mdns name support (-mdnsname flag)
|
||||||
|
+ Added LAN tag in statistic [#131](https://github.com/tobychui/zoraxy/issues/131)
|
||||||
|
|
||||||
|
|
||||||
|
# v3.0.2 Apr 24 2024
|
||||||
|
|
||||||
|
+ Added alias for HTTP proxy host names [#76](https://github.com/tobychui/zoraxy/issues/76)
|
||||||
|
+ Added separator support for create new proxy rules (use "," to add alias when creating new proxy rule)
|
||||||
|
+ Added HTTP proxy host based access rules [#69](https://github.com/tobychui/zoraxy/issues/69)
|
||||||
|
+ Added EAD Configuration for ACME (by [yeungalan](https://github.com/yeungalan)) [#45](https://github.com/tobychui/zoraxy/issues/45)
|
||||||
|
+ Fixed bug for bypassGlobalTLS endpoint do not support basic-auth
|
||||||
|
+ Fixed panic due to empty domain field in json config [#120](https://github.com/tobychui/zoraxy/issues/120)
|
||||||
|
+ Removed dependencies on management panel css for online font files
|
||||||
|
|
||||||
|
# v3.0.1 Apr 04 2024
|
||||||
|
|
||||||
|
## Bugfixupdate for big release of V3, read update notes from V3 if you are still on V2
|
||||||
|
|
||||||
|
+ Added regex support for redirect (slow, don't use it unless you really needs it) [#42](https://github.com/tobychui/zoraxy/issues/42)
|
||||||
|
+ Added new dpcore implementations for faster proxy speed
|
||||||
|
+ Added support for CF-Connecting-IP to X-Real-IP auto rewrite [#114](https://github.com/tobychui/zoraxy/issues/114)
|
||||||
|
+ Added enable / disable of HTTP proxy rules in runtime via slider [#108](https://github.com/tobychui/zoraxy/issues/108)
|
||||||
|
+ Added better 404 page
|
||||||
|
+ Added option to bypass websocket origin check [#107](https://github.com/tobychui/zoraxy/issues/107)
|
||||||
|
+ Updated project homepage design
|
||||||
|
+ Fixed recursive port detection logic
|
||||||
|
+ Fixed UserAgent in resp bug
|
||||||
|
+ Updated minimum required Go version to v1.22 (Notes: Windows 7 support is dropped) [#112](https://github.com/tobychui/zoraxy/issues/112)
|
||||||
|
|
||||||
|
|
||||||
# v3.0.0 Feb 18 2024
|
# v3.0.0 Feb 18 2024
|
||||||
|
|
||||||
## IMPORTANT: V3 is a big rewrite and it is incompatible with V2! There is NO migration, if you want to stay on V2, please use V2 branch!
|
## IMPORTANT: V3 is a big rewrite and it is incompatible with V2! There is NO migration, if you want to stay on V2, please use V2 branch!
|
||||||
|
22
README.md
22
README.md
@ -9,15 +9,16 @@ General purpose request (reverse) proxy and forwarding tool for networking noobs
|
|||||||
### Features
|
### Features
|
||||||
|
|
||||||
- Simple to use interface with detail in-system instructions
|
- Simple to use interface with detail in-system instructions
|
||||||
- Reverse Proxy
|
- Reverse Proxy (HTTP/2)
|
||||||
- Virtual Directory
|
- Virtual Directory
|
||||||
|
- WebSocket Proxy (automatic, no set-up needed)
|
||||||
- Basic Auth
|
- Basic Auth
|
||||||
|
- Alias Hostnames
|
||||||
- Custom Headers
|
- Custom Headers
|
||||||
- Redirection Rules
|
- Redirection Rules
|
||||||
- TLS / SSL setup and deploy
|
- TLS / SSL setup and deploy
|
||||||
- ACME features like auto-renew to serve your sites in http**s**
|
- ACME features like auto-renew to serve your sites in http**s**
|
||||||
- SNI support (one certificate contains multiple host names)
|
- SNI support (and SAN certs)
|
||||||
|
|
||||||
- Blacklist / Whitelist by country or IP address (single IP, CIDR or wildcard for beginners)
|
- Blacklist / Whitelist by country or IP address (single IP, CIDR or wildcard for beginners)
|
||||||
- Global Area Network Controller Web UI (ZeroTier not included)
|
- Global Area Network Controller Web UI (ZeroTier not included)
|
||||||
- TCP Tunneling / Proxy
|
- TCP Tunneling / Proxy
|
||||||
@ -33,6 +34,7 @@ General purpose request (reverse) proxy and forwarding tool for networking noobs
|
|||||||
- SMTP config for password reset
|
- SMTP config for password reset
|
||||||
|
|
||||||
## Downloads
|
## Downloads
|
||||||
|
|
||||||
[Windows](https://github.com/tobychui/zoraxy/releases/latest/download/zoraxy_windows_amd64.exe)
|
[Windows](https://github.com/tobychui/zoraxy/releases/latest/download/zoraxy_windows_amd64.exe)
|
||||||
/[Linux (amd64)](https://github.com/tobychui/zoraxy/releases/latest/download/zoraxy_linux_amd64)
|
/[Linux (amd64)](https://github.com/tobychui/zoraxy/releases/latest/download/zoraxy_linux_amd64)
|
||||||
/[Linux (arm64)](https://github.com/tobychui/zoraxy/releases/latest/download/zoraxy_linux_arm64)
|
/[Linux (arm64)](https://github.com/tobychui/zoraxy/releases/latest/download/zoraxy_linux_arm64)
|
||||||
@ -40,6 +42,7 @@ General purpose request (reverse) proxy and forwarding tool for networking noobs
|
|||||||
For other systems or architectures, please see [Release](https://github.com/tobychui/zoraxy/releases/latest/)
|
For other systems or architectures, please see [Release](https://github.com/tobychui/zoraxy/releases/latest/)
|
||||||
|
|
||||||
## Build from Source
|
## Build from Source
|
||||||
|
|
||||||
Requires Go 1.22 or higher
|
Requires Go 1.22 or higher
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@ -78,21 +81,23 @@ The installation method is same as Linux. If you are using a Raspberry Pi 4 or n
|
|||||||
The installation method is same as Linux. For other ARM SBCs, please refer to your SBC's CPU architecture and pick the one that is suitable for your device.
|
The installation method is same as Linux. For other ARM SBCs, please refer to your SBC's CPU architecture and pick the one that is suitable for your device.
|
||||||
|
|
||||||
#### Docker
|
#### Docker
|
||||||
|
|
||||||
See the [/docker](https://github.com/tobychui/zoraxy/tree/main/docker) folder for more details.
|
See the [/docker](https://github.com/tobychui/zoraxy/tree/main/docker) folder for more details.
|
||||||
|
|
||||||
### Start Paramters
|
### Start Paramters
|
||||||
|
|
||||||
```
|
```
|
||||||
Usage of zoraxy:
|
Usage of zoraxy:
|
||||||
-autorenew int
|
-autorenew int
|
||||||
ACME auto TLS/SSL certificate renew check interval (seconds) (default 86400)
|
ACME auto TLS/SSL certificate renew check interval (seconds) (default 86400)
|
||||||
-fastgeoip
|
-fastgeoip
|
||||||
Enable high speed geoip lookup, require 1GB extra memory (Not recommend for low end devices)
|
Enable high speed geoip lookup, require 1GB extra memory (Not recommend for low end devices)
|
||||||
-info
|
|
||||||
Show information about this program in JSON
|
|
||||||
-log
|
-log
|
||||||
Log terminal output to file (default true)
|
Log terminal output to file (default true)
|
||||||
-mdns
|
-mdns
|
||||||
Enable mDNS scanner and transponder (default true)
|
Enable mDNS scanner and transponder (default true)
|
||||||
|
-mdnsname string
|
||||||
|
mDNS name, leave empty to use default (zoraxy_{node-uuid}.local)
|
||||||
-noauth
|
-noauth
|
||||||
Disable authentication for management interface
|
Disable authentication for management interface
|
||||||
-port string
|
-port string
|
||||||
@ -152,6 +157,7 @@ This allows you to have an infinite number of network members in your Global Are
|
|||||||
## Web SSH
|
## Web SSH
|
||||||
|
|
||||||
Web SSH currently only supports Linux based OSes. The following platforms are supported:
|
Web SSH currently only supports Linux based OSes. The following platforms are supported:
|
||||||
|
|
||||||
- linux/amd64
|
- linux/amd64
|
||||||
- linux/arm64
|
- linux/arm64
|
||||||
- linux/armv6 (experimental)
|
- linux/armv6 (experimental)
|
||||||
@ -166,12 +172,14 @@ Loopback web SSH connection, by default, is disabled. This means that if you are
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Sponsor This Project
|
## Sponsor This Project
|
||||||
|
|
||||||
If you like the project and want to support us, please consider a donation. You can use the links below
|
If you like the project and want to support us, please consider a donation. You can use the links below
|
||||||
|
|
||||||
- [tobychui (Primary author)](https://paypal.me/tobychui)
|
- [tobychui (Primary author)](https://paypal.me/tobychui)
|
||||||
- PassiveLemon (Docker compatibility maintainer)
|
- PassiveLemon (Docker compatibility maintainer)
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is open-sourced under AGPL. I open-sourced this project so everyone can check for security issues and benefit all users. **If you plan to use this project in a commercial environment (which violate the AGPL terms), please contact toby@imuslab.com for an alternative license.**
|
This project is open-sourced under AGPL. I open-sourced this project so everyone can check for security issues and benefit all users. **This software is intended to be free of charge. If you have acquired this software from a third-party seller, the authors of this repository bears no responsibility for any technical difficulties assistance or support.**
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,10 +8,7 @@ RUN mkdir -p /opt/zoraxy/source/ &&\
|
|||||||
mkdir -p /opt/zoraxy/config/ &&\
|
mkdir -p /opt/zoraxy/config/ &&\
|
||||||
mkdir -p /usr/local/bin/
|
mkdir -p /usr/local/bin/
|
||||||
|
|
||||||
COPY entrypoint.sh /opt/zoraxy/
|
RUN chmod -R 770 /opt/zoraxy/
|
||||||
|
|
||||||
RUN chmod -R 755 /opt/zoraxy/ &&\
|
|
||||||
chmod +x /opt/zoraxy/entrypoint.sh
|
|
||||||
|
|
||||||
VOLUME [ "/opt/zoraxy/config/" ]
|
VOLUME [ "/opt/zoraxy/config/" ]
|
||||||
|
|
||||||
@ -24,15 +21,15 @@ RUN go mod tidy &&\
|
|||||||
go build -o /usr/local/bin/zoraxy &&\
|
go build -o /usr/local/bin/zoraxy &&\
|
||||||
rm -r /opt/zoraxy/source/
|
rm -r /opt/zoraxy/source/
|
||||||
|
|
||||||
RUN chmod +x /usr/local/bin/zoraxy
|
RUN chmod 755 /usr/local/bin/zoraxy &&\
|
||||||
|
chmod +x /usr/local/bin/zoraxy
|
||||||
|
|
||||||
WORKDIR /opt/zoraxy/config/
|
WORKDIR /opt/zoraxy/config/
|
||||||
|
|
||||||
ENV VERSION=$VERSION
|
ENV VERSION=$VERSION
|
||||||
|
|
||||||
ENV ARGS="-noauth=false"
|
ENV ARGS="-noauth=false"
|
||||||
|
|
||||||
ENTRYPOINT ["/opt/zoraxy/entrypoint.sh"]
|
ENTRYPOINT "zoraxy" "-port=:8000" "${ARGS}"
|
||||||
|
|
||||||
HEALTHCHECK --interval=5s --timeout=5s --retries=2 CMD nc -vz 127.0.0.1 8000 || exit 1
|
HEALTHCHECK --interval=5s --timeout=5s --retries=2 CMD nc -vz 127.0.0.1 8000 || exit 1
|
||||||
|
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
echo "Zoraxy version $VERSION"
|
|
||||||
|
|
||||||
zoraxy -port=:8000 ${ARGS}
|
|
18
example/README.md
Normal file
18
example/README.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Example www Folder
|
||||||
|
|
||||||
|
This is an example www folder that contains two sub-folders.
|
||||||
|
|
||||||
|
- `html/`
|
||||||
|
- `templates/`
|
||||||
|
|
||||||
|
The html file contain static resources that will be served by Zoraxy build-in static web server. You can use it as a generic web server with a static site generator like [Hugo](https://gohugo.io/) or use it as a small CDN for serving your scripts / image that commonly use across many of your sites.
|
||||||
|
|
||||||
|
The templates folder contains the template for overriding the build in error or access denied pages. The following templates are supported
|
||||||
|
|
||||||
|
- notfound.html (Default site Not-Found error page)
|
||||||
|
- whitelist.html (Error page when client being blocked by whitelist rule)
|
||||||
|
- blacklist.html (Error page when client being blocked by blacklist rule)
|
||||||
|
|
||||||
|
To use the template, copy and paste the `wwww` folder to the same directory as zoraxy executable (aka the src/ file if you `go build` with the current folder tree).
|
||||||
|
|
||||||
|
It is worth mentioning that the uwu icons for not-found and access-denied are created by @SAWARATSUKI
|
229
example/www/html/index.html
Normal file
229
example/www/html/index.html
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Zoraxy Firework!</title>
|
||||||
|
<style>
|
||||||
|
body{
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
display: block;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.2/anime.min.js" integrity="sha512-aNMyYYxdIxIaot0Y1/PLuEu3eipGCmsEUBrUq+7aVyPGMFH8z0eTP0tkqAvv34fzN6z+201d3T8HPb1svWSKHQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas id="c"></canvas>
|
||||||
|
<script>
|
||||||
|
var c = document.getElementById("c");
|
||||||
|
var ctx = c.getContext("2d");
|
||||||
|
var cH;
|
||||||
|
var cW;
|
||||||
|
var bgColor = "#FF6138";
|
||||||
|
var animations = [];
|
||||||
|
var circles = [];
|
||||||
|
|
||||||
|
var colorPicker = (function() {
|
||||||
|
var colors = ["#FF6138", "#FFBE53", "#2980B9", "#FCFCFC", "#282741"];
|
||||||
|
var index = 0;
|
||||||
|
function next() {
|
||||||
|
index = index++ < colors.length-1 ? index : 0;
|
||||||
|
return colors[index];
|
||||||
|
}
|
||||||
|
function current() {
|
||||||
|
return colors[index]
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
next: next,
|
||||||
|
current: current
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
function removeAnimation(animation) {
|
||||||
|
var index = animations.indexOf(animation);
|
||||||
|
if (index > -1) animations.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcPageFillRadius(x, y) {
|
||||||
|
var l = Math.max(x - 0, cW - x);
|
||||||
|
var h = Math.max(y - 0, cH - y);
|
||||||
|
return Math.sqrt(Math.pow(l, 2) + Math.pow(h, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
function addClickListeners() {
|
||||||
|
document.addEventListener("touchstart", handleEvent);
|
||||||
|
document.addEventListener("mousedown", handleEvent);
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleEvent(e) {
|
||||||
|
if (e.touches) {
|
||||||
|
e.preventDefault();
|
||||||
|
e = e.touches[0];
|
||||||
|
}
|
||||||
|
var currentColor = colorPicker.current();
|
||||||
|
var nextColor = colorPicker.next();
|
||||||
|
var targetR = calcPageFillRadius(e.pageX, e.pageY);
|
||||||
|
var rippleSize = Math.min(200, (cW * .4));
|
||||||
|
var minCoverDuration = 750;
|
||||||
|
|
||||||
|
var pageFill = new Circle({
|
||||||
|
x: e.pageX,
|
||||||
|
y: e.pageY,
|
||||||
|
r: 0,
|
||||||
|
fill: nextColor
|
||||||
|
});
|
||||||
|
var fillAnimation = anime({
|
||||||
|
targets: pageFill,
|
||||||
|
r: targetR,
|
||||||
|
duration: Math.max(targetR / 2 , minCoverDuration ),
|
||||||
|
easing: "easeOutQuart",
|
||||||
|
complete: function(){
|
||||||
|
bgColor = pageFill.fill;
|
||||||
|
removeAnimation(fillAnimation);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var ripple = new Circle({
|
||||||
|
x: e.pageX,
|
||||||
|
y: e.pageY,
|
||||||
|
r: 0,
|
||||||
|
fill: currentColor,
|
||||||
|
stroke: {
|
||||||
|
width: 3,
|
||||||
|
color: currentColor
|
||||||
|
},
|
||||||
|
opacity: 1
|
||||||
|
});
|
||||||
|
var rippleAnimation = anime({
|
||||||
|
targets: ripple,
|
||||||
|
r: rippleSize,
|
||||||
|
opacity: 0,
|
||||||
|
easing: "easeOutExpo",
|
||||||
|
duration: 900,
|
||||||
|
complete: removeAnimation
|
||||||
|
});
|
||||||
|
|
||||||
|
var particles = [];
|
||||||
|
for (var i=0; i<32; i++) {
|
||||||
|
var particle = new Circle({
|
||||||
|
x: e.pageX,
|
||||||
|
y: e.pageY,
|
||||||
|
fill: currentColor,
|
||||||
|
r: anime.random(24, 48)
|
||||||
|
})
|
||||||
|
particles.push(particle);
|
||||||
|
}
|
||||||
|
var particlesAnimation = anime({
|
||||||
|
targets: particles,
|
||||||
|
x: function(particle){
|
||||||
|
return particle.x + anime.random(rippleSize, -rippleSize);
|
||||||
|
},
|
||||||
|
y: function(particle){
|
||||||
|
return particle.y + anime.random(rippleSize * 1.15, -rippleSize * 1.15);
|
||||||
|
},
|
||||||
|
r: 0,
|
||||||
|
easing: "easeOutExpo",
|
||||||
|
duration: anime.random(1000,1300),
|
||||||
|
complete: removeAnimation
|
||||||
|
});
|
||||||
|
animations.push(fillAnimation, rippleAnimation, particlesAnimation);
|
||||||
|
}
|
||||||
|
|
||||||
|
function extend(a, b){
|
||||||
|
for(var key in b) {
|
||||||
|
if(b.hasOwnProperty(key)) {
|
||||||
|
a[key] = b[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
var Circle = function(opts) {
|
||||||
|
extend(this, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
Circle.prototype.draw = function() {
|
||||||
|
ctx.globalAlpha = this.opacity || 1;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);
|
||||||
|
if (this.stroke) {
|
||||||
|
ctx.strokeStyle = this.stroke.color;
|
||||||
|
ctx.lineWidth = this.stroke.width;
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
if (this.fill) {
|
||||||
|
ctx.fillStyle = this.fill;
|
||||||
|
ctx.fill();
|
||||||
|
}
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.globalAlpha = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var animate = anime({
|
||||||
|
duration: Infinity,
|
||||||
|
update: function() {
|
||||||
|
ctx.fillStyle = bgColor;
|
||||||
|
ctx.fillRect(0, 0, cW, cH);
|
||||||
|
animations.forEach(function(anim) {
|
||||||
|
anim.animatables.forEach(function(animatable) {
|
||||||
|
animatable.target.draw();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var resizeCanvas = function() {
|
||||||
|
cW = window.innerWidth;
|
||||||
|
cH = window.innerHeight;
|
||||||
|
c.width = cW * devicePixelRatio;
|
||||||
|
c.height = cH * devicePixelRatio;
|
||||||
|
ctx.scale(devicePixelRatio, devicePixelRatio);
|
||||||
|
};
|
||||||
|
|
||||||
|
(function init() {
|
||||||
|
resizeCanvas();
|
||||||
|
if (window.CP) {
|
||||||
|
// CodePen's loop detection was causin' problems
|
||||||
|
// and I have no idea why, so...
|
||||||
|
window.CP.PenTimer.MAX_TIME_IN_LOOP_WO_EXIT = 6000;
|
||||||
|
}
|
||||||
|
window.addEventListener("resize", resizeCanvas);
|
||||||
|
addClickListeners();
|
||||||
|
if (!!window.location.pathname.match(/fullcpgrid/)) {
|
||||||
|
startFauxClicking();
|
||||||
|
}
|
||||||
|
handleInactiveUser();
|
||||||
|
})();
|
||||||
|
|
||||||
|
function handleInactiveUser() {
|
||||||
|
var inactive = setTimeout(function(){
|
||||||
|
fauxClick(cW/2, cH/2);
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
function clearInactiveTimeout() {
|
||||||
|
clearTimeout(inactive);
|
||||||
|
document.removeEventListener("mousedown", clearInactiveTimeout);
|
||||||
|
document.removeEventListener("touchstart", clearInactiveTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("mousedown", clearInactiveTimeout);
|
||||||
|
document.addEventListener("touchstart", clearInactiveTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
function startFauxClicking() {
|
||||||
|
setTimeout(function(){
|
||||||
|
fauxClick(anime.random( cW * .2, cW * .8), anime.random(cH * .2, cH * .8));
|
||||||
|
startFauxClicking();
|
||||||
|
}, anime.random(200, 900));
|
||||||
|
}
|
||||||
|
|
||||||
|
function fauxClick(x, y) {
|
||||||
|
var fauxClick = new Event("mousedown");
|
||||||
|
fauxClick.pageX = x;
|
||||||
|
fauxClick.pageY = y;
|
||||||
|
document.dispatchEvent(fauxClick);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
52
example/www/templates/blacklist.html
Normal file
52
example/www/templates/blacklist.html
Normal file
File diff suppressed because one or more lines are too long
42
example/www/templates/notfound.html
Normal file
42
example/www/templates/notfound.html
Normal file
File diff suppressed because one or more lines are too long
52
example/www/templates/whitelist.html
Normal file
52
example/www/templates/whitelist.html
Normal file
File diff suppressed because one or more lines are too long
@ -3,9 +3,12 @@ package main
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/microcosm-cc/bluemonday"
|
"github.com/microcosm-cc/bluemonday"
|
||||||
"imuslab.com/zoraxy/mod/geodb"
|
|
||||||
|
"imuslab.com/zoraxy/mod/access"
|
||||||
"imuslab.com/zoraxy/mod/utils"
|
"imuslab.com/zoraxy/mod/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,6 +20,157 @@ import (
|
|||||||
banning / whitelist a specific IP address or country code
|
banning / whitelist a specific IP address or country code
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
General Function
|
||||||
|
*/
|
||||||
|
|
||||||
|
func handleListAccessRules(w http.ResponseWriter, r *http.Request) {
|
||||||
|
allAccessRules := accessController.ListAllAccessRules()
|
||||||
|
js, _ := json.Marshal(allAccessRules)
|
||||||
|
utils.SendJSONResponse(w, string(js))
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleAttachRuleToHost(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ruleid, err := utils.PostPara(r, "id")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "invalid rule name")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
host, err := utils.PostPara(r, "host")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "invalid rule name")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if access rule and proxy rule exists
|
||||||
|
targetProxyEndpoint, err := dynamicProxyRouter.LoadProxy(host)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "invalid host given")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !accessController.AccessRuleExists(ruleid) {
|
||||||
|
utils.SendErrorResponse(w, "access rule not exists")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Update the proxy host acess rule id
|
||||||
|
targetProxyEndpoint.AccessFilterUUID = ruleid
|
||||||
|
targetProxyEndpoint.UpdateToRuntime()
|
||||||
|
err = SaveReverseProxyConfig(targetProxyEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.SendOK(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new access rule, require name and desc only
|
||||||
|
func handleCreateAccessRule(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ruleName, err := utils.PostPara(r, "name")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "invalid rule name")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ruleDesc, _ := utils.PostPara(r, "desc")
|
||||||
|
|
||||||
|
//Filter out injection if any
|
||||||
|
p := bluemonday.StripTagsPolicy()
|
||||||
|
ruleName = p.Sanitize(ruleName)
|
||||||
|
ruleDesc = p.Sanitize(ruleDesc)
|
||||||
|
|
||||||
|
ruleUUID := uuid.New().String()
|
||||||
|
newAccessRule := access.AccessRule{
|
||||||
|
ID: ruleUUID,
|
||||||
|
Name: ruleName,
|
||||||
|
Desc: ruleDesc,
|
||||||
|
BlacklistEnabled: false,
|
||||||
|
WhitelistEnabled: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add it to runtime
|
||||||
|
err = accessController.AddNewAccessRule(&newAccessRule)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.SendOK(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle removing an access rule. All proxy endpoint using this rule will be
|
||||||
|
// set to use the default rule
|
||||||
|
func handleRemoveAccessRule(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ruleID, err := utils.PostPara(r, "id")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "invalid rule id given")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ruleID == "default" {
|
||||||
|
utils.SendErrorResponse(w, "default access rule cannot be removed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ruleID = strings.TrimSpace(ruleID)
|
||||||
|
|
||||||
|
//Set all proxy hosts that use this access rule back to using "default"
|
||||||
|
allProxyEndpoints := dynamicProxyRouter.GetProxyEndpointsAsMap()
|
||||||
|
for _, proxyEndpoint := range allProxyEndpoints {
|
||||||
|
if strings.EqualFold(proxyEndpoint.AccessFilterUUID, ruleID) {
|
||||||
|
//This proxy endpoint is using the current access filter.
|
||||||
|
//set it to default
|
||||||
|
proxyEndpoint.AccessFilterUUID = "default"
|
||||||
|
proxyEndpoint.UpdateToRuntime()
|
||||||
|
err = SaveReverseProxyConfig(proxyEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
SystemWideLogger.PrintAndLog("Access", "Unable to save updated proxy endpoint "+proxyEndpoint.RootOrMatchingDomain, err)
|
||||||
|
} else {
|
||||||
|
SystemWideLogger.PrintAndLog("Access", "Updated "+proxyEndpoint.RootOrMatchingDomain+" access filter to \"default\"", nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Remove the access rule by ID
|
||||||
|
err = accessController.RemoveAccessRuleByID(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemWideLogger.PrintAndLog("Access", "Access Rule "+ruleID+" removed", nil)
|
||||||
|
utils.SendOK(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only the name and desc, for other properties use blacklist / whitelist api
|
||||||
|
func handleUpadateAccessRule(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ruleID, err := utils.PostPara(r, "id")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "invalid rule id")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ruleName, err := utils.PostPara(r, "name")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "invalid rule name")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ruleDesc, _ := utils.PostPara(r, "desc")
|
||||||
|
|
||||||
|
//Filter anything weird
|
||||||
|
p := bluemonday.StrictPolicy()
|
||||||
|
ruleName = p.Sanitize(ruleName)
|
||||||
|
ruleDesc = p.Sanitize(ruleDesc)
|
||||||
|
|
||||||
|
err = accessController.UpdateAccessRule(ruleID, ruleName, ruleDesc)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.SendOK(w)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Blacklist Related
|
Blacklist Related
|
||||||
*/
|
*/
|
||||||
@ -28,11 +182,24 @@ func handleListBlacklisted(w http.ResponseWriter, r *http.Request) {
|
|||||||
bltype = "country"
|
bltype = "country"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ruleID, err := utils.GetPara(r, "id")
|
||||||
|
if err != nil {
|
||||||
|
//Use default if not set
|
||||||
|
ruleID = "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
//Load the target rule from access controller
|
||||||
|
rule, err := accessController.GetAccessRuleByID(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
resulst := []string{}
|
resulst := []string{}
|
||||||
if bltype == "country" {
|
if bltype == "country" {
|
||||||
resulst = geodbStore.GetAllBlacklistedCountryCode()
|
resulst = rule.GetAllBlacklistedCountryCode()
|
||||||
} else if bltype == "ip" {
|
} else if bltype == "ip" {
|
||||||
resulst = geodbStore.GetAllBlacklistedIp()
|
resulst = rule.GetAllBlacklistedIp()
|
||||||
}
|
}
|
||||||
|
|
||||||
js, _ := json.Marshal(resulst)
|
js, _ := json.Marshal(resulst)
|
||||||
@ -47,7 +214,23 @@ func handleCountryBlacklistAdd(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
geodbStore.AddCountryCodeToBlackList(countryCode)
|
ruleID, err := utils.PostPara(r, "id")
|
||||||
|
if err != nil {
|
||||||
|
ruleID = "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
comment, _ := utils.PostPara(r, "comment")
|
||||||
|
p := bluemonday.StripTagsPolicy()
|
||||||
|
comment = p.Sanitize(comment)
|
||||||
|
|
||||||
|
//Load the target rule from access controller
|
||||||
|
rule, err := accessController.GetAccessRuleByID(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rule.AddCountryCodeToBlackList(countryCode, comment)
|
||||||
|
|
||||||
utils.SendOK(w)
|
utils.SendOK(w)
|
||||||
}
|
}
|
||||||
@ -59,7 +242,19 @@ func handleCountryBlacklistRemove(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
geodbStore.RemoveCountryCodeFromBlackList(countryCode)
|
ruleID, err := utils.PostPara(r, "id")
|
||||||
|
if err != nil {
|
||||||
|
ruleID = "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
//Load the target rule from access controller
|
||||||
|
rule, err := accessController.GetAccessRuleByID(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rule.RemoveCountryCodeFromBlackList(countryCode)
|
||||||
|
|
||||||
utils.SendOK(w)
|
utils.SendOK(w)
|
||||||
}
|
}
|
||||||
@ -71,7 +266,24 @@ func handleIpBlacklistAdd(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
geodbStore.AddIPToBlackList(ipAddr)
|
ruleID, err := utils.PostPara(r, "id")
|
||||||
|
if err != nil {
|
||||||
|
ruleID = "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
//Load the target rule from access controller
|
||||||
|
rule, err := accessController.GetAccessRuleByID(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
comment, _ := utils.GetPara(r, "comment")
|
||||||
|
p := bluemonday.StripTagsPolicy()
|
||||||
|
comment = p.Sanitize(comment)
|
||||||
|
|
||||||
|
rule.AddIPToBlackList(ipAddr, comment)
|
||||||
|
utils.SendOK(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleIpBlacklistRemove(w http.ResponseWriter, r *http.Request) {
|
func handleIpBlacklistRemove(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -81,23 +293,46 @@ func handleIpBlacklistRemove(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
geodbStore.RemoveIPFromBlackList(ipAddr)
|
ruleID, err := utils.PostPara(r, "id")
|
||||||
|
if err != nil {
|
||||||
|
ruleID = "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
//Load the target rule from access controller
|
||||||
|
rule, err := accessController.GetAccessRuleByID(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rule.RemoveIPFromBlackList(ipAddr)
|
||||||
|
|
||||||
utils.SendOK(w)
|
utils.SendOK(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleBlacklistEnable(w http.ResponseWriter, r *http.Request) {
|
func handleBlacklistEnable(w http.ResponseWriter, r *http.Request) {
|
||||||
enable, err := utils.PostPara(r, "enable")
|
enable, _ := utils.PostPara(r, "enable")
|
||||||
|
ruleID, err := utils.PostPara(r, "id")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//Return the current enabled state
|
ruleID = "default"
|
||||||
currentEnabled := geodbStore.BlacklistEnabled
|
}
|
||||||
|
|
||||||
|
rule, err := accessController.GetAccessRuleByID(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if enable == "" {
|
||||||
|
//enable paramter not set
|
||||||
|
currentEnabled := rule.BlacklistEnabled
|
||||||
js, _ := json.Marshal(currentEnabled)
|
js, _ := json.Marshal(currentEnabled)
|
||||||
utils.SendJSONResponse(w, string(js))
|
utils.SendJSONResponse(w, string(js))
|
||||||
} else {
|
} else {
|
||||||
if enable == "true" {
|
if enable == "true" {
|
||||||
geodbStore.ToggleBlacklist(true)
|
rule.ToggleBlacklist(true)
|
||||||
} else if enable == "false" {
|
} else if enable == "false" {
|
||||||
geodbStore.ToggleBlacklist(false)
|
rule.ToggleBlacklist(false)
|
||||||
} else {
|
} else {
|
||||||
utils.SendErrorResponse(w, "invalid enable state: only true and false is accepted")
|
utils.SendErrorResponse(w, "invalid enable state: only true and false is accepted")
|
||||||
return
|
return
|
||||||
@ -117,11 +352,22 @@ func handleListWhitelisted(w http.ResponseWriter, r *http.Request) {
|
|||||||
bltype = "country"
|
bltype = "country"
|
||||||
}
|
}
|
||||||
|
|
||||||
resulst := []*geodb.WhitelistEntry{}
|
ruleID, err := utils.GetPara(r, "id")
|
||||||
|
if err != nil {
|
||||||
|
ruleID = "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
rule, err := accessController.GetAccessRuleByID(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resulst := []*access.WhitelistEntry{}
|
||||||
if bltype == "country" {
|
if bltype == "country" {
|
||||||
resulst = geodbStore.GetAllWhitelistedCountryCode()
|
resulst = rule.GetAllWhitelistedCountryCode()
|
||||||
} else if bltype == "ip" {
|
} else if bltype == "ip" {
|
||||||
resulst = geodbStore.GetAllWhitelistedIp()
|
resulst = rule.GetAllWhitelistedIp()
|
||||||
}
|
}
|
||||||
|
|
||||||
js, _ := json.Marshal(resulst)
|
js, _ := json.Marshal(resulst)
|
||||||
@ -136,11 +382,22 @@ func handleCountryWhitelistAdd(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ruleID, err := utils.PostPara(r, "id")
|
||||||
|
if err != nil {
|
||||||
|
ruleID = "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
rule, err := accessController.GetAccessRuleByID(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
comment, _ := utils.PostPara(r, "comment")
|
comment, _ := utils.PostPara(r, "comment")
|
||||||
p := bluemonday.StrictPolicy()
|
p := bluemonday.StrictPolicy()
|
||||||
comment = p.Sanitize(comment)
|
comment = p.Sanitize(comment)
|
||||||
|
|
||||||
geodbStore.AddCountryCodeToWhitelist(countryCode, comment)
|
rule.AddCountryCodeToWhitelist(countryCode, comment)
|
||||||
|
|
||||||
utils.SendOK(w)
|
utils.SendOK(w)
|
||||||
}
|
}
|
||||||
@ -152,7 +409,18 @@ func handleCountryWhitelistRemove(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
geodbStore.RemoveCountryCodeFromWhitelist(countryCode)
|
ruleID, err := utils.PostPara(r, "id")
|
||||||
|
if err != nil {
|
||||||
|
ruleID = "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
rule, err := accessController.GetAccessRuleByID(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rule.RemoveCountryCodeFromWhitelist(countryCode)
|
||||||
|
|
||||||
utils.SendOK(w)
|
utils.SendOK(w)
|
||||||
}
|
}
|
||||||
@ -164,11 +432,23 @@ func handleIpWhitelistAdd(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ruleID, err := utils.PostPara(r, "id")
|
||||||
|
if err != nil {
|
||||||
|
ruleID = "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
rule, err := accessController.GetAccessRuleByID(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
comment, _ := utils.PostPara(r, "comment")
|
comment, _ := utils.PostPara(r, "comment")
|
||||||
p := bluemonday.StrictPolicy()
|
p := bluemonday.StrictPolicy()
|
||||||
comment = p.Sanitize(comment)
|
comment = p.Sanitize(comment)
|
||||||
|
|
||||||
geodbStore.AddIPToWhiteList(ipAddr, comment)
|
rule.AddIPToWhiteList(ipAddr, comment)
|
||||||
|
utils.SendOK(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleIpWhitelistRemove(w http.ResponseWriter, r *http.Request) {
|
func handleIpWhitelistRemove(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -178,23 +458,45 @@ func handleIpWhitelistRemove(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
geodbStore.RemoveIPFromWhiteList(ipAddr)
|
ruleID, err := utils.PostPara(r, "id")
|
||||||
|
if err != nil {
|
||||||
|
ruleID = "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
rule, err := accessController.GetAccessRuleByID(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rule.RemoveIPFromWhiteList(ipAddr)
|
||||||
|
|
||||||
utils.SendOK(w)
|
utils.SendOK(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleWhitelistEnable(w http.ResponseWriter, r *http.Request) {
|
func handleWhitelistEnable(w http.ResponseWriter, r *http.Request) {
|
||||||
enable, err := utils.PostPara(r, "enable")
|
enable, _ := utils.PostPara(r, "enable")
|
||||||
|
ruleID, err := utils.PostPara(r, "id")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
ruleID = "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
rule, err := accessController.GetAccessRuleByID(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if enable == "" {
|
||||||
//Return the current enabled state
|
//Return the current enabled state
|
||||||
currentEnabled := geodbStore.WhitelistEnabled
|
currentEnabled := rule.WhitelistEnabled
|
||||||
js, _ := json.Marshal(currentEnabled)
|
js, _ := json.Marshal(currentEnabled)
|
||||||
utils.SendJSONResponse(w, string(js))
|
utils.SendJSONResponse(w, string(js))
|
||||||
} else {
|
} else {
|
||||||
if enable == "true" {
|
if enable == "true" {
|
||||||
geodbStore.ToggleWhitelist(true)
|
rule.ToggleWhitelist(true)
|
||||||
} else if enable == "false" {
|
} else if enable == "false" {
|
||||||
geodbStore.ToggleWhitelist(false)
|
rule.ToggleWhitelist(false)
|
||||||
} else {
|
} else {
|
||||||
utils.SendErrorResponse(w, "invalid enable state: only true and false is accepted")
|
utils.SendErrorResponse(w, "invalid enable state: only true and false is accepted")
|
||||||
return
|
return
|
||||||
|
40
src/acme.go
40
src/acme.go
@ -38,7 +38,7 @@ func initACME() *acme.ACMEHandler {
|
|||||||
port = getRandomPort(30000)
|
port = getRandomPort(30000)
|
||||||
}
|
}
|
||||||
|
|
||||||
return acme.NewACME("https://acme-v02.api.letsencrypt.org/directory", strconv.Itoa(port))
|
return acme.NewACME("https://acme-v02.api.letsencrypt.org/directory", strconv.Itoa(port), sysdb)
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the special routing rule for ACME
|
// create the special routing rule for ACME
|
||||||
@ -85,22 +85,26 @@ func acmeRegisterSpecialRoutingRule() {
|
|||||||
// This function check if the renew setup is satisfied. If not, toggle them automatically
|
// This function check if the renew setup is satisfied. If not, toggle them automatically
|
||||||
func AcmeCheckAndHandleRenewCertificate(w http.ResponseWriter, r *http.Request) {
|
func AcmeCheckAndHandleRenewCertificate(w http.ResponseWriter, r *http.Request) {
|
||||||
isForceHttpsRedirectEnabledOriginally := false
|
isForceHttpsRedirectEnabledOriginally := false
|
||||||
if dynamicProxyRouter.Option.Port == 443 {
|
dnsPara, _ := utils.PostBool(r, "dns")
|
||||||
//Enable port 80 to 443 redirect
|
if !dnsPara {
|
||||||
if !dynamicProxyRouter.Option.ForceHttpsRedirect {
|
if dynamicProxyRouter.Option.Port == 443 {
|
||||||
SystemWideLogger.Println("Temporary enabling HTTP to HTTPS redirect for ACME certificate renew requests")
|
//Enable port 80 to 443 redirect
|
||||||
dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(true)
|
if !dynamicProxyRouter.Option.ForceHttpsRedirect {
|
||||||
|
SystemWideLogger.Println("Temporary enabling HTTP to HTTPS redirect for ACME certificate renew requests")
|
||||||
|
dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(true)
|
||||||
|
} else {
|
||||||
|
//Set this to true, so after renew, do not turn it off
|
||||||
|
isForceHttpsRedirectEnabledOriginally = true
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if dynamicProxyRouter.Option.Port == 80 {
|
||||||
|
//Go ahead
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//Set this to true, so after renew, do not turn it off
|
//This port do not support ACME
|
||||||
isForceHttpsRedirectEnabledOriginally = true
|
utils.SendErrorResponse(w, "ACME renew only support web server listening on port 80 (http) or 443 (https)")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if dynamicProxyRouter.Option.Port == 80 {
|
|
||||||
//Go ahead
|
|
||||||
|
|
||||||
} else {
|
|
||||||
//This port do not support ACME
|
|
||||||
utils.SendErrorResponse(w, "ACME renew only support web server listening on port 80 (http) or 443 (https)")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add a 3 second delay to make sure everything is settle down
|
//Add a 3 second delay to make sure everything is settle down
|
||||||
@ -109,7 +113,11 @@ func AcmeCheckAndHandleRenewCertificate(w http.ResponseWriter, r *http.Request)
|
|||||||
// Pass over to the acmeHandler to deal with the communication
|
// Pass over to the acmeHandler to deal with the communication
|
||||||
acmeHandler.HandleRenewCertificate(w, r)
|
acmeHandler.HandleRenewCertificate(w, r)
|
||||||
|
|
||||||
if dynamicProxyRouter.Option.Port == 443 {
|
//Update the TLS cert store buffer
|
||||||
|
tlsCertManager.UpdateLoadedCertList()
|
||||||
|
|
||||||
|
//Restore original settings
|
||||||
|
if dynamicProxyRouter.Option.Port == 443 && !dnsPara {
|
||||||
if !isForceHttpsRedirectEnabledOriginally {
|
if !isForceHttpsRedirectEnabledOriginally {
|
||||||
//Default is off. Turn the redirection off
|
//Default is off. Turn the redirection off
|
||||||
SystemWideLogger.PrintAndLog("ACME", "Restoring HTTP to HTTPS redirect settings", nil)
|
SystemWideLogger.PrintAndLog("ACME", "Restoring HTTP to HTTPS redirect settings", nil)
|
||||||
|
13
src/api.go
13
src/api.go
@ -5,6 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/http/pprof"
|
"net/http/pprof"
|
||||||
|
|
||||||
|
"imuslab.com/zoraxy/mod/acme/acmedns"
|
||||||
"imuslab.com/zoraxy/mod/acme/acmewizard"
|
"imuslab.com/zoraxy/mod/acme/acmewizard"
|
||||||
"imuslab.com/zoraxy/mod/auth"
|
"imuslab.com/zoraxy/mod/auth"
|
||||||
"imuslab.com/zoraxy/mod/netstat"
|
"imuslab.com/zoraxy/mod/netstat"
|
||||||
@ -49,7 +50,9 @@ func initAPIs() {
|
|||||||
authRouter.HandleFunc("/api/proxy/status", ReverseProxyStatus)
|
authRouter.HandleFunc("/api/proxy/status", ReverseProxyStatus)
|
||||||
authRouter.HandleFunc("/api/proxy/toggle", ReverseProxyToggleRuleSet)
|
authRouter.HandleFunc("/api/proxy/toggle", ReverseProxyToggleRuleSet)
|
||||||
authRouter.HandleFunc("/api/proxy/list", ReverseProxyList)
|
authRouter.HandleFunc("/api/proxy/list", ReverseProxyList)
|
||||||
|
authRouter.HandleFunc("/api/proxy/detail", ReverseProxyListDetail)
|
||||||
authRouter.HandleFunc("/api/proxy/edit", ReverseProxyHandleEditEndpoint)
|
authRouter.HandleFunc("/api/proxy/edit", ReverseProxyHandleEditEndpoint)
|
||||||
|
authRouter.HandleFunc("/api/proxy/setAlias", ReverseProxyHandleAlias)
|
||||||
authRouter.HandleFunc("/api/proxy/del", DeleteProxyEndpoint)
|
authRouter.HandleFunc("/api/proxy/del", DeleteProxyEndpoint)
|
||||||
authRouter.HandleFunc("/api/proxy/updateCredentials", UpdateProxyBasicAuthCredentials)
|
authRouter.HandleFunc("/api/proxy/updateCredentials", UpdateProxyBasicAuthCredentials)
|
||||||
authRouter.HandleFunc("/api/proxy/tlscheck", HandleCheckSiteSupportTLS)
|
authRouter.HandleFunc("/api/proxy/tlscheck", HandleCheckSiteSupportTLS)
|
||||||
@ -87,6 +90,12 @@ func initAPIs() {
|
|||||||
authRouter.HandleFunc("/api/redirect/delete", handleDeleteRedirectionRule)
|
authRouter.HandleFunc("/api/redirect/delete", handleDeleteRedirectionRule)
|
||||||
authRouter.HandleFunc("/api/redirect/regex", handleToggleRedirectRegexpSupport)
|
authRouter.HandleFunc("/api/redirect/regex", handleToggleRedirectRegexpSupport)
|
||||||
|
|
||||||
|
//Access Rules API
|
||||||
|
authRouter.HandleFunc("/api/access/list", handleListAccessRules)
|
||||||
|
authRouter.HandleFunc("/api/access/attach", handleAttachRuleToHost)
|
||||||
|
authRouter.HandleFunc("/api/access/create", handleCreateAccessRule)
|
||||||
|
authRouter.HandleFunc("/api/access/remove", handleRemoveAccessRule)
|
||||||
|
authRouter.HandleFunc("/api/access/update", handleUpadateAccessRule)
|
||||||
//Blacklist APIs
|
//Blacklist APIs
|
||||||
authRouter.HandleFunc("/api/blacklist/list", handleListBlacklisted)
|
authRouter.HandleFunc("/api/blacklist/list", handleListBlacklisted)
|
||||||
authRouter.HandleFunc("/api/blacklist/country/add", handleCountryBlacklistAdd)
|
authRouter.HandleFunc("/api/blacklist/country/add", handleCountryBlacklistAdd)
|
||||||
@ -94,7 +103,6 @@ func initAPIs() {
|
|||||||
authRouter.HandleFunc("/api/blacklist/ip/add", handleIpBlacklistAdd)
|
authRouter.HandleFunc("/api/blacklist/ip/add", handleIpBlacklistAdd)
|
||||||
authRouter.HandleFunc("/api/blacklist/ip/remove", handleIpBlacklistRemove)
|
authRouter.HandleFunc("/api/blacklist/ip/remove", handleIpBlacklistRemove)
|
||||||
authRouter.HandleFunc("/api/blacklist/enable", handleBlacklistEnable)
|
authRouter.HandleFunc("/api/blacklist/enable", handleBlacklistEnable)
|
||||||
|
|
||||||
//Whitelist APIs
|
//Whitelist APIs
|
||||||
authRouter.HandleFunc("/api/whitelist/list", handleListWhitelisted)
|
authRouter.HandleFunc("/api/whitelist/list", handleListWhitelisted)
|
||||||
authRouter.HandleFunc("/api/whitelist/country/add", handleCountryWhitelistAdd)
|
authRouter.HandleFunc("/api/whitelist/country/add", handleCountryWhitelistAdd)
|
||||||
@ -179,9 +187,12 @@ func initAPIs() {
|
|||||||
authRouter.HandleFunc("/api/acme/autoRenew/ca", HandleACMEPreferredCA)
|
authRouter.HandleFunc("/api/acme/autoRenew/ca", HandleACMEPreferredCA)
|
||||||
authRouter.HandleFunc("/api/acme/autoRenew/email", acmeAutoRenewer.HandleACMEEmail)
|
authRouter.HandleFunc("/api/acme/autoRenew/email", acmeAutoRenewer.HandleACMEEmail)
|
||||||
authRouter.HandleFunc("/api/acme/autoRenew/setDomains", acmeAutoRenewer.HandleSetAutoRenewDomains)
|
authRouter.HandleFunc("/api/acme/autoRenew/setDomains", acmeAutoRenewer.HandleSetAutoRenewDomains)
|
||||||
|
authRouter.HandleFunc("/api/acme/autoRenew/setEAB", acmeAutoRenewer.HanldeSetEAB)
|
||||||
|
authRouter.HandleFunc("/api/acme/autoRenew/setDNS", acmeAutoRenewer.HanldeSetDNS)
|
||||||
authRouter.HandleFunc("/api/acme/autoRenew/listDomains", acmeAutoRenewer.HandleLoadAutoRenewDomains)
|
authRouter.HandleFunc("/api/acme/autoRenew/listDomains", acmeAutoRenewer.HandleLoadAutoRenewDomains)
|
||||||
authRouter.HandleFunc("/api/acme/autoRenew/renewPolicy", acmeAutoRenewer.HandleRenewPolicy)
|
authRouter.HandleFunc("/api/acme/autoRenew/renewPolicy", acmeAutoRenewer.HandleRenewPolicy)
|
||||||
authRouter.HandleFunc("/api/acme/autoRenew/renewNow", acmeAutoRenewer.HandleRenewNow)
|
authRouter.HandleFunc("/api/acme/autoRenew/renewNow", acmeAutoRenewer.HandleRenewNow)
|
||||||
|
authRouter.HandleFunc("/api/acme/dns/providers", acmedns.HandleServeProvidersJson)
|
||||||
authRouter.HandleFunc("/api/acme/wizard", acmewizard.HandleGuidedStepCheck) //ACME Wizard
|
authRouter.HandleFunc("/api/acme/wizard", acmewizard.HandleGuidedStepCheck) //ACME Wizard
|
||||||
|
|
||||||
//Static Web Server
|
//Static Web Server
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"imuslab.com/zoraxy/mod/acme"
|
||||||
"imuslab.com/zoraxy/mod/utils"
|
"imuslab.com/zoraxy/mod/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -46,6 +47,7 @@ func handleListCertificate(w http.ResponseWriter, r *http.Request) {
|
|||||||
LastModifiedDate string
|
LastModifiedDate string
|
||||||
ExpireDate string
|
ExpireDate string
|
||||||
RemainingDays int
|
RemainingDays int
|
||||||
|
UseDNS bool
|
||||||
}
|
}
|
||||||
|
|
||||||
results := []*CertInfo{}
|
results := []*CertInfo{}
|
||||||
@ -81,12 +83,19 @@ func handleListCertificate(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
certInfoFilename := filepath.Join(tlsCertManager.CertStore, filename+".json")
|
||||||
|
useDNSValidation := false //Default to false for HTTP TLS certificates
|
||||||
|
certInfo, err := acme.LoadCertInfoJSON(certInfoFilename) //Note: Not all certs have info json
|
||||||
|
if err == nil {
|
||||||
|
useDNSValidation = certInfo.UseDNS
|
||||||
|
}
|
||||||
|
|
||||||
thisCertInfo := CertInfo{
|
thisCertInfo := CertInfo{
|
||||||
Domain: filename,
|
Domain: filename,
|
||||||
LastModifiedDate: modifiedTime,
|
LastModifiedDate: modifiedTime,
|
||||||
ExpireDate: certExpireTime,
|
ExpireDate: certExpireTime,
|
||||||
RemainingDays: expiredIn,
|
RemainingDays: expiredIn,
|
||||||
|
UseDNS: useDNSValidation,
|
||||||
}
|
}
|
||||||
|
|
||||||
results = append(results, &thisCertInfo)
|
results = append(results, &thisCertInfo)
|
||||||
|
@ -155,7 +155,7 @@ func GetDefaultRootConfig() (*dynamicproxy.ProxyEndpoint, error) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
func ExportConfigAsZip(w http.ResponseWriter, r *http.Request) {
|
func ExportConfigAsZip(w http.ResponseWriter, r *http.Request) {
|
||||||
includeSysDBRaw, err := utils.GetPara(r, "includeDB")
|
includeSysDBRaw, _ := utils.GetPara(r, "includeDB")
|
||||||
includeSysDB := false
|
includeSysDB := false
|
||||||
if includeSysDBRaw == "true" {
|
if includeSysDBRaw == "true" {
|
||||||
//Include the system database in backup snapshot
|
//Include the system database in backup snapshot
|
||||||
@ -177,7 +177,7 @@ func ExportConfigAsZip(w http.ResponseWriter, r *http.Request) {
|
|||||||
defer zipWriter.Close()
|
defer zipWriter.Close()
|
||||||
|
|
||||||
// Walk through the folder and add files to the zip
|
// Walk through the folder and add files to the zip
|
||||||
err = filepath.Walk(folderPath, func(filePath string, fileInfo os.FileInfo, err error) error {
|
err := filepath.Walk(folderPath, func(filePath string, fileInfo os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,6 @@ func HandleSMTPSet(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
domain, err := utils.PostPara(r, "domain")
|
|
||||||
if err != nil {
|
|
||||||
utils.SendErrorResponse(w, "domain cannot be empty")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
portString, err := utils.PostPara(r, "port")
|
portString, err := utils.PostPara(r, "port")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.SendErrorResponse(w, "port must be a valid integer")
|
utils.SendErrorResponse(w, "port must be a valid integer")
|
||||||
@ -76,7 +70,6 @@ func HandleSMTPSet(w http.ResponseWriter, r *http.Request) {
|
|||||||
//Set the email sender properties
|
//Set the email sender properties
|
||||||
thisEmailSender := email.Sender{
|
thisEmailSender := email.Sender{
|
||||||
Hostname: strings.TrimSpace(hostname),
|
Hostname: strings.TrimSpace(hostname),
|
||||||
Domain: strings.TrimSpace(domain),
|
|
||||||
Port: port,
|
Port: port,
|
||||||
Username: strings.TrimSpace(username),
|
Username: strings.TrimSpace(username),
|
||||||
Password: strings.TrimSpace(password),
|
Password: strings.TrimSpace(password),
|
||||||
@ -206,7 +199,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func HandleAdminAccountResetEmail(w http.ResponseWriter, r *http.Request) {
|
func HandleAdminAccountResetEmail(w http.ResponseWriter, r *http.Request) {
|
||||||
if EmailSender.Username == "" || EmailSender.Domain == "" {
|
if EmailSender.Username == "" {
|
||||||
//Reset account not setup
|
//Reset account not setup
|
||||||
utils.SendErrorResponse(w, "Reset account not setup.")
|
utils.SendErrorResponse(w, "Reset account not setup.")
|
||||||
return
|
return
|
||||||
|
140
src/go.mod
140
src/go.mod
@ -20,15 +20,155 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
cloud.google.com/go/compute v1.20.1 // indirect
|
||||||
|
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||||
|
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
|
||||||
|
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 // indirect
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 // indirect
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.1.0 // indirect
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.1.0 // indirect
|
||||||
|
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||||
|
github.com/Azure/go-autorest/autorest v0.11.29 // indirect
|
||||||
|
github.com/Azure/go-autorest/autorest/adal v0.9.22 // indirect
|
||||||
|
github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 // indirect
|
||||||
|
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect
|
||||||
|
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||||
|
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
|
||||||
|
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||||
|
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||||
|
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect
|
||||||
|
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
|
||||||
|
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 // indirect
|
||||||
|
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 // indirect
|
||||||
|
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2 v1.24.1 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/config v1.26.6 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/credentials v1.16.16 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/lightsail v1.34.0 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.37.0 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sso v1.18.7 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 // indirect
|
||||||
|
github.com/aws/smithy-go v1.19.0 // indirect
|
||||||
github.com/aymerick/douceur v0.2.0 // indirect
|
github.com/aymerick/douceur v0.2.0 // indirect
|
||||||
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||||
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
|
github.com/civo/civogo v0.3.11 // indirect
|
||||||
|
github.com/cloudflare/cloudflare-go v0.86.0 // indirect
|
||||||
|
github.com/cpu/goacmedns v0.1.1 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/deepmap/oapi-codegen v1.9.1 // indirect
|
||||||
|
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||||
|
github.com/dnsimple/dnsimple-go v1.2.0 // indirect
|
||||||
|
github.com/exoscale/egoscale v0.102.3 // indirect
|
||||||
|
github.com/fatih/structs v1.1.0 // indirect
|
||||||
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||||
|
github.com/ghodss/yaml v1.0.0 // indirect
|
||||||
|
github.com/go-errors/errors v1.0.1 // indirect
|
||||||
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
|
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
|
||||||
|
github.com/go-resty/resty/v2 v2.11.0 // indirect
|
||||||
|
github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect
|
||||||
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
|
github.com/gofrs/uuid v4.4.0+incompatible // indirect
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||||
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
|
github.com/google/s2a-go v0.1.4 // indirect
|
||||||
|
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
|
||||||
|
github.com/googleapis/gax-go/v2 v2.11.0 // indirect
|
||||||
|
github.com/gophercloud/gophercloud v1.0.0 // indirect
|
||||||
|
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae // indirect
|
||||||
github.com/gorilla/css v1.0.1 // indirect
|
github.com/gorilla/css v1.0.1 // indirect
|
||||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||||
|
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||||
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
|
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
|
||||||
|
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
|
||||||
|
github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect
|
||||||
|
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b // indirect
|
||||||
|
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||||
|
github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect
|
||||||
|
github.com/labbsr0x/goh v1.0.1 // indirect
|
||||||
|
github.com/linode/linodego v1.28.0 // indirect
|
||||||
|
github.com/liquidweb/liquidweb-cli v0.6.9 // indirect
|
||||||
|
github.com/liquidweb/liquidweb-go v1.6.4 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/miekg/dns v1.1.58 // indirect
|
github.com/miekg/dns v1.1.58 // indirect
|
||||||
|
github.com/mimuret/golang-iij-dpf v0.9.1 // indirect
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect
|
||||||
|
github.com/nrdcg/auroradns v1.1.0 // indirect
|
||||||
|
github.com/nrdcg/bunny-go v0.0.0-20230728143221-c9dda82568d9 // indirect
|
||||||
|
github.com/nrdcg/desec v0.7.0 // indirect
|
||||||
|
github.com/nrdcg/dnspod-go v0.4.0 // indirect
|
||||||
|
github.com/nrdcg/freemyip v0.2.0 // indirect
|
||||||
|
github.com/nrdcg/goinwx v0.10.0 // indirect
|
||||||
|
github.com/nrdcg/mailinabox v0.2.0 // indirect
|
||||||
|
github.com/nrdcg/namesilo v0.2.1 // indirect
|
||||||
|
github.com/nrdcg/nodion v0.1.0 // indirect
|
||||||
|
github.com/nrdcg/porkbun v0.3.0 // indirect
|
||||||
|
github.com/nzdjb/go-metaname v1.0.0 // indirect
|
||||||
|
github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect
|
||||||
|
github.com/ovh/go-ovh v1.4.3 // indirect
|
||||||
|
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||||
|
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/pquerna/otp v1.4.0 // indirect
|
||||||
|
github.com/sacloud/api-client-go v0.2.8 // indirect
|
||||||
|
github.com/sacloud/go-http v0.1.6 // indirect
|
||||||
|
github.com/sacloud/iaas-api-go v1.11.1 // indirect
|
||||||
|
github.com/sacloud/packages-go v0.0.9 // indirect
|
||||||
|
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.22 // indirect
|
||||||
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
|
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect
|
||||||
|
github.com/softlayer/softlayer-go v1.1.3 // indirect
|
||||||
|
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
|
||||||
|
github.com/spf13/cast v1.3.1 // indirect
|
||||||
|
github.com/stretchr/objx v0.5.1 // indirect
|
||||||
|
github.com/stretchr/testify v1.8.4 // indirect
|
||||||
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 // indirect
|
||||||
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 // indirect
|
||||||
|
github.com/transip/gotransip/v6 v6.23.0 // indirect
|
||||||
|
github.com/ultradns/ultradns-go-sdk v1.6.1-20231103022937-8589b6a // indirect
|
||||||
|
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
|
||||||
|
github.com/vultr/govultr/v2 v2.17.2 // indirect
|
||||||
|
github.com/yandex-cloud/go-genproto v0.0.0-20220805142335-27b56ddae16f // indirect
|
||||||
|
github.com/yandex-cloud/go-sdk v0.0.0-20220805164847-cf028e604997 // indirect
|
||||||
|
go.opencensus.io v0.24.0 // indirect
|
||||||
|
go.uber.org/ratelimit v0.2.0 // indirect
|
||||||
golang.org/x/crypto v0.21.0 // indirect
|
golang.org/x/crypto v0.21.0 // indirect
|
||||||
golang.org/x/mod v0.16.0 // indirect
|
golang.org/x/mod v0.16.0 // indirect
|
||||||
|
golang.org/x/oauth2 v0.16.0 // indirect
|
||||||
golang.org/x/sync v0.6.0 // indirect
|
golang.org/x/sync v0.6.0 // indirect
|
||||||
|
golang.org/x/time v0.5.0 // indirect
|
||||||
golang.org/x/tools v0.19.0 // indirect
|
golang.org/x/tools v0.19.0 // indirect
|
||||||
|
google.golang.org/api v0.126.0 // indirect
|
||||||
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
|
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
|
||||||
|
google.golang.org/grpc v1.55.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.31.0 // indirect
|
||||||
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
|
gopkg.in/ns1/ns1-go.v2 v2.7.13 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
912
src/go.sum
912
src/go.sum
@ -1,85 +1,993 @@
|
|||||||
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||||
|
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||||
|
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||||
|
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||||
|
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||||
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
|
cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg=
|
||||||
|
cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
|
||||||
|
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||||
|
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||||
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
|
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||||
|
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||||
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
|
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 h1:Dy3M9aegiI7d7PF1LUdjbVigJReo+QOceYsMyFh9qoE=
|
||||||
|
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0/go.mod h1:ZakZtbCXxCz82NJvq7MoREtiQesnDfrtF6RFUGzQfLo=
|
||||||
|
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
|
||||||
|
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 h1:8kDqDngH+DmVBiCtIjCFTGa7MBnsIOkF9IccInFEbjk=
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg=
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U=
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY=
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.1.0 h1:8iR6OLffWWorFdzL2JFCab5xpD8VKEE2DUBBl+HNTDY=
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.1.0/go.mod h1:copqlcjMWc/wgQ1N2fzsJFQxDdqKGg1EQt8T5wJMOGE=
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 h1:mLY+pNLjCUeKhgnAJWAKhEUQM+RJQo2H1fuGSw1Ky1E=
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2/go.mod h1:FbdwsQ2EzwvXxOPcMFYO8ogEc9uMMIj3YkmCdXdAFmk=
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.1.0 h1:rR8ZW79lE/ppfXTfiYSnMFv5EzmVuY4pfZWIkscIJ64=
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.1.0/go.mod h1:y2zXtLSMM/X5Mfawq0lOftpWn3f4V6OCsRdINsvWBPI=
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0 h1:ECsQtyERDVz3NP3kvDOTLvbQhqWp/x9EsGKtb4ogUr8=
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0/go.mod h1:s1tW/At+xHqjNFvWU4G0c0Qv33KOhvbGNj0RCTQDV8s=
|
||||||
|
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
|
||||||
|
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||||
|
github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc=
|
||||||
|
github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw=
|
||||||
|
github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs=
|
||||||
|
github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
|
||||||
|
github.com/Azure/go-autorest/autorest/adal v0.9.22 h1:/GblQdIudfEM3AWWZ0mrYJQSd7JS4S/Mbzh6F0ov0Xc=
|
||||||
|
github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk=
|
||||||
|
github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 h1:wkAZRgT/pn8HhFyzfe9UnqOjJYqlembgCTi72Bm/xKk=
|
||||||
|
github.com/Azure/go-autorest/autorest/azure/auth v0.5.12/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg=
|
||||||
|
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 h1:0W/yGmFdTIT77fvdlGZ0LMISoLHFJ7Tx4U0yeB+uFs4=
|
||||||
|
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg=
|
||||||
|
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
|
||||||
|
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
|
||||||
|
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
|
||||||
|
github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw=
|
||||||
|
github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU=
|
||||||
|
github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk=
|
||||||
|
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
|
||||||
|
github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
|
||||||
|
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||||
|
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||||
|
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||||
|
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY=
|
||||||
|
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
|
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 h1:xPMsUicZ3iosVPSIP7bW5EcGUzjiiMl1OYTe14y/R24=
|
||||||
|
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
|
||||||
|
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 h1:F1j7z+/DKEsYqZNoxC6wvfmaiDneLsQOFQmuq9NADSY=
|
||||||
|
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2/go.mod h1:QlXr/TrICfQ/ANa76sLeQyhAJyNR9sEcfNuZBkY9jgY=
|
||||||
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 h1:J45/QHgrzUdqe/Vco/Vxk0wRvdS2nKUxmf/zLgvfass=
|
||||||
|
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU=
|
||||||
|
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI=
|
||||||
|
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg=
|
||||||
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
|
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||||
|
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||||
|
github.com/aws/aws-sdk-go-v2 v1.24.1 h1:xAojnj+ktS95YZlDf0zxWBkbFtymPeDP+rvUQIH3uAU=
|
||||||
|
github.com/aws/aws-sdk-go-v2 v1.24.1/go.mod h1:LNh45Br1YAkEKaAqvmE1m8FUx6a5b/V0oAKV7of29b4=
|
||||||
|
github.com/aws/aws-sdk-go-v2/config v1.26.6 h1:Z/7w9bUqlRI0FFQpetVuFYEsjzE3h7fpU6HuGmfPL/o=
|
||||||
|
github.com/aws/aws-sdk-go-v2/config v1.26.6/go.mod h1:uKU6cnDmYCvJ+pxO9S4cWDb2yWWIH5hra+32hVh1MI4=
|
||||||
|
github.com/aws/aws-sdk-go-v2/credentials v1.16.16 h1:8q6Rliyv0aUFAVtzaldUEcS+T5gbadPbWdV1WcAddK8=
|
||||||
|
github.com/aws/aws-sdk-go-v2/credentials v1.16.16/go.mod h1:UHVZrdUsv63hPXFo1H7c5fEneoVo9UXiz36QG1GEPi0=
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 h1:c5I5iH+DZcH3xOIMlz3/tCKJDaHFwYEmxvlh2fAcFo8=
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11/go.mod h1:cRrYDYAMUohBJUtUnOhydaMHtiK/1NZ0Otc9lIb6O0Y=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 h1:vF+Zgd9s+H4vOXd5BMaPWykta2a6Ih0AKLq/X6NYKn4=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10/go.mod h1:6BkRjejp/GR4411UGqkX8+wFMbFbqsUIimfK4XjOKR4=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 h1:nYPe006ktcqUji8S2mqXf9c/7NdiKriOwMvWQHgYztw=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10/go.mod h1:6UV4SZkVvmODfXKql4LCbaZUpF7HO2BX38FgBf9ZOLw=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3 h1:n3GDfwqF2tzEkXlv5cuy4iy7LpKDtqDMcNLfZDu9rls=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 h1:/b31bi3YVNlkzkBrm9LfpaKoaYZUxIAj4sHfOTmLfqw=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4/go.mod h1:2aGXHFmbInwgP9ZfpmdIfOELL79zhdNYNmReK8qDfdQ=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 h1:DBYTXwIGQSGs9w4jKm60F5dmCQ3EEruxdc0MFh+3EY4=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10/go.mod h1:wohMUQiFdzo0NtxbBg0mSRGZ4vL3n0dKjLTINdcIino=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/lightsail v1.34.0 h1:LvWkxBi/bsWHqj3bFTUuDLl4OAlbaM1HDZ9YPhj5+jg=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/lightsail v1.34.0/go.mod h1:35MKNS46RX7Lb9EIFP2bPy3WrJu+bxU6QgLis8K1aa4=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.37.0 h1:f3hBZWtpn9clZGXJoqahQeec9ZPZnu22g8pg+zNyif0=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.37.0/go.mod h1:8qqfpG4mug2JLlEyWPSFhEGvJiaZ9iPmMDDMYc5Xtas=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sso v1.18.7 h1:eajuO3nykDPdYicLlP3AGgOyVN3MOlFmZv7WGTuJPow=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sso v1.18.7/go.mod h1:+mJNDdF+qiUlNKNC3fxn74WWNN+sOiGOEImje+3ScPM=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7 h1:QPMJf+Jw8E1l7zqhZmMlFw6w1NmfkfiSK8mS4zOx3BA=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7/go.mod h1:ykf3COxYI0UJmxcfcxcVuz7b6uADi1FkiUz6Eb7AgM8=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 h1:NzO4Vrau795RkUdSHKEwiR01FaGzGOH1EETJ+5QHnm0=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7/go.mod h1:6h2YuIoxaMSCFf5fi1EgZAwdfkGMgDY+DVfa61uLe4U=
|
||||||
|
github.com/aws/smithy-go v1.19.0 h1:KWFKQV80DpP3vJrrA9sVAHQ5gc2z8i4EzrLhLlWXcBM=
|
||||||
|
github.com/aws/smithy-go v1.19.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE=
|
||||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||||
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
|
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||||
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
|
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
|
||||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||||
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
|
||||||
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||||
|
github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7FVlAwDAVw=
|
||||||
|
github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
|
||||||
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
||||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
|
github.com/civo/civogo v0.3.11 h1:mON/fyrV946Sbk6paRtOSGsN+asCgCmHCgArf5xmGxM=
|
||||||
|
github.com/civo/civogo v0.3.11/go.mod h1:7+GeeFwc4AYTULaEshpT2vIcl3Qq8HPoxA17viX3l6g=
|
||||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/cloudflare/cloudflare-go v0.86.0 h1:jEKN5VHNYNYtfDL2lUFLTRo+nOVNPFxpXTstVx0rqHI=
|
||||||
|
github.com/cloudflare/cloudflare-go v0.86.0/go.mod h1:wYW/5UP02TUfBToa/yKbQHV+r6h1NnJ1Je7XjuGM4Jw=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
|
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
|
github.com/cpu/goacmedns v0.1.1 h1:DM3H2NiN2oam7QljgGY5ygy4yDXhK5Z4JUnqaugs2C4=
|
||||||
|
github.com/cpu/goacmedns v0.1.1/go.mod h1:MuaouqEhPAHxsbqjgnck5zeghuwBP1dLnPoobeGqugQ=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
|
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||||
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=
|
||||||
|
github.com/deepmap/oapi-codegen v1.9.1 h1:yHmEnA7jSTUMQgV+uN02WpZtwHnz2CBW3mZRIxr1vtI=
|
||||||
|
github.com/deepmap/oapi-codegen v1.9.1/go.mod h1:PLqNAhdedP8ttRpBBkzLKU3bp+Fpy+tTgeAMlztR2cw=
|
||||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
|
github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
|
||||||
|
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
|
||||||
|
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
|
||||||
|
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||||
|
github.com/dnsimple/dnsimple-go v1.2.0 h1:ddTGyLVKly5HKb5L65AkLqFqwZlWo3WnR0BlFZlIddM=
|
||||||
|
github.com/dnsimple/dnsimple-go v1.2.0/go.mod h1:z/cs26v/eiRvUyXsHQBLd8lWF8+cD6GbmkPH84plM4U=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
|
github.com/exoscale/egoscale v0.102.3 h1:DYqN2ipoLKpiFoprRGQkp2av/Ze7sUYYlGhi1N62tfY=
|
||||||
|
github.com/exoscale/egoscale v0.102.3/go.mod h1:RPf2Gah6up+6kAEayHTQwqapzXlm93f0VQas/UEGU5c=
|
||||||
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
|
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||||
|
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||||
|
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||||
|
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
|
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||||
|
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||||
|
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||||
|
github.com/getkin/kin-openapi v0.87.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
||||||
|
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||||
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
|
github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
||||||
github.com/go-acme/lego/v4 v4.16.1 h1:JxZ93s4KG0jL27rZ30UsIgxap6VGzKuREsSkkyzeoCQ=
|
github.com/go-acme/lego/v4 v4.16.1 h1:JxZ93s4KG0jL27rZ30UsIgxap6VGzKuREsSkkyzeoCQ=
|
||||||
github.com/go-acme/lego/v4 v4.16.1/go.mod h1:AVvwdPned/IWpD/ihHhMsKnveF7HHYAz/CmtXi7OZoE=
|
github.com/go-acme/lego/v4 v4.16.1/go.mod h1:AVvwdPned/IWpD/ihHhMsKnveF7HHYAz/CmtXi7OZoE=
|
||||||
|
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
|
||||||
|
github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s=
|
||||||
|
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||||
|
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||||
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
|
github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
|
||||||
github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
|
github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
|
||||||
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
|
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||||
github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw=
|
github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw=
|
||||||
github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
|
github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||||
|
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||||
|
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||||
|
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||||
|
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||||
|
github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||||
|
github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8=
|
||||||
|
github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
|
||||||
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
|
github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c=
|
||||||
|
github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||||
|
github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b h1:/vQ+oYKu+JoyaMPDsv5FzwuL2wwWBgBbtj/YLCi4LuA=
|
||||||
|
github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b/go.mod h1:Xo4aNUOrJnVruqWQJBtW6+bTBDTniY8yZum5rF3b5jw=
|
||||||
|
github.com/goccy/go-json v0.7.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
|
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||||
|
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
|
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
|
||||||
|
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
|
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
|
||||||
|
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||||
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
|
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||||
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
|
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||||
|
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
|
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
|
||||||
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||||
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
|
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
|
||||||
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
|
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||||
|
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
|
github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc=
|
||||||
|
github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
|
||||||
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k=
|
||||||
|
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI=
|
||||||
|
github.com/gophercloud/gophercloud v0.15.1-0.20210202035223-633d73521055/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4=
|
||||||
|
github.com/gophercloud/gophercloud v1.0.0 h1:9nTGx0jizmHxDobe4mck89FyQHVyA3CaXLIUSGJjP9k=
|
||||||
|
github.com/gophercloud/gophercloud v1.0.0/go.mod h1:Q8fZtyi5zZxPS/j9aj3sSxtvj41AdQMDwyo1myduD5c=
|
||||||
|
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae h1:Hi3IgB9RQDE15Kfovd8MTZrcana+UlQqNbOif8dLpA0=
|
||||||
|
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae/go.mod h1:wx8HMD8oQD0Ryhz6+6ykq75PJ79iPyEqYHfwZ4l7OsA=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
||||||
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
|
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
|
||||||
|
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
||||||
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
||||||
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
|
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
|
||||||
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
|
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
|
||||||
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
||||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
||||||
github.com/grandcat/zeroconf v1.0.0 h1:uHhahLBKqwWBV6WZUDAT71044vwOTL+McW0mBJvo6kE=
|
github.com/grandcat/zeroconf v1.0.0 h1:uHhahLBKqwWBV6WZUDAT71044vwOTL+McW0mBJvo6kE=
|
||||||
github.com/grandcat/zeroconf v1.0.0/go.mod h1:lTKmG1zh86XyCoUeIHSA4FJMBwCJiQmGfcP2PdzytEs=
|
github.com/grandcat/zeroconf v1.0.0/go.mod h1:lTKmG1zh86XyCoUeIHSA4FJMBwCJiQmGfcP2PdzytEs=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
||||||
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||||
|
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||||
|
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||||
|
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||||
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||||
|
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||||
|
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||||
|
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||||
|
github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM=
|
||||||
|
github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||||
|
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||||
|
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||||
|
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||||
|
github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M=
|
||||||
|
github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
|
||||||
|
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||||
|
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||||
|
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||||
|
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
|
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
|
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
|
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
|
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||||
|
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||||
|
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||||
|
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||||
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df h1:MZf03xP9WdakyXhOWuAD5uPK3wHh96wCsqe3hCMKh8E=
|
||||||
|
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
github.com/infobloxopen/infoblox-go-client v1.1.1 h1:728A6LbLjptj/7kZjHyIxQnm768PWHfGFm0HH8FnbtU=
|
||||||
|
github.com/infobloxopen/infoblox-go-client v1.1.1/go.mod h1:BXiw7S2b9qJoM8MS40vfgCNB2NLHGusk1DtO16BD9zI=
|
||||||
|
github.com/jarcoal/httpmock v1.0.8/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
||||||
|
github.com/jarcoal/httpmock v1.3.0 h1:2RJ8GP0IIaWwcC9Fp2BmVi8Kog3v2Hn7VXM3fTd+nuc=
|
||||||
|
github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
|
||||||
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||||
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||||
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||||
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
|
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 h1:qGQQKEcAR99REcMpsXCp3lJ03zYT1PkRd3kQGPn9GVg=
|
||||||
|
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
|
||||||
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00=
|
||||||
|
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||||
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
|
github.com/labbsr0x/bindman-dns-webhook v1.0.2 h1:I7ITbmQPAVwrDdhd6dHKi+MYJTJqPCK0jE6YNBAevnk=
|
||||||
|
github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA=
|
||||||
|
github.com/labbsr0x/goh v1.0.1 h1:97aBJkDjpyBZGPbQuOK5/gHcSFbcr5aRsq3RSRJFpPk=
|
||||||
|
github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w=
|
||||||
|
github.com/labstack/echo/v4 v4.6.3/go.mod h1:Hk5OiHj0kDqmFq7aHe7eDqI7CUhuCrfpupQtLGGLm7A=
|
||||||
|
github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
||||||
|
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||||
|
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||||
|
github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
|
||||||
|
github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ=
|
||||||
|
github.com/lestrrat-go/codegen v1.0.2/go.mod h1:JhJw6OQAuPEfVKUCLItpaVLumDGWQznd1VaXrBk9TdM=
|
||||||
|
github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE=
|
||||||
|
github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=
|
||||||
|
github.com/lestrrat-go/jwx v1.2.7/go.mod h1:bw24IXWbavc0R2RsOtpXL7RtMyP589yZ1+L7kd09ZGA=
|
||||||
|
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||||
github.com/likexian/gokit v0.25.13 h1:p2Uw3+6fGG53CwdU2Dz0T6bOycdb2+bAFAa3ymwWVkM=
|
github.com/likexian/gokit v0.25.13 h1:p2Uw3+6fGG53CwdU2Dz0T6bOycdb2+bAFAa3ymwWVkM=
|
||||||
github.com/likexian/gokit v0.25.13/go.mod h1:qQhEWFBEfqLCO3/vOEo2EDKd+EycekVtUK4tex+l2H4=
|
github.com/likexian/gokit v0.25.13/go.mod h1:qQhEWFBEfqLCO3/vOEo2EDKd+EycekVtUK4tex+l2H4=
|
||||||
github.com/likexian/whois v1.15.1 h1:6vTMI8n9s1eJdmcO4R9h1x99aQWIZZX1CD3am68gApU=
|
github.com/likexian/whois v1.15.1 h1:6vTMI8n9s1eJdmcO4R9h1x99aQWIZZX1CD3am68gApU=
|
||||||
github.com/likexian/whois v1.15.1/go.mod h1:/nxmQ6YXvLz+qTxC/QFtEJNAt0zLuRxJrKiWpBJX8X0=
|
github.com/likexian/whois v1.15.1/go.mod h1:/nxmQ6YXvLz+qTxC/QFtEJNAt0zLuRxJrKiWpBJX8X0=
|
||||||
|
github.com/linode/linodego v1.28.0 h1:lzxxJebsYg5cCWRNDLyL2StW3sfMyAwf/FYfxFjFrlk=
|
||||||
|
github.com/linode/linodego v1.28.0/go.mod h1:5oAsx+uinHtVo6U77nXXXtox7MWzUW6aEkTOKXxA9uo=
|
||||||
|
github.com/liquidweb/go-lwApi v0.0.0-20190605172801-52a4864d2738/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=
|
||||||
|
github.com/liquidweb/liquidweb-cli v0.6.9 h1:acbIvdRauiwbxIsOCEMXGwF75aSJDbDiyAWPjVnwoYM=
|
||||||
|
github.com/liquidweb/liquidweb-cli v0.6.9/go.mod h1:cE1uvQ+x24NGUL75D0QagOFCG8Wdvmwu8aL9TLmA/eQ=
|
||||||
|
github.com/liquidweb/liquidweb-go v1.6.4 h1:6S0m3hHSpiLqGD7AFSb7lH/W/qr1wx+tKil9fgIbjMc=
|
||||||
|
github.com/liquidweb/liquidweb-go v1.6.4/go.mod h1:B934JPIIcdA+uTq2Nz5PgOtG6CuCaEvQKe/Ge/5GgZ4=
|
||||||
|
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
|
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||||
|
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
|
||||||
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
|
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
|
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
|
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||||
|
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||||
|
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||||
|
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
|
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||||
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
|
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
|
github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
|
github.com/maxatome/go-testdeep v1.12.0 h1:Ql7Go8Tg0C1D/uMMX59LAoYK7LffeJQ6X2T04nTH68g=
|
||||||
|
github.com/maxatome/go-testdeep v1.12.0/go.mod h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
|
github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
|
github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
|
||||||
|
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||||
|
github.com/miekg/dns v1.1.47/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||||
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
||||||
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
|
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
|
||||||
|
github.com/mimuret/golang-iij-dpf v0.9.1 h1:Gj6EhHJkOhr+q2RnvRPJsPMcjuVnWPSccEHyoEehU34=
|
||||||
|
github.com/mimuret/golang-iij-dpf v0.9.1/go.mod h1:sl9KyOkESib9+KRD3HaGpgi1xk7eoN2+d96LCLsME2M=
|
||||||
|
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||||
|
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
|
||||||
|
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||||
|
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||||
|
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||||
|
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
|
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 h1:o6uBwrhM5C8Ll3MAAxrQxRHEu7FkapwTuI2WmL1rw4g=
|
||||||
|
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8=
|
||||||
|
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
|
github.com/nrdcg/auroradns v1.1.0 h1:KekGh8kmf2MNwqZVVYo/fw/ZONt8QMEmbMFOeljteWo=
|
||||||
|
github.com/nrdcg/auroradns v1.1.0/go.mod h1:O7tViUZbAcnykVnrGkXzIJTHoQCHcgalgAe6X1mzHfk=
|
||||||
|
github.com/nrdcg/bunny-go v0.0.0-20230728143221-c9dda82568d9 h1:qpB3wZR4+MPK92cTC9zZPnndkJgDgPvQqPUAgVc1NXU=
|
||||||
|
github.com/nrdcg/bunny-go v0.0.0-20230728143221-c9dda82568d9/go.mod h1:HUoHXDrFvidN1NK9Wb/mZKNOfDNutKkzF2Pg71M9hHA=
|
||||||
|
github.com/nrdcg/desec v0.7.0 h1:iuGhi4pstF3+vJWwt292Oqe2+AsSPKDynQna/eu1fDs=
|
||||||
|
github.com/nrdcg/desec v0.7.0/go.mod h1:e1uRqqKv1mJdd5+SQROAhmy75lKMphLzWIuASLkpeFY=
|
||||||
|
github.com/nrdcg/dnspod-go v0.4.0 h1:c/jn1mLZNKF3/osJ6mz3QPxTudvPArXTjpkmYj0uK6U=
|
||||||
|
github.com/nrdcg/dnspod-go v0.4.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgPTGKr6KQ=
|
||||||
|
github.com/nrdcg/freemyip v0.2.0 h1:/GscavT4GVqAY13HExl5UyoB4wlchv6Cg5NYDGsUoJ8=
|
||||||
|
github.com/nrdcg/freemyip v0.2.0/go.mod h1:HjF0Yz0lSb37HD2ihIyGz9esyGcxbCrrGFLPpKevbx4=
|
||||||
|
github.com/nrdcg/goinwx v0.10.0 h1:6W630bjDxQD6OuXKqrFRYVpTt0G/9GXXm3CeOrN0zJM=
|
||||||
|
github.com/nrdcg/goinwx v0.10.0/go.mod h1:mnMSTi7CXBu2io4DzdOBoGFA1XclD0sEPWJaDhNgkA4=
|
||||||
|
github.com/nrdcg/mailinabox v0.2.0 h1:IKq8mfKiVwNW2hQii/ng1dJ4yYMMv3HAP3fMFIq2CFk=
|
||||||
|
github.com/nrdcg/mailinabox v0.2.0/go.mod h1:0yxqeYOiGyxAu7Sb94eMxHPIOsPYXAjTeA9ZhePhGnc=
|
||||||
|
github.com/nrdcg/namesilo v0.2.1 h1:kLjCjsufdW/IlC+iSfAqj0iQGgKjlbUUeDJio5Y6eMg=
|
||||||
|
github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw=
|
||||||
|
github.com/nrdcg/nodion v0.1.0 h1:zLKaqTn2X0aDuBHHfyA1zFgeZfiCpmu/O9DM73okavw=
|
||||||
|
github.com/nrdcg/nodion v0.1.0/go.mod h1:inbuh3neCtIWlMPZHtEpe43TmRXxHV6+hk97iCZicms=
|
||||||
|
github.com/nrdcg/porkbun v0.3.0 h1:jnRV7j2zd3hmh+tSDOGetJyy3+WklaMxbs7HtTTmWMs=
|
||||||
|
github.com/nrdcg/porkbun v0.3.0/go.mod h1:jh1DKz96jGHW+NCdG3AmTbbnQeBlNUz1KeSgeN/cBVw=
|
||||||
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
|
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||||
|
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||||
|
github.com/nzdjb/go-metaname v1.0.0 h1:sNASlZC1RM3nSudtBTE1a3ZVTDyTpjqI5WXRPrdZ9Hg=
|
||||||
|
github.com/nzdjb/go-metaname v1.0.0/go.mod h1:0GR0LshZax1Lz4VrOrfNSE4dGvTp7HGjiemdczXT2H4=
|
||||||
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
|
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||||
|
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||||
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
|
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||||
|
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
||||||
|
github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
|
||||||
|
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||||
|
github.com/oracle/oci-go-sdk v24.3.0+incompatible h1:x4mcfb4agelf1O4/1/auGlZ1lr97jXRSSN5MxTgG/zU=
|
||||||
|
github.com/oracle/oci-go-sdk v24.3.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
|
||||||
|
github.com/ovh/go-ovh v1.4.3 h1:Gs3V823zwTFpzgGLZNI6ILS4rmxZgJwJCz54Er9LwD0=
|
||||||
|
github.com/ovh/go-ovh v1.4.3/go.mod h1:AkPXVtgwB6xlKblMjRKJJmjRp+ogrE7fz2lVgcQY8SY=
|
||||||
|
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
|
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||||
|
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||||
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
|
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||||
|
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||||
|
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||||
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||||
|
github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||||
|
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
|
||||||
|
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||||
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
|
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||||
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
|
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
|
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
|
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
|
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||||
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
|
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||||
|
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
|
||||||
|
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
|
||||||
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
|
github.com/sacloud/api-client-go v0.2.8 h1:tIY6PZNBX900K66TqEPa4d6UIbedUczfCBnPJkzi8kw=
|
||||||
|
github.com/sacloud/api-client-go v0.2.8/go.mod h1:0CV/kWNYlS1hCNdnk6Wx7Wdg8DPFCnv0zOIzdXjeAeY=
|
||||||
|
github.com/sacloud/go-http v0.1.6 h1:lJGXDt9xrxJiDszRPaN9NIP8MVj10YKMzmnyzdSfI8w=
|
||||||
|
github.com/sacloud/go-http v0.1.6/go.mod h1:oLAHoDJRkptf8sq4fE8oERLkdCh0kJWfWu+paoJY7I0=
|
||||||
|
github.com/sacloud/iaas-api-go v1.11.1 h1:2MsFZ4H1uRdRVx2nVXuERWQ3swoFc3XreIV5hJ3Nsws=
|
||||||
|
github.com/sacloud/iaas-api-go v1.11.1/go.mod h1:uBDSa06F/V0OnoR66jGdbH0PVnCJw+NeE9RVbVgMfss=
|
||||||
|
github.com/sacloud/packages-go v0.0.9 h1:GbinkBLC/eirFhHpLjoDW6JV7+95Rnd2d8RWj7Afeks=
|
||||||
|
github.com/sacloud/packages-go v0.0.9/go.mod h1:k+EEUMF2LlncjbNIJNOqLyZ9wjTESPIWIk1OA7x9j2Q=
|
||||||
|
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.22 h1:wJrcTdddKOI8TFxs8cemnhKP2EmKy3yfUKHj3ZdfzYo=
|
||||||
|
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.22/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
|
||||||
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
|
github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w=
|
||||||
|
github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
|
||||||
|
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 h1:hp2CYQUINdZMHdvTdXtPOY2ainKl4IoMcpAXEf2xj3Q=
|
||||||
|
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
|
||||||
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
|
github.com/smartystreets/gunit v1.0.4 h1:tpTjnuH7MLlqhoD21vRoMZbMIi5GmBsAJDFyF67GhZA=
|
||||||
|
github.com/smartystreets/gunit v1.0.4/go.mod h1:EH5qMBab2UclzXUcpR8b93eHsIlp9u+pDQIRp5DZNzQ=
|
||||||
|
github.com/softlayer/softlayer-go v1.1.3 h1:dfFzt5eOKIAyB/b78fHMyDu5ICx0ZtxL9NRhBlf831A=
|
||||||
|
github.com/softlayer/softlayer-go v1.1.3/go.mod h1:Pc7F57OgUKaAam7TtpqkUeqL7QyKknfiUI4R49h41/U=
|
||||||
|
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e h1:3OgWYFw7jxCZPcvAg+4R8A50GZ+CCkARF10lxu2qDsQ=
|
||||||
|
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e/go.mod h1:fKZCUVdirrxrBpwd9wb+lSoVixvpwAu8eHzbQB2tums=
|
||||||
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
|
github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||||
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
|
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
|
||||||
|
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
|
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
|
||||||
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
|
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||||
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||||
|
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0=
|
||||||
|
github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 h1:mmz27tVi2r70JYnm5y0Zk8w0Qzsx+vfUw3oqSyrEfP8=
|
||||||
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
|
||||||
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 h1:g9SWTaTy/rEuhMErC2jWq9Qt5ci+jBYSvXnJsLq4adg=
|
||||||
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490/go.mod h1:l9q4vc1QiawUB1m3RU+87yLvrrxe54jc0w/kEl4DbSQ=
|
||||||
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
|
github.com/transip/gotransip/v6 v6.23.0 h1:PsTdjortrEZ8IFFifEryzjVjOy9SgK4ahlnhKBBIQgA=
|
||||||
|
github.com/transip/gotransip/v6 v6.23.0/go.mod h1:nzv9eN2tdsUrm5nG5ZX6AugYIU4qgsMwIn2c0EZLk8c=
|
||||||
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
|
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
|
||||||
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
|
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
|
||||||
|
github.com/ultradns/ultradns-go-sdk v1.6.1-20231103022937-8589b6a h1:w4PK5/N9kq8PfNxBv8a5t1bqlYRrVT7XzT7iTPTtiPk=
|
||||||
|
github.com/ultradns/ultradns-go-sdk v1.6.1-20231103022937-8589b6a/go.mod h1:Xwz7o+ExFtxR/i0aJDnTXuiccQJlOxDgNe6FsZC4TzQ=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
|
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||||
|
github.com/vinyldns/go-vinyldns v0.9.16 h1:GZJStDkcCk1F1AcRc64LuuMh+ENL8pHA0CVd4ulRMcQ=
|
||||||
|
github.com/vinyldns/go-vinyldns v0.9.16/go.mod h1:5qIJOdmzAnatKjurI+Tl4uTus7GJKJxb+zitufjHs3Q=
|
||||||
|
github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs=
|
||||||
|
github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI=
|
||||||
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||||
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||||
|
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||||
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
|
github.com/yandex-cloud/go-genproto v0.0.0-20220805142335-27b56ddae16f h1:cG+ehPRJSlqljSufLf1KXeXpUd1dLNjnzA18mZcB/O0=
|
||||||
|
github.com/yandex-cloud/go-genproto v0.0.0-20220805142335-27b56ddae16f/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE=
|
||||||
|
github.com/yandex-cloud/go-sdk v0.0.0-20220805164847-cf028e604997 h1:2wzke3JH7OtN20WsNDZx2VH/TCmsbqtDEbXzjF+i05E=
|
||||||
|
github.com/yandex-cloud/go-sdk v0.0.0-20220805164847-cf028e604997/go.mod h1:2CHKs/YGbCcNn/BPaCkEBwKz/FNCELi+MLILjR9RaTA=
|
||||||
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
|
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||||
|
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||||
|
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||||
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
|
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||||
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
|
go.uber.org/ratelimit v0.2.0 h1:UQE2Bgi7p2B85uP5dC2bbRtig0C+OeNRnNEafLjsLPA=
|
||||||
|
go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg=
|
||||||
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
|
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||||
|
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||||
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
|
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||||
|
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||||
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
|
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
|
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
|
||||||
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
|
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||||
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
|
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
|
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||||
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
|
||||||
|
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
|
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||||
|
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||||
|
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||||
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
|
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
|
||||||
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
|
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
|
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||||
|
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
|
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
|
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.126.0 h1:q4GJq+cAdMAC7XP7njvQ4tvohGLiSlytuL4BQxbIZ+o=
|
||||||
|
google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw=
|
||||||
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
|
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||||
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||||
|
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
|
google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc h1:8DyZCyvI8mE1IdLy/60bS+52xfymkE72wv1asokgtao=
|
||||||
|
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
|
||||||
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||||
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||||
|
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
|
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
|
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||||
|
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
||||||
|
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
||||||
|
google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
|
||||||
|
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
|
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
|
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||||
|
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
gopkg.in/h2non/gock.v1 v1.0.15 h1:SzLqcIlb/fDfg7UvukMpNcWsu7sI5tWwL+KCATZqks0=
|
||||||
|
gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE=
|
||||||
|
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||||
|
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/ns1/ns1-go.v2 v2.7.13 h1:r07CLALg18f/L1KIK1ZJdbirBV349UtYT1rDWGjnaTk=
|
||||||
|
gopkg.in/ns1/ns1-go.v2 v2.7.13/go.mod h1:pfaU0vECVP7DIOr453z03HXS6dFJpXdNRwOyRzwmPSc=
|
||||||
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"imuslab.com/zoraxy/mod/access"
|
||||||
"imuslab.com/zoraxy/mod/acme"
|
"imuslab.com/zoraxy/mod/acme"
|
||||||
"imuslab.com/zoraxy/mod/auth"
|
"imuslab.com/zoraxy/mod/auth"
|
||||||
"imuslab.com/zoraxy/mod/database"
|
"imuslab.com/zoraxy/mod/database"
|
||||||
@ -40,6 +41,7 @@ var noauth = flag.Bool("noauth", false, "Disable authentication for management i
|
|||||||
var showver = flag.Bool("version", false, "Show version of this server")
|
var showver = flag.Bool("version", false, "Show version of this server")
|
||||||
var allowSshLoopback = flag.Bool("sshlb", false, "Allow loopback web ssh connection (DANGER)")
|
var allowSshLoopback = flag.Bool("sshlb", false, "Allow loopback web ssh connection (DANGER)")
|
||||||
var allowMdnsScanning = flag.Bool("mdns", true, "Enable mDNS scanner and transponder")
|
var allowMdnsScanning = flag.Bool("mdns", true, "Enable mDNS scanner and transponder")
|
||||||
|
var mdnsName = flag.String("mdnsname", "", "mDNS name, leave empty to use default (zoraxy_{node-uuid}.local)")
|
||||||
var ztAuthToken = flag.String("ztauth", "", "ZeroTier authtoken for the local node")
|
var ztAuthToken = flag.String("ztauth", "", "ZeroTier authtoken for the local node")
|
||||||
var ztAPIPort = flag.Int("ztport", 9993, "ZeroTier controller API port")
|
var ztAPIPort = flag.Int("ztport", 9993, "ZeroTier controller API port")
|
||||||
var acmeAutoRenewInterval = flag.Int("autorenew", 86400, "ACME auto TLS/SSL certificate renew check interval (seconds)")
|
var acmeAutoRenewInterval = flag.Int("autorenew", 86400, "ACME auto TLS/SSL certificate renew check interval (seconds)")
|
||||||
@ -50,7 +52,7 @@ var logOutputToFile = flag.Bool("log", true, "Log terminal output to file")
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
name = "Zoraxy"
|
name = "Zoraxy"
|
||||||
version = "3.0.1"
|
version = "3.0.4"
|
||||||
nodeUUID = "generic"
|
nodeUUID = "generic"
|
||||||
development = false //Set this to false to use embedded web fs
|
development = false //Set this to false to use embedded web fs
|
||||||
bootTime = time.Now().Unix()
|
bootTime = time.Now().Unix()
|
||||||
@ -69,7 +71,8 @@ var (
|
|||||||
tlsCertManager *tlscert.Manager //TLS / SSL management
|
tlsCertManager *tlscert.Manager //TLS / SSL management
|
||||||
redirectTable *redirection.RuleTable //Handle special redirection rule sets
|
redirectTable *redirection.RuleTable //Handle special redirection rule sets
|
||||||
pathRuleHandler *pathrule.Handler //Handle specific path blocking or custom headers
|
pathRuleHandler *pathrule.Handler //Handle specific path blocking or custom headers
|
||||||
geodbStore *geodb.Store //GeoIP database, also handle black list and whitelist features
|
geodbStore *geodb.Store //GeoIP database, for resolving IP into country code
|
||||||
|
accessController *access.Controller //Access controller, handle black list and white list
|
||||||
netstatBuffers *netstat.NetStatBuffers //Realtime graph buffers
|
netstatBuffers *netstat.NetStatBuffers //Realtime graph buffers
|
||||||
statisticCollector *statistic.Collector //Collecting statistic from visitors
|
statisticCollector *statistic.Collector //Collecting statistic from visitors
|
||||||
uptimeMonitor *uptime.Monitor //Uptime monitor service worker
|
uptimeMonitor *uptime.Monitor //Uptime monitor service worker
|
||||||
|
221
src/mod/access/access.go
Normal file
221
src/mod/access/access.go
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
package access
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"imuslab.com/zoraxy/mod/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Access.go
|
||||||
|
|
||||||
|
This module is the new version of access control system
|
||||||
|
where now the blacklist / whitelist are seperated from
|
||||||
|
geodb module
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Create a new access controller to handle blacklist / whitelist
|
||||||
|
func NewAccessController(options *Options) (*Controller, error) {
|
||||||
|
sysdb := options.Database
|
||||||
|
if sysdb == nil {
|
||||||
|
return nil, errors.New("missing database access")
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create the config folder if not exists
|
||||||
|
confFolder := options.ConfigFolder
|
||||||
|
if !utils.FileExists(confFolder) {
|
||||||
|
err := os.MkdirAll(confFolder, 0775)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the global access rule if not exists
|
||||||
|
var defaultAccessRule = AccessRule{
|
||||||
|
ID: "default",
|
||||||
|
Name: "Default",
|
||||||
|
Desc: "Default access rule for all HTTP proxy hosts",
|
||||||
|
BlacklistEnabled: false,
|
||||||
|
WhitelistEnabled: false,
|
||||||
|
WhiteListCountryCode: &map[string]string{},
|
||||||
|
WhiteListIP: &map[string]string{},
|
||||||
|
BlackListContryCode: &map[string]string{},
|
||||||
|
BlackListIP: &map[string]string{},
|
||||||
|
}
|
||||||
|
defaultRuleSettingFile := filepath.Join(confFolder, "default.json")
|
||||||
|
if utils.FileExists(defaultRuleSettingFile) {
|
||||||
|
//Load from file
|
||||||
|
defaultRuleBytes, err := os.ReadFile(defaultRuleSettingFile)
|
||||||
|
if err == nil {
|
||||||
|
err = json.Unmarshal(defaultRuleBytes, &defaultAccessRule)
|
||||||
|
if err != nil {
|
||||||
|
options.Logger.PrintAndLog("Access", "Unable to parse default routing rule config file. Using default", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Create one
|
||||||
|
js, _ := json.MarshalIndent(defaultAccessRule, "", " ")
|
||||||
|
os.WriteFile(defaultRuleSettingFile, js, 0775)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Generate a controller object
|
||||||
|
thisController := Controller{
|
||||||
|
DefaultAccessRule: &defaultAccessRule,
|
||||||
|
ProxyAccessRule: &sync.Map{},
|
||||||
|
Options: options,
|
||||||
|
}
|
||||||
|
|
||||||
|
//Assign default access rule parent
|
||||||
|
thisController.DefaultAccessRule.parent = &thisController
|
||||||
|
|
||||||
|
//Load all acccess rules from file
|
||||||
|
configFiles, err := filepath.Glob(options.ConfigFolder + "/*.json")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ProxyAccessRules := sync.Map{}
|
||||||
|
for _, configFile := range configFiles {
|
||||||
|
if filepath.Base(configFile) == "default.json" {
|
||||||
|
//Skip this, as this was already loaded as default
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
configContent, err := os.ReadFile(configFile)
|
||||||
|
if err != nil {
|
||||||
|
options.Logger.PrintAndLog("Access", "Unable to load config "+filepath.Base(configFile), err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
//Parse the config file into AccessRule
|
||||||
|
thisAccessRule := AccessRule{}
|
||||||
|
err = json.Unmarshal(configContent, &thisAccessRule)
|
||||||
|
if err != nil {
|
||||||
|
options.Logger.PrintAndLog("Access", "Unable to parse config "+filepath.Base(configFile), err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
thisAccessRule.parent = &thisController
|
||||||
|
ProxyAccessRules.Store(thisAccessRule.ID, &thisAccessRule)
|
||||||
|
}
|
||||||
|
thisController.ProxyAccessRule = &ProxyAccessRules
|
||||||
|
|
||||||
|
return &thisController, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the global access rule
|
||||||
|
func (c *Controller) GetGlobalAccessRule() (*AccessRule, error) {
|
||||||
|
if c.DefaultAccessRule == nil {
|
||||||
|
return nil, errors.New("global access rule is not set")
|
||||||
|
}
|
||||||
|
return c.DefaultAccessRule, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load access rules to runtime, require rule ID
|
||||||
|
func (c *Controller) GetAccessRuleByID(accessRuleID string) (*AccessRule, error) {
|
||||||
|
if accessRuleID == "default" || accessRuleID == "" {
|
||||||
|
|
||||||
|
return c.DefaultAccessRule, nil
|
||||||
|
}
|
||||||
|
//Load from sync.Map, should be O(1)
|
||||||
|
targetRule, ok := c.ProxyAccessRule.Load(accessRuleID)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("target access rule not exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
ar, ok := targetRule.(*AccessRule)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("assertion of access rule failed, version too old?")
|
||||||
|
}
|
||||||
|
return ar, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return all the access rules currently in runtime, including default
|
||||||
|
func (c *Controller) ListAllAccessRules() []*AccessRule {
|
||||||
|
results := []*AccessRule{c.DefaultAccessRule}
|
||||||
|
c.ProxyAccessRule.Range(func(key, value interface{}) bool {
|
||||||
|
results = append(results, value.(*AccessRule))
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if an access rule exists given the rule id
|
||||||
|
func (c *Controller) AccessRuleExists(ruleID string) bool {
|
||||||
|
r, _ := c.GetAccessRuleByID(ruleID)
|
||||||
|
if r != nil {
|
||||||
|
//An access rule with identical ID exists
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a new access rule to runtime and save it to file
|
||||||
|
func (c *Controller) AddNewAccessRule(newRule *AccessRule) error {
|
||||||
|
r, _ := c.GetAccessRuleByID(newRule.ID)
|
||||||
|
if r != nil {
|
||||||
|
//An access rule with identical ID exists
|
||||||
|
return errors.New("access rule already exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if the blacklist and whitelist are populated with empty map
|
||||||
|
if newRule.BlackListContryCode == nil {
|
||||||
|
newRule.BlackListContryCode = &map[string]string{}
|
||||||
|
}
|
||||||
|
if newRule.BlackListIP == nil {
|
||||||
|
newRule.BlackListIP = &map[string]string{}
|
||||||
|
}
|
||||||
|
if newRule.WhiteListCountryCode == nil {
|
||||||
|
newRule.WhiteListCountryCode = &map[string]string{}
|
||||||
|
}
|
||||||
|
if newRule.WhiteListIP == nil {
|
||||||
|
newRule.WhiteListIP = &map[string]string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add access rule to runtime
|
||||||
|
newRule.parent = c
|
||||||
|
c.ProxyAccessRule.Store(newRule.ID, newRule)
|
||||||
|
|
||||||
|
//Save rule to file
|
||||||
|
newRule.SaveChanges()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the access rule meta info.
|
||||||
|
func (c *Controller) UpdateAccessRule(ruleID string, name string, desc string) error {
|
||||||
|
targetAccessRule, err := c.GetAccessRuleByID(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
///Update the name and desc
|
||||||
|
targetAccessRule.Name = name
|
||||||
|
targetAccessRule.Desc = desc
|
||||||
|
|
||||||
|
//Overwrite the rule currently in sync map
|
||||||
|
if ruleID == "default" {
|
||||||
|
c.DefaultAccessRule = targetAccessRule
|
||||||
|
} else {
|
||||||
|
c.ProxyAccessRule.Store(ruleID, targetAccessRule)
|
||||||
|
}
|
||||||
|
return targetAccessRule.SaveChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the access rule by its id
|
||||||
|
func (c *Controller) RemoveAccessRuleByID(ruleID string) error {
|
||||||
|
if !c.AccessRuleExists(ruleID) {
|
||||||
|
return errors.New("access rule not exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
//Default cannot be removed
|
||||||
|
if ruleID == "default" {
|
||||||
|
return errors.New("default access rule cannot be removed")
|
||||||
|
}
|
||||||
|
|
||||||
|
//Remove it
|
||||||
|
return c.DeleteAccessRuleByID(ruleID)
|
||||||
|
}
|
153
src/mod/access/accessRule.go
Normal file
153
src/mod/access/accessRule.go
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
package access
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check both blacklist and whitelist for access for both geoIP and ip / CIDR ranges
|
||||||
|
func (s *AccessRule) AllowIpAccess(ipaddr string) bool {
|
||||||
|
if s.IsBlacklisted(ipaddr) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.IsWhitelisted(ipaddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check both blacklist and whitelist for access using net.Conn
|
||||||
|
func (s *AccessRule) AllowConnectionAccess(conn net.Conn) bool {
|
||||||
|
if addr, ok := conn.RemoteAddr().(*net.TCPAddr); ok {
|
||||||
|
return s.AllowIpAccess(addr.IP.String())
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle black list
|
||||||
|
func (s *AccessRule) ToggleBlacklist(enabled bool) {
|
||||||
|
s.BlacklistEnabled = enabled
|
||||||
|
s.SaveChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggel white list
|
||||||
|
func (s *AccessRule) ToggleWhitelist(enabled bool) {
|
||||||
|
s.WhitelistEnabled = enabled
|
||||||
|
s.SaveChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check if a IP address is blacklisted, in either country or IP blacklist
|
||||||
|
IsBlacklisted default return is false (allow access)
|
||||||
|
*/
|
||||||
|
func (s *AccessRule) IsBlacklisted(ipAddr string) bool {
|
||||||
|
if !s.BlacklistEnabled {
|
||||||
|
//Blacklist not enabled. Always return false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if ipAddr == "" {
|
||||||
|
//Unable to get the target IP address
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
countryCode, err := s.parent.Options.GeoDB.ResolveCountryCodeFromIP(ipAddr)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.IsCountryCodeBlacklisted(countryCode.CountryIsoCode) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.IsIPBlacklisted(ipAddr) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
IsWhitelisted check if a given IP address is in the current
|
||||||
|
server's white list.
|
||||||
|
|
||||||
|
Note that the Whitelist default result is true even
|
||||||
|
when encountered error
|
||||||
|
*/
|
||||||
|
func (s *AccessRule) IsWhitelisted(ipAddr string) bool {
|
||||||
|
if !s.WhitelistEnabled {
|
||||||
|
//Whitelist not enabled. Always return true (allow access)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ipAddr == "" {
|
||||||
|
//Unable to get the target IP address, assume ok
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
countryCode, err := s.parent.Options.GeoDB.ResolveCountryCodeFromIP(ipAddr)
|
||||||
|
if err != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.IsCountryCodeWhitelisted(countryCode.CountryIsoCode) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.IsIPWhitelisted(ipAddr) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Utilities function */
|
||||||
|
|
||||||
|
// Update the current access rule to json file
|
||||||
|
func (s *AccessRule) SaveChanges() error {
|
||||||
|
if s.parent == nil {
|
||||||
|
return errors.New("save failed: access rule detached from controller")
|
||||||
|
}
|
||||||
|
saveTarget := filepath.Join(s.parent.Options.ConfigFolder, s.ID+".json")
|
||||||
|
js, err := json.MarshalIndent(s, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile(saveTarget, js, 0775)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete this access rule, this will only delete the config file.
|
||||||
|
// for runtime delete, use DeleteAccessRuleByID from parent Controller
|
||||||
|
func (s *AccessRule) DeleteConfigFile() error {
|
||||||
|
saveTarget := filepath.Join(s.parent.Options.ConfigFolder, s.ID+".json")
|
||||||
|
return os.Remove(saveTarget)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the access rule by given ID
|
||||||
|
func (c *Controller) DeleteAccessRuleByID(accessRuleID string) error {
|
||||||
|
targetAccessRule, err := c.GetAccessRuleByID(accessRuleID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//Delete config file associated with this access rule
|
||||||
|
err = targetAccessRule.DeleteConfigFile()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//Delete the access rule in runtime
|
||||||
|
c.ProxyAccessRule.Delete(accessRuleID)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a deep copy object of the access rule list
|
||||||
|
func deepCopy(valueList map[string]string) map[string]string {
|
||||||
|
result := map[string]string{}
|
||||||
|
js, _ := json.Marshal(valueList)
|
||||||
|
json.Unmarshal(js, &result)
|
||||||
|
return result
|
||||||
|
}
|
94
src/mod/access/blacklist.go
Normal file
94
src/mod/access/blacklist.go
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package access
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"imuslab.com/zoraxy/mod/netutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Blacklist.go
|
||||||
|
|
||||||
|
This script store the blacklist related functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Geo Blacklist
|
||||||
|
func (s *AccessRule) AddCountryCodeToBlackList(countryCode string, comment string) {
|
||||||
|
countryCode = strings.ToLower(countryCode)
|
||||||
|
newBlacklistCountryCode := deepCopy(*s.BlackListContryCode)
|
||||||
|
newBlacklistCountryCode[countryCode] = comment
|
||||||
|
s.BlackListContryCode = &newBlacklistCountryCode
|
||||||
|
s.SaveChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *AccessRule) RemoveCountryCodeFromBlackList(countryCode string) {
|
||||||
|
countryCode = strings.ToLower(countryCode)
|
||||||
|
newBlacklistCountryCode := deepCopy(*s.BlackListContryCode)
|
||||||
|
delete(newBlacklistCountryCode, countryCode)
|
||||||
|
s.BlackListContryCode = &newBlacklistCountryCode
|
||||||
|
s.SaveChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *AccessRule) IsCountryCodeBlacklisted(countryCode string) bool {
|
||||||
|
countryCode = strings.ToLower(countryCode)
|
||||||
|
blacklistMap := *s.BlackListContryCode
|
||||||
|
_, ok := blacklistMap[countryCode]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *AccessRule) GetAllBlacklistedCountryCode() []string {
|
||||||
|
bannedCountryCodes := []string{}
|
||||||
|
blacklistMap := *s.BlackListContryCode
|
||||||
|
for cc, _ := range blacklistMap {
|
||||||
|
bannedCountryCodes = append(bannedCountryCodes, cc)
|
||||||
|
}
|
||||||
|
return bannedCountryCodes
|
||||||
|
}
|
||||||
|
|
||||||
|
// IP Blacklsits
|
||||||
|
func (s *AccessRule) AddIPToBlackList(ipAddr string, comment string) {
|
||||||
|
newBlackListIP := deepCopy(*s.BlackListIP)
|
||||||
|
newBlackListIP[ipAddr] = comment
|
||||||
|
s.BlackListIP = &newBlackListIP
|
||||||
|
s.SaveChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *AccessRule) RemoveIPFromBlackList(ipAddr string) {
|
||||||
|
newBlackListIP := deepCopy(*s.BlackListIP)
|
||||||
|
delete(newBlackListIP, ipAddr)
|
||||||
|
s.BlackListIP = &newBlackListIP
|
||||||
|
s.SaveChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *AccessRule) GetAllBlacklistedIp() []string {
|
||||||
|
bannedIps := []string{}
|
||||||
|
blacklistMap := *s.BlackListIP
|
||||||
|
for ip, _ := range blacklistMap {
|
||||||
|
bannedIps = append(bannedIps, ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
return bannedIps
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *AccessRule) IsIPBlacklisted(ipAddr string) bool {
|
||||||
|
IPBlacklist := *s.BlackListIP
|
||||||
|
_, ok := IPBlacklist[ipAddr]
|
||||||
|
if ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check for CIDR
|
||||||
|
for ipOrCIDR, _ := range IPBlacklist {
|
||||||
|
wildcardMatch := netutils.MatchIpWildcard(ipAddr, ipOrCIDR)
|
||||||
|
if wildcardMatch {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
cidrMatch := netutils.MatchIpCIDR(ipAddr, ipOrCIDR)
|
||||||
|
if cidrMatch {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
38
src/mod/access/typedef.go
Normal file
38
src/mod/access/typedef.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package access
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"imuslab.com/zoraxy/mod/database"
|
||||||
|
"imuslab.com/zoraxy/mod/geodb"
|
||||||
|
"imuslab.com/zoraxy/mod/info/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Options struct {
|
||||||
|
Logger logger.Logger
|
||||||
|
ConfigFolder string //Path for storing config files
|
||||||
|
GeoDB *geodb.Store //For resolving country code
|
||||||
|
Database *database.Database //System key-value database
|
||||||
|
}
|
||||||
|
|
||||||
|
type AccessRule struct {
|
||||||
|
ID string
|
||||||
|
Name string
|
||||||
|
Desc string
|
||||||
|
BlacklistEnabled bool
|
||||||
|
WhitelistEnabled bool
|
||||||
|
|
||||||
|
/* Whitelist Blacklist Table, value is comment if supported */
|
||||||
|
WhiteListCountryCode *map[string]string
|
||||||
|
WhiteListIP *map[string]string
|
||||||
|
BlackListContryCode *map[string]string
|
||||||
|
BlackListIP *map[string]string
|
||||||
|
|
||||||
|
parent *Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
type Controller struct {
|
||||||
|
DefaultAccessRule *AccessRule
|
||||||
|
ProxyAccessRule *sync.Map
|
||||||
|
Options *Options
|
||||||
|
}
|
112
src/mod/access/whitelist.go
Normal file
112
src/mod/access/whitelist.go
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
package access
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"imuslab.com/zoraxy/mod/netutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Whitelist.go
|
||||||
|
|
||||||
|
This script handles whitelist related functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
const (
|
||||||
|
EntryType_CountryCode int = 0
|
||||||
|
EntryType_IP int = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
type WhitelistEntry struct {
|
||||||
|
EntryType int //Entry type of whitelist, Country Code or IP
|
||||||
|
CC string //ISO Country Code
|
||||||
|
IP string //IP address or range
|
||||||
|
Comment string //Comment for this entry
|
||||||
|
}
|
||||||
|
|
||||||
|
//Geo Whitelist
|
||||||
|
|
||||||
|
func (s *AccessRule) AddCountryCodeToWhitelist(countryCode string, comment string) {
|
||||||
|
countryCode = strings.ToLower(countryCode)
|
||||||
|
newWhitelistCC := deepCopy(*s.WhiteListCountryCode)
|
||||||
|
newWhitelistCC[countryCode] = comment
|
||||||
|
s.WhiteListCountryCode = &newWhitelistCC
|
||||||
|
s.SaveChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *AccessRule) RemoveCountryCodeFromWhitelist(countryCode string) {
|
||||||
|
countryCode = strings.ToLower(countryCode)
|
||||||
|
newWhitelistCC := deepCopy(*s.WhiteListCountryCode)
|
||||||
|
delete(newWhitelistCC, countryCode)
|
||||||
|
s.WhiteListCountryCode = &newWhitelistCC
|
||||||
|
s.SaveChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *AccessRule) IsCountryCodeWhitelisted(countryCode string) bool {
|
||||||
|
countryCode = strings.ToLower(countryCode)
|
||||||
|
whitelistCC := *s.WhiteListCountryCode
|
||||||
|
_, ok := whitelistCC[countryCode]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *AccessRule) GetAllWhitelistedCountryCode() []*WhitelistEntry {
|
||||||
|
whitelistedCountryCode := []*WhitelistEntry{}
|
||||||
|
whitelistCC := *s.WhiteListCountryCode
|
||||||
|
for cc, comment := range whitelistCC {
|
||||||
|
whitelistedCountryCode = append(whitelistedCountryCode, &WhitelistEntry{
|
||||||
|
EntryType: EntryType_CountryCode,
|
||||||
|
CC: cc,
|
||||||
|
Comment: comment,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return whitelistedCountryCode
|
||||||
|
}
|
||||||
|
|
||||||
|
//IP Whitelist
|
||||||
|
|
||||||
|
func (s *AccessRule) AddIPToWhiteList(ipAddr string, comment string) {
|
||||||
|
newWhitelistIP := deepCopy(*s.WhiteListIP)
|
||||||
|
newWhitelistIP[ipAddr] = comment
|
||||||
|
s.WhiteListIP = &newWhitelistIP
|
||||||
|
s.SaveChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *AccessRule) RemoveIPFromWhiteList(ipAddr string) {
|
||||||
|
newWhitelistIP := deepCopy(*s.WhiteListIP)
|
||||||
|
delete(newWhitelistIP, ipAddr)
|
||||||
|
s.WhiteListIP = &newWhitelistIP
|
||||||
|
s.SaveChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *AccessRule) IsIPWhitelisted(ipAddr string) bool {
|
||||||
|
//Check for IP wildcard and CIRD rules
|
||||||
|
WhitelistedIP := *s.WhiteListIP
|
||||||
|
for ipOrCIDR, _ := range WhitelistedIP {
|
||||||
|
wildcardMatch := netutils.MatchIpWildcard(ipAddr, ipOrCIDR)
|
||||||
|
if wildcardMatch {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
cidrMatch := netutils.MatchIpCIDR(ipAddr, ipOrCIDR)
|
||||||
|
if cidrMatch {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *AccessRule) GetAllWhitelistedIp() []*WhitelistEntry {
|
||||||
|
whitelistedIp := []*WhitelistEntry{}
|
||||||
|
currentWhitelistedIP := *s.WhiteListIP
|
||||||
|
for ipOrCIDR, comment := range currentWhitelistedIP {
|
||||||
|
thisEntry := WhitelistEntry{
|
||||||
|
EntryType: EntryType_IP,
|
||||||
|
IP: ipOrCIDR,
|
||||||
|
Comment: comment,
|
||||||
|
}
|
||||||
|
whitelistedIp = append(whitelistedIp, &thisEntry)
|
||||||
|
}
|
||||||
|
|
||||||
|
return whitelistedIp
|
||||||
|
}
|
@ -9,6 +9,7 @@ import (
|
|||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
@ -24,6 +25,7 @@ import (
|
|||||||
"github.com/go-acme/lego/v4/challenge/http01"
|
"github.com/go-acme/lego/v4/challenge/http01"
|
||||||
"github.com/go-acme/lego/v4/lego"
|
"github.com/go-acme/lego/v4/lego"
|
||||||
"github.com/go-acme/lego/v4/registration"
|
"github.com/go-acme/lego/v4/registration"
|
||||||
|
"imuslab.com/zoraxy/mod/database"
|
||||||
"imuslab.com/zoraxy/mod/utils"
|
"imuslab.com/zoraxy/mod/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -31,6 +33,7 @@ type CertificateInfoJSON struct {
|
|||||||
AcmeName string `json:"acme_name"`
|
AcmeName string `json:"acme_name"`
|
||||||
AcmeUrl string `json:"acme_url"`
|
AcmeUrl string `json:"acme_url"`
|
||||||
SkipTLS bool `json:"skip_tls"`
|
SkipTLS bool `json:"skip_tls"`
|
||||||
|
UseDNS bool `json:"dns"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ACMEUser represents a user in the ACME system.
|
// ACMEUser represents a user in the ACME system.
|
||||||
@ -40,6 +43,11 @@ type ACMEUser struct {
|
|||||||
key crypto.PrivateKey
|
key crypto.PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type EABConfig struct {
|
||||||
|
Kid string `json:"kid"`
|
||||||
|
HmacKey string `json:"HmacKey"`
|
||||||
|
}
|
||||||
|
|
||||||
// GetEmail returns the email of the ACMEUser.
|
// GetEmail returns the email of the ACMEUser.
|
||||||
func (u *ACMEUser) GetEmail() string {
|
func (u *ACMEUser) GetEmail() string {
|
||||||
return u.Email
|
return u.Email
|
||||||
@ -59,18 +67,20 @@ func (u *ACMEUser) GetPrivateKey() crypto.PrivateKey {
|
|||||||
type ACMEHandler struct {
|
type ACMEHandler struct {
|
||||||
DefaultAcmeServer string
|
DefaultAcmeServer string
|
||||||
Port string
|
Port string
|
||||||
|
Database *database.Database
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewACME creates a new ACMEHandler instance.
|
// NewACME creates a new ACMEHandler instance.
|
||||||
func NewACME(acmeServer string, port string) *ACMEHandler {
|
func NewACME(acmeServer string, port string, database *database.Database) *ACMEHandler {
|
||||||
return &ACMEHandler{
|
return &ACMEHandler{
|
||||||
DefaultAcmeServer: acmeServer,
|
DefaultAcmeServer: acmeServer,
|
||||||
Port: port,
|
Port: port,
|
||||||
|
Database: database,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObtainCert obtains a certificate for the specified domains.
|
// ObtainCert obtains a certificate for the specified domains.
|
||||||
func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email string, caName string, caUrl string, skipTLS bool) (bool, error) {
|
func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email string, caName string, caUrl string, skipTLS bool, useDNS bool) (bool, error) {
|
||||||
log.Println("[ACME] Obtaining certificate...")
|
log.Println("[ACME] Obtaining certificate...")
|
||||||
|
|
||||||
// generate private key
|
// generate private key
|
||||||
@ -107,6 +117,11 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Fallback to Let's Encrypt if it is not set
|
||||||
|
if caName == "" {
|
||||||
|
caName = "Let's Encrypt"
|
||||||
|
}
|
||||||
|
|
||||||
// setup the custom ACME url endpoint.
|
// setup the custom ACME url endpoint.
|
||||||
if caUrl != "" {
|
if caUrl != "" {
|
||||||
config.CADirURL = caUrl
|
config.CADirURL = caUrl
|
||||||
@ -136,17 +151,107 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setup how to receive challenge
|
// setup how to receive challenge
|
||||||
err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", a.Port))
|
if useDNS {
|
||||||
if err != nil {
|
if !a.Database.TableExists("acme") {
|
||||||
log.Println(err)
|
a.Database.NewTable("acme")
|
||||||
return false, err
|
return false, errors.New("DNS Provider and DNS Credenital configuration required for ACME Provider (Error -1)")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !a.Database.KeyExists("acme", certificateName+"_dns_provider") || !a.Database.KeyExists("acme", certificateName+"_dns_credentials") {
|
||||||
|
return false, errors.New("DNS Provider and DNS Credenital configuration required for ACME Provider (Error -2)")
|
||||||
|
}
|
||||||
|
|
||||||
|
var dnsCredentials string
|
||||||
|
err := a.Database.Read("acme", certificateName+"_dns_credentials", &dnsCredentials)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var dnsProvider string
|
||||||
|
err = a.Database.Read("acme", certificateName+"_dns_provider", &dnsProvider)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
provider, err := GetDnsChallengeProviderByName(dnsProvider, dnsCredentials)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = client.Challenge.SetDNS01Provider(provider)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", a.Port))
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// New users will need to register
|
// New users will need to register
|
||||||
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
|
/*
|
||||||
if err != nil {
|
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
|
||||||
log.Println(err)
|
if err != nil {
|
||||||
return false, err
|
log.Println(err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
var reg *registration.Resource
|
||||||
|
// New users will need to register
|
||||||
|
if client.GetExternalAccountRequired() {
|
||||||
|
log.Println("External Account Required for this ACME Provider.")
|
||||||
|
// IF KID and HmacEncoded is overidden
|
||||||
|
|
||||||
|
if !a.Database.TableExists("acme") {
|
||||||
|
a.Database.NewTable("acme")
|
||||||
|
return false, errors.New("kid and HmacEncoded configuration required for ACME Provider (Error -1)")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !a.Database.KeyExists("acme", config.CADirURL+"_kid") || !a.Database.KeyExists("acme", config.CADirURL+"_hmacEncoded") {
|
||||||
|
return false, errors.New("kid and HmacEncoded configuration required for ACME Provider (Error -2)")
|
||||||
|
}
|
||||||
|
|
||||||
|
var kid string
|
||||||
|
var hmacEncoded string
|
||||||
|
err := a.Database.Read("acme", config.CADirURL+"_kid", &kid)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = a.Database.Read("acme", config.CADirURL+"_hmacEncoded", &hmacEncoded)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("EAB Credential retrieved.", kid, hmacEncoded)
|
||||||
|
if kid != "" && hmacEncoded != "" {
|
||||||
|
reg, err = client.Registration.RegisterWithExternalAccountBinding(registration.RegisterEABOptions{
|
||||||
|
TermsOfServiceAgreed: true,
|
||||||
|
Kid: kid,
|
||||||
|
HmacEncoded: hmacEncoded,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
//return false, errors.New("External Account Required for this ACME Provider.")
|
||||||
|
} else {
|
||||||
|
reg, err = client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
adminUser.Registration = reg
|
adminUser.Registration = reg
|
||||||
|
|
||||||
@ -179,6 +284,7 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
|
|||||||
AcmeName: caName,
|
AcmeName: caName,
|
||||||
AcmeUrl: caUrl,
|
AcmeUrl: caUrl,
|
||||||
SkipTLS: skipTLS,
|
SkipTLS: skipTLS,
|
||||||
|
UseDNS: useDNS,
|
||||||
}
|
}
|
||||||
|
|
||||||
certInfoBytes, err := json.Marshal(certInfo)
|
certInfoBytes, err := json.Marshal(certInfo)
|
||||||
@ -291,6 +397,8 @@ func (a *ACMEHandler) HandleRenewCertificate(w http.ResponseWriter, r *http.Requ
|
|||||||
utils.SendErrorResponse(w, jsonEscape(err.Error()))
|
utils.SendErrorResponse(w, jsonEscape(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
//Make sure the wildcard * do not goes into the filename
|
||||||
|
filename = strings.ReplaceAll(filename, "*", "_")
|
||||||
|
|
||||||
email, err := utils.PostPara(r, "email")
|
email, err := utils.PostPara(r, "email")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -329,8 +437,18 @@ func (a *ACMEHandler) HandleRenewCertificate(w http.ResponseWriter, r *http.Requ
|
|||||||
skipTLS = true
|
skipTLS = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dns bool
|
||||||
|
|
||||||
|
if dnsString, err := utils.PostPara(r, "dns"); err != nil {
|
||||||
|
dns = false
|
||||||
|
} else if dnsString != "true" {
|
||||||
|
dns = false
|
||||||
|
} else {
|
||||||
|
dns = true
|
||||||
|
}
|
||||||
|
|
||||||
domains := strings.Split(domainPara, ",")
|
domains := strings.Split(domainPara, ",")
|
||||||
result, err := a.ObtainCert(domains, filename, email, ca, caUrl, skipTLS)
|
result, err := a.ObtainCert(domains, filename, email, ca, caUrl, skipTLS, dns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.SendErrorResponse(w, jsonEscape(err.Error()))
|
utils.SendErrorResponse(w, jsonEscape(err.Error()))
|
||||||
return
|
return
|
||||||
@ -362,7 +480,7 @@ func IsPortInUse(port int) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load cert information from json file
|
// Load cert information from json file
|
||||||
func loadCertInfoJSON(filename string) (*CertificateInfoJSON, error) {
|
func LoadCertInfoJSON(filename string) (*CertificateInfoJSON, error) {
|
||||||
certInfoBytes, err := os.ReadFile(filename)
|
certInfoBytes, err := os.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
72
src/mod/acme/acme_dns.go
Normal file
72
src/mod/acme/acme_dns.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package acme
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-acme/lego/v4/challenge"
|
||||||
|
"imuslab.com/zoraxy/mod/acme/acmedns"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetDnsChallengeProviderByName(dnsProvider string, dnsCredentials string) (challenge.Provider, error) {
|
||||||
|
|
||||||
|
//Original Implementation
|
||||||
|
/*credentials, err := extractDnsCredentials(dnsCredentials)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
setCredentialsIntoEnvironmentVariables(credentials)
|
||||||
|
|
||||||
|
provider, err := dns.NewDNSChallengeProviderByName(dnsProvider)
|
||||||
|
*/
|
||||||
|
|
||||||
|
//New implementation using acmedns CICD pipeline generated datatype
|
||||||
|
return acmedns.GetDNSProviderByJsonConfig(dnsProvider, dnsCredentials)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Original implementation of DNS ACME using OS.Env as payload
|
||||||
|
*/
|
||||||
|
|
||||||
|
func setCredentialsIntoEnvironmentVariables(credentials map[string]string) {
|
||||||
|
for key, value := range credentials {
|
||||||
|
err := os.Setenv(key, value)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("[ERR] Failed to set environment variable %s: %v", key, err)
|
||||||
|
} else {
|
||||||
|
log.Println("[INFO] Environment variable %s set successfully", key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractDnsCredentials(input string) (map[string]string, error) {
|
||||||
|
result := make(map[string]string)
|
||||||
|
|
||||||
|
// Split the input string by newline character
|
||||||
|
lines := strings.Split(input, "\n")
|
||||||
|
|
||||||
|
// Iterate over each line
|
||||||
|
for _, line := range lines {
|
||||||
|
// Split the line by "=" character
|
||||||
|
//use SpliyN to make sure not to split the value if the value is base64
|
||||||
|
parts := strings.SplitN(line, "=", 1)
|
||||||
|
|
||||||
|
// Check if the line is in the correct format
|
||||||
|
if len(parts) == 2 {
|
||||||
|
key := strings.TrimSpace(parts[0])
|
||||||
|
value := strings.TrimSpace(parts[1])
|
||||||
|
|
||||||
|
// Add the key-value pair to the map
|
||||||
|
result[key] = value
|
||||||
|
|
||||||
|
if value == "" || key == "" {
|
||||||
|
//invalid config
|
||||||
|
return result, errors.New("DNS credential extract failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
982
src/mod/acme/acmedns/acmedns.go
Normal file
982
src/mod/acme/acmedns/acmedns.go
Normal file
@ -0,0 +1,982 @@
|
|||||||
|
package acmedns
|
||||||
|
/*
|
||||||
|
THIS MODULE IS GENERATED AUTOMATICALLY
|
||||||
|
DO NOT EDIT THIS FILE
|
||||||
|
*/
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-acme/lego/v4/challenge"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/alidns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/allinkl"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/arvancloud"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/auroradns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/autodns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/azure"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/azuredns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/bindman"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/bluecat"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/brandit"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/bunny"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/checkdomain"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/civo"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/clouddns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/cloudflare"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/cloudns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/cloudru"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/cloudxns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/conoha"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/constellix"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/cpanel"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/derak"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/desec"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/digitalocean"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/dnshomede"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/dnsimple"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/dnsmadeeasy"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/dnspod"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/dode"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/domeneshop"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/dreamhost"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/duckdns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/dyn"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/dynu"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/easydns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/efficientip"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/epik"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/exoscale"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/freemyip"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/gandi"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/gandiv5"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/gcore"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/glesys"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/godaddy"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/googledomains"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/hetzner"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/hostingde"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/hosttech"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/httpnet"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/hyperone"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/ibmcloud"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/iij"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/iijdpf"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/infoblox"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/infomaniak"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/internetbs"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/inwx"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/ionos"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/ipv64"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/iwantmyname"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/joker"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/liara"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/lightsail"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/linode"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/liquidweb"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/loopia"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/luadns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/mailinabox"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/metaname"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/mydnsjp"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/namecheap"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/namedotcom"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/namesilo"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/nearlyfreespeech"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/netcup"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/netlify"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/nicmanager"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/nifcloud"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/njalla"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/nodion"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/ns1"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/otc"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/ovh"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/pdns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/plesk"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/porkbun"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/rackspace"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/rcodezero"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/regru"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/rfc2136"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/rimuhosting"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/route53"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/safedns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/sakuracloud"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/scaleway"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/selectel"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/servercow"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/shellrent"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/simply"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/sonic"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/stackpath"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/tencentcloud"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/transip"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/ultradns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/variomedia"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/vegadns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/vercel"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/versio"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/vinyldns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/vkcloud"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/vscale"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/vultr"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/webnames"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/websupport"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/wedos"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/yandex"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/yandex360"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/yandexcloud"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/zoneee"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/zonomi"
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
//name is the DNS provider name, e.g. cloudflare or gandi
|
||||||
|
//JSON (js) must be in key-value string that match ConfigableFields Title in providers.json, e.g. {"Username":"far","Password":"boo"}
|
||||||
|
func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, error){
|
||||||
|
switch name {
|
||||||
|
|
||||||
|
case "alidns":
|
||||||
|
cfg := alidns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return alidns.NewDNSProviderConfig(cfg)
|
||||||
|
case "allinkl":
|
||||||
|
cfg := allinkl.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return allinkl.NewDNSProviderConfig(cfg)
|
||||||
|
case "arvancloud":
|
||||||
|
cfg := arvancloud.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return arvancloud.NewDNSProviderConfig(cfg)
|
||||||
|
case "auroradns":
|
||||||
|
cfg := auroradns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return auroradns.NewDNSProviderConfig(cfg)
|
||||||
|
case "autodns":
|
||||||
|
cfg := autodns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return autodns.NewDNSProviderConfig(cfg)
|
||||||
|
case "azure":
|
||||||
|
cfg := azure.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return azure.NewDNSProviderConfig(cfg)
|
||||||
|
case "azuredns":
|
||||||
|
cfg := azuredns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return azuredns.NewDNSProviderConfig(cfg)
|
||||||
|
case "bindman":
|
||||||
|
cfg := bindman.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bindman.NewDNSProviderConfig(cfg)
|
||||||
|
case "bluecat":
|
||||||
|
cfg := bluecat.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bluecat.NewDNSProviderConfig(cfg)
|
||||||
|
case "brandit":
|
||||||
|
cfg := brandit.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return brandit.NewDNSProviderConfig(cfg)
|
||||||
|
case "bunny":
|
||||||
|
cfg := bunny.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bunny.NewDNSProviderConfig(cfg)
|
||||||
|
case "checkdomain":
|
||||||
|
cfg := checkdomain.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return checkdomain.NewDNSProviderConfig(cfg)
|
||||||
|
case "civo":
|
||||||
|
cfg := civo.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return civo.NewDNSProviderConfig(cfg)
|
||||||
|
case "clouddns":
|
||||||
|
cfg := clouddns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return clouddns.NewDNSProviderConfig(cfg)
|
||||||
|
case "cloudflare":
|
||||||
|
cfg := cloudflare.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return cloudflare.NewDNSProviderConfig(cfg)
|
||||||
|
case "cloudns":
|
||||||
|
cfg := cloudns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return cloudns.NewDNSProviderConfig(cfg)
|
||||||
|
case "cloudru":
|
||||||
|
cfg := cloudru.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return cloudru.NewDNSProviderConfig(cfg)
|
||||||
|
case "cloudxns":
|
||||||
|
cfg := cloudxns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return cloudxns.NewDNSProviderConfig(cfg)
|
||||||
|
case "conoha":
|
||||||
|
cfg := conoha.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return conoha.NewDNSProviderConfig(cfg)
|
||||||
|
case "constellix":
|
||||||
|
cfg := constellix.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return constellix.NewDNSProviderConfig(cfg)
|
||||||
|
case "cpanel":
|
||||||
|
cfg := cpanel.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return cpanel.NewDNSProviderConfig(cfg)
|
||||||
|
case "derak":
|
||||||
|
cfg := derak.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return derak.NewDNSProviderConfig(cfg)
|
||||||
|
case "desec":
|
||||||
|
cfg := desec.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return desec.NewDNSProviderConfig(cfg)
|
||||||
|
case "digitalocean":
|
||||||
|
cfg := digitalocean.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return digitalocean.NewDNSProviderConfig(cfg)
|
||||||
|
case "dnshomede":
|
||||||
|
cfg := dnshomede.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dnshomede.NewDNSProviderConfig(cfg)
|
||||||
|
case "dnsimple":
|
||||||
|
cfg := dnsimple.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dnsimple.NewDNSProviderConfig(cfg)
|
||||||
|
case "dnsmadeeasy":
|
||||||
|
cfg := dnsmadeeasy.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dnsmadeeasy.NewDNSProviderConfig(cfg)
|
||||||
|
case "dnspod":
|
||||||
|
cfg := dnspod.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dnspod.NewDNSProviderConfig(cfg)
|
||||||
|
case "dode":
|
||||||
|
cfg := dode.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dode.NewDNSProviderConfig(cfg)
|
||||||
|
case "domeneshop":
|
||||||
|
cfg := domeneshop.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return domeneshop.NewDNSProviderConfig(cfg)
|
||||||
|
case "dreamhost":
|
||||||
|
cfg := dreamhost.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dreamhost.NewDNSProviderConfig(cfg)
|
||||||
|
case "duckdns":
|
||||||
|
cfg := duckdns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return duckdns.NewDNSProviderConfig(cfg)
|
||||||
|
case "dyn":
|
||||||
|
cfg := dyn.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dyn.NewDNSProviderConfig(cfg)
|
||||||
|
case "dynu":
|
||||||
|
cfg := dynu.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dynu.NewDNSProviderConfig(cfg)
|
||||||
|
case "easydns":
|
||||||
|
cfg := easydns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return easydns.NewDNSProviderConfig(cfg)
|
||||||
|
case "efficientip":
|
||||||
|
cfg := efficientip.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return efficientip.NewDNSProviderConfig(cfg)
|
||||||
|
case "epik":
|
||||||
|
cfg := epik.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return epik.NewDNSProviderConfig(cfg)
|
||||||
|
case "exoscale":
|
||||||
|
cfg := exoscale.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return exoscale.NewDNSProviderConfig(cfg)
|
||||||
|
case "freemyip":
|
||||||
|
cfg := freemyip.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return freemyip.NewDNSProviderConfig(cfg)
|
||||||
|
case "gandi":
|
||||||
|
cfg := gandi.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return gandi.NewDNSProviderConfig(cfg)
|
||||||
|
case "gandiv5":
|
||||||
|
cfg := gandiv5.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return gandiv5.NewDNSProviderConfig(cfg)
|
||||||
|
case "gcore":
|
||||||
|
cfg := gcore.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return gcore.NewDNSProviderConfig(cfg)
|
||||||
|
case "glesys":
|
||||||
|
cfg := glesys.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return glesys.NewDNSProviderConfig(cfg)
|
||||||
|
case "godaddy":
|
||||||
|
cfg := godaddy.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return godaddy.NewDNSProviderConfig(cfg)
|
||||||
|
case "googledomains":
|
||||||
|
cfg := googledomains.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return googledomains.NewDNSProviderConfig(cfg)
|
||||||
|
case "hetzner":
|
||||||
|
cfg := hetzner.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return hetzner.NewDNSProviderConfig(cfg)
|
||||||
|
case "hostingde":
|
||||||
|
cfg := hostingde.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return hostingde.NewDNSProviderConfig(cfg)
|
||||||
|
case "hosttech":
|
||||||
|
cfg := hosttech.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return hosttech.NewDNSProviderConfig(cfg)
|
||||||
|
case "httpnet":
|
||||||
|
cfg := httpnet.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return httpnet.NewDNSProviderConfig(cfg)
|
||||||
|
case "hyperone":
|
||||||
|
cfg := hyperone.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return hyperone.NewDNSProviderConfig(cfg)
|
||||||
|
case "ibmcloud":
|
||||||
|
cfg := ibmcloud.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ibmcloud.NewDNSProviderConfig(cfg)
|
||||||
|
case "iij":
|
||||||
|
cfg := iij.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return iij.NewDNSProviderConfig(cfg)
|
||||||
|
case "iijdpf":
|
||||||
|
cfg := iijdpf.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return iijdpf.NewDNSProviderConfig(cfg)
|
||||||
|
case "infoblox":
|
||||||
|
cfg := infoblox.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return infoblox.NewDNSProviderConfig(cfg)
|
||||||
|
case "infomaniak":
|
||||||
|
cfg := infomaniak.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return infomaniak.NewDNSProviderConfig(cfg)
|
||||||
|
case "internetbs":
|
||||||
|
cfg := internetbs.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return internetbs.NewDNSProviderConfig(cfg)
|
||||||
|
case "inwx":
|
||||||
|
cfg := inwx.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return inwx.NewDNSProviderConfig(cfg)
|
||||||
|
case "ionos":
|
||||||
|
cfg := ionos.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ionos.NewDNSProviderConfig(cfg)
|
||||||
|
case "ipv64":
|
||||||
|
cfg := ipv64.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ipv64.NewDNSProviderConfig(cfg)
|
||||||
|
case "iwantmyname":
|
||||||
|
cfg := iwantmyname.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return iwantmyname.NewDNSProviderConfig(cfg)
|
||||||
|
case "joker":
|
||||||
|
cfg := joker.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return joker.NewDNSProviderConfig(cfg)
|
||||||
|
case "liara":
|
||||||
|
cfg := liara.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return liara.NewDNSProviderConfig(cfg)
|
||||||
|
case "lightsail":
|
||||||
|
cfg := lightsail.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return lightsail.NewDNSProviderConfig(cfg)
|
||||||
|
case "linode":
|
||||||
|
cfg := linode.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return linode.NewDNSProviderConfig(cfg)
|
||||||
|
case "liquidweb":
|
||||||
|
cfg := liquidweb.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return liquidweb.NewDNSProviderConfig(cfg)
|
||||||
|
case "loopia":
|
||||||
|
cfg := loopia.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return loopia.NewDNSProviderConfig(cfg)
|
||||||
|
case "luadns":
|
||||||
|
cfg := luadns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return luadns.NewDNSProviderConfig(cfg)
|
||||||
|
case "mailinabox":
|
||||||
|
cfg := mailinabox.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return mailinabox.NewDNSProviderConfig(cfg)
|
||||||
|
case "metaname":
|
||||||
|
cfg := metaname.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return metaname.NewDNSProviderConfig(cfg)
|
||||||
|
case "mydnsjp":
|
||||||
|
cfg := mydnsjp.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return mydnsjp.NewDNSProviderConfig(cfg)
|
||||||
|
case "namecheap":
|
||||||
|
cfg := namecheap.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return namecheap.NewDNSProviderConfig(cfg)
|
||||||
|
case "namedotcom":
|
||||||
|
cfg := namedotcom.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return namedotcom.NewDNSProviderConfig(cfg)
|
||||||
|
case "namesilo":
|
||||||
|
cfg := namesilo.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return namesilo.NewDNSProviderConfig(cfg)
|
||||||
|
case "nearlyfreespeech":
|
||||||
|
cfg := nearlyfreespeech.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nearlyfreespeech.NewDNSProviderConfig(cfg)
|
||||||
|
case "netcup":
|
||||||
|
cfg := netcup.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return netcup.NewDNSProviderConfig(cfg)
|
||||||
|
case "netlify":
|
||||||
|
cfg := netlify.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return netlify.NewDNSProviderConfig(cfg)
|
||||||
|
case "nicmanager":
|
||||||
|
cfg := nicmanager.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nicmanager.NewDNSProviderConfig(cfg)
|
||||||
|
case "nifcloud":
|
||||||
|
cfg := nifcloud.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nifcloud.NewDNSProviderConfig(cfg)
|
||||||
|
case "njalla":
|
||||||
|
cfg := njalla.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return njalla.NewDNSProviderConfig(cfg)
|
||||||
|
case "nodion":
|
||||||
|
cfg := nodion.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nodion.NewDNSProviderConfig(cfg)
|
||||||
|
case "ns1":
|
||||||
|
cfg := ns1.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ns1.NewDNSProviderConfig(cfg)
|
||||||
|
case "otc":
|
||||||
|
cfg := otc.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return otc.NewDNSProviderConfig(cfg)
|
||||||
|
case "ovh":
|
||||||
|
cfg := ovh.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ovh.NewDNSProviderConfig(cfg)
|
||||||
|
case "pdns":
|
||||||
|
cfg := pdns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return pdns.NewDNSProviderConfig(cfg)
|
||||||
|
case "plesk":
|
||||||
|
cfg := plesk.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return plesk.NewDNSProviderConfig(cfg)
|
||||||
|
case "porkbun":
|
||||||
|
cfg := porkbun.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return porkbun.NewDNSProviderConfig(cfg)
|
||||||
|
case "rackspace":
|
||||||
|
cfg := rackspace.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rackspace.NewDNSProviderConfig(cfg)
|
||||||
|
case "rcodezero":
|
||||||
|
cfg := rcodezero.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rcodezero.NewDNSProviderConfig(cfg)
|
||||||
|
case "regru":
|
||||||
|
cfg := regru.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return regru.NewDNSProviderConfig(cfg)
|
||||||
|
case "rfc2136":
|
||||||
|
cfg := rfc2136.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rfc2136.NewDNSProviderConfig(cfg)
|
||||||
|
case "rimuhosting":
|
||||||
|
cfg := rimuhosting.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rimuhosting.NewDNSProviderConfig(cfg)
|
||||||
|
case "route53":
|
||||||
|
cfg := route53.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return route53.NewDNSProviderConfig(cfg)
|
||||||
|
case "safedns":
|
||||||
|
cfg := safedns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return safedns.NewDNSProviderConfig(cfg)
|
||||||
|
case "sakuracloud":
|
||||||
|
cfg := sakuracloud.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return sakuracloud.NewDNSProviderConfig(cfg)
|
||||||
|
case "scaleway":
|
||||||
|
cfg := scaleway.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return scaleway.NewDNSProviderConfig(cfg)
|
||||||
|
case "selectel":
|
||||||
|
cfg := selectel.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return selectel.NewDNSProviderConfig(cfg)
|
||||||
|
case "servercow":
|
||||||
|
cfg := servercow.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return servercow.NewDNSProviderConfig(cfg)
|
||||||
|
case "shellrent":
|
||||||
|
cfg := shellrent.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return shellrent.NewDNSProviderConfig(cfg)
|
||||||
|
case "simply":
|
||||||
|
cfg := simply.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return simply.NewDNSProviderConfig(cfg)
|
||||||
|
case "sonic":
|
||||||
|
cfg := sonic.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return sonic.NewDNSProviderConfig(cfg)
|
||||||
|
case "stackpath":
|
||||||
|
cfg := stackpath.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return stackpath.NewDNSProviderConfig(cfg)
|
||||||
|
case "tencentcloud":
|
||||||
|
cfg := tencentcloud.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return tencentcloud.NewDNSProviderConfig(cfg)
|
||||||
|
case "transip":
|
||||||
|
cfg := transip.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return transip.NewDNSProviderConfig(cfg)
|
||||||
|
case "ultradns":
|
||||||
|
cfg := ultradns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ultradns.NewDNSProviderConfig(cfg)
|
||||||
|
case "variomedia":
|
||||||
|
cfg := variomedia.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return variomedia.NewDNSProviderConfig(cfg)
|
||||||
|
case "vegadns":
|
||||||
|
cfg := vegadns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return vegadns.NewDNSProviderConfig(cfg)
|
||||||
|
case "vercel":
|
||||||
|
cfg := vercel.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return vercel.NewDNSProviderConfig(cfg)
|
||||||
|
case "versio":
|
||||||
|
cfg := versio.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return versio.NewDNSProviderConfig(cfg)
|
||||||
|
case "vinyldns":
|
||||||
|
cfg := vinyldns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return vinyldns.NewDNSProviderConfig(cfg)
|
||||||
|
case "vkcloud":
|
||||||
|
cfg := vkcloud.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return vkcloud.NewDNSProviderConfig(cfg)
|
||||||
|
case "vscale":
|
||||||
|
cfg := vscale.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return vscale.NewDNSProviderConfig(cfg)
|
||||||
|
case "vultr":
|
||||||
|
cfg := vultr.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return vultr.NewDNSProviderConfig(cfg)
|
||||||
|
case "webnames":
|
||||||
|
cfg := webnames.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return webnames.NewDNSProviderConfig(cfg)
|
||||||
|
case "websupport":
|
||||||
|
cfg := websupport.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return websupport.NewDNSProviderConfig(cfg)
|
||||||
|
case "wedos":
|
||||||
|
cfg := wedos.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return wedos.NewDNSProviderConfig(cfg)
|
||||||
|
case "yandex":
|
||||||
|
cfg := yandex.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return yandex.NewDNSProviderConfig(cfg)
|
||||||
|
case "yandex360":
|
||||||
|
cfg := yandex360.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return yandex360.NewDNSProviderConfig(cfg)
|
||||||
|
case "yandexcloud":
|
||||||
|
cfg := yandexcloud.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return yandexcloud.NewDNSProviderConfig(cfg)
|
||||||
|
case "zoneee":
|
||||||
|
cfg := zoneee.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return zoneee.NewDNSProviderConfig(cfg)
|
||||||
|
case "zonomi":
|
||||||
|
cfg := zonomi.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return zonomi.NewDNSProviderConfig(cfg)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unrecognized DNS provider: %s", name)
|
||||||
|
}
|
||||||
|
}
|
27
src/mod/acme/acmedns/acmedns_test.go
Normal file
27
src/mod/acme/acmedns/acmedns_test.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package acmedns_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"imuslab.com/zoraxy/mod/acme/acmedns"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Test if the structure of ACME DNS config can be reflected from lego source code definations
|
||||||
|
func TestACMEDNSConfigStructureReflector(t *testing.T) {
|
||||||
|
providers := []string{
|
||||||
|
"gandi",
|
||||||
|
"cloudflare",
|
||||||
|
"azure",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, provider := range providers {
|
||||||
|
strcture, err := acmedns.GetProviderConfigStructure(provider)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(strcture)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
3493
src/mod/acme/acmedns/providers.json
Normal file
3493
src/mod/acme/acmedns/providers.json
Normal file
File diff suppressed because it is too large
Load Diff
80
src/mod/acme/acmedns/providerutils.go
Normal file
80
src/mod/acme/acmedns/providerutils.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package acmedns
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"imuslab.com/zoraxy/mod/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed providers.json
|
||||||
|
var providers []byte //A list of providers generated by acmedns code-generator
|
||||||
|
|
||||||
|
type ConfigTemplate struct {
|
||||||
|
Name string `json:"Name"`
|
||||||
|
ConfigableFields []struct {
|
||||||
|
Title string `json:"Title"`
|
||||||
|
Datatype string `json:"Datatype"`
|
||||||
|
} `json:"ConfigableFields"`
|
||||||
|
HiddenFields []struct {
|
||||||
|
Title string `json:"Title"`
|
||||||
|
Datatype string `json:"Datatype"`
|
||||||
|
} `json:"HiddenFields"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a map of string => datatype
|
||||||
|
func GetProviderConfigStructure(providerName string) (map[string]string, error) {
|
||||||
|
//Load the target config template from embedded providers.json
|
||||||
|
configTemplateMap := map[string]ConfigTemplate{}
|
||||||
|
err := json.Unmarshal(providers, &configTemplateMap)
|
||||||
|
if err != nil {
|
||||||
|
return map[string]string{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
targetConfigTemplate, ok := configTemplateMap[providerName]
|
||||||
|
if !ok {
|
||||||
|
return map[string]string{}, errors.New("provider not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
results := map[string]string{}
|
||||||
|
for _, field := range targetConfigTemplate.ConfigableFields {
|
||||||
|
results[field.Title] = field.Datatype
|
||||||
|
}
|
||||||
|
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleServeProvidersJson return the list of supported providers as json
|
||||||
|
func HandleServeProvidersJson(w http.ResponseWriter, r *http.Request) {
|
||||||
|
providerName, _ := utils.GetPara(r, "name")
|
||||||
|
if providerName == "" {
|
||||||
|
//Send the current list of providers
|
||||||
|
configTemplateMap := map[string]ConfigTemplate{}
|
||||||
|
err := json.Unmarshal(providers, &configTemplateMap)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "failed to load DNS provider")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Parse the provider names into an array
|
||||||
|
providers := []string{}
|
||||||
|
for providerName, _ := range configTemplateMap {
|
||||||
|
providers = append(providers, providerName)
|
||||||
|
}
|
||||||
|
|
||||||
|
js, _ := json.Marshal(providers)
|
||||||
|
utils.SendJSONResponse(w, string(js))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//Get the config for that provider
|
||||||
|
confTemplate, err := GetProviderConfigStructure(providerName)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
js, _ := json.Marshal(confTemplate)
|
||||||
|
utils.SendJSONResponse(w, string(js))
|
||||||
|
}
|
@ -344,7 +344,7 @@ func (a *AutoRenewer) renewExpiredDomains(certs []*ExpiredCerts) ([]string, erro
|
|||||||
|
|
||||||
// Load certificate info for ACME detail
|
// Load certificate info for ACME detail
|
||||||
certInfoFilename := fmt.Sprintf("%s/%s.json", filepath.Dir(expiredCert.Filepath), certName)
|
certInfoFilename := fmt.Sprintf("%s/%s.json", filepath.Dir(expiredCert.Filepath), certName)
|
||||||
certInfo, err := loadCertInfoJSON(certInfoFilename)
|
certInfo, err := LoadCertInfoJSON(certInfoFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Renew %s certificate error, can't get the ACME detail for cert: %v, trying org section as ca", certName, err)
|
log.Printf("Renew %s certificate error, can't get the ACME detail for cert: %v, trying org section as ca", certName, err)
|
||||||
|
|
||||||
@ -356,7 +356,7 @@ func (a *AutoRenewer) renewExpiredDomains(certs []*ExpiredCerts) ([]string, erro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = a.AcmeHandler.ObtainCert(expiredCert.Domains, certName, a.RenewerConfig.Email, certInfo.AcmeName, certInfo.AcmeUrl, certInfo.SkipTLS)
|
_, err = a.AcmeHandler.ObtainCert(expiredCert.Domains, certName, a.RenewerConfig.Email, certInfo.AcmeName, certInfo.AcmeUrl, certInfo.SkipTLS, certInfo.UseDNS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Renew " + fileName + "(" + strings.Join(expiredCert.Domains, ",") + ") failed: " + err.Error())
|
log.Println("Renew " + fileName + "(" + strings.Join(expiredCert.Domains, ",") + ") failed: " + err.Error())
|
||||||
} else {
|
} else {
|
||||||
@ -373,3 +373,65 @@ func (a *AutoRenewer) saveRenewConfigToFile() error {
|
|||||||
js, _ := json.MarshalIndent(a.RenewerConfig, "", " ")
|
js, _ := json.MarshalIndent(a.RenewerConfig, "", " ")
|
||||||
return os.WriteFile(a.ConfigFilePath, js, 0775)
|
return os.WriteFile(a.ConfigFilePath, js, 0775)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle update auto renew EAD configuration
|
||||||
|
func (a *AutoRenewer) HanldeSetEAB(w http.ResponseWriter, r *http.Request) {
|
||||||
|
kid, err := utils.GetPara(r, "kid")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "kid not set")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
hmacEncoded, err := utils.GetPara(r, "hmacEncoded")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "hmacEncoded not set")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
acmeDirectoryURL, err := utils.GetPara(r, "acmeDirectoryURL")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "acmeDirectoryURL not set")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !a.AcmeHandler.Database.TableExists("acme") {
|
||||||
|
a.AcmeHandler.Database.NewTable("acme")
|
||||||
|
}
|
||||||
|
|
||||||
|
a.AcmeHandler.Database.Write("acme", acmeDirectoryURL+"_kid", kid)
|
||||||
|
a.AcmeHandler.Database.Write("acme", acmeDirectoryURL+"_hmacEncoded", hmacEncoded)
|
||||||
|
|
||||||
|
utils.SendOK(w)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle update auto renew DNS configuration
|
||||||
|
func (a *AutoRenewer) HanldeSetDNS(w http.ResponseWriter, r *http.Request) {
|
||||||
|
dnsProvider, err := utils.PostPara(r, "dnsProvider")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "dnsProvider not set")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dnsCredentials, err := utils.PostPara(r, "dnsCredentials")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "dnsCredentials not set")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
filename, err := utils.PostPara(r, "filename")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "filename not set")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !a.AcmeHandler.Database.TableExists("acme") {
|
||||||
|
a.AcmeHandler.Database.NewTable("acme")
|
||||||
|
}
|
||||||
|
|
||||||
|
a.AcmeHandler.Database.Write("acme", filename+"_dns_provider", dnsProvider)
|
||||||
|
a.AcmeHandler.Database.Write("acme", filename+"_dns_credentials", dnsCredentials)
|
||||||
|
|
||||||
|
utils.SendOK(w)
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
package aroz
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
//To be used with arozos system
|
|
||||||
type ArozHandler struct {
|
|
||||||
Port string
|
|
||||||
restfulEndpoint string
|
|
||||||
}
|
|
||||||
|
|
||||||
//Information required for registering this subservice to arozos
|
|
||||||
type ServiceInfo struct {
|
|
||||||
Name string //Name of this module. e.g. "Audio"
|
|
||||||
Desc string //Description for this module
|
|
||||||
Group string //Group of the module, e.g. "system" / "media" etc
|
|
||||||
IconPath string //Module icon image path e.g. "Audio/img/function_icon.png"
|
|
||||||
Version string //Version of the module. Format: [0-9]*.[0-9][0-9].[0-9]
|
|
||||||
StartDir string //Default starting dir, e.g. "Audio/index.html"
|
|
||||||
SupportFW bool //Support floatWindow. If yes, floatWindow dir will be loaded
|
|
||||||
LaunchFWDir string //This link will be launched instead of 'StartDir' if fw mode
|
|
||||||
SupportEmb bool //Support embedded mode
|
|
||||||
LaunchEmb string //This link will be launched instead of StartDir / Fw if a file is opened with this module
|
|
||||||
InitFWSize []int //Floatwindow init size. [0] => Width, [1] => Height
|
|
||||||
InitEmbSize []int //Embedded mode init size. [0] => Width, [1] => Height
|
|
||||||
SupportedExt []string //Supported File Extensions. e.g. ".mp3", ".flac", ".wav"
|
|
||||||
}
|
|
||||||
|
|
||||||
//This function will request the required flag from the startup paramters and parse it to the need of the arozos.
|
|
||||||
func HandleFlagParse(info ServiceInfo) *ArozHandler {
|
|
||||||
var infoRequestMode = flag.Bool("info", false, "Show information about this program in JSON")
|
|
||||||
var port = flag.String("port", ":8000", "Management web interface listening port")
|
|
||||||
var restful = flag.String("rpt", "", "Reserved")
|
|
||||||
//Parse the flags
|
|
||||||
flag.Parse()
|
|
||||||
if *infoRequestMode {
|
|
||||||
//Information request mode
|
|
||||||
jsonString, _ := json.MarshalIndent(info, "", " ")
|
|
||||||
fmt.Println(string(jsonString))
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
return &ArozHandler{
|
|
||||||
Port: *port,
|
|
||||||
restfulEndpoint: *restful,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Get the username and resources access token from the request, return username, token
|
|
||||||
func (a *ArozHandler) GetUserInfoFromRequest(w http.ResponseWriter, r *http.Request) (string, string) {
|
|
||||||
username := r.Header.Get("aouser")
|
|
||||||
token := r.Header.Get("aotoken")
|
|
||||||
|
|
||||||
return username, token
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *ArozHandler) IsUsingExternalPermissionManager() bool {
|
|
||||||
return !(a.restfulEndpoint == "")
|
|
||||||
}
|
|
||||||
|
|
||||||
//Request gateway interface for advance permission sandbox control
|
|
||||||
func (a *ArozHandler) RequestGatewayInterface(token string, script string) (*http.Response, error) {
|
|
||||||
resp, err := http.PostForm(a.restfulEndpoint,
|
|
||||||
url.Values{"token": {token}, "script": {script}})
|
|
||||||
if err != nil {
|
|
||||||
// handle error
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
Binary file not shown.
@ -6,8 +6,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"imuslab.com/zoraxy/mod/geodb"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -32,14 +30,6 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
matchedRoutingRule := h.Parent.GetMatchingRoutingRule(r)
|
matchedRoutingRule := h.Parent.GetMatchingRoutingRule(r)
|
||||||
if matchedRoutingRule != nil {
|
if matchedRoutingRule != nil {
|
||||||
//Matching routing rule found. Let the sub-router handle it
|
//Matching routing rule found. Let the sub-router handle it
|
||||||
if matchedRoutingRule.UseSystemAccessControl {
|
|
||||||
//This matching rule request system access control.
|
|
||||||
//check access logic
|
|
||||||
respWritten := h.handleAccessRouting(w, r)
|
|
||||||
if respWritten {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
matchedRoutingRule.Route(w, r)
|
matchedRoutingRule.Route(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -47,14 +37,6 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
//Inject headers
|
//Inject headers
|
||||||
w.Header().Set("x-proxy-by", "zoraxy/"+h.Parent.Option.HostVersion)
|
w.Header().Set("x-proxy-by", "zoraxy/"+h.Parent.Option.HostVersion)
|
||||||
|
|
||||||
/*
|
|
||||||
General Access Check
|
|
||||||
*/
|
|
||||||
respWritten := h.handleAccessRouting(w, r)
|
|
||||||
if respWritten {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Redirection Routing
|
Redirection Routing
|
||||||
*/
|
*/
|
||||||
@ -65,19 +47,30 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//Extract request host to see if it is virtual directory or subdomain
|
/*
|
||||||
|
Host Routing
|
||||||
|
*/
|
||||||
|
//Extract request host to see if any proxy rule is matched
|
||||||
domainOnly := r.Host
|
domainOnly := r.Host
|
||||||
if strings.Contains(r.Host, ":") {
|
if strings.Contains(r.Host, ":") {
|
||||||
hostPath := strings.Split(r.Host, ":")
|
hostPath := strings.Split(r.Host, ":")
|
||||||
domainOnly = hostPath[0]
|
domainOnly = hostPath[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Host Routing
|
|
||||||
*/
|
|
||||||
|
|
||||||
sep := h.Parent.getProxyEndpointFromHostname(domainOnly)
|
sep := h.Parent.getProxyEndpointFromHostname(domainOnly)
|
||||||
if sep != nil && !sep.Disabled {
|
if sep != nil && !sep.Disabled {
|
||||||
|
//Matching proxy rule found
|
||||||
|
//Access Check (blacklist / whitelist)
|
||||||
|
ruleID := sep.AccessFilterUUID
|
||||||
|
if sep.AccessFilterUUID == "" {
|
||||||
|
//Use default rule
|
||||||
|
ruleID = "default"
|
||||||
|
}
|
||||||
|
if h.handleAccessRouting(ruleID, w, r) {
|
||||||
|
//Request handled by subroute
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Validate basic auth
|
||||||
if sep.RequireBasicAuth {
|
if sep.RequireBasicAuth {
|
||||||
err := h.handleBasicAuthRouting(w, r, sep)
|
err := h.handleBasicAuthRouting(w, r, sep)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -94,7 +87,7 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
} else if !strings.HasSuffix(proxyingPath, "/") && sep.ProxyType != ProxyType_Root {
|
} else if !strings.HasSuffix(proxyingPath, "/") && sep.ProxyType != ProxyType_Root {
|
||||||
potentialProxtEndpoint := sep.GetVirtualDirectoryHandlerFromRequestURI(proxyingPath + "/")
|
potentialProxtEndpoint := sep.GetVirtualDirectoryHandlerFromRequestURI(proxyingPath + "/")
|
||||||
if potentialProxtEndpoint != nil && !targetProxyEndpoint.Disabled {
|
if potentialProxtEndpoint != nil && !potentialProxtEndpoint.Disabled {
|
||||||
//Missing tailing slash. Redirect to target proxy endpoint
|
//Missing tailing slash. Redirect to target proxy endpoint
|
||||||
http.Redirect(w, r, r.RequestURI+"/", http.StatusTemporaryRedirect)
|
http.Redirect(w, r, r.RequestURI+"/", http.StatusTemporaryRedirect)
|
||||||
return
|
return
|
||||||
@ -109,6 +102,13 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
/*
|
/*
|
||||||
Root Router Handling
|
Root Router Handling
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//Root access control based on default rule
|
||||||
|
blocked := h.handleAccessRouting("default", w, r)
|
||||||
|
if blocked {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
//Clean up the request URI
|
//Clean up the request URI
|
||||||
proxyingPath := strings.TrimSpace(r.RequestURI)
|
proxyingPath := strings.TrimSpace(r.RequestURI)
|
||||||
if !strings.HasSuffix(proxyingPath, "/") {
|
if !strings.HasSuffix(proxyingPath, "/") {
|
||||||
@ -136,7 +136,6 @@ Once entered this routing segment, the root routing options will take over
|
|||||||
for the routing logic.
|
for the routing logic.
|
||||||
*/
|
*/
|
||||||
func (h *ProxyHandler) handleRootRouting(w http.ResponseWriter, r *http.Request) {
|
func (h *ProxyHandler) handleRootRouting(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
domainOnly := r.Host
|
domainOnly := r.Host
|
||||||
if strings.Contains(r.Host, ":") {
|
if strings.Contains(r.Host, ":") {
|
||||||
hostPath := strings.Split(r.Host, ":")
|
hostPath := strings.Split(r.Host, ":")
|
||||||
@ -203,38 +202,3 @@ func (h *ProxyHandler) handleRootRouting(w http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle access routing logic. Return true if the request is handled or blocked by the access control logic
|
|
||||||
// if the return value is false, you can continue process the response writer
|
|
||||||
func (h *ProxyHandler) handleAccessRouting(w http.ResponseWriter, r *http.Request) bool {
|
|
||||||
//Check if this ip is in blacklist
|
|
||||||
clientIpAddr := geodb.GetRequesterIP(r)
|
|
||||||
if h.Parent.Option.GeodbStore.IsBlacklisted(clientIpAddr) {
|
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
||||||
w.WriteHeader(http.StatusForbidden)
|
|
||||||
template, err := os.ReadFile(filepath.Join(h.Parent.Option.WebDirectory, "templates/blacklist.html"))
|
|
||||||
if err != nil {
|
|
||||||
w.Write(page_forbidden)
|
|
||||||
} else {
|
|
||||||
w.Write(template)
|
|
||||||
}
|
|
||||||
h.logRequest(r, false, 403, "blacklist", "")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check if this ip is in whitelist
|
|
||||||
if !h.Parent.Option.GeodbStore.IsWhitelisted(clientIpAddr) {
|
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
||||||
w.WriteHeader(http.StatusForbidden)
|
|
||||||
template, err := os.ReadFile(filepath.Join(h.Parent.Option.WebDirectory, "templates/whitelist.html"))
|
|
||||||
if err != nil {
|
|
||||||
w.Write(page_forbidden)
|
|
||||||
} else {
|
|
||||||
w.Write(template)
|
|
||||||
}
|
|
||||||
h.logRequest(r, false, 403, "whitelist", "")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
65
src/mod/dynamicproxy/access.go
Normal file
65
src/mod/dynamicproxy/access.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package dynamicproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"imuslab.com/zoraxy/mod/access"
|
||||||
|
"imuslab.com/zoraxy/mod/netutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Handle access check (blacklist / whitelist), return true if request is handled (aka blocked)
|
||||||
|
// if the return value is false, you can continue process the response writer
|
||||||
|
func (h *ProxyHandler) handleAccessRouting(ruleID string, w http.ResponseWriter, r *http.Request) bool {
|
||||||
|
accessRule, err := h.Parent.Option.AccessController.GetAccessRuleByID(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
//Unable to load access rule. Target rule not found?
|
||||||
|
log.Println("[Proxy] Unable to load access rule: " + ruleID)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
w.Write([]byte("500 - Internal Server Error"))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
isBlocked, blockedReason := accessRequestBlocked(accessRule, h.Parent.Option.WebDirectory, w, r)
|
||||||
|
if isBlocked {
|
||||||
|
h.logRequest(r, false, 403, blockedReason, "")
|
||||||
|
}
|
||||||
|
return isBlocked
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return boolean, return true if access is blocked
|
||||||
|
// For string, it will return the blocked reason (if any)
|
||||||
|
func accessRequestBlocked(accessRule *access.AccessRule, templateDirectory string, w http.ResponseWriter, r *http.Request) (bool, string) {
|
||||||
|
//Check if this ip is in blacklist
|
||||||
|
clientIpAddr := netutils.GetRequesterIP(r)
|
||||||
|
if accessRule.IsBlacklisted(clientIpAddr) {
|
||||||
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
w.WriteHeader(http.StatusForbidden)
|
||||||
|
template, err := os.ReadFile(filepath.Join(templateDirectory, "templates/blacklist.html"))
|
||||||
|
if err != nil {
|
||||||
|
w.Write(page_forbidden)
|
||||||
|
} else {
|
||||||
|
w.Write(template)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, "blacklist"
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if this ip is in whitelist
|
||||||
|
if !accessRule.IsWhitelisted(clientIpAddr) {
|
||||||
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
w.WriteHeader(http.StatusForbidden)
|
||||||
|
template, err := os.ReadFile(filepath.Join(templateDirectory, "templates/whitelist.html"))
|
||||||
|
if err != nil {
|
||||||
|
w.Write(page_forbidden)
|
||||||
|
} else {
|
||||||
|
w.Write(template)
|
||||||
|
}
|
||||||
|
return true, "whitelist"
|
||||||
|
}
|
||||||
|
|
||||||
|
//Not blocked.
|
||||||
|
return false, ""
|
||||||
|
}
|
@ -16,6 +16,16 @@ import (
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
func (h *ProxyHandler) handleBasicAuthRouting(w http.ResponseWriter, r *http.Request, pe *ProxyEndpoint) error {
|
func (h *ProxyHandler) handleBasicAuthRouting(w http.ResponseWriter, r *http.Request, pe *ProxyEndpoint) error {
|
||||||
|
err := handleBasicAuth(w, r, pe)
|
||||||
|
if err != nil {
|
||||||
|
h.logRequest(r, false, 401, "host", pe.Domain)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle basic auth logic
|
||||||
|
// do not write to http.ResponseWriter if err return is not nil (already handled by this function)
|
||||||
|
func handleBasicAuth(w http.ResponseWriter, r *http.Request, pe *ProxyEndpoint) error {
|
||||||
if len(pe.BasicAuthExceptionRules) > 0 {
|
if len(pe.BasicAuthExceptionRules) > 0 {
|
||||||
//Check if the current path matches the exception rules
|
//Check if the current path matches the exception rules
|
||||||
for _, exceptionRule := range pe.BasicAuthExceptionRules {
|
for _, exceptionRule := range pe.BasicAuthExceptionRules {
|
||||||
@ -44,7 +54,6 @@ func (h *ProxyHandler) handleBasicAuthRouting(w http.ResponseWriter, r *http.Req
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !matchingFound {
|
if !matchingFound {
|
||||||
h.logRequest(r, false, 401, "host", pe.Domain)
|
|
||||||
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
|
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
|
||||||
w.WriteHeader(401)
|
w.WriteHeader(401)
|
||||||
return errors.New("unauthorized")
|
return errors.New("unauthorized")
|
||||||
|
@ -115,6 +115,28 @@ func (router *Router) StartProxyService() error {
|
|||||||
r.URL, _ = url.Parse(originalHostHeader)
|
r.URL, _ = url.Parse(originalHostHeader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Access Check (blacklist / whitelist)
|
||||||
|
ruleID := sep.AccessFilterUUID
|
||||||
|
if sep.AccessFilterUUID == "" {
|
||||||
|
//Use default rule
|
||||||
|
ruleID = "default"
|
||||||
|
}
|
||||||
|
accessRule, err := router.Option.AccessController.GetAccessRuleByID(ruleID)
|
||||||
|
if err == nil {
|
||||||
|
isBlocked, _ := accessRequestBlocked(accessRule, router.Option.WebDirectory, w, r)
|
||||||
|
if isBlocked {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Validate basic auth
|
||||||
|
if sep.RequireBasicAuth {
|
||||||
|
err := handleBasicAuth(w, r, sep)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sep.proxy.ServeHTTP(w, r, &dpcore.ResponseRewriteRuleSet{
|
sep.proxy.ServeHTTP(w, r, &dpcore.ResponseRewriteRuleSet{
|
||||||
ProxyDomain: sep.Domain,
|
ProxyDomain: sep.Domain,
|
||||||
OriginalHost: originalHostHeader,
|
OriginalHost: originalHostHeader,
|
||||||
|
@ -70,7 +70,8 @@ func (ep *ProxyEndpoint) AddUserDefinedHeader(key string, value string) error {
|
|||||||
func (ep *ProxyEndpoint) GetVirtualDirectoryHandlerFromRequestURI(requestURI string) *VirtualDirectoryEndpoint {
|
func (ep *ProxyEndpoint) GetVirtualDirectoryHandlerFromRequestURI(requestURI string) *VirtualDirectoryEndpoint {
|
||||||
for _, vdir := range ep.VirtualDirectories {
|
for _, vdir := range ep.VirtualDirectories {
|
||||||
if strings.HasPrefix(requestURI, vdir.MatchingPath) {
|
if strings.HasPrefix(requestURI, vdir.MatchingPath) {
|
||||||
return vdir
|
thisVdir := vdir
|
||||||
|
return thisVdir
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -80,7 +81,8 @@ func (ep *ProxyEndpoint) GetVirtualDirectoryHandlerFromRequestURI(requestURI str
|
|||||||
func (ep *ProxyEndpoint) GetVirtualDirectoryRuleByMatchingPath(matchingPath string) *VirtualDirectoryEndpoint {
|
func (ep *ProxyEndpoint) GetVirtualDirectoryRuleByMatchingPath(matchingPath string) *VirtualDirectoryEndpoint {
|
||||||
for _, vdir := range ep.VirtualDirectories {
|
for _, vdir := range ep.VirtualDirectories {
|
||||||
if vdir.MatchingPath == matchingPath {
|
if vdir.MatchingPath == matchingPath {
|
||||||
return vdir
|
thisVdir := vdir
|
||||||
|
return thisVdir
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"imuslab.com/zoraxy/mod/dynamicproxy/dpcore"
|
"imuslab.com/zoraxy/mod/dynamicproxy/dpcore"
|
||||||
"imuslab.com/zoraxy/mod/geodb"
|
"imuslab.com/zoraxy/mod/netutils"
|
||||||
"imuslab.com/zoraxy/mod/statistic"
|
"imuslab.com/zoraxy/mod/statistic"
|
||||||
"imuslab.com/zoraxy/mod/websocketproxy"
|
"imuslab.com/zoraxy/mod/websocketproxy"
|
||||||
)
|
)
|
||||||
@ -34,23 +34,45 @@ func (router *Router) getProxyEndpointFromHostname(hostname string) *ProxyEndpoi
|
|||||||
var targetSubdomainEndpoint *ProxyEndpoint = nil
|
var targetSubdomainEndpoint *ProxyEndpoint = nil
|
||||||
ep, ok := router.ProxyEndpoints.Load(hostname)
|
ep, ok := router.ProxyEndpoints.Load(hostname)
|
||||||
if ok {
|
if ok {
|
||||||
|
//Exact hit
|
||||||
targetSubdomainEndpoint = ep.(*ProxyEndpoint)
|
targetSubdomainEndpoint = ep.(*ProxyEndpoint)
|
||||||
|
if !targetSubdomainEndpoint.Disabled {
|
||||||
|
return targetSubdomainEndpoint
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//No hit. Try with wildcard
|
//No hit. Try with wildcard and alias
|
||||||
matchProxyEndpoints := []*ProxyEndpoint{}
|
matchProxyEndpoints := []*ProxyEndpoint{}
|
||||||
router.ProxyEndpoints.Range(func(k, v interface{}) bool {
|
router.ProxyEndpoints.Range(func(k, v interface{}) bool {
|
||||||
ep := v.(*ProxyEndpoint)
|
ep := v.(*ProxyEndpoint)
|
||||||
match, err := filepath.Match(ep.RootOrMatchingDomain, hostname)
|
match, err := filepath.Match(ep.RootOrMatchingDomain, hostname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//Continue
|
//Bad pattern. Skip this rule
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if match {
|
if match {
|
||||||
//targetSubdomainEndpoint = ep
|
//Wildcard matches. Skip checking alias
|
||||||
matchProxyEndpoints = append(matchProxyEndpoints, ep)
|
matchProxyEndpoints = append(matchProxyEndpoints, ep)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Wildcard not match. Check for alias
|
||||||
|
if ep.MatchingDomainAlias != nil && len(ep.MatchingDomainAlias) > 0 {
|
||||||
|
for _, aliasDomain := range ep.MatchingDomainAlias {
|
||||||
|
match, err := filepath.Match(aliasDomain, hostname)
|
||||||
|
if err != nil {
|
||||||
|
//Bad pattern. Skip this alias
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if match {
|
||||||
|
//This alias match
|
||||||
|
matchProxyEndpoints = append(matchProxyEndpoints, ep)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -224,7 +246,7 @@ func (h *ProxyHandler) logRequest(r *http.Request, succ bool, statusCode int, fo
|
|||||||
if h.Parent.Option.StatisticCollector != nil {
|
if h.Parent.Option.StatisticCollector != nil {
|
||||||
go func() {
|
go func() {
|
||||||
requestInfo := statistic.RequestInfo{
|
requestInfo := statistic.RequestInfo{
|
||||||
IpAddr: geodb.GetRequesterIP(r),
|
IpAddr: netutils.GetRequesterIP(r),
|
||||||
RequestOriginalCountryISOCode: h.Parent.Option.GeodbStore.GetRequesterCountryISOCode(r),
|
RequestOriginalCountryISOCode: h.Parent.Option.GeodbStore.GetRequesterCountryISOCode(r),
|
||||||
Succ: succ,
|
Succ: succ,
|
||||||
StatusCode: statusCode,
|
StatusCode: statusCode,
|
||||||
|
@ -19,6 +19,9 @@ import (
|
|||||||
func (router *Router) PrepareProxyRoute(endpoint *ProxyEndpoint) (*ProxyEndpoint, error) {
|
func (router *Router) PrepareProxyRoute(endpoint *ProxyEndpoint) (*ProxyEndpoint, error) {
|
||||||
//Filter the tailing slash if any
|
//Filter the tailing slash if any
|
||||||
domain := endpoint.Domain
|
domain := endpoint.Domain
|
||||||
|
if len(domain) == 0 {
|
||||||
|
return nil, errors.New("invalid endpoint config")
|
||||||
|
}
|
||||||
if domain[len(domain)-1:] == "/" {
|
if domain[len(domain)-1:] == "/" {
|
||||||
domain = domain[:len(domain)-1]
|
domain = domain[:len(domain)-1]
|
||||||
}
|
}
|
||||||
@ -51,6 +54,10 @@ func (router *Router) PrepareProxyRoute(endpoint *ProxyEndpoint) (*ProxyEndpoint
|
|||||||
//Prepare proxy routing hjandler for each of the virtual directories
|
//Prepare proxy routing hjandler for each of the virtual directories
|
||||||
for _, vdir := range endpoint.VirtualDirectories {
|
for _, vdir := range endpoint.VirtualDirectories {
|
||||||
domain := vdir.Domain
|
domain := vdir.Domain
|
||||||
|
if len(domain) == 0 {
|
||||||
|
//invalid vdir
|
||||||
|
continue
|
||||||
|
}
|
||||||
if domain[len(domain)-1:] == "/" {
|
if domain[len(domain)-1:] == "/" {
|
||||||
domain = domain[:len(domain)-1]
|
domain = domain[:len(domain)-1]
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
<h3 style="margin-top: 1em;">403 - Forbidden</h3>
|
<h3 style="margin-top: 1em;">403 - Forbidden</h3>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
<p>You do not have permission to view this directory or page. <br>
|
<p>You do not have permission to view this directory or page. <br>
|
||||||
This might cause by the region limit setting of this site.</p>
|
This might be caused by the region limit setting of this site.</p>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
<div style="text-align: left;">
|
<div style="text-align: left;">
|
||||||
<small>Request time: <span id="reqtime"></span></small><br>
|
<small>Request time: <span id="reqtime"></span></small><br>
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"imuslab.com/zoraxy/mod/access"
|
||||||
"imuslab.com/zoraxy/mod/dynamicproxy/dpcore"
|
"imuslab.com/zoraxy/mod/dynamicproxy/dpcore"
|
||||||
"imuslab.com/zoraxy/mod/dynamicproxy/redirection"
|
"imuslab.com/zoraxy/mod/dynamicproxy/redirection"
|
||||||
"imuslab.com/zoraxy/mod/geodb"
|
"imuslab.com/zoraxy/mod/geodb"
|
||||||
@ -34,7 +35,8 @@ type RouterOption struct {
|
|||||||
ForceHttpsRedirect bool //Force redirection of http to https endpoint
|
ForceHttpsRedirect bool //Force redirection of http to https endpoint
|
||||||
TlsManager *tlscert.Manager
|
TlsManager *tlscert.Manager
|
||||||
RedirectRuleTable *redirection.RuleTable
|
RedirectRuleTable *redirection.RuleTable
|
||||||
GeodbStore *geodb.Store //GeoIP blacklist and whitelist
|
GeodbStore *geodb.Store //GeoIP resolver
|
||||||
|
AccessController *access.Controller //Blacklist / whitelist controller
|
||||||
StatisticCollector *statistic.Collector
|
StatisticCollector *statistic.Collector
|
||||||
WebDirectory string //The static web server directory containing the templates folder
|
WebDirectory string //The static web server directory containing the templates folder
|
||||||
}
|
}
|
||||||
@ -90,9 +92,10 @@ type VirtualDirectoryEndpoint struct {
|
|||||||
|
|
||||||
// A proxy endpoint record, a general interface for handling inbound routing
|
// A proxy endpoint record, a general interface for handling inbound routing
|
||||||
type ProxyEndpoint struct {
|
type ProxyEndpoint struct {
|
||||||
ProxyType int //The type of this proxy, see const def
|
ProxyType int //The type of this proxy, see const def
|
||||||
RootOrMatchingDomain string //Matching domain for host, also act as key
|
RootOrMatchingDomain string //Matching domain for host, also act as key
|
||||||
Domain string //Domain or IP to proxy to
|
MatchingDomainAlias []string //A list of domains that alias to this rule
|
||||||
|
Domain string //Domain or IP to proxy to
|
||||||
|
|
||||||
//TLS/SSL Related
|
//TLS/SSL Related
|
||||||
RequireTLS bool //Target domain require TLS
|
RequireTLS bool //Target domain require TLS
|
||||||
@ -111,14 +114,17 @@ type ProxyEndpoint struct {
|
|||||||
BasicAuthCredentials []*BasicAuthCredentials //Basic auth credentials
|
BasicAuthCredentials []*BasicAuthCredentials //Basic auth credentials
|
||||||
BasicAuthExceptionRules []*BasicAuthExceptionRule //Path to exclude in a basic auth enabled proxy target
|
BasicAuthExceptionRules []*BasicAuthExceptionRule //Path to exclude in a basic auth enabled proxy target
|
||||||
|
|
||||||
//Fallback routing logic
|
//Access Control
|
||||||
DefaultSiteOption int //Fallback routing logic options
|
AccessFilterUUID string //Access filter ID
|
||||||
DefaultSiteValue string //Fallback routing target, optional
|
|
||||||
|
|
||||||
Disabled bool //If the rule is disabled
|
Disabled bool //If the rule is disabled
|
||||||
|
|
||||||
|
//Fallback routing logic (Special Rule Sets Only)
|
||||||
|
DefaultSiteOption int //Fallback routing logic options
|
||||||
|
DefaultSiteValue string //Fallback routing target, optional
|
||||||
|
|
||||||
//Internal Logic Elements
|
//Internal Logic Elements
|
||||||
parent *Router
|
parent *Router `json:"-"`
|
||||||
proxy *dpcore.ReverseProxy `json:"-"`
|
proxy *dpcore.ReverseProxy `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,18 +13,16 @@ import (
|
|||||||
|
|
||||||
type Sender struct {
|
type Sender struct {
|
||||||
Hostname string //E.g. mail.gandi.net
|
Hostname string //E.g. mail.gandi.net
|
||||||
Domain string //E.g. arozos.com
|
|
||||||
Port int //E.g. 587
|
Port int //E.g. 587
|
||||||
Username string //Username of the email account
|
Username string //Username of the email account
|
||||||
Password string //Password of the email account
|
Password string //Password of the email account
|
||||||
SenderAddr string //e.g. admin@arozos.com
|
SenderAddr string //e.g. admin@arozos.com
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create a new email sender object
|
// Create a new email sender object
|
||||||
func NewEmailSender(hostname string, domain string, port int, username string, password string, senderAddr string) *Sender {
|
func NewEmailSender(hostname string, port int, username string, password string, senderAddr string) *Sender {
|
||||||
return &Sender{
|
return &Sender{
|
||||||
Hostname: hostname,
|
Hostname: hostname,
|
||||||
Domain: domain,
|
|
||||||
Port: port,
|
Port: port,
|
||||||
Username: username,
|
Username: username,
|
||||||
Password: password,
|
Password: password,
|
||||||
@ -33,13 +31,15 @@ func NewEmailSender(hostname string, domain string, port int, username string, p
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Send a email to a reciving addr
|
Send a email to a reciving addr
|
||||||
Example Usage:
|
Example Usage:
|
||||||
SendEmail(
|
SendEmail(
|
||||||
test@example.com,
|
|
||||||
"Free donuts",
|
test@example.com,
|
||||||
"Come get your free donuts on this Sunday!"
|
"Free donuts",
|
||||||
)
|
"Come get your free donuts on this Sunday!"
|
||||||
|
|
||||||
|
)
|
||||||
*/
|
*/
|
||||||
func (s *Sender) SendEmail(to string, subject string, content string) error {
|
func (s *Sender) SendEmail(to string, subject string, content string) error {
|
||||||
//Parse the email content
|
//Parse the email content
|
||||||
@ -50,7 +50,9 @@ func (s *Sender) SendEmail(to string, subject string, content string) error {
|
|||||||
content + "\n\n")
|
content + "\n\n")
|
||||||
|
|
||||||
//Login to the SMTP server
|
//Login to the SMTP server
|
||||||
auth := smtp.PlainAuth("", s.Username+"@"+s.Domain, s.Password, s.Hostname)
|
//Username can be username (e.g. admin) or email (e.g. admin@example.com), depending on SMTP service provider
|
||||||
|
auth := smtp.PlainAuth("", s.Username, s.Password, s.Hostname)
|
||||||
|
|
||||||
err := smtp.SendMail(s.Hostname+":"+strconv.Itoa(s.Port), auth, s.SenderAddr, []string{to}, msg)
|
err := smtp.SendMail(s.Hostname+":"+strconv.Itoa(s.Port), auth, s.SenderAddr, []string{to}, msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
8
src/mod/geodb/README.txt
Normal file
8
src/mod/geodb/README.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
The data source for geoip is licensed under CC0
|
||||||
|
If you want to build your own version of geodb with updated whitelist,
|
||||||
|
you can go to this repo and get the "GeoFeed + Whois + ASN" version of
|
||||||
|
both the IPV4 and IPV6 mapping (the one without -num)
|
||||||
|
|
||||||
|
https://github.com/sapics/ip-location-db/tree/main/geolite2-country
|
||||||
|
|
||||||
|
And rename it to "gepipv4.csv" and "gepipv6.csv"
|
@ -1,91 +0,0 @@
|
|||||||
package geodb
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
/*
|
|
||||||
Blacklist.go
|
|
||||||
|
|
||||||
This script store the blacklist related functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
//Geo Blacklist
|
|
||||||
|
|
||||||
func (s *Store) AddCountryCodeToBlackList(countryCode string) {
|
|
||||||
countryCode = strings.ToLower(countryCode)
|
|
||||||
s.sysdb.Write("blacklist-cn", countryCode, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) RemoveCountryCodeFromBlackList(countryCode string) {
|
|
||||||
countryCode = strings.ToLower(countryCode)
|
|
||||||
s.sysdb.Delete("blacklist-cn", countryCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) IsCountryCodeBlacklisted(countryCode string) bool {
|
|
||||||
countryCode = strings.ToLower(countryCode)
|
|
||||||
var isBlacklisted bool = false
|
|
||||||
s.sysdb.Read("blacklist-cn", countryCode, &isBlacklisted)
|
|
||||||
return isBlacklisted
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) GetAllBlacklistedCountryCode() []string {
|
|
||||||
bannedCountryCodes := []string{}
|
|
||||||
entries, err := s.sysdb.ListTable("blacklist-cn")
|
|
||||||
if err != nil {
|
|
||||||
return bannedCountryCodes
|
|
||||||
}
|
|
||||||
for _, keypairs := range entries {
|
|
||||||
ip := string(keypairs[0])
|
|
||||||
bannedCountryCodes = append(bannedCountryCodes, ip)
|
|
||||||
}
|
|
||||||
|
|
||||||
return bannedCountryCodes
|
|
||||||
}
|
|
||||||
|
|
||||||
//IP Blacklsits
|
|
||||||
|
|
||||||
func (s *Store) AddIPToBlackList(ipAddr string) {
|
|
||||||
s.sysdb.Write("blacklist-ip", ipAddr, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) RemoveIPFromBlackList(ipAddr string) {
|
|
||||||
s.sysdb.Delete("blacklist-ip", ipAddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) GetAllBlacklistedIp() []string {
|
|
||||||
bannedIps := []string{}
|
|
||||||
entries, err := s.sysdb.ListTable("blacklist-ip")
|
|
||||||
if err != nil {
|
|
||||||
return bannedIps
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, keypairs := range entries {
|
|
||||||
ip := string(keypairs[0])
|
|
||||||
bannedIps = append(bannedIps, ip)
|
|
||||||
}
|
|
||||||
|
|
||||||
return bannedIps
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) IsIPBlacklisted(ipAddr string) bool {
|
|
||||||
var isBlacklisted bool = false
|
|
||||||
s.sysdb.Read("blacklist-ip", ipAddr, &isBlacklisted)
|
|
||||||
if isBlacklisted {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check for IP wildcard and CIRD rules
|
|
||||||
AllBlacklistedIps := s.GetAllBlacklistedIp()
|
|
||||||
for _, blacklistRule := range AllBlacklistedIps {
|
|
||||||
wildcardMatch := MatchIpWildcard(ipAddr, blacklistRule)
|
|
||||||
if wildcardMatch {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
cidrMatch := MatchIpCIDR(ipAddr, blacklistRule)
|
|
||||||
if cidrMatch {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
@ -2,11 +2,10 @@ package geodb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"imuslab.com/zoraxy/mod/database"
|
"imuslab.com/zoraxy/mod/database"
|
||||||
|
"imuslab.com/zoraxy/mod/netutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed geoipv4.csv
|
//go:embed geoipv4.csv
|
||||||
@ -16,12 +15,10 @@ var geoipv4 []byte //Geodb dataset for ipv4
|
|||||||
var geoipv6 []byte //Geodb dataset for ipv6
|
var geoipv6 []byte //Geodb dataset for ipv6
|
||||||
|
|
||||||
type Store struct {
|
type Store struct {
|
||||||
BlacklistEnabled bool
|
geodb [][]string //Parsed geodb list
|
||||||
WhitelistEnabled bool
|
geodbIpv6 [][]string //Parsed geodb list for ipv6
|
||||||
geodb [][]string //Parsed geodb list
|
geotrie *trie
|
||||||
geodbIpv6 [][]string //Parsed geodb list for ipv6
|
geotrieIpv6 *trie
|
||||||
geotrie *trie
|
|
||||||
geotrieIpv6 *trie
|
|
||||||
//geoipCache sync.Map
|
//geoipCache sync.Map
|
||||||
sysdb *database.Database
|
sysdb *database.Database
|
||||||
option *StoreOptions
|
option *StoreOptions
|
||||||
@ -48,40 +45,6 @@ func NewGeoDb(sysdb *database.Database, option *StoreOptions) (*Store, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
blacklistEnabled := false
|
|
||||||
whitelistEnabled := false
|
|
||||||
if sysdb != nil {
|
|
||||||
err = sysdb.NewTable("blacklist-cn")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = sysdb.NewTable("blacklist-ip")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = sysdb.NewTable("whitelist-cn")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = sysdb.NewTable("whitelist-ip")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = sysdb.NewTable("blackwhitelist")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
sysdb.Read("blackwhitelist", "blacklistEnabled", &blacklistEnabled)
|
|
||||||
sysdb.Read("blackwhitelist", "whitelistEnabled", &whitelistEnabled)
|
|
||||||
} else {
|
|
||||||
log.Println("Database pointer set to nil: Entering debug mode")
|
|
||||||
}
|
|
||||||
|
|
||||||
var ipv4Trie *trie
|
var ipv4Trie *trie
|
||||||
if !option.AllowSlowIpv4LookUp {
|
if !option.AllowSlowIpv4LookUp {
|
||||||
ipv4Trie = constrctTrieTree(parsedGeoData)
|
ipv4Trie = constrctTrieTree(parsedGeoData)
|
||||||
@ -93,27 +56,15 @@ func NewGeoDb(sysdb *database.Database, option *StoreOptions) (*Store, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &Store{
|
return &Store{
|
||||||
BlacklistEnabled: blacklistEnabled,
|
geodb: parsedGeoData,
|
||||||
WhitelistEnabled: whitelistEnabled,
|
geotrie: ipv4Trie,
|
||||||
geodb: parsedGeoData,
|
geodbIpv6: parsedGeoDataIpv6,
|
||||||
geotrie: ipv4Trie,
|
geotrieIpv6: ipv6Trie,
|
||||||
geodbIpv6: parsedGeoDataIpv6,
|
sysdb: sysdb,
|
||||||
geotrieIpv6: ipv6Trie,
|
option: option,
|
||||||
sysdb: sysdb,
|
|
||||||
option: option,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) ToggleBlacklist(enabled bool) {
|
|
||||||
s.sysdb.Write("blackwhitelist", "blacklistEnabled", enabled)
|
|
||||||
s.BlacklistEnabled = enabled
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) ToggleWhitelist(enabled bool) {
|
|
||||||
s.sysdb.Write("blackwhitelist", "whitelistEnabled", enabled)
|
|
||||||
s.WhitelistEnabled = enabled
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) ResolveCountryCodeFromIP(ipstring string) (*CountryInfo, error) {
|
func (s *Store) ResolveCountryCodeFromIP(ipstring string) (*CountryInfo, error) {
|
||||||
cc := s.search(ipstring)
|
cc := s.search(ipstring)
|
||||||
return &CountryInfo{
|
return &CountryInfo{
|
||||||
@ -127,93 +78,16 @@ func (s *Store) Close() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Check if a IP address is blacklisted, in either country or IP blacklist
|
|
||||||
IsBlacklisted default return is false (allow access)
|
|
||||||
*/
|
|
||||||
func (s *Store) IsBlacklisted(ipAddr string) bool {
|
|
||||||
if !s.BlacklistEnabled {
|
|
||||||
//Blacklist not enabled. Always return false
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if ipAddr == "" {
|
|
||||||
//Unable to get the target IP address
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
countryCode, err := s.ResolveCountryCodeFromIP(ipAddr)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.IsCountryCodeBlacklisted(countryCode.CountryIsoCode) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.IsIPBlacklisted(ipAddr) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
IsWhitelisted check if a given IP address is in the current
|
|
||||||
server's white list.
|
|
||||||
|
|
||||||
Note that the Whitelist default result is true even
|
|
||||||
when encountered error
|
|
||||||
*/
|
|
||||||
func (s *Store) IsWhitelisted(ipAddr string) bool {
|
|
||||||
if !s.WhitelistEnabled {
|
|
||||||
//Whitelist not enabled. Always return true (allow access)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if ipAddr == "" {
|
|
||||||
//Unable to get the target IP address, assume ok
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
countryCode, err := s.ResolveCountryCodeFromIP(ipAddr)
|
|
||||||
if err != nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.IsCountryCodeWhitelisted(countryCode.CountryIsoCode) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.IsIPWhitelisted(ipAddr) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// A helper function that check both blacklist and whitelist for access
|
|
||||||
// for both geoIP and ip / CIDR ranges
|
|
||||||
func (s *Store) AllowIpAccess(ipaddr string) bool {
|
|
||||||
if s.IsBlacklisted(ipaddr) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.IsWhitelisted(ipaddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) AllowConnectionAccess(conn net.Conn) bool {
|
|
||||||
if addr, ok := conn.RemoteAddr().(*net.TCPAddr); ok {
|
|
||||||
return s.AllowIpAccess(addr.IP.String())
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) GetRequesterCountryISOCode(r *http.Request) string {
|
func (s *Store) GetRequesterCountryISOCode(r *http.Request) string {
|
||||||
ipAddr := GetRequesterIP(r)
|
ipAddr := netutils.GetRequesterIP(r)
|
||||||
if ipAddr == "" {
|
if ipAddr == "" {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if netutils.IsPrivateIP(ipAddr) {
|
||||||
|
return "LAN"
|
||||||
|
}
|
||||||
|
|
||||||
countryCode, err := s.ResolveCountryCodeFromIP(ipAddr)
|
countryCode, err := s.ResolveCountryCodeFromIP(ipAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
|
@ -51,8 +51,29 @@ func TestResolveCountryCodeFromIP(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test an IP address that should return a valid country code
|
// Test an IP address that should return a valid country code
|
||||||
ip := "8.8.8.8"
|
knownIpCountryMap := [][]string{
|
||||||
expected := "US"
|
{"3.224.220.101", "US"},
|
||||||
|
{"176.113.115.113", "RU"},
|
||||||
|
{"65.21.233.213", "FI"},
|
||||||
|
{"94.23.207.193", "FR"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testcase := range knownIpCountryMap {
|
||||||
|
ip := testcase[0]
|
||||||
|
expected := testcase[1]
|
||||||
|
info, err := store.ResolveCountryCodeFromIP(ip)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error resolving country code for IP %s: %v", ip, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if info.CountryIsoCode != expected {
|
||||||
|
t.Errorf("expected country code %s, but got %s for IP %s", expected, info.CountryIsoCode, ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test an IP address that should return an empty country code
|
||||||
|
ip := "127.0.0.1"
|
||||||
|
expected := ""
|
||||||
info, err := store.ResolveCountryCodeFromIP(ip)
|
info, err := store.ResolveCountryCodeFromIP(ip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("error resolving country code for IP %s: %v", ip, err)
|
t.Errorf("error resolving country code for IP %s: %v", ip, err)
|
||||||
@ -61,16 +82,4 @@ func TestResolveCountryCodeFromIP(t *testing.T) {
|
|||||||
if info.CountryIsoCode != expected {
|
if info.CountryIsoCode != expected {
|
||||||
t.Errorf("expected country code %s, but got %s for IP %s", expected, info.CountryIsoCode, ip)
|
t.Errorf("expected country code %s, but got %s for IP %s", expected, info.CountryIsoCode, ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test an IP address that should return an empty country code
|
|
||||||
ip = "127.0.0.1"
|
|
||||||
expected = ""
|
|
||||||
info, err = store.ResolveCountryCodeFromIP(ip)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error resolving country code for IP %s: %v", ip, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if info.CountryIsoCode != expected {
|
|
||||||
t.Errorf("expected country code %s, but got %s for IP %s", expected, info.CountryIsoCode, ip)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
123399
src/mod/geodb/geoipv4.csv
123399
src/mod/geodb/geoipv4.csv
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,8 @@ import (
|
|||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"imuslab.com/zoraxy/mod/netutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Store) search(ip string) string {
|
func (s *Store) search(ip string) string {
|
||||||
@ -24,7 +26,7 @@ func (s *Store) search(ip string) string {
|
|||||||
|
|
||||||
//Search in geotrie tree
|
//Search in geotrie tree
|
||||||
cc := ""
|
cc := ""
|
||||||
if IsIPv6(ip) {
|
if netutils.IsIPv6(ip) {
|
||||||
if s.geotrieIpv6 == nil {
|
if s.geotrieIpv6 == nil {
|
||||||
cc = s.slowSearchIpv6(ip)
|
cc = s.slowSearchIpv6(ip)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,129 +0,0 @@
|
|||||||
package geodb
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
Whitelist.go
|
|
||||||
|
|
||||||
This script handles whitelist related functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
const (
|
|
||||||
EntryType_CountryCode int = 0
|
|
||||||
EntryType_IP int = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
type WhitelistEntry struct {
|
|
||||||
EntryType int //Entry type of whitelist, Country Code or IP
|
|
||||||
CC string //ISO Country Code
|
|
||||||
IP string //IP address or range
|
|
||||||
Comment string //Comment for this entry
|
|
||||||
}
|
|
||||||
|
|
||||||
//Geo Whitelist
|
|
||||||
|
|
||||||
func (s *Store) AddCountryCodeToWhitelist(countryCode string, comment string) {
|
|
||||||
countryCode = strings.ToLower(countryCode)
|
|
||||||
entry := WhitelistEntry{
|
|
||||||
EntryType: EntryType_CountryCode,
|
|
||||||
CC: countryCode,
|
|
||||||
Comment: comment,
|
|
||||||
}
|
|
||||||
|
|
||||||
s.sysdb.Write("whitelist-cn", countryCode, entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) RemoveCountryCodeFromWhitelist(countryCode string) {
|
|
||||||
countryCode = strings.ToLower(countryCode)
|
|
||||||
s.sysdb.Delete("whitelist-cn", countryCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) IsCountryCodeWhitelisted(countryCode string) bool {
|
|
||||||
countryCode = strings.ToLower(countryCode)
|
|
||||||
return s.sysdb.KeyExists("whitelist-cn", countryCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) GetAllWhitelistedCountryCode() []*WhitelistEntry {
|
|
||||||
whitelistedCountryCode := []*WhitelistEntry{}
|
|
||||||
entries, err := s.sysdb.ListTable("whitelist-cn")
|
|
||||||
if err != nil {
|
|
||||||
return whitelistedCountryCode
|
|
||||||
}
|
|
||||||
for _, keypairs := range entries {
|
|
||||||
thisWhitelistEntry := WhitelistEntry{}
|
|
||||||
json.Unmarshal(keypairs[1], &thisWhitelistEntry)
|
|
||||||
whitelistedCountryCode = append(whitelistedCountryCode, &thisWhitelistEntry)
|
|
||||||
}
|
|
||||||
|
|
||||||
return whitelistedCountryCode
|
|
||||||
}
|
|
||||||
|
|
||||||
//IP Whitelist
|
|
||||||
|
|
||||||
func (s *Store) AddIPToWhiteList(ipAddr string, comment string) {
|
|
||||||
thisIpEntry := WhitelistEntry{
|
|
||||||
EntryType: EntryType_IP,
|
|
||||||
IP: ipAddr,
|
|
||||||
Comment: comment,
|
|
||||||
}
|
|
||||||
|
|
||||||
s.sysdb.Write("whitelist-ip", ipAddr, thisIpEntry)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) RemoveIPFromWhiteList(ipAddr string) {
|
|
||||||
s.sysdb.Delete("whitelist-ip", ipAddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) IsIPWhitelisted(ipAddr string) bool {
|
|
||||||
isWhitelisted := s.sysdb.KeyExists("whitelist-ip", ipAddr)
|
|
||||||
if isWhitelisted {
|
|
||||||
//single IP whitelist entry
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check for IP wildcard and CIRD rules
|
|
||||||
AllWhitelistedIps := s.GetAllWhitelistedIpAsStringSlice()
|
|
||||||
for _, whitelistRules := range AllWhitelistedIps {
|
|
||||||
wildcardMatch := MatchIpWildcard(ipAddr, whitelistRules)
|
|
||||||
if wildcardMatch {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
cidrMatch := MatchIpCIDR(ipAddr, whitelistRules)
|
|
||||||
if cidrMatch {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) GetAllWhitelistedIp() []*WhitelistEntry {
|
|
||||||
whitelistedIp := []*WhitelistEntry{}
|
|
||||||
entries, err := s.sysdb.ListTable("whitelist-ip")
|
|
||||||
if err != nil {
|
|
||||||
return whitelistedIp
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, keypairs := range entries {
|
|
||||||
//ip := string(keypairs[0])
|
|
||||||
thisEntry := WhitelistEntry{}
|
|
||||||
json.Unmarshal(keypairs[1], &thisEntry)
|
|
||||||
whitelistedIp = append(whitelistedIp, &thisEntry)
|
|
||||||
}
|
|
||||||
|
|
||||||
return whitelistedIp
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) GetAllWhitelistedIpAsStringSlice() []string {
|
|
||||||
allWhitelistedIPs := []string{}
|
|
||||||
entries := s.GetAllWhitelistedIp()
|
|
||||||
for _, entry := range entries {
|
|
||||||
allWhitelistedIPs = append(allWhitelistedIPs, entry.IP)
|
|
||||||
}
|
|
||||||
|
|
||||||
return allWhitelistedIPs
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package geodb
|
package netutils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
@ -6,7 +6,13 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Utilities function
|
/*
|
||||||
|
MatchIP.go
|
||||||
|
|
||||||
|
This script contains function for matching IP address, comparing
|
||||||
|
CIDR and IPv4 / v6 validations
|
||||||
|
*/
|
||||||
|
|
||||||
func GetRequesterIP(r *http.Request) string {
|
func GetRequesterIP(r *http.Request) string {
|
||||||
ip := r.Header.Get("X-Real-Ip")
|
ip := r.Header.Get("X-Real-Ip")
|
||||||
if ip == "" {
|
if ip == "" {
|
||||||
@ -87,6 +93,10 @@ func MatchIpCIDR(ip string, cidr string) bool {
|
|||||||
|
|
||||||
// Check if a ip is private IP range
|
// Check if a ip is private IP range
|
||||||
func IsPrivateIP(ipStr string) bool {
|
func IsPrivateIP(ipStr string) bool {
|
||||||
|
if ipStr == "127.0.0.1" || ipStr == "::1" {
|
||||||
|
//local loopback
|
||||||
|
return true
|
||||||
|
}
|
||||||
ip := net.ParseIP(ipStr)
|
ip := net.ParseIP(ipStr)
|
||||||
if ip == nil {
|
if ip == nil {
|
||||||
return false
|
return false
|
@ -94,6 +94,7 @@ func ReverseProxtInit() {
|
|||||||
GeodbStore: geodbStore,
|
GeodbStore: geodbStore,
|
||||||
StatisticCollector: statisticCollector,
|
StatisticCollector: statisticCollector,
|
||||||
WebDirectory: *staticWebServerRoot,
|
WebDirectory: *staticWebServerRoot,
|
||||||
|
AccessController: accessController,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
SystemWideLogger.PrintAndLog("Proxy", "Unable to create dynamic proxy router", err)
|
SystemWideLogger.PrintAndLog("Proxy", "Unable to create dynamic proxy router", err)
|
||||||
@ -194,6 +195,7 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
useTLS := (tls == "true")
|
useTLS := (tls == "true")
|
||||||
|
|
||||||
|
//Bypass global TLS value / allow direct access from port 80?
|
||||||
bypassGlobalTLS, _ := utils.PostPara(r, "bypassGlobalTLS")
|
bypassGlobalTLS, _ := utils.PostPara(r, "bypassGlobalTLS")
|
||||||
if bypassGlobalTLS == "" {
|
if bypassGlobalTLS == "" {
|
||||||
bypassGlobalTLS = "false"
|
bypassGlobalTLS = "false"
|
||||||
@ -201,6 +203,7 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
useBypassGlobalTLS := bypassGlobalTLS == "true"
|
useBypassGlobalTLS := bypassGlobalTLS == "true"
|
||||||
|
|
||||||
|
//Enable TLS validation?
|
||||||
stv, _ := utils.PostPara(r, "tlsval")
|
stv, _ := utils.PostPara(r, "tlsval")
|
||||||
if stv == "" {
|
if stv == "" {
|
||||||
stv = "false"
|
stv = "false"
|
||||||
@ -208,6 +211,17 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
skipTlsValidation := (stv == "true")
|
skipTlsValidation := (stv == "true")
|
||||||
|
|
||||||
|
//Get access rule ID
|
||||||
|
accessRuleID, _ := utils.PostPara(r, "access")
|
||||||
|
if accessRuleID == "" {
|
||||||
|
accessRuleID = "default"
|
||||||
|
}
|
||||||
|
if !accessController.AccessRuleExists(accessRuleID) {
|
||||||
|
utils.SendErrorResponse(w, "invalid access rule ID selected")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Require basic auth?
|
||||||
rba, _ := utils.PostPara(r, "bauth")
|
rba, _ := utils.PostPara(r, "bauth")
|
||||||
if rba == "" {
|
if rba == "" {
|
||||||
rba = "false"
|
rba = "false"
|
||||||
@ -254,19 +268,37 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
if eptype == "host" {
|
if eptype == "host" {
|
||||||
rootOrMatchingDomain, err := utils.PostPara(r, "rootname")
|
rootOrMatchingDomain, err := utils.PostPara(r, "rootname")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.SendErrorResponse(w, "subdomain not defined")
|
utils.SendErrorResponse(w, "hostname not defined")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
rootOrMatchingDomain = strings.TrimSpace(rootOrMatchingDomain)
|
||||||
|
|
||||||
|
//Check if it contains ",", if yes, split the remainings as alias
|
||||||
|
aliasHostnames := []string{}
|
||||||
|
if strings.Contains(rootOrMatchingDomain, ",") {
|
||||||
|
matchingDomains := strings.Split(rootOrMatchingDomain, ",")
|
||||||
|
if len(matchingDomains) > 1 {
|
||||||
|
rootOrMatchingDomain = matchingDomains[0]
|
||||||
|
for _, aliasHostname := range matchingDomains[1:] {
|
||||||
|
//Filter out any space
|
||||||
|
aliasHostnames = append(aliasHostnames, strings.TrimSpace(aliasHostname))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Generate a proxy endpoint object
|
||||||
thisProxyEndpoint := dynamicproxy.ProxyEndpoint{
|
thisProxyEndpoint := dynamicproxy.ProxyEndpoint{
|
||||||
//I/O
|
//I/O
|
||||||
ProxyType: dynamicproxy.ProxyType_Host,
|
ProxyType: dynamicproxy.ProxyType_Host,
|
||||||
RootOrMatchingDomain: rootOrMatchingDomain,
|
RootOrMatchingDomain: rootOrMatchingDomain,
|
||||||
|
MatchingDomainAlias: aliasHostnames,
|
||||||
Domain: endpoint,
|
Domain: endpoint,
|
||||||
//TLS
|
//TLS
|
||||||
RequireTLS: useTLS,
|
RequireTLS: useTLS,
|
||||||
BypassGlobalTLS: useBypassGlobalTLS,
|
BypassGlobalTLS: useBypassGlobalTLS,
|
||||||
SkipCertValidations: skipTlsValidation,
|
SkipCertValidations: skipTlsValidation,
|
||||||
SkipWebSocketOriginCheck: bypassWebsocketOriginCheck,
|
SkipWebSocketOriginCheck: bypassWebsocketOriginCheck,
|
||||||
|
AccessFilterUUID: accessRuleID,
|
||||||
//VDir
|
//VDir
|
||||||
VirtualDirectories: []*dynamicproxy.VirtualDirectoryEndpoint{},
|
VirtualDirectories: []*dynamicproxy.VirtualDirectoryEndpoint{},
|
||||||
//Custom headers
|
//Custom headers
|
||||||
@ -439,6 +471,62 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
utils.SendOK(w)
|
utils.SendOK(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ReverseProxyHandleAlias(w http.ResponseWriter, r *http.Request) {
|
||||||
|
rootNameOrMatchingDomain, err := utils.PostPara(r, "ep")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "Invalid ep given")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//No need to check for type as root (/) can be set to default route
|
||||||
|
//and hence, you will not need alias
|
||||||
|
|
||||||
|
//Load the previous alias from current proxy rules
|
||||||
|
targetProxyEntry, err := dynamicProxyRouter.LoadProxy(rootNameOrMatchingDomain)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "Target proxy config not found or could not be loaded")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
newAliasJSON, err := utils.PostPara(r, "alias")
|
||||||
|
if err != nil {
|
||||||
|
//No new set of alias given
|
||||||
|
utils.SendErrorResponse(w, "new alias not given")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Write new alias to runtime and file
|
||||||
|
newAlias := []string{}
|
||||||
|
err = json.Unmarshal([]byte(newAliasJSON), &newAlias)
|
||||||
|
if err != nil {
|
||||||
|
SystemWideLogger.PrintAndLog("Proxy", "Unable to parse new alias list", err)
|
||||||
|
utils.SendErrorResponse(w, "Invalid alias list given")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set the current alias
|
||||||
|
newProxyEndpoint := dynamicproxy.CopyEndpoint(targetProxyEntry)
|
||||||
|
newProxyEndpoint.MatchingDomainAlias = newAlias
|
||||||
|
|
||||||
|
// Prepare to replace the current routing rule
|
||||||
|
readyRoutingRule, err := dynamicProxyRouter.PrepareProxyRoute(newProxyEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
targetProxyEntry.Remove()
|
||||||
|
dynamicProxyRouter.AddProxyRouteToRuntime(readyRoutingRule)
|
||||||
|
|
||||||
|
// Save it to file
|
||||||
|
err = SaveReverseProxyConfig(newProxyEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "Alias update failed")
|
||||||
|
SystemWideLogger.PrintAndLog("Proxy", "Unable to save alias update", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.SendOK(w)
|
||||||
|
}
|
||||||
|
|
||||||
func DeleteProxyEndpoint(w http.ResponseWriter, r *http.Request) {
|
func DeleteProxyEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
ep, err := utils.GetPara(r, "ep")
|
ep, err := utils.GetPara(r, "ep")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -740,6 +828,35 @@ func ReverseProxyToggleRuleSet(w http.ResponseWriter, r *http.Request) {
|
|||||||
utils.SendOK(w)
|
utils.SendOK(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ReverseProxyListDetail(w http.ResponseWriter, r *http.Request) {
|
||||||
|
eptype, err := utils.PostPara(r, "type") //Support root and host
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "type not defined")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if eptype == "host" {
|
||||||
|
epname, err := utils.PostPara(r, "epname")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "epname not defined")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
endpointRaw, ok := dynamicProxyRouter.ProxyEndpoints.Load(epname)
|
||||||
|
if !ok {
|
||||||
|
utils.SendErrorResponse(w, "proxy rule not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
targetEndpoint := dynamicproxy.CopyEndpoint(endpointRaw.(*dynamicproxy.ProxyEndpoint))
|
||||||
|
js, _ := json.Marshal(targetEndpoint)
|
||||||
|
utils.SendJSONResponse(w, string(js))
|
||||||
|
} else if eptype == "root" {
|
||||||
|
js, _ := json.Marshal(dynamicProxyRouter.Root)
|
||||||
|
utils.SendJSONResponse(w, string(js))
|
||||||
|
} else {
|
||||||
|
utils.SendErrorResponse(w, "Invalid type given")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func ReverseProxyList(w http.ResponseWriter, r *http.Request) {
|
func ReverseProxyList(w http.ResponseWriter, r *http.Request) {
|
||||||
eptype, err := utils.PostPara(r, "type") //Support root and host
|
eptype, err := utils.PostPara(r, "type") //Support root and host
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
24
src/start.go
24
src/start.go
@ -8,6 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"imuslab.com/zoraxy/mod/access"
|
||||||
"imuslab.com/zoraxy/mod/acme"
|
"imuslab.com/zoraxy/mod/acme"
|
||||||
"imuslab.com/zoraxy/mod/auth"
|
"imuslab.com/zoraxy/mod/auth"
|
||||||
"imuslab.com/zoraxy/mod/database"
|
"imuslab.com/zoraxy/mod/database"
|
||||||
@ -91,6 +92,16 @@ func startupSequence() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Create the access controller
|
||||||
|
accessController, err = access.NewAccessController(&access.Options{
|
||||||
|
Database: sysdb,
|
||||||
|
GeoDB: geodbStore,
|
||||||
|
ConfigFolder: "./conf/access",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
//Create a statistic collector
|
//Create a statistic collector
|
||||||
statisticCollector, err = statistic.NewStatisticCollector(statistic.CollectorOption{
|
statisticCollector, err = statistic.NewStatisticCollector(statistic.CollectorOption{
|
||||||
Database: sysdb,
|
Database: sysdb,
|
||||||
@ -149,8 +160,17 @@ func startupSequence() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
portInt = 8000
|
portInt = 8000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hostName := *mdnsName
|
||||||
|
if hostName == "" {
|
||||||
|
hostName = "zoraxy_" + nodeUUID
|
||||||
|
} else {
|
||||||
|
//Trim off the suffix
|
||||||
|
hostName = strings.TrimSuffix(hostName, ".local")
|
||||||
|
}
|
||||||
|
|
||||||
mdnsScanner, err = mdns.NewMDNS(mdns.NetworkHost{
|
mdnsScanner, err = mdns.NewMDNS(mdns.NetworkHost{
|
||||||
HostName: "zoraxy_" + nodeUUID,
|
HostName: hostName,
|
||||||
Port: portInt,
|
Port: portInt,
|
||||||
Domain: "zoraxy.arozos.com",
|
Domain: "zoraxy.arozos.com",
|
||||||
Model: "Network Gateway",
|
Model: "Network Gateway",
|
||||||
@ -211,7 +231,7 @@ func startupSequence() {
|
|||||||
//Create TCP Proxy Manager
|
//Create TCP Proxy Manager
|
||||||
tcpProxyManager = tcpprox.NewTCProxy(&tcpprox.Options{
|
tcpProxyManager = tcpprox.NewTCProxy(&tcpprox.Options{
|
||||||
Database: sysdb,
|
Database: sysdb,
|
||||||
AccessControlHandler: geodbStore.AllowConnectionAccess,
|
AccessControlHandler: accessController.DefaultAccessRule.AllowConnectionAccess,
|
||||||
})
|
})
|
||||||
|
|
||||||
//Create WoL MAC storage table
|
//Create WoL MAC storage table
|
||||||
|
2
src/start.sh
Normal file
2
src/start.sh
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#/bin/bash
|
||||||
|
sudo ./zoraxy
|
File diff suppressed because it is too large
Load Diff
@ -66,6 +66,7 @@
|
|||||||
<tr><th>Domain</th>
|
<tr><th>Domain</th>
|
||||||
<th>Last Update</th>
|
<th>Last Update</th>
|
||||||
<th>Expire At</th>
|
<th>Expire At</th>
|
||||||
|
<th>DNS Challenge</th>
|
||||||
<th class="no-sort">Renew</th>
|
<th class="no-sort">Renew</th>
|
||||||
<th class="no-sort">Remove</th>
|
<th class="no-sort">Remove</th>
|
||||||
</tr></thead>
|
</tr></thead>
|
||||||
@ -147,7 +148,7 @@
|
|||||||
|
|
||||||
|
|
||||||
//Renew certificate by button press
|
//Renew certificate by button press
|
||||||
function renewCertificate(domain, btn=undefined){
|
function renewCertificate(domain, dns, btn=undefined){
|
||||||
let defaultCA = $("#defaultCA").dropdown("get value");
|
let defaultCA = $("#defaultCA").dropdown("get value");
|
||||||
if (defaultCA.trim() == ""){
|
if (defaultCA.trim() == ""){
|
||||||
defaultCA = "Let's Encrypt";
|
defaultCA = "Let's Encrypt";
|
||||||
@ -160,7 +161,7 @@
|
|||||||
$(btn).addClass('disabled');
|
$(btn).addClass('disabled');
|
||||||
$(btn).html(`<i class="ui loading spinner icon"></i>`);
|
$(btn).html(`<i class="ui loading spinner icon"></i>`);
|
||||||
}
|
}
|
||||||
obtainCertificate(domain, defaultCA.trim(), function(succ){
|
obtainCertificate(domain, dns, defaultCA.trim(), function(succ){
|
||||||
if (btn != undefined){
|
if (btn != undefined){
|
||||||
$(btn).removeClass('disabled');
|
$(btn).removeClass('disabled');
|
||||||
if (succ){
|
if (succ){
|
||||||
@ -181,7 +182,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Obtain certificate from API, only support one domain
|
// Obtain certificate from API, only support one domain
|
||||||
function obtainCertificate(domains, usingCa = "Let's Encrypt", callback=undefined) {
|
function obtainCertificate(domains, dns, usingCa = "Let's Encrypt", callback=undefined) {
|
||||||
//Load the ACME email from server side
|
//Load the ACME email from server side
|
||||||
let acmeEmail = "";
|
let acmeEmail = "";
|
||||||
$.get("/api/acme/autoRenew/email", function(data){
|
$.get("/api/acme/autoRenew/email", function(data){
|
||||||
@ -213,6 +214,8 @@
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
//Filename cannot contain wildcards, and wildcards are possible with DNS challenges
|
||||||
|
filename = filename.replace("*", "_");
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "/api/acme/obtainCert",
|
url: "/api/acme/obtainCert",
|
||||||
@ -222,6 +225,7 @@
|
|||||||
filename: filename,
|
filename: filename,
|
||||||
email: email,
|
email: email,
|
||||||
ca: usingCa,
|
ca: usingCa,
|
||||||
|
dns: dns
|
||||||
},
|
},
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
@ -237,7 +241,7 @@
|
|||||||
msgbox("Certificate installed successfully");
|
msgbox("Certificate installed successfully");
|
||||||
|
|
||||||
if (callback != undefined){
|
if (callback != undefined){
|
||||||
callback(false);
|
callback(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -357,7 +361,8 @@
|
|||||||
<td>${entry.Domain}</td>
|
<td>${entry.Domain}</td>
|
||||||
<td>${entry.LastModifiedDate}</td>
|
<td>${entry.LastModifiedDate}</td>
|
||||||
<td class="${isExpired?"expired":"valid"} certdate">${entry.ExpireDate} (${!isExpired?entry.RemainingDays+" days left":"Expired"})</td>
|
<td class="${isExpired?"expired":"valid"} certdate">${entry.ExpireDate} (${!isExpired?entry.RemainingDays+" days left":"Expired"})</td>
|
||||||
<td><button title="Renew Certificate" class="ui mini basic icon button renewButton" onclick="renewCertificate('${entry.Domain}', this);"><i class="ui green refresh icon"></i></button></td>
|
<td><i class="${entry.UseDNS?"green check": "red times"} circle outline icon"></i></td>
|
||||||
|
<td><button title="Renew Certificate" class="ui mini basic icon button renewButton" onclick="renewCertificate('${entry.Domain}', '${entry.UseDNS}', this);"><i class="ui green refresh icon"></i></button></td>
|
||||||
<td><button title="Delete key-pair" class="ui mini basic red icon button" onclick="deleteCertificate('${entry.Domain}');"><i class="ui red trash icon"></i></button></td>
|
<td><button title="Delete key-pair" class="ui mini basic red icon button" onclick="deleteCertificate('${entry.Domain}');"><i class="ui red trash icon"></i></button></td>
|
||||||
</tr>`);
|
</tr>`);
|
||||||
});
|
});
|
||||||
|
@ -7,8 +7,12 @@
|
|||||||
#httpProxyList .ui.toggle.checkbox input:checked ~ label::before{
|
#httpProxyList .ui.toggle.checkbox input:checked ~ label::before{
|
||||||
background-color: #00ca52 !important;
|
background-color: #00ca52 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.subdEntry td:not(.ignoremw){
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<div style="width: 100%; overflow-x: auto; margin-bottom: 1em;">
|
<div style="width: 100%; overflow-x: auto; margin-bottom: 1em; min-height: 300px;">
|
||||||
<table class="ui celled sortable unstackable compact table">
|
<table class="ui celled sortable unstackable compact table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -16,7 +20,7 @@
|
|||||||
<th>Destination</th>
|
<th>Destination</th>
|
||||||
<th>Virtual Directory</th>
|
<th>Virtual Directory</th>
|
||||||
<th>Basic Auth</th>
|
<th>Basic Auth</th>
|
||||||
<th class="no-sort" style="min-width:100px;">Actions</th>
|
<th class="no-sort" style="min-width:150px;">Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="httpProxyList">
|
<tbody id="httpProxyList">
|
||||||
@ -30,6 +34,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
/* List all proxy endpoints */
|
||||||
function listProxyEndpoints(){
|
function listProxyEndpoints(){
|
||||||
$.get("/api/proxy/list?type=host", function(data){
|
$.get("/api/proxy/list?type=host", function(data){
|
||||||
$("#httpProxyList").html(``);
|
$("#httpProxyList").html(``);
|
||||||
@ -42,6 +48,8 @@
|
|||||||
<td data-label="" colspan="5"><i class="green check circle icon"></i> No HTTP Proxy Record</td>
|
<td data-label="" colspan="5"><i class="green check circle icon"></i> No HTTP Proxy Record</td>
|
||||||
</tr>`);
|
</tr>`);
|
||||||
}else{
|
}else{
|
||||||
|
//Sort by RootOrMatchingDomain field
|
||||||
|
data.sort((a,b) => (a.RootOrMatchingDomain > b.RootOrMatchingDomain) ? 1 : ((b.RootOrMatchingDomain > a.RootOrMatchingDomain) ? -1 : 0))
|
||||||
data.forEach(subd => {
|
data.forEach(subd => {
|
||||||
let tlsIcon = "";
|
let tlsIcon = "";
|
||||||
let subdData = encodeURIComponent(JSON.stringify(subd));
|
let subdData = encodeURIComponent(JSON.stringify(subd));
|
||||||
@ -73,17 +81,33 @@
|
|||||||
vdList = `<small style="opacity: 0.3; pointer-events: none; user-select: none;"><i class="check icon"></i> No Virtual Directory</small>`;
|
vdList = `<small style="opacity: 0.3; pointer-events: none; user-select: none;"><i class="check icon"></i> No Virtual Directory</small>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
var enableChecked = "checked";
|
let enableChecked = "checked";
|
||||||
if (subd.Disabled){
|
if (subd.Disabled){
|
||||||
enableChecked = "";
|
enableChecked = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let aliasDomains = ``;
|
||||||
|
if (subd.MatchingDomainAlias != undefined && subd.MatchingDomainAlias.length > 0){
|
||||||
|
aliasDomains = `<small class="aliasDomains" eptuuid="${subd.RootOrMatchingDomain}" style="color: #636363;">Alias: `;
|
||||||
|
subd.MatchingDomainAlias.forEach(alias => {
|
||||||
|
aliasDomains += `<a href="//${alias}" target="_blank">${alias}</a>, `;
|
||||||
|
});
|
||||||
|
aliasDomains = aliasDomains.substr(0, aliasDomains.length - 2); //Remove the last tailing seperator
|
||||||
|
aliasDomains += `</small><br>`;
|
||||||
|
}
|
||||||
|
|
||||||
$("#httpProxyList").append(`<tr eptuuid="${subd.RootOrMatchingDomain}" payload="${subdData}" class="subdEntry">
|
$("#httpProxyList").append(`<tr eptuuid="${subd.RootOrMatchingDomain}" payload="${subdData}" class="subdEntry">
|
||||||
<td data-label="" editable="true" datatype="inbound"><a href="//${subd.RootOrMatchingDomain}" target="_blank">${subd.RootOrMatchingDomain}</a> ${inboundTlsIcon}</td>
|
<td data-label="" editable="true" datatype="inbound">
|
||||||
|
<a href="//${subd.RootOrMatchingDomain}" target="_blank">${subd.RootOrMatchingDomain}</a> ${inboundTlsIcon}<br>
|
||||||
|
${aliasDomains}
|
||||||
|
<small class="accessRuleNameUnderHost" ruleid="${subd.AccessFilterUUID}"></small>
|
||||||
|
</td>
|
||||||
<td data-label="" editable="true" datatype="domain">${subd.Domain} ${tlsIcon}</td>
|
<td data-label="" editable="true" datatype="domain">${subd.Domain} ${tlsIcon}</td>
|
||||||
<td data-label="" editable="true" datatype="vdir">${vdList}</td>
|
<td data-label="" editable="true" datatype="vdir">${vdList}</td>
|
||||||
<td data-label="" editable="true" datatype="basicauth">${subd.RequireBasicAuth?`<i class="ui green check icon"></i>`:`<i class="ui grey remove icon"></i>`}</td>
|
<td data-label="" editable="true" datatype="basicauth">
|
||||||
<td class="center aligned" editable="true" datatype="action" data-label="">
|
${subd.RequireBasicAuth?`<i class="ui green check icon"></i>`:`<i class="ui grey remove icon"></i>`}
|
||||||
|
</td>
|
||||||
|
<td class="center aligned ignoremw" editable="true" datatype="action" data-label="">
|
||||||
<div class="ui toggle tiny fitted checkbox" style="margin-bottom: -0.5em; margin-right: 0.4em;" title="Enable / Disable Rule">
|
<div class="ui toggle tiny fitted checkbox" style="margin-bottom: -0.5em; margin-right: 0.4em;" title="Enable / Disable Rule">
|
||||||
<input type="checkbox" class="enableToggle" name="active" ${enableChecked} eptuuid="${subd.RootOrMatchingDomain}" onchange="handleProxyRuleToggle(this);">
|
<input type="checkbox" class="enableToggle" name="active" ${enableChecked} eptuuid="${subd.RootOrMatchingDomain}" onchange="handleProxyRuleToggle(this);">
|
||||||
<label></label>
|
<label></label>
|
||||||
@ -94,9 +118,87 @@
|
|||||||
</tr>`);
|
</tr>`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resolveAccessRuleNameOnHostRPlist();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Perform realtime alias update without refreshing the whole page
|
||||||
|
function updateAliasListForEndpoint(endpointName, newAliasDomainList){
|
||||||
|
let targetEle = $(`.aliasDomains[eptuuid='${endpointName}']`);
|
||||||
|
console.log(targetEle);
|
||||||
|
if (targetEle.length == 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let aliasDomains = ``;
|
||||||
|
if (newAliasDomainList != undefined && newAliasDomainList.length > 0){
|
||||||
|
aliasDomains = `Alias: `;
|
||||||
|
newAliasDomainList.forEach(alias => {
|
||||||
|
aliasDomains += `<a href="//${alias}" target="_blank">${alias}</a>, `;
|
||||||
|
});
|
||||||
|
aliasDomains = aliasDomains.substr(0, aliasDomains.length - 2); //Remove the last tailing seperator
|
||||||
|
$(targetEle).html(aliasDomains);
|
||||||
|
$(targetEle).show();
|
||||||
|
}else{
|
||||||
|
$(targetEle).hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Resolve & Update all rule names on host PR list
|
||||||
|
function resolveAccessRuleNameOnHostRPlist(){
|
||||||
|
//Resolve the access filters
|
||||||
|
$.get("/api/access/list", function(data){
|
||||||
|
console.log(data);
|
||||||
|
if (data.error == undefined){
|
||||||
|
//Build a map base on the data
|
||||||
|
let accessRuleMap = {};
|
||||||
|
for (var i = 0; i < data.length; i++){
|
||||||
|
accessRuleMap[data[i].ID] = data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$(".accessRuleNameUnderHost").each(function(){
|
||||||
|
let thisAccessRuleID = $(this).attr("ruleid");
|
||||||
|
if (thisAccessRuleID== ""){
|
||||||
|
thisAccessRuleID = "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thisAccessRuleID == "default"){
|
||||||
|
//No need to label default access rules
|
||||||
|
$(this).html("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let rule = accessRuleMap[thisAccessRuleID];
|
||||||
|
let icon = `<i class="ui grey filter icon"></i>`;
|
||||||
|
if (rule.ID == "default"){
|
||||||
|
icon = `<i class="ui yellow star icon"></i>`;
|
||||||
|
}else if (rule.BlacklistEnabled && !rule.WhitelistEnabled){
|
||||||
|
//This is a blacklist filter
|
||||||
|
icon = `<i class="ui red filter icon"></i>`;
|
||||||
|
}else if (rule.WhitelistEnabled && !rule.BlacklistEnabled){
|
||||||
|
//This is a whitelist filter
|
||||||
|
icon = `<i class="ui green filter icon"></i>`;
|
||||||
|
}else if (rule.WhitelistEnabled && rule.BlacklistEnabled){
|
||||||
|
//Whitelist and blacklist filter
|
||||||
|
icon = `<i class="ui yellow filter icon"></i>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule != undefined){
|
||||||
|
$(this).html(`${icon} ${rule.Name}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//Update the access rule name on given epuuid, call by hostAccessEditor.html
|
||||||
|
function updateAccessRuleNameUnderHost(epuuid, newruleUID){
|
||||||
|
$(`tr[eptuuid='${epuuid}'].subdEntry`).find(".accessRuleNameUnderHost").attr("ruleid", newruleUID);
|
||||||
|
resolveAccessRuleNameOnHostRPlist();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Inline editor for httprp.html
|
Inline editor for httprp.html
|
||||||
@ -176,7 +278,7 @@
|
|||||||
|
|
||||||
column.empty().append(`<div class="ui checkbox" style="margin-top: 0.4em;">
|
column.empty().append(`<div class="ui checkbox" style="margin-top: 0.4em;">
|
||||||
<input type="checkbox" class="RequireBasicAuth" ${checkstate}>
|
<input type="checkbox" class="RequireBasicAuth" ${checkstate}>
|
||||||
<label>Require Basic Auth</label>
|
<label>Require Basic Auth</label>
|
||||||
</div>
|
</div>
|
||||||
<button class="ui basic tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editBasicAuthCredentials('${uuid}');"><i class="ui blue user circle icon"></i> Edit Credentials</button>
|
<button class="ui basic tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editBasicAuthCredentials('${uuid}');"><i class="ui blue user circle icon"></i> Edit Credentials</button>
|
||||||
<div class="ui basic advance segment" style="padding: 0.4em !important; border-radius: 0.4em;">
|
<div class="ui basic advance segment" style="padding: 0.4em !important; border-radius: 0.4em;">
|
||||||
@ -191,6 +293,7 @@
|
|||||||
<label>Skip WebSocket Origin Check<br>
|
<label>Skip WebSocket Origin Check<br>
|
||||||
<small>Check this to allow cross-origin websocket requests</small></label>
|
<small>Check this to allow cross-origin websocket requests</small></label>
|
||||||
</div>
|
</div>
|
||||||
|
<br>
|
||||||
<button class="ui basic compact tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editCustomHeaders('${uuid}');"><i class="heading icon"></i> Custom Headers</button>
|
<button class="ui basic compact tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editCustomHeaders('${uuid}');"><i class="heading icon"></i> Custom Headers</button>
|
||||||
<!-- <button class="ui basic compact tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editLoadBalanceOptions('${uuid}');"><i class="blue server icon"></i> Load Balance</button> -->
|
<!-- <button class="ui basic compact tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editLoadBalanceOptions('${uuid}');"><i class="blue server icon"></i> Load Balance</button> -->
|
||||||
</div>
|
</div>
|
||||||
@ -213,7 +316,12 @@
|
|||||||
<label>Allow plain HTTP access<br>
|
<label>Allow plain HTTP access<br>
|
||||||
<small>Allow inbound connections without TLS/SSL</small></label>
|
<small>Allow inbound connections without TLS/SSL</small></label>
|
||||||
</div><br>
|
</div><br>
|
||||||
|
<button class="ui basic compact tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editAliasHostnames('${uuid}');"><i class=" blue at icon"></i> Alias</button>
|
||||||
|
<button class="ui basic compact tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editAccessRule('${uuid}');"><i class="ui filter icon"></i> Access Rule</button>
|
||||||
|
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
$(".hostAccessRuleSelector").dropdown();
|
||||||
}else{
|
}else{
|
||||||
//Unknown field. Leave it untouched
|
//Unknown field. Leave it untouched
|
||||||
}
|
}
|
||||||
@ -277,6 +385,22 @@
|
|||||||
showSideWrapper("snippet/basicAuthEditor.html?t=" + Date.now() + "#" + payload);
|
showSideWrapper("snippet/basicAuthEditor.html?t=" + Date.now() + "#" + payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function editAccessRule(uuid){
|
||||||
|
let payload = encodeURIComponent(JSON.stringify({
|
||||||
|
ept: "host",
|
||||||
|
ep: uuid
|
||||||
|
}));
|
||||||
|
showSideWrapper("snippet/hostAccessEditor.html?t=" + Date.now() + "#" + payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
function editAliasHostnames(uuid){
|
||||||
|
let payload = encodeURIComponent(JSON.stringify({
|
||||||
|
ept: "host",
|
||||||
|
ep: uuid
|
||||||
|
}));
|
||||||
|
showSideWrapper("snippet/aliasEditor.html?t=" + Date.now() + "#" + payload);
|
||||||
|
}
|
||||||
|
|
||||||
function quickEditVdir(uuid){
|
function quickEditVdir(uuid){
|
||||||
openTabById("vdir");
|
openTabById("vdir");
|
||||||
$("#vdirBaseRoutingRule").parent().dropdown("set selected", uuid);
|
$("#vdirBaseRoutingRule").parent().dropdown("set selected", uuid);
|
||||||
@ -314,6 +438,9 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Access List handling */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Bind on tab switch events
|
//Bind on tab switch events
|
||||||
tabSwitchEventBind["httprp"] = function(){
|
tabSwitchEventBind["httprp"] = function(){
|
||||||
|
@ -5,6 +5,12 @@
|
|||||||
color: var(--theme_lgrey);
|
color: var(--theme_lgrey);
|
||||||
border-radius: 1em !important;
|
border-radius: 1em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui.form .sub.field{
|
||||||
|
background-color: var(--theme_advance);
|
||||||
|
border-radius: 0.6em;
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<div class="standardContainer">
|
<div class="standardContainer">
|
||||||
<div class="ui stackable grid">
|
<div class="ui stackable grid">
|
||||||
@ -16,7 +22,7 @@
|
|||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Matching Keyword / Domain</label>
|
<label>Matching Keyword / Domain</label>
|
||||||
<input type="text" id="rootname" placeholder="mydomain.com">
|
<input type="text" id="rootname" placeholder="mydomain.com">
|
||||||
<small>Support subdomain and wildcard, e.g. s1.mydomain.com or *.test.mydomain.com</small>
|
<small>Support subdomain and wildcard, e.g. s1.mydomain.com or *.test.mydomain.com. Use comma (,) for alias hostnames. </small>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Target IP Address or Domain Name with port</label>
|
<label>Target IP Address or Domain Name with port</label>
|
||||||
@ -37,7 +43,18 @@
|
|||||||
Advance Settings
|
Advance Settings
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<p></p>
|
<div class="field">
|
||||||
|
<label>Access Rule</label>
|
||||||
|
<div class="ui selection dropdown">
|
||||||
|
<input type="hidden" id="newProxyRuleAccessFilter" value="default">
|
||||||
|
<i class="dropdown icon"></i>
|
||||||
|
<div class="default text">Default</div>
|
||||||
|
<div class="menu" id="newProxyRuleAccessList">
|
||||||
|
<div class="item" data-value="default"><i class="ui yellow star icon"></i> Default</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<small>Allow regional access control using blacklist or whitelist. Use "default" for "allow all".</small>
|
||||||
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" id="skipTLSValidation">
|
<input type="checkbox" id="skipTLSValidation">
|
||||||
@ -121,8 +138,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
$("#advanceProxyRules").accordion();
|
|
||||||
|
|
||||||
|
|
||||||
//New Proxy Endpoint
|
//New Proxy Endpoint
|
||||||
function newProxyEndpoint(){
|
function newProxyEndpoint(){
|
||||||
@ -133,6 +148,7 @@
|
|||||||
var bypassGlobalTLS = $("#bypassGlobalTLS")[0].checked;
|
var bypassGlobalTLS = $("#bypassGlobalTLS")[0].checked;
|
||||||
var requireBasicAuth = $("#requireBasicAuth")[0].checked;
|
var requireBasicAuth = $("#requireBasicAuth")[0].checked;
|
||||||
var skipWebSocketOriginCheck = $("#skipWebsocketOriginCheck")[0].checked;
|
var skipWebSocketOriginCheck = $("#skipWebsocketOriginCheck")[0].checked;
|
||||||
|
var accessRuleToUse = $("#newProxyRuleAccessFilter").val();
|
||||||
|
|
||||||
if (rootname.trim() == ""){
|
if (rootname.trim() == ""){
|
||||||
$("#rootname").parent().addClass("error");
|
$("#rootname").parent().addClass("error");
|
||||||
@ -161,7 +177,7 @@
|
|||||||
bypassGlobalTLS: bypassGlobalTLS,
|
bypassGlobalTLS: bypassGlobalTLS,
|
||||||
bauth: requireBasicAuth,
|
bauth: requireBasicAuth,
|
||||||
cred: JSON.stringify(credentials),
|
cred: JSON.stringify(credentials),
|
||||||
|
access: accessRuleToUse,
|
||||||
},
|
},
|
||||||
success: function(data){
|
success: function(data){
|
||||||
if (data.error != undefined){
|
if (data.error != undefined){
|
||||||
@ -343,4 +359,47 @@
|
|||||||
return back;
|
return back;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Access Rule dropdown Initialization
|
||||||
|
*/
|
||||||
|
|
||||||
|
function initNewProxyRuleAccessDropdownList(callback=undefined){
|
||||||
|
$.get("/api/access/list", function(data){
|
||||||
|
if (data.error == undefined){
|
||||||
|
$("#newProxyRuleAccessList").html("");
|
||||||
|
data.forEach(function(rule){
|
||||||
|
let icon = `<i class="ui grey filter icon"></i>`;
|
||||||
|
if (rule.ID == "default"){
|
||||||
|
icon = `<i class="ui yellow star icon"></i>`;
|
||||||
|
}else if (rule.BlacklistEnabled && !rule.WhitelistEnabled){
|
||||||
|
//This is a blacklist filter
|
||||||
|
icon = `<i class="ui red filter icon"></i>`;
|
||||||
|
}else if (rule.WhitelistEnabled && !rule.BlacklistEnabled){
|
||||||
|
//This is a whitelist filter
|
||||||
|
icon = `<i class="ui green filter icon"></i>`;
|
||||||
|
}
|
||||||
|
$("#newProxyRuleAccessList").append(`<div class="item" data-value="${rule.ID}">${icon} ${rule.Name}</div>`);
|
||||||
|
});
|
||||||
|
$("#newProxyRuleAccessFilter").parent().dropdown();
|
||||||
|
if (callback != undefined){
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
msgbox("Access rule load failed: " + data.error, false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
initNewProxyRuleAccessDropdownList();
|
||||||
|
|
||||||
|
//Bind on tab switch events
|
||||||
|
tabSwitchEventBind["rules"] = function(){
|
||||||
|
//Update the access rule list
|
||||||
|
initNewProxyRuleAccessDropdownList();
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
$("#advanceProxyRules").accordion();
|
||||||
|
$("#newProxyRuleAccessFilter").parent().dropdown();
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
@ -765,8 +765,11 @@
|
|||||||
let data = Object.values(visitorData);
|
let data = Object.values(visitorData);
|
||||||
|
|
||||||
Object.keys(visitorData).forEach(function(cc){
|
Object.keys(visitorData).forEach(function(cc){
|
||||||
|
console.log(cc);
|
||||||
if (cc == ""){
|
if (cc == ""){
|
||||||
labels.push("Local / Unknown")
|
labels.push("Unknown")
|
||||||
|
}else if (cc == "lan"){
|
||||||
|
labels.push(`LAN / Loopback`);
|
||||||
}else{
|
}else{
|
||||||
labels.push(`${getCountryName(cc)} [${cc.toUpperCase()}]` );
|
labels.push(`${getCountryName(cc)} [${cc.toUpperCase()}]` );
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<i class="red remove icon"></i>
|
<i class="red remove icon"></i>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
Uptime Monitoring service is currently unavailable
|
Uptime Monitoring service is currently unavailable
|
||||||
<div class="sub header">This might cause by an error in cluster communication within the host servers. Please wait for administrator to resolve the issue.</div>
|
<div class="sub header">This might be caused by an error in cluster communication within the host servers. Please wait for administrator to resolve the issue.</div>
|
||||||
</div>
|
</div>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
|
@ -65,21 +65,9 @@
|
|||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<p><i class="caret down icon"></i> Credentials for SMTP server authentications</p>
|
<p><i class="caret down icon"></i> Credentials for SMTP server authentications</p>
|
||||||
<div class="two fields">
|
<div class="field">
|
||||||
<div class="field">
|
<label>Sender Username / Email</label>
|
||||||
<label>Sender Username</label>
|
<input type="text" name="username" placeholder="e.g. admin or admin@mydomain.com">
|
||||||
<input type="text" name="username" placeholder="E.g. admin">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field">
|
|
||||||
<label>Sender Domain</label>
|
|
||||||
<div class="ui labeled input">
|
|
||||||
<div class="ui basic label">
|
|
||||||
@
|
|
||||||
</div>
|
|
||||||
<input type="text" name="domain" min="1" max="65534" placeholder="E.g. arozos.com">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
@ -272,7 +260,6 @@
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var data = {
|
var data = {
|
||||||
hostname: $('input[name=hostname]').val(),
|
hostname: $('input[name=hostname]').val(),
|
||||||
domain: $('input[name=domain]').val(),
|
|
||||||
port: parseInt($('input[name=port]').val()),
|
port: parseInt($('input[name=port]').val()),
|
||||||
username: $('input[name=username]').val(),
|
username: $('input[name=username]').val(),
|
||||||
password: $('input[name=password]').val(),
|
password: $('input[name=password]').val(),
|
||||||
@ -306,7 +293,6 @@
|
|||||||
function initSMTPSettings(){
|
function initSMTPSettings(){
|
||||||
$.get("/api/tools/smtp/get", function(data){
|
$.get("/api/tools/smtp/get", function(data){
|
||||||
$('#email-form input[name=hostname]').val(data.Hostname);
|
$('#email-form input[name=hostname]').val(data.Hostname);
|
||||||
$('#email-form input[name=domain]').val(data.Domain);
|
|
||||||
$('#email-form input[name=port]').val(data.Port);
|
$('#email-form input[name=port]').val(data.Port);
|
||||||
$('#email-form input[name=username]').val(data.Username);
|
$('#email-form input[name=username]').val(data.Username);
|
||||||
$('#email-form input[name=senderAddr]').val(data.SenderAddr);
|
$('#email-form input[name=senderAddr]').val(data.SenderAddr);
|
||||||
@ -345,14 +331,6 @@
|
|||||||
form.find('input[name="hostname"]').parent().removeClass('error');
|
form.find('input[name="hostname"]').parent().removeClass('error');
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate domain
|
|
||||||
const domain = form.find('input[name="domain"]').val().trim();
|
|
||||||
if (!domainRegex.test(domain)) {
|
|
||||||
form.find('input[name="domain"]').parent().addClass('error');
|
|
||||||
isValid = false;
|
|
||||||
} else {
|
|
||||||
form.find('input[name="domain"]').parent().removeClass('error');
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate username
|
// validate username
|
||||||
const username = form.find('input[name="username"]').val().trim();
|
const username = form.find('input[name="username"]').val().trim();
|
||||||
|
@ -2,9 +2,6 @@
|
|||||||
index.html style overwrite
|
index.html style overwrite
|
||||||
*/
|
*/
|
||||||
:root{
|
:root{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--theme_background: linear-gradient(60deg, rgb(84, 58, 183) 0%, rgb(0, 172, 193) 100%);
|
--theme_background: linear-gradient(60deg, rgb(84, 58, 183) 0%, rgb(0, 172, 193) 100%);
|
||||||
--theme_background_inverted: linear-gradient(215deg, rgba(38,60,71,1) 13%, rgba(2,3,42,1) 84%);
|
--theme_background_inverted: linear-gradient(215deg, rgba(38,60,71,1) 13%, rgba(2,3,42,1) 84%);
|
||||||
--theme_green: linear-gradient(270deg, #27e7ff, #00ca52);
|
--theme_green: linear-gradient(270deg, #27e7ff, #00ca52);
|
||||||
@ -256,7 +253,7 @@ body{
|
|||||||
|
|
||||||
.sideWrapperMenu{
|
.sideWrapperMenu{
|
||||||
height: 3px;
|
height: 3px;
|
||||||
background-color: #414141;
|
background: var(--theme_background);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
font-family: 'Lato';
|
font-family: 'Lato';
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
src: local('Lato Bold'), local('Lato-Bold'), url(https://fonts.gstatic.com/s/lato/v17/S6u9w4BMUTPHh6UVSwaPGR_p.woff2) format('woff2');
|
src: local('Lato Bold'), local('Lato-Bold'), url(fonts/S6u9w4BMUTPHh6UVSwaPGR_p.woff2) format('woff2');
|
||||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||||
}
|
}
|
||||||
/* latin */
|
/* latin */
|
||||||
@ -59,6 +59,6 @@
|
|||||||
font-family: 'Lato';
|
font-family: 'Lato';
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
src: local('Lato Bold'), local('Lato-Bold'), url(https://fonts.gstatic.com/s/lato/v17/S6u9w4BMUTPHh6UVSwiPGQ.woff2) format('woff2');
|
src: local('Lato Bold'), local('Lato-Bold'), url(fonts/S6u9w4BMUTPHh6UVSwiPGQ.woff2) format('woff2');
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
}
|
}
|
||||||
|
267
src/web/snippet/accessRuleEditor.html
Normal file
267
src/web/snippet/accessRuleEditor.html
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!-- Notes: This should be open in its original path-->
|
||||||
|
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||||
|
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||||
|
<script src="../script/semantic/semantic.min.js"></script>
|
||||||
|
<style>
|
||||||
|
#refreshAccessRuleListBtn{
|
||||||
|
position: absolute;
|
||||||
|
top: 0.4em;
|
||||||
|
right: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<br>
|
||||||
|
<div class="ui container">
|
||||||
|
<div class="ui header">
|
||||||
|
<div class="content">
|
||||||
|
Access Rule Editor
|
||||||
|
<div class="sub header">Create, Edit or Remove Access Rules</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<div class="ui top attached tabular menu">
|
||||||
|
<a class="active item" data-tab="new"><i class="ui green add icon"></i> New</a>
|
||||||
|
<a class="item" data-tab="edit"><i class="ui grey edit icon"></i> Edit</a>
|
||||||
|
</div>
|
||||||
|
<div class="ui bottom attached active tab segment" data-tab="new">
|
||||||
|
<p>Create a new Access Rule</p>
|
||||||
|
<form class="ui form" id="accessRuleForm">
|
||||||
|
<div class="field">
|
||||||
|
<label>Rule Name</label>
|
||||||
|
<input type="text" name="accessRuleName" placeholder="Rule Name" required>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label>Description</label>
|
||||||
|
<textarea name="description" placeholder="Description" required></textarea>
|
||||||
|
</div>
|
||||||
|
<button class="ui basic button" type="submit"><i class="ui green add icon"></i> Create</button>
|
||||||
|
</form>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
<div class="ui bottom attached tab segment" data-tab="edit">
|
||||||
|
<p>Select an Access Rule to edit</p>
|
||||||
|
<button id="refreshAccessRuleListBtn" class="ui circular basic icon button" onclick="reloadAccessRuleList()"><i class="ui green refresh icon"></i></button>
|
||||||
|
<div class="ui selection fluid dropdown" id="accessRuleSelector">
|
||||||
|
<input type="hidden" name="targetAccessRule" value="default">
|
||||||
|
<i class="dropdown icon"></i>
|
||||||
|
<div class="default text"></div>
|
||||||
|
<div class="menu" id="accessRuleList">
|
||||||
|
<div class="item" data-value="default"><i class="ui yellow star icon"></i> Default</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<form class="ui form" id="modifyRuleInfo">
|
||||||
|
<div class="disabled field">
|
||||||
|
<label>Rule ID</label>
|
||||||
|
<input type="text" name="accessRuleUUID">
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label>Rule Name</label>
|
||||||
|
<input type="text" name="accessRuleName" placeholder="Rule Name" required>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label>Description</label>
|
||||||
|
<textarea name="description" placeholder="Description" required></textarea>
|
||||||
|
</div>
|
||||||
|
<button class="ui basic button" type="submit"><i class="ui green save icon"></i> Save Changes</button>
|
||||||
|
<button class="ui basic button" onclick="removeAccessRule(event);"><i class="ui red trash icon"></i> Remove Rule</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<button class="ui basic button" style="float: right;" onclick="parent.hideSideWrapper();"><i class="remove icon"></i> Close</button>
|
||||||
|
<br><br><br>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let accessRuleList = [];
|
||||||
|
$('.dropdown').dropdown();
|
||||||
|
$('.menu .item').tab();
|
||||||
|
|
||||||
|
function handleCreateNewAccessRule(event) {
|
||||||
|
event.preventDefault(); // Prevent the default form submission
|
||||||
|
const formData = new FormData(event.target);
|
||||||
|
const accessRuleName = formData.get('accessRuleName');
|
||||||
|
const description = formData.get('description');
|
||||||
|
|
||||||
|
console.log('Access Rule Name:', accessRuleName);
|
||||||
|
console.log('Description:', description);
|
||||||
|
|
||||||
|
$("#accessRuleForm input[name='accessRuleName']").val("");
|
||||||
|
$("#accessRuleForm textarea[name='description']").val("");
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/access/create",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
"name": accessRuleName,
|
||||||
|
"desc": description
|
||||||
|
},
|
||||||
|
success: function(data){
|
||||||
|
if (data.error != undefined){
|
||||||
|
parent.msgbox(data.error, false);
|
||||||
|
}else{
|
||||||
|
parent.msgbox("Access Rule Created", true);
|
||||||
|
reloadAccessRuleList();
|
||||||
|
if (parent != undefined && parent.reloadAccessRules != undefined){
|
||||||
|
parent.reloadAccessRules();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//Handle on change of the dropdown selection
|
||||||
|
function handleSelectEditingAccessRule(){
|
||||||
|
const selectedValue = document.querySelector('#accessRuleSelector').querySelector('input').value;
|
||||||
|
console.log('Selected Value:', selectedValue);
|
||||||
|
//Load the information from list
|
||||||
|
loadAccessRuleInfoIntoEditFields(selectedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Load the access rules information into the fields
|
||||||
|
function loadAccessRuleInfoIntoEditFields(targetAccessRuleUUID){
|
||||||
|
var targetAccessRule = undefined;
|
||||||
|
for (var i = 0; i < accessRuleList.length; i++){
|
||||||
|
let thisAccessRule = accessRuleList[i];
|
||||||
|
if (thisAccessRule.ID == targetAccessRuleUUID){
|
||||||
|
targetAccessRule = thisAccessRule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetAccessRule == undefined){
|
||||||
|
//Target exists rule no longer exists
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let accessRuleID = targetAccessRule.ID;
|
||||||
|
let accessRuleName = targetAccessRule.Name;
|
||||||
|
let accessRuleDesc = targetAccessRule.Desc;
|
||||||
|
|
||||||
|
//Load the information into the form input field
|
||||||
|
//Load the information into the form input field
|
||||||
|
document.querySelector('#modifyRuleInfo input[name="accessRuleUUID"]').value = accessRuleID;
|
||||||
|
document.querySelector('#modifyRuleInfo input[name="accessRuleName"]').value = accessRuleName;
|
||||||
|
document.querySelector('#modifyRuleInfo textarea[name="description"]').value = accessRuleDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Bind events to modify rule form
|
||||||
|
document.getElementById('modifyRuleInfo').addEventListener('submit', function(event){
|
||||||
|
event.preventDefault(); // Prevent the default form submission
|
||||||
|
|
||||||
|
const accessRuleUUID = document.querySelector('#modifyRuleInfo input[name="accessRuleUUID"]').value;
|
||||||
|
const accessRuleName = document.querySelector('#modifyRuleInfo input[name="accessRuleName"]').value;
|
||||||
|
const description = document.querySelector('#modifyRuleInfo textarea[name="description"]').value;
|
||||||
|
|
||||||
|
|
||||||
|
console.log('Access Rule UUID:', accessRuleUUID);
|
||||||
|
console.log('Access Rule Name:', accessRuleName);
|
||||||
|
console.log('Description:', description);
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/access/update",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
"id":accessRuleUUID,
|
||||||
|
"name":accessRuleName,
|
||||||
|
"desc":description
|
||||||
|
},
|
||||||
|
success: function(data){
|
||||||
|
if (data.error != undefined){
|
||||||
|
parent.msgbox(data.error, false);
|
||||||
|
}else{
|
||||||
|
parent.msgbox("Access rule updated", true);
|
||||||
|
initAccessRuleList(function(){
|
||||||
|
$("#accessRuleSelector").dropdown("set selected", accessRuleUUID);
|
||||||
|
loadAccessRuleInfoIntoEditFields(accessRuleUUID);
|
||||||
|
});
|
||||||
|
if (parent != undefined && parent.reloadAccessRules != undefined){
|
||||||
|
parent.reloadAccessRules();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
function initAccessRuleList(callback=undefined){
|
||||||
|
$.get("/api/access/list", function(data){
|
||||||
|
if (data.error == undefined){
|
||||||
|
$("#accessRuleList").html("");
|
||||||
|
data.forEach(function(rule){
|
||||||
|
let icon = `<i class="ui grey filter icon"></i>`;
|
||||||
|
if (rule.ID == "default"){
|
||||||
|
icon = `<i class="ui yellow star icon"></i>`;
|
||||||
|
}else if (rule.BlacklistEnabled && !rule.WhitelistEnabled){
|
||||||
|
//This is a blacklist filter
|
||||||
|
icon = `<i class="ui red filter icon"></i>`;
|
||||||
|
}else if (rule.WhitelistEnabled && !rule.BlacklistEnabled){
|
||||||
|
//This is a whitelist filter
|
||||||
|
icon = `<i class="ui green filter icon"></i>`;
|
||||||
|
}
|
||||||
|
$("#accessRuleList").append(`<div class="item" data-value="${rule.ID}">${icon} ${rule.Name}</div>`);
|
||||||
|
});
|
||||||
|
accessRuleList = data;
|
||||||
|
$(".dropdown").dropdown();
|
||||||
|
if (callback != undefined){
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
initAccessRuleList(function(){
|
||||||
|
$("#accessRuleSelector").dropdown("set selected", "default");
|
||||||
|
loadAccessRuleInfoIntoEditFields("default");
|
||||||
|
});
|
||||||
|
|
||||||
|
function reloadAccessRuleList(){
|
||||||
|
initAccessRuleList(function(){
|
||||||
|
$("#accessRuleSelector").dropdown("set selected", "default");
|
||||||
|
loadAccessRuleInfoIntoEditFields("default");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeAccessRule(event){
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
|
||||||
|
let accessRuleUUID = $("#modifyRuleInfo input[name='accessRuleUUID']").val();
|
||||||
|
if (accessRuleUUID == ""){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (accessRuleUUID == "default"){
|
||||||
|
parent.msgbox("Default access rule cannot be removed", false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let accessRuleName = $("#modifyRuleInfo input[name='accessRuleName']").val();
|
||||||
|
if (confirm("Confirm removing access rule " + accessRuleName + "?")){
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/access/remove",
|
||||||
|
data: {
|
||||||
|
"id": accessRuleUUID
|
||||||
|
},
|
||||||
|
method: "POST",
|
||||||
|
success: function(data){
|
||||||
|
if (data.error != undefined){
|
||||||
|
parent.msgbox(data.error, false);
|
||||||
|
}else{
|
||||||
|
parent.msgbox("Access rule removed", true);
|
||||||
|
reloadAccessRuleList();
|
||||||
|
if (parent != undefined && parent.reloadAccessRules != undefined){
|
||||||
|
parent.reloadAccessRules();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
document.getElementById('accessRuleSelector').addEventListener('change', handleSelectEditingAccessRule);
|
||||||
|
document.getElementById('accessRuleForm').addEventListener('submit', handleCreateNewAccessRule);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -114,10 +114,52 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="field" id="dnsChallenge">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input type="checkbox" id="useDnsChallenge" onchange="toggleDnsChallenge()">
|
||||||
|
<label>Use a DNS Challenge<br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field dnsChallengeOnly" style="display:none;">
|
||||||
|
<label>DNS Provider</label>
|
||||||
|
<div class="ui search selection dropdown" id="dnsProvider">
|
||||||
|
<input type="hidden" name="dnsProvider" value="">
|
||||||
|
<i class="dropdown icon"></i>
|
||||||
|
<div class="default text">Pick a DNS Provider</div>
|
||||||
|
<div class="menu" id="dnsProviderList">
|
||||||
|
<!-- Auto populate moved to acmedns module and initDNSProviderList() -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field dnsChallengeOnly" style="display:none;">
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<p>DNS Credentials (Leave all fields empty to use previous settings)<br>
|
||||||
|
<small><i class="yellow exclamation triangle icon"></i> Note that domain DNS credentials are stored separately. For each new subdomain, you will need to enter a new DNS credentials.</small></p>
|
||||||
|
<div id="dnsProviderAPIFields">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!--
|
||||||
|
<label>Credentials File Content</label>
|
||||||
|
<textarea id="dnsCredentials" placeholder=""></textarea>
|
||||||
|
<small>For more information on the supported DNS Providers and their attirbutes look <a href="https://go-acme.github.io/lego/dns/" target="_blank">here</a>! </small>
|
||||||
|
<div class="ui negative message">
|
||||||
|
<i class="icon exclamation triangle"></i>
|
||||||
|
These credentials will be stored as plaintext in the database and in environment variables!
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
<div class="field" id="caInput" style="display:none;">
|
<div class="field" id="caInput" style="display:none;">
|
||||||
<label>ACME Server URL</label>
|
<label>ACME Server URL</label>
|
||||||
<input id="caURL" type="text" placeholder="https://example.com/acme/dictionary">
|
<input id="caURL" type="text" placeholder="https://example.com/acme/dictionary">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="field" id="kidInput" style="display:none;">
|
||||||
|
<label>EAB Credentials (KID) for current provider</label>
|
||||||
|
<input id="eab_kid" type="text" placeholder="Leave this field blank to keep the current configuration">
|
||||||
|
</div>
|
||||||
|
<div class="field" id="hmacInput" style="display:none;">
|
||||||
|
<label>EAB HMAC Key for current provider</label>
|
||||||
|
<input id="eab_hmac" type="text" placeholder="Leave this field blank to keep the current configuration">
|
||||||
|
</div>
|
||||||
<div class="field" id="skipTLS" style="display:none;">
|
<div class="field" id="skipTLS" style="display:none;">
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" id="skipTLSCheckbox">
|
<input type="checkbox" id="skipTLSCheckbox">
|
||||||
@ -314,29 +356,106 @@
|
|||||||
// Button click event handler for obtaining certificate
|
// Button click event handler for obtaining certificate
|
||||||
$("#obtainButton").click(function() {
|
$("#obtainButton").click(function() {
|
||||||
$("#obtainButton").addClass("loading").addClass("disabled");
|
$("#obtainButton").addClass("loading").addClass("disabled");
|
||||||
obtainCertificate();
|
updateCertificateEAB(function(succ){
|
||||||
|
if (succ){
|
||||||
|
//Continue to next step
|
||||||
|
updateCertificateDNS(function(succ){
|
||||||
|
if (succ){
|
||||||
|
obtainCertificate(function(succ){
|
||||||
|
$("#obtainButton").removeClass("loading").removeClass("disabled");
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
$("#obtainButton").removeClass("loading").removeClass("disabled");
|
||||||
|
console.log("update Certificate DNS process halted");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
console.log("Update Certificate EAB process halted");
|
||||||
|
$("#obtainButton").removeClass("loading").removeClass("disabled");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//On CA change in dropdown
|
||||||
$("input[name=ca]").on('change', function() {
|
$("input[name=ca]").on('change', function() {
|
||||||
if(this.value == "Custom ACME Server") {
|
if(this.value == "Custom ACME Server") {
|
||||||
$("#caInput").show();
|
$("#caInput").show();
|
||||||
|
$("#kidInput").show();
|
||||||
|
$("#hmacInput").show();
|
||||||
$("#skipTLS").show();
|
$("#skipTLS").show();
|
||||||
} else {
|
$("#dnsChallenge").hide();
|
||||||
|
$(".dnsChallengeOnly").hide();
|
||||||
|
} else if (this.value == "ZeroSSL") {
|
||||||
|
$("#kidInput").show();
|
||||||
|
$("#hmacInput").show();
|
||||||
|
$("#dnsChallenge").hide();
|
||||||
|
$(".dnsChallengeOnly").hide();
|
||||||
|
$("#skipTLS").hide();
|
||||||
|
} else if (this.value == "Buypass") {
|
||||||
|
$("#kidInput").show();
|
||||||
|
$("#hmacInput").show();
|
||||||
|
$("#dnsChallenge").hide();
|
||||||
|
$(".dnsChallengeOnly").hide();
|
||||||
|
$("#skipTLS").hide();
|
||||||
|
}else {
|
||||||
$("#caInput").hide();
|
$("#caInput").hide();
|
||||||
$("#skipTLS").hide();
|
$("#skipTLS").hide();
|
||||||
|
$("#kidInput").hide();
|
||||||
|
$("#hmacInput").hide();
|
||||||
|
$("#dnsChallenge").show();
|
||||||
|
if ($("#useDnsChallenge")[0].checked){
|
||||||
|
$(".dnsChallengeOnly").show();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Obtain certificate from API
|
//On DNS provider dropdown change
|
||||||
function obtainCertificate() {
|
$("input[name=dnsProvider]").on('change', function() {
|
||||||
|
let newProviderName = $("#dnsProvider").find("input").val();
|
||||||
|
$.get("/api/acme/dns/providers?name=" + newProviderName, function(data){
|
||||||
|
console.log("Loaded required config", data);
|
||||||
|
$("#dnsProviderAPIFields").html("");
|
||||||
|
//Generate a form for this config
|
||||||
|
let booleanFieldsHTML = "";
|
||||||
|
for (const [key, datatype] of Object.entries(data)) {
|
||||||
|
if (datatype == "int"){
|
||||||
|
$("#dnsProviderAPIFields").append(`<div class="ui fluid labeled dnsConfigField input" key="${key}" style="margin-top: 0.2em;">
|
||||||
|
<div class="ui basic blue label" style="font-weight: 300;">
|
||||||
|
${key}
|
||||||
|
</div>
|
||||||
|
<input type="number" value="300">
|
||||||
|
</div>`);
|
||||||
|
}else if (datatype == "bool"){
|
||||||
|
booleanFieldsHTML += (`<div class="ui checkbox dnsConfigField" key="${key}" style="margin-top: 1em !important; padding-left: 0.4em;">
|
||||||
|
<input type="checkbox">
|
||||||
|
<label>${key}</label>
|
||||||
|
</div>`);
|
||||||
|
}else{
|
||||||
|
//Default to string
|
||||||
|
$("#dnsProviderAPIFields").append(`<div class="ui fluid labeled input dnsConfigField" key="${key}" style="margin-top: 0.2em;">
|
||||||
|
<div class="ui basic label" style="font-weight: 300;">
|
||||||
|
${key}
|
||||||
|
</div>
|
||||||
|
<input type="text">
|
||||||
|
</div>`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Append the boolean fields at the bottom, if exists
|
||||||
|
$("#dnsProviderAPIFields").append(booleanFieldsHTML);
|
||||||
|
if (booleanFieldsHTML != ""){
|
||||||
|
$(".dnsConfigField.checkbox").checkbox();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get filename form domains and input
|
||||||
|
function getFilename() {
|
||||||
var domains = $("#domainsInput").val();
|
var domains = $("#domainsInput").val();
|
||||||
var filename = $("#filenameInput").val();
|
var filename = $("#filenameInput").val();
|
||||||
var email = $("#caRegisterEmail").val();
|
|
||||||
if (email == ""){
|
|
||||||
parent.msgbox("ACME renew email is not set", false)
|
|
||||||
$("#obtainButton").removeClass("loading").removeClass("disabled");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (filename.trim() == "" && !domains.includes(",")){
|
if (filename.trim() == "" && !domains.includes(",")){
|
||||||
//Zoraxy filename are the matching name for domains.
|
//Zoraxy filename are the matching name for domains.
|
||||||
//Use the same as domains
|
//Use the same as domains
|
||||||
@ -351,6 +470,215 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Filename cannot contain wildcards, and wildcards are possible with DNS challenges
|
||||||
|
filename = filename.replace("*", "_");
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Update EAB values for autorenewal
|
||||||
|
function updateCertificateEAB(callback=undefined) {
|
||||||
|
var ca = $("#ca").dropdown("get value");
|
||||||
|
var caURL = "";
|
||||||
|
if (ca == "Custom ACME Server") {
|
||||||
|
ca = "custom";
|
||||||
|
caURL = $("#caURL").val();
|
||||||
|
}else if(ca == "Buypass") {
|
||||||
|
caURL = "https://api.buypass.com/acme/directory";
|
||||||
|
}else if(ca == "ZeroSSL") {
|
||||||
|
caURL = "https://acme.zerossl.com/v2/DV90";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(caURL == "") {
|
||||||
|
//Skip update
|
||||||
|
if (callback != undefined){
|
||||||
|
callback(true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var kid = $("#eab_kid").val();
|
||||||
|
var hmac = $("#eab_hmac").val();
|
||||||
|
|
||||||
|
if(kid == "" || hmac == "") {
|
||||||
|
//Skip update
|
||||||
|
if (callback != undefined){
|
||||||
|
callback(true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(caURL + " " + kid + " " + hmac);
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/acme/autoRenew/setEAB",
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
acmeDirectoryURL: caURL,
|
||||||
|
kid: kid,
|
||||||
|
hmacEncoded: hmac,
|
||||||
|
},
|
||||||
|
success: function(response) {
|
||||||
|
//$("#obtainButton").removeClass("loading").removeClass("disabled");
|
||||||
|
if (response.error) {
|
||||||
|
console.log("Error:", response.error);
|
||||||
|
// Show error message
|
||||||
|
parent.msgbox(response.error, false, 12000);
|
||||||
|
if (callback != undefined){
|
||||||
|
callback(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log("Certificate EAB updated successfully");
|
||||||
|
// Show success message
|
||||||
|
parent.msgbox("Certificate EAB updated successfully");
|
||||||
|
|
||||||
|
// Renew the parent certificate list
|
||||||
|
parent.initManagedDomainCertificateList();
|
||||||
|
if (callback != undefined){
|
||||||
|
callback(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(error) {
|
||||||
|
//$("#obtainButton").removeClass("loading").removeClass("disabled");
|
||||||
|
console.log("Failed to update EAB configuration:", error);
|
||||||
|
parent.msgbox("Failed to update EAB configuration");
|
||||||
|
if (callback != undefined){
|
||||||
|
callback(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//Read DNS credential from form and generate a key value structure that looks like
|
||||||
|
// the old DNSCredential TextArea input
|
||||||
|
|
||||||
|
function readDnsCredentials(){
|
||||||
|
let dnsCredentials = {};
|
||||||
|
$(".dnsConfigField").each(function(){
|
||||||
|
let thisKey = $(this).attr("key");
|
||||||
|
let value = "";
|
||||||
|
if ($(this).hasClass("checkbox")){
|
||||||
|
//Boolean option
|
||||||
|
let checked = $(this).find("input")[0].checked;
|
||||||
|
dnsCredentials[thisKey] = checked;
|
||||||
|
}else{
|
||||||
|
//String or int options
|
||||||
|
let value = $(this).find("input").val().trim();
|
||||||
|
dnsCredentials[thisKey] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return dnsCredentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update DNS values for autorenewal
|
||||||
|
function updateCertificateDNS(callback=undefined) {
|
||||||
|
var dns = $("#useDnsChallenge")[0].checked;
|
||||||
|
var dnsProvider = "";
|
||||||
|
var dnsCredentials = "";
|
||||||
|
|
||||||
|
if (!dns) {
|
||||||
|
if (callback != undefined){
|
||||||
|
callback(true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if all fields is empty. If yes, do not update the config
|
||||||
|
let allFieldsEmpty = true;
|
||||||
|
$(".dnsConfigField").each(function(){
|
||||||
|
if ($(this).find("input").val().trim() != ""){
|
||||||
|
allFieldsEmpty = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (allFieldsEmpty){
|
||||||
|
//Do not update config on server side
|
||||||
|
if (callback != undefined){
|
||||||
|
callback(true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dnsProvider = $("#dnsProvider").dropdown("get value");
|
||||||
|
|
||||||
|
//dnsCredentials = $("#dnsCredentials").val();
|
||||||
|
dnsCredentials = readDnsCredentials();
|
||||||
|
|
||||||
|
if(dnsProvider == "") {
|
||||||
|
parent.msgbox("DNS Provider cannot be empty", false, 5000);
|
||||||
|
$("#obtainButton").removeClass("loading").removeClass("disabled");
|
||||||
|
if (callback != undefined){
|
||||||
|
callback(false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var filename = getFilename();
|
||||||
|
if (filename == '') {
|
||||||
|
parent.msgbox("Domain to renew cannot be empty", false, 5000);
|
||||||
|
if (callback != undefined){
|
||||||
|
callback(false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/acme/autoRenew/setDNS",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
filename: filename,
|
||||||
|
dnsProvider: dnsProvider,
|
||||||
|
dnsCredentials: JSON.stringify(dnsCredentials),
|
||||||
|
},
|
||||||
|
success: function(response) {
|
||||||
|
//$("#obtainButton").removeClass("loading").removeClass("disabled");
|
||||||
|
if (response.error) {
|
||||||
|
console.log("Error:", response.error);
|
||||||
|
// Show error message
|
||||||
|
parent.msgbox(response.error, false, 12000);
|
||||||
|
if (callback != undefined){
|
||||||
|
callback(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log("Certificate DNS Credentials updated successfully");
|
||||||
|
// Show success message
|
||||||
|
parent.msgbox("Certificate DNS Credentials updated successfully");
|
||||||
|
if (callback != undefined){
|
||||||
|
callback(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(error) {
|
||||||
|
//$("#obtainButton").removeClass("loading").removeClass("disabled");
|
||||||
|
console.log("Failed to update DNS configuration:", error);
|
||||||
|
parent.msgbox("Failed to update DNS configuration");
|
||||||
|
if (callback != undefined){
|
||||||
|
callback(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtain certificate from API
|
||||||
|
function obtainCertificate(callback=undefined) {
|
||||||
|
var domains = $("#domainsInput").val();
|
||||||
|
var filename = getFilename();
|
||||||
|
if (filename == '') {
|
||||||
|
if (callback != undefined){
|
||||||
|
parent.msgbox("Domain to obtain certificate cannot be empty", false)
|
||||||
|
callback(false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var email = $("#caRegisterEmail").val();
|
||||||
|
if (email == ""){
|
||||||
|
parent.msgbox("ACME renew email is not set", false)
|
||||||
|
if (callback != undefined){callback(false);}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var ca = $("#ca").dropdown("get value");
|
var ca = $("#ca").dropdown("get value");
|
||||||
var caURL = "";
|
var caURL = "";
|
||||||
if (ca == "Custom ACME Server") {
|
if (ca == "Custom ACME Server") {
|
||||||
@ -358,6 +686,8 @@
|
|||||||
caURL = $("#caURL").val();
|
caURL = $("#caURL").val();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var dns = $("#useDnsChallenge")[0].checked;
|
||||||
var skipTLSValue = $("#skipTLSCheckbox")[0].checked;
|
var skipTLSValue = $("#skipTLSCheckbox")[0].checked;
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@ -370,6 +700,7 @@
|
|||||||
ca: ca,
|
ca: ca,
|
||||||
caURL: caURL,
|
caURL: caURL,
|
||||||
skipTLS: skipTLSValue,
|
skipTLS: skipTLSValue,
|
||||||
|
dns: dns,
|
||||||
},
|
},
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
$("#obtainButton").removeClass("loading").removeClass("disabled");
|
$("#obtainButton").removeClass("loading").removeClass("disabled");
|
||||||
@ -377,6 +708,7 @@
|
|||||||
console.log("Error:", response.error);
|
console.log("Error:", response.error);
|
||||||
// Show error message
|
// Show error message
|
||||||
parent.msgbox(response.error, false, 12000);
|
parent.msgbox(response.error, false, 12000);
|
||||||
|
if (callback != undefined){callback(false);}
|
||||||
} else {
|
} else {
|
||||||
console.log("Certificate renewed successfully");
|
console.log("Certificate renewed successfully");
|
||||||
// Show success message
|
// Show success message
|
||||||
@ -384,11 +716,14 @@
|
|||||||
|
|
||||||
// Renew the parent certificate list
|
// Renew the parent certificate list
|
||||||
parent.initManagedDomainCertificateList();
|
parent.initManagedDomainCertificateList();
|
||||||
|
|
||||||
|
if (callback != undefined){callback(true);}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: function(error) {
|
error: function(error) {
|
||||||
$("#obtainButton").removeClass("loading").removeClass("disabled");
|
$("#obtainButton").removeClass("loading").removeClass("disabled");
|
||||||
console.log("Failed to renewed certificate:", error);
|
console.log("Failed to renewed certificate:", error);
|
||||||
|
if (callback != undefined){callback(false);}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -402,6 +737,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleDnsChallenge(){
|
||||||
|
if ( $("#useDnsChallenge")[0].checked){
|
||||||
|
$(".dnsChallengeOnly").show();
|
||||||
|
}else{
|
||||||
|
$(".dnsChallengeOnly").hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Grab the longest common suffix of all domains
|
//Grab the longest common suffix of all domains
|
||||||
//not that smart technically
|
//not that smart technically
|
||||||
function autoDetectMatchingRules(){
|
function autoDetectMatchingRules(){
|
||||||
@ -513,7 +856,35 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Clear up the input field when page load
|
//Load the json map and create the dropdown for DNS provider names
|
||||||
|
let dnsProviderNameMap = {};
|
||||||
|
function initDNSProviderList(){
|
||||||
|
$.get("dnsnames.json", function(namemap){
|
||||||
|
dnsProviderNameMap = namemap;
|
||||||
|
//Load a list of supported DNS provider from backend
|
||||||
|
$("#dnsProviderList").html("");
|
||||||
|
$.get("/api/acme/dns/providers", function(providerList){
|
||||||
|
providerList.sort();
|
||||||
|
providerList.forEach(providerid => {
|
||||||
|
let providerName = providerid;
|
||||||
|
if (dnsProviderNameMap[providerid] != undefined){
|
||||||
|
providerName = dnsProviderNameMap[providerid];
|
||||||
|
}
|
||||||
|
$("#dnsProviderList").append(`<div class="item" data-value="${providerid}">${providerName}</div>`);
|
||||||
|
});
|
||||||
|
$("#dnsProvider").dropdown();
|
||||||
|
setTimeout(function(){
|
||||||
|
//The dropdown is large, it takes some time to load
|
||||||
|
$("#dnsProvider").dropdown("set selected", "cloudflare");
|
||||||
|
}, 300)
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
initDNSProviderList();
|
||||||
|
|
||||||
|
|
||||||
|
//Clear up the input field when page load
|
||||||
$("#filenameInput").val("");
|
$("#filenameInput").val("");
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
178
src/web/snippet/aliasEditor.html
Normal file
178
src/web/snippet/aliasEditor.html
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!-- Notes: This should be open in its original path-->
|
||||||
|
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||||
|
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||||
|
<script src="../script/semantic/semantic.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<br>
|
||||||
|
<div class="ui container">
|
||||||
|
<div class="ui header">
|
||||||
|
<div class="content">
|
||||||
|
Alias Hostname
|
||||||
|
<div class="sub header epname"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<div class="scrolling content ui form">
|
||||||
|
<div id="inlineEditBasicAuthCredentials" class="field">
|
||||||
|
<p>Enter alias hostname or wildcard matching keywords for <code class="epname"></code></p>
|
||||||
|
<table class="ui very basic compacted unstackable celled table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Alias Hostname</th>
|
||||||
|
<th>Remove</th>
|
||||||
|
</tr></thead>
|
||||||
|
<tbody id="inlineEditTable">
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><i class="ui green circle check icon"></i> No Alias Hostname</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<div class="three small fields">
|
||||||
|
<div class="field">
|
||||||
|
<label>Alias Hostname</label>
|
||||||
|
<input id="aliasHostname" type="text" placeholder="alias.mydomain.com" autocomplete="off">
|
||||||
|
<small>Support wildcards e.g. alias.mydomain.com or *.alias.mydomain.com</small>
|
||||||
|
</div>
|
||||||
|
<div class="field" >
|
||||||
|
<button class="ui basic button" onclick="addAliasToRoutingRule();"><i class="green add icon"></i> Add Alias</button>
|
||||||
|
</div>
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<div class="field" >
|
||||||
|
<button class="ui basic button" style="float: right;" onclick="closeThisWrapper();">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br><br><br><br>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
let aliasList = [];
|
||||||
|
let editingEndpoint = {};
|
||||||
|
|
||||||
|
if (window.location.hash.length > 1){
|
||||||
|
let payloadHash = window.location.hash.substr(1);
|
||||||
|
try{
|
||||||
|
payloadHash = JSON.parse(decodeURIComponent(payloadHash));
|
||||||
|
$(".epname").text(payloadHash.ep);
|
||||||
|
editingEndpoint = payloadHash;
|
||||||
|
}catch(ex){
|
||||||
|
console.log("Unable to load endpoint data from hash")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initAliasNames(){
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/proxy/detail",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
"type":"host",
|
||||||
|
"epname": editingEndpoint.ep
|
||||||
|
},
|
||||||
|
success: function(data){
|
||||||
|
if (data.error != undefined){
|
||||||
|
//This endpoint not exists?
|
||||||
|
alert(data.error);
|
||||||
|
return;
|
||||||
|
}else{
|
||||||
|
$("#inlineEditTable").html("");
|
||||||
|
if (data.MatchingDomainAlias != undefined){
|
||||||
|
aliasList = data.MatchingDomainAlias;
|
||||||
|
renderAliasList();
|
||||||
|
}else{
|
||||||
|
//Assume no alias
|
||||||
|
$("#inlineEditTable").html(`<tr>
|
||||||
|
<td colspan="2"><i class="ui green circle check icon"></i> No Alias Hostname</td>
|
||||||
|
</tr>`);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
initAliasNames();
|
||||||
|
|
||||||
|
function removeAliasDomain(targetDomain){
|
||||||
|
aliasList.splice(aliasList.indexOf(targetDomain), 1);
|
||||||
|
saveCurrentAliasList(function(data){
|
||||||
|
if (data.error != undefined){
|
||||||
|
parent.msgbox(data.error);
|
||||||
|
}else{
|
||||||
|
initAliasNames();
|
||||||
|
parent.msgbox("Alias hostname removed")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addAliasToRoutingRule(){
|
||||||
|
let newAliasHostname = $("#aliasHostname").val().trim();
|
||||||
|
aliasList.push(newAliasHostname);
|
||||||
|
$("#aliasHostname").val("");
|
||||||
|
saveCurrentAliasList(function(data){
|
||||||
|
if (data.error != undefined){
|
||||||
|
parent.msgbox(data.error);
|
||||||
|
}else{
|
||||||
|
parent.msgbox("New alias hostname added")
|
||||||
|
initAliasNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveCurrentAliasList(callback=undefined){
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/proxy/setAlias",
|
||||||
|
method: "POST",
|
||||||
|
data:{
|
||||||
|
"ep":editingEndpoint.ep,
|
||||||
|
"alias": JSON.stringify(aliasList)
|
||||||
|
},
|
||||||
|
success: function(data){
|
||||||
|
if (callback != undefined){
|
||||||
|
callback(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.error == undefined && parent != undefined && parent.document != undefined){
|
||||||
|
//Try to update the parent object's rules if exists
|
||||||
|
parent.updateAliasListForEndpoint(editingEndpoint.ep, aliasList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderAliasList(){
|
||||||
|
$("#inlineEditTable").html("");
|
||||||
|
aliasList.forEach(aliasDomain => {
|
||||||
|
let domainLink = `<a href="//${aliasDomain}" target="_blank">${aliasDomain}</a>`
|
||||||
|
if (aliasDomain.includes("*")){
|
||||||
|
//This is a wildcard hostname
|
||||||
|
domainLink = aliasDomain;
|
||||||
|
}
|
||||||
|
$("#inlineEditTable").append(`<tr>
|
||||||
|
<td>${domainLink}</td>
|
||||||
|
<td><button class="ui basic button" onclick="removeAliasDomain('${aliasDomain}');"><i class="red remove icon"></i> Remove</button></td>
|
||||||
|
</tr>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (aliasList.length == 0){
|
||||||
|
$("#inlineEditTable").html(`<tr>
|
||||||
|
<td colspan="2"><i class="ui green circle check icon"></i> No Alias Hostname</td>
|
||||||
|
</tr>`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeThisWrapper(){
|
||||||
|
parent.hideSideWrapper(true);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
132
src/web/snippet/dnsnames.json
Normal file
132
src/web/snippet/dnsnames.json
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"edgedns": "Akamai EdgeDNS",
|
||||||
|
"alidns": "Alibaba Cloud DNS",
|
||||||
|
"allinkl": "all-inkl",
|
||||||
|
"lightsail": "Amazon Lightsail",
|
||||||
|
"route53": "Amazon Route 53",
|
||||||
|
"arvancloud": "ArvanCloud",
|
||||||
|
"auroradns": "Aurora DNS",
|
||||||
|
"autodns": "Autodns",
|
||||||
|
"azure": "Azure (deprecated)",
|
||||||
|
"azuredns": "Azure DNS",
|
||||||
|
"bindman": "Bindman",
|
||||||
|
"bluecat": "Bluecat",
|
||||||
|
"brandit": "Brandit",
|
||||||
|
"bunny": "Bunny",
|
||||||
|
"checkdomain": "Checkdomain",
|
||||||
|
"civo": "Civo",
|
||||||
|
"cloudru": "Cloud.ru",
|
||||||
|
"clouddns": "CloudDNS",
|
||||||
|
"cloudflare": "Cloudflare",
|
||||||
|
"cloudns": "ClouDNS",
|
||||||
|
"cloudxns": "CloudXNS",
|
||||||
|
"conoha": "ConoHa",
|
||||||
|
"constellix": "Constellix",
|
||||||
|
"cpanel": "CPanel/WHM",
|
||||||
|
"derak": "Derak Cloud",
|
||||||
|
"desec": "deSEC.io",
|
||||||
|
"designate": "Designate DNSaaS for Openstack",
|
||||||
|
"digitalocean": "Digital Ocean",
|
||||||
|
"dnsmadeeasy": "DNS Made Easy",
|
||||||
|
"dnshomede": "dnsHome.de",
|
||||||
|
"dnsimple": "DNSimple",
|
||||||
|
"dnspod": "DNSPod (deprecated)",
|
||||||
|
"dode": "Domain Offensive (do.de)",
|
||||||
|
"domeneshop": "Domeneshop",
|
||||||
|
"dreamhost": "DreamHost",
|
||||||
|
"duckdns": "Duck DNS",
|
||||||
|
"dyn": "Dyn",
|
||||||
|
"dynu": "Dynu",
|
||||||
|
"easydns": "EasyDNS",
|
||||||
|
"efficientip": "Efficient IP",
|
||||||
|
"epik": "Epik",
|
||||||
|
"exoscale": "Exoscale",
|
||||||
|
"exec": "External program",
|
||||||
|
"freemyip": "freemyip.com",
|
||||||
|
"gcore": "G-Core",
|
||||||
|
"gandi": "Gandi",
|
||||||
|
"gandiv5": "Gandi Live DNS (v5)",
|
||||||
|
"glesys": "Glesys",
|
||||||
|
"godaddy": "Go Daddy",
|
||||||
|
"gcloud": "Google Cloud",
|
||||||
|
"googledomains": "Google Domains",
|
||||||
|
"hetzner": "Hetzner",
|
||||||
|
"hostingde": "Hosting.de",
|
||||||
|
"hosttech": "Hosttech",
|
||||||
|
"httpreq": "HTTP request",
|
||||||
|
"httpnet": "http.net",
|
||||||
|
"hurricane": "Hurricane Electric DNS",
|
||||||
|
"hyperone": "HyperOne",
|
||||||
|
"ibmcloud": "IBM Cloud (SoftLayer)",
|
||||||
|
"iijdpf": "IIJ DNS Platform Service",
|
||||||
|
"infoblox": "Infoblox",
|
||||||
|
"infomaniak": "Infomaniak",
|
||||||
|
"iij": "Internet Initiative Japan",
|
||||||
|
"internetbs": "Internet.bs",
|
||||||
|
"inwx": "INWX",
|
||||||
|
"ionos": "Ionos",
|
||||||
|
"ipv64": "IPv64",
|
||||||
|
"iwantmyname": "iwantmyname",
|
||||||
|
"joker": "Joker",
|
||||||
|
"acme-dns": "Joohoi's ACME-DNS",
|
||||||
|
"liara": "Liara",
|
||||||
|
"linode": "Linode (v4)",
|
||||||
|
"liquidweb": "Liquid Web",
|
||||||
|
"loopia": "Loopia",
|
||||||
|
"luadns": "LuaDNS",
|
||||||
|
"mailinabox": "Mail-in-a-Box",
|
||||||
|
"metaname": "Metaname",
|
||||||
|
"mydnsjp": "MyDNS.jp",
|
||||||
|
"mythicbeasts": "MythicBeasts",
|
||||||
|
"namedotcom": "Name.com",
|
||||||
|
"namecheap": "Namecheap",
|
||||||
|
"namesilo": "Namesilo",
|
||||||
|
"nearlyfreespeech": "NearlyFreeSpeech.NET",
|
||||||
|
"netcup": "Netcup",
|
||||||
|
"netlify": "Netlify",
|
||||||
|
"nicmanager": "Nicmanager",
|
||||||
|
"nifcloud": "NIFCloud",
|
||||||
|
"njalla": "Njalla",
|
||||||
|
"nodion": "Nodion",
|
||||||
|
"ns1": "NS1",
|
||||||
|
"otc": "Open Telekom Cloud",
|
||||||
|
"oraclecloud": "Oracle Cloud",
|
||||||
|
"ovh": "OVH",
|
||||||
|
"plesk": "plesk.com",
|
||||||
|
"porkbun": "Porkbun",
|
||||||
|
"pdns": "PowerDNS",
|
||||||
|
"rackspace": "Rackspace",
|
||||||
|
"rcodezero": "RcodeZero",
|
||||||
|
"regru": "reg.ru",
|
||||||
|
"rfc2136": "RFC2136",
|
||||||
|
"rimuhosting": "RimuHosting",
|
||||||
|
"sakuracloud": "Sakura Cloud",
|
||||||
|
"scaleway": "Scaleway",
|
||||||
|
"selectel": "Selectel",
|
||||||
|
"servercow": "Servercow",
|
||||||
|
"shellrent": "Shellrent",
|
||||||
|
"simply": "Simply.com",
|
||||||
|
"sonic": "Sonic",
|
||||||
|
"stackpath": "Stackpath",
|
||||||
|
"tencentcloud": "Tencent Cloud DNS",
|
||||||
|
"transip": "TransIP",
|
||||||
|
"safedns": "UKFast SafeDNS",
|
||||||
|
"ultradns": "Ultradns",
|
||||||
|
"variomedia": "Variomedia",
|
||||||
|
"vegadns": "VegaDNS",
|
||||||
|
"vercel": "Vercel",
|
||||||
|
"versio": "Versio.[nl|eu|uk]",
|
||||||
|
"vinyldns": "VinylDNS",
|
||||||
|
"vkcloud": "VK Cloud",
|
||||||
|
"vscale": "Vscale",
|
||||||
|
"vultr": "Vultr",
|
||||||
|
"webnames": "Webnames",
|
||||||
|
"websupport": "Websupport",
|
||||||
|
"wedos": "WEDOS",
|
||||||
|
"yandex360": "Yandex 360",
|
||||||
|
"yandexcloud": "Yandex Cloud",
|
||||||
|
"yandex": "Yandex PDD",
|
||||||
|
"zoneee": "Zone.ee",
|
||||||
|
"zonomi": "Zonomi"
|
||||||
|
}
|
||||||
|
|
187
src/web/snippet/hostAccessEditor.html
Normal file
187
src/web/snippet/hostAccessEditor.html
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!-- Notes: This should be open in its original path-->
|
||||||
|
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||||
|
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||||
|
<script src="../script/semantic/semantic.min.js"></script>
|
||||||
|
<style>
|
||||||
|
.accessRule{
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 0.4em !important;
|
||||||
|
border: 1px solid rgb(233, 233, 233) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accessRule:hover{
|
||||||
|
background-color: rgb(241, 241, 241) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accessRule.active{
|
||||||
|
background-color: rgb(241, 241, 241) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accessRule .selected{
|
||||||
|
position: absolute;
|
||||||
|
top: 1em;
|
||||||
|
right: 0.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accessRule:not(.active) .selected{
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#accessRuleList{
|
||||||
|
padding: 0.6em;
|
||||||
|
border: 1px solid rgb(228, 228, 228);
|
||||||
|
border-radius: 0.4em !important;
|
||||||
|
max-height: calc(100vh - 15em);
|
||||||
|
min-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<br>
|
||||||
|
<div class="ui container">
|
||||||
|
<div class="ui header">
|
||||||
|
<div class="content">
|
||||||
|
Host Access Settings
|
||||||
|
<div class="sub header" id="epname"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<p>Select an access rule to apply blacklist / whitelist filtering</p>
|
||||||
|
<div id="accessRuleList">
|
||||||
|
<div class="ui segment accessRule">
|
||||||
|
<div class="ui header">
|
||||||
|
<i class="filter icon"></i>
|
||||||
|
<div class="content">
|
||||||
|
Account Settings
|
||||||
|
<div class="sub header">Manage your preferences</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<button class="ui basic button" onclick="applyChangeAndClose()"><i class="ui green check icon"></i> Apply Change</button>
|
||||||
|
|
||||||
|
<button class="ui basic button" style="float: right;" onclick="parent.hideSideWrapper();"><i class="remove icon"></i> Close</button>
|
||||||
|
<br><br><br>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
let editingEndpoint = {};
|
||||||
|
if (window.location.hash.length > 1){
|
||||||
|
let payloadHash = window.location.hash.substr(1);
|
||||||
|
try{
|
||||||
|
payloadHash = JSON.parse(decodeURIComponent(payloadHash));
|
||||||
|
$("#epname").text(payloadHash.ep);
|
||||||
|
editingEndpoint = payloadHash;
|
||||||
|
}catch(ex){
|
||||||
|
console.log("Unable to load endpoint data from hash")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initAccessRuleList(callback = undefined){
|
||||||
|
$("#accessRuleList").html("<small>Loading</small>");
|
||||||
|
$.get("/api/access/list", function(data){
|
||||||
|
if (data.error == undefined){
|
||||||
|
$("#accessRuleList").html("");
|
||||||
|
data.forEach(function(rule){
|
||||||
|
let icon = `<i class="ui grey filter icon"></i>`;
|
||||||
|
if (rule.ID == "default"){
|
||||||
|
icon = `<i class="ui yellow star icon"></i>`;
|
||||||
|
}else if (rule.BlacklistEnabled && !rule.WhitelistEnabled){
|
||||||
|
//This is a blacklist filter
|
||||||
|
icon = `<i class="ui red filter icon"></i>`;
|
||||||
|
}else if (rule.WhitelistEnabled && !rule.BlacklistEnabled){
|
||||||
|
//This is a whitelist filter
|
||||||
|
icon = `<i class="ui green filter icon"></i>`;
|
||||||
|
}else if (rule.WhitelistEnabled && rule.BlacklistEnabled){
|
||||||
|
//Whitelist and blacklist filter
|
||||||
|
icon = `<i class="ui yellow filter icon"></i>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#accessRuleList").append(`<div class="ui basic segment accessRule" ruleid="${rule.ID}" onclick="selectThisRule(this);">
|
||||||
|
<h5 class="ui header">
|
||||||
|
${icon}
|
||||||
|
<div class="content">
|
||||||
|
${rule.Name}
|
||||||
|
<div class="sub header">${rule.ID}</div>
|
||||||
|
</div>
|
||||||
|
</h5>
|
||||||
|
<p>${rule.Desc}</p>
|
||||||
|
${rule.BlacklistEnabled?`<small><i class="ui red filter icon"></i> Blacklist Enabled</small>`:""}
|
||||||
|
${rule.WhitelistEnabled?`<small><i class="ui green filter icon"></i> Whitelist Enabled</small>`:""}
|
||||||
|
<div class="selected"><i class="ui large green check icon"></i></div>
|
||||||
|
</div>`);
|
||||||
|
});
|
||||||
|
accessRuleList = data;
|
||||||
|
$(".dropdown").dropdown();
|
||||||
|
if (callback != undefined){
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
initAccessRuleList(function(){
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/proxy/detail",
|
||||||
|
method: "POST",
|
||||||
|
data: {"type":"host", "epname": editingEndpoint.ep },
|
||||||
|
success: function(data){
|
||||||
|
console.log(data);
|
||||||
|
if (data.error != undefined){
|
||||||
|
alert(data.error);
|
||||||
|
}else{
|
||||||
|
let currentAccessFilter = data.AccessFilterUUID;
|
||||||
|
if (currentAccessFilter == ""){
|
||||||
|
//Use default
|
||||||
|
currentAccessFilter = "default";
|
||||||
|
}
|
||||||
|
|
||||||
|
$(`.accessRule[ruleid=${currentAccessFilter}]`).addClass("active");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function selectThisRule(accessRuleObject){
|
||||||
|
let accessRuleID = $(accessRuleObject).attr("ruleid");
|
||||||
|
$(".accessRule").removeClass('active');
|
||||||
|
$(accessRuleObject).addClass('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyChangeAndClose(){
|
||||||
|
let newAccessRuleID = $(".accessRule.active").attr("ruleid");
|
||||||
|
let targetEndpoint = editingEndpoint.ep;
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/access/attach",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
id: newAccessRuleID,
|
||||||
|
host: targetEndpoint
|
||||||
|
},
|
||||||
|
success: function(data){
|
||||||
|
if (data.error != undefined){
|
||||||
|
parent.msgbox(data.error, false);
|
||||||
|
}else{
|
||||||
|
parent.msgbox("Access Rule Updated");
|
||||||
|
|
||||||
|
//Modify the parent list if exists
|
||||||
|
if (parent != undefined && parent.updateAccessRuleNameUnderHost){
|
||||||
|
parent.updateAccessRuleNameUnderHost(targetEndpoint, newAccessRuleID);
|
||||||
|
}
|
||||||
|
parent.hideSideWrapper();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
48
tools/dns_challenge_update/code-gen/README.md
Normal file
48
tools/dns_challenge_update/code-gen/README.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
### DNS Challenge Update Data Structure Code Generator
|
||||||
|
|
||||||
|
This script is designed to automatically pull lego, update the `acmedns` module with new json file and create a function for automatically create a provider based on the given providers name and config json.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
To update the module, simply run update.sh
|
||||||
|
|
||||||
|
```
|
||||||
|
./update.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
The updated files will be written into the `acmedns` folder. Then, you can copy it to the ACME module folder (or later-on a CICD pipeline will be made to do this automatically, but for now you have to manually copy it into the module under `src/mod/acme/`)
|
||||||
|
|
||||||
|
### Build for Windows 7 (NT6.1)
|
||||||
|
|
||||||
|
If you want to build Zoraxy with NT6.1, the lego version must be kept on or below 4.15.0. To build acmedns module for win7, add -- "win7" as go run paramter as follows.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go run ./extract.go -- "win7"
|
||||||
|
```
|
||||||
|
|
||||||
|
After moving the generated modules into the acmedns folder, you will also need to force override the version of the lego in the go.mod file under `src/`. by adding this line at the bottom of the go.mod file
|
||||||
|
|
||||||
|
```
|
||||||
|
replace github.com/go-acme/lego/v4 v4.16.1 => github.com/go-acme/lego/v4 v4.15.0
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Make sure your Go version is on or below `1.20` for Windows 7 support.
|
||||||
|
|
||||||
|
### Module Usage
|
||||||
|
|
||||||
|
To use the module, you can call to the following function inside the `acmedns`
|
||||||
|
|
||||||
|
```go
|
||||||
|
func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, error)
|
||||||
|
|
||||||
|
//For example
|
||||||
|
providersdef.GetDNSProviderByJsonConfig("gandi", "{\"Username\":\"far\",\"Password\":\"boo\"}")
|
||||||
|
```
|
||||||
|
|
||||||
|
This should be able to replace the default lego v4 build in one (the one attached below) that requires the use of environment variables
|
||||||
|
|
||||||
|
```go
|
||||||
|
// NewDNSChallengeProviderByName Factory for DNS providers.
|
||||||
|
func NewDNSChallengeProviderByName(name string) (challenge.Provider, error)
|
||||||
|
```
|
982
tools/dns_challenge_update/code-gen/acmedns/acmedns.go
Normal file
982
tools/dns_challenge_update/code-gen/acmedns/acmedns.go
Normal file
@ -0,0 +1,982 @@
|
|||||||
|
package acmedns
|
||||||
|
/*
|
||||||
|
THIS MODULE IS GENERATED AUTOMATICALLY
|
||||||
|
DO NOT EDIT THIS FILE
|
||||||
|
*/
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-acme/lego/v4/challenge"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/alidns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/allinkl"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/arvancloud"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/auroradns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/autodns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/azure"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/azuredns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/bindman"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/bluecat"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/brandit"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/bunny"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/checkdomain"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/civo"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/clouddns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/cloudflare"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/cloudns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/cloudru"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/cloudxns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/conoha"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/constellix"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/cpanel"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/derak"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/desec"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/digitalocean"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/dnshomede"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/dnsimple"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/dnsmadeeasy"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/dnspod"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/dode"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/domeneshop"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/dreamhost"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/duckdns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/dyn"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/dynu"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/easydns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/efficientip"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/epik"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/exoscale"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/freemyip"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/gandi"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/gandiv5"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/gcore"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/glesys"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/godaddy"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/googledomains"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/hetzner"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/hostingde"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/hosttech"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/httpnet"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/hyperone"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/ibmcloud"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/iij"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/iijdpf"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/infoblox"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/infomaniak"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/internetbs"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/inwx"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/ionos"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/ipv64"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/iwantmyname"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/joker"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/liara"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/lightsail"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/linode"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/liquidweb"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/loopia"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/luadns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/mailinabox"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/metaname"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/mydnsjp"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/namecheap"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/namedotcom"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/namesilo"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/nearlyfreespeech"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/netcup"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/netlify"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/nicmanager"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/nifcloud"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/njalla"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/nodion"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/ns1"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/otc"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/ovh"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/pdns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/plesk"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/porkbun"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/rackspace"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/rcodezero"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/regru"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/rfc2136"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/rimuhosting"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/route53"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/safedns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/sakuracloud"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/scaleway"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/selectel"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/servercow"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/shellrent"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/simply"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/sonic"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/stackpath"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/tencentcloud"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/transip"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/ultradns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/variomedia"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/vegadns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/vercel"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/versio"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/vinyldns"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/vkcloud"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/vscale"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/vultr"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/webnames"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/websupport"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/wedos"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/yandex"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/yandex360"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/yandexcloud"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/zoneee"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/zonomi"
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
//name is the DNS provider name, e.g. cloudflare or gandi
|
||||||
|
//JSON (js) must be in key-value string that match ConfigableFields Title in providers.json, e.g. {"Username":"far","Password":"boo"}
|
||||||
|
func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, error){
|
||||||
|
switch name {
|
||||||
|
|
||||||
|
case "alidns":
|
||||||
|
cfg := alidns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return alidns.NewDNSProviderConfig(cfg)
|
||||||
|
case "allinkl":
|
||||||
|
cfg := allinkl.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return allinkl.NewDNSProviderConfig(cfg)
|
||||||
|
case "arvancloud":
|
||||||
|
cfg := arvancloud.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return arvancloud.NewDNSProviderConfig(cfg)
|
||||||
|
case "auroradns":
|
||||||
|
cfg := auroradns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return auroradns.NewDNSProviderConfig(cfg)
|
||||||
|
case "autodns":
|
||||||
|
cfg := autodns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return autodns.NewDNSProviderConfig(cfg)
|
||||||
|
case "azure":
|
||||||
|
cfg := azure.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return azure.NewDNSProviderConfig(cfg)
|
||||||
|
case "azuredns":
|
||||||
|
cfg := azuredns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return azuredns.NewDNSProviderConfig(cfg)
|
||||||
|
case "bindman":
|
||||||
|
cfg := bindman.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bindman.NewDNSProviderConfig(cfg)
|
||||||
|
case "bluecat":
|
||||||
|
cfg := bluecat.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bluecat.NewDNSProviderConfig(cfg)
|
||||||
|
case "brandit":
|
||||||
|
cfg := brandit.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return brandit.NewDNSProviderConfig(cfg)
|
||||||
|
case "bunny":
|
||||||
|
cfg := bunny.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bunny.NewDNSProviderConfig(cfg)
|
||||||
|
case "checkdomain":
|
||||||
|
cfg := checkdomain.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return checkdomain.NewDNSProviderConfig(cfg)
|
||||||
|
case "civo":
|
||||||
|
cfg := civo.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return civo.NewDNSProviderConfig(cfg)
|
||||||
|
case "clouddns":
|
||||||
|
cfg := clouddns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return clouddns.NewDNSProviderConfig(cfg)
|
||||||
|
case "cloudflare":
|
||||||
|
cfg := cloudflare.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return cloudflare.NewDNSProviderConfig(cfg)
|
||||||
|
case "cloudns":
|
||||||
|
cfg := cloudns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return cloudns.NewDNSProviderConfig(cfg)
|
||||||
|
case "cloudru":
|
||||||
|
cfg := cloudru.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return cloudru.NewDNSProviderConfig(cfg)
|
||||||
|
case "cloudxns":
|
||||||
|
cfg := cloudxns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return cloudxns.NewDNSProviderConfig(cfg)
|
||||||
|
case "conoha":
|
||||||
|
cfg := conoha.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return conoha.NewDNSProviderConfig(cfg)
|
||||||
|
case "constellix":
|
||||||
|
cfg := constellix.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return constellix.NewDNSProviderConfig(cfg)
|
||||||
|
case "cpanel":
|
||||||
|
cfg := cpanel.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return cpanel.NewDNSProviderConfig(cfg)
|
||||||
|
case "derak":
|
||||||
|
cfg := derak.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return derak.NewDNSProviderConfig(cfg)
|
||||||
|
case "desec":
|
||||||
|
cfg := desec.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return desec.NewDNSProviderConfig(cfg)
|
||||||
|
case "digitalocean":
|
||||||
|
cfg := digitalocean.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return digitalocean.NewDNSProviderConfig(cfg)
|
||||||
|
case "dnshomede":
|
||||||
|
cfg := dnshomede.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dnshomede.NewDNSProviderConfig(cfg)
|
||||||
|
case "dnsimple":
|
||||||
|
cfg := dnsimple.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dnsimple.NewDNSProviderConfig(cfg)
|
||||||
|
case "dnsmadeeasy":
|
||||||
|
cfg := dnsmadeeasy.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dnsmadeeasy.NewDNSProviderConfig(cfg)
|
||||||
|
case "dnspod":
|
||||||
|
cfg := dnspod.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dnspod.NewDNSProviderConfig(cfg)
|
||||||
|
case "dode":
|
||||||
|
cfg := dode.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dode.NewDNSProviderConfig(cfg)
|
||||||
|
case "domeneshop":
|
||||||
|
cfg := domeneshop.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return domeneshop.NewDNSProviderConfig(cfg)
|
||||||
|
case "dreamhost":
|
||||||
|
cfg := dreamhost.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dreamhost.NewDNSProviderConfig(cfg)
|
||||||
|
case "duckdns":
|
||||||
|
cfg := duckdns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return duckdns.NewDNSProviderConfig(cfg)
|
||||||
|
case "dyn":
|
||||||
|
cfg := dyn.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dyn.NewDNSProviderConfig(cfg)
|
||||||
|
case "dynu":
|
||||||
|
cfg := dynu.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dynu.NewDNSProviderConfig(cfg)
|
||||||
|
case "easydns":
|
||||||
|
cfg := easydns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return easydns.NewDNSProviderConfig(cfg)
|
||||||
|
case "efficientip":
|
||||||
|
cfg := efficientip.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return efficientip.NewDNSProviderConfig(cfg)
|
||||||
|
case "epik":
|
||||||
|
cfg := epik.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return epik.NewDNSProviderConfig(cfg)
|
||||||
|
case "exoscale":
|
||||||
|
cfg := exoscale.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return exoscale.NewDNSProviderConfig(cfg)
|
||||||
|
case "freemyip":
|
||||||
|
cfg := freemyip.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return freemyip.NewDNSProviderConfig(cfg)
|
||||||
|
case "gandi":
|
||||||
|
cfg := gandi.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return gandi.NewDNSProviderConfig(cfg)
|
||||||
|
case "gandiv5":
|
||||||
|
cfg := gandiv5.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return gandiv5.NewDNSProviderConfig(cfg)
|
||||||
|
case "gcore":
|
||||||
|
cfg := gcore.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return gcore.NewDNSProviderConfig(cfg)
|
||||||
|
case "glesys":
|
||||||
|
cfg := glesys.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return glesys.NewDNSProviderConfig(cfg)
|
||||||
|
case "godaddy":
|
||||||
|
cfg := godaddy.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return godaddy.NewDNSProviderConfig(cfg)
|
||||||
|
case "googledomains":
|
||||||
|
cfg := googledomains.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return googledomains.NewDNSProviderConfig(cfg)
|
||||||
|
case "hetzner":
|
||||||
|
cfg := hetzner.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return hetzner.NewDNSProviderConfig(cfg)
|
||||||
|
case "hostingde":
|
||||||
|
cfg := hostingde.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return hostingde.NewDNSProviderConfig(cfg)
|
||||||
|
case "hosttech":
|
||||||
|
cfg := hosttech.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return hosttech.NewDNSProviderConfig(cfg)
|
||||||
|
case "httpnet":
|
||||||
|
cfg := httpnet.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return httpnet.NewDNSProviderConfig(cfg)
|
||||||
|
case "hyperone":
|
||||||
|
cfg := hyperone.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return hyperone.NewDNSProviderConfig(cfg)
|
||||||
|
case "ibmcloud":
|
||||||
|
cfg := ibmcloud.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ibmcloud.NewDNSProviderConfig(cfg)
|
||||||
|
case "iij":
|
||||||
|
cfg := iij.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return iij.NewDNSProviderConfig(cfg)
|
||||||
|
case "iijdpf":
|
||||||
|
cfg := iijdpf.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return iijdpf.NewDNSProviderConfig(cfg)
|
||||||
|
case "infoblox":
|
||||||
|
cfg := infoblox.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return infoblox.NewDNSProviderConfig(cfg)
|
||||||
|
case "infomaniak":
|
||||||
|
cfg := infomaniak.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return infomaniak.NewDNSProviderConfig(cfg)
|
||||||
|
case "internetbs":
|
||||||
|
cfg := internetbs.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return internetbs.NewDNSProviderConfig(cfg)
|
||||||
|
case "inwx":
|
||||||
|
cfg := inwx.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return inwx.NewDNSProviderConfig(cfg)
|
||||||
|
case "ionos":
|
||||||
|
cfg := ionos.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ionos.NewDNSProviderConfig(cfg)
|
||||||
|
case "ipv64":
|
||||||
|
cfg := ipv64.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ipv64.NewDNSProviderConfig(cfg)
|
||||||
|
case "iwantmyname":
|
||||||
|
cfg := iwantmyname.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return iwantmyname.NewDNSProviderConfig(cfg)
|
||||||
|
case "joker":
|
||||||
|
cfg := joker.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return joker.NewDNSProviderConfig(cfg)
|
||||||
|
case "liara":
|
||||||
|
cfg := liara.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return liara.NewDNSProviderConfig(cfg)
|
||||||
|
case "lightsail":
|
||||||
|
cfg := lightsail.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return lightsail.NewDNSProviderConfig(cfg)
|
||||||
|
case "linode":
|
||||||
|
cfg := linode.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return linode.NewDNSProviderConfig(cfg)
|
||||||
|
case "liquidweb":
|
||||||
|
cfg := liquidweb.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return liquidweb.NewDNSProviderConfig(cfg)
|
||||||
|
case "loopia":
|
||||||
|
cfg := loopia.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return loopia.NewDNSProviderConfig(cfg)
|
||||||
|
case "luadns":
|
||||||
|
cfg := luadns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return luadns.NewDNSProviderConfig(cfg)
|
||||||
|
case "mailinabox":
|
||||||
|
cfg := mailinabox.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return mailinabox.NewDNSProviderConfig(cfg)
|
||||||
|
case "metaname":
|
||||||
|
cfg := metaname.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return metaname.NewDNSProviderConfig(cfg)
|
||||||
|
case "mydnsjp":
|
||||||
|
cfg := mydnsjp.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return mydnsjp.NewDNSProviderConfig(cfg)
|
||||||
|
case "namecheap":
|
||||||
|
cfg := namecheap.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return namecheap.NewDNSProviderConfig(cfg)
|
||||||
|
case "namedotcom":
|
||||||
|
cfg := namedotcom.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return namedotcom.NewDNSProviderConfig(cfg)
|
||||||
|
case "namesilo":
|
||||||
|
cfg := namesilo.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return namesilo.NewDNSProviderConfig(cfg)
|
||||||
|
case "nearlyfreespeech":
|
||||||
|
cfg := nearlyfreespeech.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nearlyfreespeech.NewDNSProviderConfig(cfg)
|
||||||
|
case "netcup":
|
||||||
|
cfg := netcup.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return netcup.NewDNSProviderConfig(cfg)
|
||||||
|
case "netlify":
|
||||||
|
cfg := netlify.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return netlify.NewDNSProviderConfig(cfg)
|
||||||
|
case "nicmanager":
|
||||||
|
cfg := nicmanager.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nicmanager.NewDNSProviderConfig(cfg)
|
||||||
|
case "nifcloud":
|
||||||
|
cfg := nifcloud.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nifcloud.NewDNSProviderConfig(cfg)
|
||||||
|
case "njalla":
|
||||||
|
cfg := njalla.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return njalla.NewDNSProviderConfig(cfg)
|
||||||
|
case "nodion":
|
||||||
|
cfg := nodion.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nodion.NewDNSProviderConfig(cfg)
|
||||||
|
case "ns1":
|
||||||
|
cfg := ns1.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ns1.NewDNSProviderConfig(cfg)
|
||||||
|
case "otc":
|
||||||
|
cfg := otc.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return otc.NewDNSProviderConfig(cfg)
|
||||||
|
case "ovh":
|
||||||
|
cfg := ovh.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ovh.NewDNSProviderConfig(cfg)
|
||||||
|
case "pdns":
|
||||||
|
cfg := pdns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return pdns.NewDNSProviderConfig(cfg)
|
||||||
|
case "plesk":
|
||||||
|
cfg := plesk.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return plesk.NewDNSProviderConfig(cfg)
|
||||||
|
case "porkbun":
|
||||||
|
cfg := porkbun.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return porkbun.NewDNSProviderConfig(cfg)
|
||||||
|
case "rackspace":
|
||||||
|
cfg := rackspace.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rackspace.NewDNSProviderConfig(cfg)
|
||||||
|
case "rcodezero":
|
||||||
|
cfg := rcodezero.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rcodezero.NewDNSProviderConfig(cfg)
|
||||||
|
case "regru":
|
||||||
|
cfg := regru.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return regru.NewDNSProviderConfig(cfg)
|
||||||
|
case "rfc2136":
|
||||||
|
cfg := rfc2136.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rfc2136.NewDNSProviderConfig(cfg)
|
||||||
|
case "rimuhosting":
|
||||||
|
cfg := rimuhosting.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rimuhosting.NewDNSProviderConfig(cfg)
|
||||||
|
case "route53":
|
||||||
|
cfg := route53.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return route53.NewDNSProviderConfig(cfg)
|
||||||
|
case "safedns":
|
||||||
|
cfg := safedns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return safedns.NewDNSProviderConfig(cfg)
|
||||||
|
case "sakuracloud":
|
||||||
|
cfg := sakuracloud.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return sakuracloud.NewDNSProviderConfig(cfg)
|
||||||
|
case "scaleway":
|
||||||
|
cfg := scaleway.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return scaleway.NewDNSProviderConfig(cfg)
|
||||||
|
case "selectel":
|
||||||
|
cfg := selectel.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return selectel.NewDNSProviderConfig(cfg)
|
||||||
|
case "servercow":
|
||||||
|
cfg := servercow.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return servercow.NewDNSProviderConfig(cfg)
|
||||||
|
case "shellrent":
|
||||||
|
cfg := shellrent.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return shellrent.NewDNSProviderConfig(cfg)
|
||||||
|
case "simply":
|
||||||
|
cfg := simply.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return simply.NewDNSProviderConfig(cfg)
|
||||||
|
case "sonic":
|
||||||
|
cfg := sonic.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return sonic.NewDNSProviderConfig(cfg)
|
||||||
|
case "stackpath":
|
||||||
|
cfg := stackpath.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return stackpath.NewDNSProviderConfig(cfg)
|
||||||
|
case "tencentcloud":
|
||||||
|
cfg := tencentcloud.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return tencentcloud.NewDNSProviderConfig(cfg)
|
||||||
|
case "transip":
|
||||||
|
cfg := transip.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return transip.NewDNSProviderConfig(cfg)
|
||||||
|
case "ultradns":
|
||||||
|
cfg := ultradns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ultradns.NewDNSProviderConfig(cfg)
|
||||||
|
case "variomedia":
|
||||||
|
cfg := variomedia.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return variomedia.NewDNSProviderConfig(cfg)
|
||||||
|
case "vegadns":
|
||||||
|
cfg := vegadns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return vegadns.NewDNSProviderConfig(cfg)
|
||||||
|
case "vercel":
|
||||||
|
cfg := vercel.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return vercel.NewDNSProviderConfig(cfg)
|
||||||
|
case "versio":
|
||||||
|
cfg := versio.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return versio.NewDNSProviderConfig(cfg)
|
||||||
|
case "vinyldns":
|
||||||
|
cfg := vinyldns.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return vinyldns.NewDNSProviderConfig(cfg)
|
||||||
|
case "vkcloud":
|
||||||
|
cfg := vkcloud.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return vkcloud.NewDNSProviderConfig(cfg)
|
||||||
|
case "vscale":
|
||||||
|
cfg := vscale.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return vscale.NewDNSProviderConfig(cfg)
|
||||||
|
case "vultr":
|
||||||
|
cfg := vultr.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return vultr.NewDNSProviderConfig(cfg)
|
||||||
|
case "webnames":
|
||||||
|
cfg := webnames.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return webnames.NewDNSProviderConfig(cfg)
|
||||||
|
case "websupport":
|
||||||
|
cfg := websupport.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return websupport.NewDNSProviderConfig(cfg)
|
||||||
|
case "wedos":
|
||||||
|
cfg := wedos.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return wedos.NewDNSProviderConfig(cfg)
|
||||||
|
case "yandex":
|
||||||
|
cfg := yandex.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return yandex.NewDNSProviderConfig(cfg)
|
||||||
|
case "yandex360":
|
||||||
|
cfg := yandex360.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return yandex360.NewDNSProviderConfig(cfg)
|
||||||
|
case "yandexcloud":
|
||||||
|
cfg := yandexcloud.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return yandexcloud.NewDNSProviderConfig(cfg)
|
||||||
|
case "zoneee":
|
||||||
|
cfg := zoneee.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return zoneee.NewDNSProviderConfig(cfg)
|
||||||
|
case "zonomi":
|
||||||
|
cfg := zonomi.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return zonomi.NewDNSProviderConfig(cfg)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unrecognized DNS provider: %s", name)
|
||||||
|
}
|
||||||
|
}
|
3493
tools/dns_challenge_update/code-gen/acmedns/providers.json
Normal file
3493
tools/dns_challenge_update/code-gen/acmedns/providers.json
Normal file
File diff suppressed because it is too large
Load Diff
289
tools/dns_challenge_update/code-gen/extract.go
Normal file
289
tools/dns_challenge_update/code-gen/extract.go
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Usage
|
||||||
|
|
||||||
|
git clone {repo_link_for_lego}
|
||||||
|
go run extract.go
|
||||||
|
//go run extract.go -- "win7"
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
var legoProvidersSourceFolder string = "./lego/providers/dns/"
|
||||||
|
var outputDir string = "./acmedns"
|
||||||
|
var defTemplate string = `package acmedns
|
||||||
|
/*
|
||||||
|
THIS MODULE IS GENERATED AUTOMATICALLY
|
||||||
|
DO NOT EDIT THIS FILE
|
||||||
|
*/
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-acme/lego/v4/challenge"
|
||||||
|
{{imports}}
|
||||||
|
)
|
||||||
|
|
||||||
|
//name is the DNS provider name, e.g. cloudflare or gandi
|
||||||
|
//JSON (js) must be in key-value string that match ConfigableFields Title in providers.json, e.g. {"Username":"far","Password":"boo"}
|
||||||
|
func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, error){
|
||||||
|
switch name {
|
||||||
|
{{magic}}
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unrecognized DNS provider: %s", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
type Field struct {
|
||||||
|
Title string
|
||||||
|
Datatype string
|
||||||
|
}
|
||||||
|
type ProviderInfo struct {
|
||||||
|
Name string //Name of this provider
|
||||||
|
ConfigableFields []*Field //Field that shd be expose to user for filling in
|
||||||
|
HiddenFields []*Field //Fields that is usable but shd be hidden from user
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileExists(filePath string) bool {
|
||||||
|
_, err := os.Stat(filePath)
|
||||||
|
if err == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// For other errors, you may handle them differently
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function define the DNS not supported by zoraxy
|
||||||
|
func getExcludedDNSProviders() []string {
|
||||||
|
return []string{
|
||||||
|
"edgedns", //Too complex data structure
|
||||||
|
"exec", //Not a DNS provider
|
||||||
|
"httpreq", //Not a DNS provider
|
||||||
|
"hurricane", //Multi-credentials arch
|
||||||
|
"oraclecloud", //Evil company
|
||||||
|
"acmedns", //Not a DNS provider
|
||||||
|
"selectelv2", //Not sure why not working with our code generator
|
||||||
|
"designate", //OpenStack, if you are using this you shd not be using zoraxy
|
||||||
|
"mythicbeasts", //Module require url.URL, which cannot be automatically parsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exclude list for Windows build, due to limitations for lego versions
|
||||||
|
func getExcludedDNSProvidersNT61() []string {
|
||||||
|
return []string{
|
||||||
|
"edgedns", //Too complex data structure
|
||||||
|
"exec", //Not a DNS provider
|
||||||
|
"httpreq", //Not a DNS provider
|
||||||
|
"hurricane", //Multi-credentials arch
|
||||||
|
"oraclecloud", //Evil company
|
||||||
|
"acmedns", //Not a DNS provider
|
||||||
|
"selectelv2", //Not sure why not working with our code generator
|
||||||
|
"designate", //OpenStack, if you are using this you shd not be using zoraxy
|
||||||
|
"mythicbeasts", //Module require url.URL, which cannot be automatically parsed
|
||||||
|
|
||||||
|
//The following suppliers was not in lego v1.15 (Windows 7 last supported version of lego)
|
||||||
|
"cpanel",
|
||||||
|
"mailinabox",
|
||||||
|
"shellrent",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isInSlice(str string, slice []string) bool {
|
||||||
|
for _, s := range slice {
|
||||||
|
if s == str {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isExcludedDNSProvider(providerName string) bool {
|
||||||
|
return isInSlice(providerName, getExcludedDNSProviders())
|
||||||
|
}
|
||||||
|
|
||||||
|
func isExcludedDNSProviderNT61(providerName string) bool {
|
||||||
|
return isInSlice(providerName, getExcludedDNSProvidersNT61())
|
||||||
|
}
|
||||||
|
|
||||||
|
// extractConfigStruct extracts the name of the config struct and its content as plain text from a given source code.
|
||||||
|
func extractConfigStruct(sourceCode string) (string, string) {
|
||||||
|
// Regular expression to match the struct declaration.
|
||||||
|
structRegex := regexp.MustCompile(`type\s+([A-Za-z0-9_]+)\s+struct\s*{([^{}]*)}`)
|
||||||
|
|
||||||
|
// Find the first match of the struct declaration.
|
||||||
|
match := structRegex.FindStringSubmatch(sourceCode)
|
||||||
|
if len(match) < 3 {
|
||||||
|
return "", "" // No match found
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the struct name and its content.
|
||||||
|
structName := match[1]
|
||||||
|
structContent := match[2]
|
||||||
|
|
||||||
|
return structName, structContent
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// A map of provider name to information on what can be filled
|
||||||
|
extractedProviderList := map[string]*ProviderInfo{}
|
||||||
|
buildForWindowsSeven := (len(os.Args) > 2 && os.Args[2] == "win7")
|
||||||
|
|
||||||
|
//Search all providers
|
||||||
|
providers, err := filepath.Glob(filepath.Join(legoProvidersSourceFolder, "/*"))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create output folder if not exists
|
||||||
|
err = os.MkdirAll(outputDir, 0775)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
generatedConvertcode := ""
|
||||||
|
importList := ""
|
||||||
|
for _, provider := range providers {
|
||||||
|
providerName := filepath.Base(provider)
|
||||||
|
|
||||||
|
if buildForWindowsSeven {
|
||||||
|
if isExcludedDNSProviderNT61(providerName) {
|
||||||
|
//Ignore this provider
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if isExcludedDNSProvider(providerName) {
|
||||||
|
//Ignore this provider
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if {provider_name}.go exists
|
||||||
|
providerDef := filepath.Join(provider, providerName+".go")
|
||||||
|
if !fileExists(providerDef) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Extracting config structure for: " + providerDef)
|
||||||
|
providerSrc, err := os.ReadFile(providerDef)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, strctContent := extractConfigStruct(string(providerSrc))
|
||||||
|
|
||||||
|
//Filter and write the content to json
|
||||||
|
/*
|
||||||
|
Example of stctContent (Note the tab prefix)
|
||||||
|
|
||||||
|
Token string
|
||||||
|
PropagationTimeout time.Duration
|
||||||
|
PollingInterval time.Duration
|
||||||
|
SequenceInterval time.Duration
|
||||||
|
HTTPClient *http.Client
|
||||||
|
*/
|
||||||
|
strctContentLines := strings.Split(strctContent, "\n")
|
||||||
|
configKeys := []*Field{}
|
||||||
|
hiddenKeys := []*Field{}
|
||||||
|
for _, lineDef := range strctContentLines {
|
||||||
|
fields := strings.Fields(lineDef)
|
||||||
|
if len(fields) < 2 || strings.HasPrefix(fields[0], "//") {
|
||||||
|
//Ignore this line
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
//Filter out the fields that is not user-filled
|
||||||
|
switch fields[1] {
|
||||||
|
case "*url.URL":
|
||||||
|
fallthrough
|
||||||
|
case "string":
|
||||||
|
configKeys = append(configKeys, &Field{
|
||||||
|
Title: fields[0],
|
||||||
|
Datatype: fields[1],
|
||||||
|
})
|
||||||
|
case "int":
|
||||||
|
if fields[0] != "TTL" {
|
||||||
|
configKeys = append(configKeys, &Field{
|
||||||
|
Title: fields[0],
|
||||||
|
Datatype: fields[1],
|
||||||
|
})
|
||||||
|
} else if fields[0] == "TTL" {
|
||||||
|
//haveTTLField = true
|
||||||
|
} else {
|
||||||
|
hiddenKeys = append(hiddenKeys, &Field{
|
||||||
|
Title: fields[0],
|
||||||
|
Datatype: fields[1],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
case "bool":
|
||||||
|
if fields[0] == "InsecureSkipVerify" || fields[0] == "SSLVerify" || fields[0] == "Debug" {
|
||||||
|
configKeys = append(configKeys, &Field{
|
||||||
|
Title: fields[0],
|
||||||
|
Datatype: fields[1],
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
hiddenKeys = append(hiddenKeys, &Field{
|
||||||
|
Title: fields[0],
|
||||||
|
Datatype: fields[1],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
//Not used fields
|
||||||
|
hiddenKeys = append(hiddenKeys, &Field{
|
||||||
|
Title: fields[0],
|
||||||
|
Datatype: fields[1],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println(strctContent)
|
||||||
|
|
||||||
|
extractedProviderList[providerName] = &ProviderInfo{
|
||||||
|
Name: providerName,
|
||||||
|
ConfigableFields: configKeys,
|
||||||
|
HiddenFields: hiddenKeys,
|
||||||
|
}
|
||||||
|
|
||||||
|
//Generate the code for converting incoming json into target config
|
||||||
|
codeSegment := `
|
||||||
|
case "` + providerName + `":
|
||||||
|
cfg := ` + providerName + `.NewDefaultConfig()
|
||||||
|
err := json.Unmarshal([]byte(js), &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ` + providerName + `.NewDNSProviderConfig(cfg)`
|
||||||
|
|
||||||
|
generatedConvertcode += codeSegment
|
||||||
|
importList += ` "github.com/go-acme/lego/v4/providers/dns/` + providerName + "\"\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
js, err := json.MarshalIndent(extractedProviderList, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fullCodeSnippet := strings.ReplaceAll(defTemplate, "{{magic}}", generatedConvertcode)
|
||||||
|
fullCodeSnippet = strings.ReplaceAll(fullCodeSnippet, "{{imports}}", importList)
|
||||||
|
|
||||||
|
outJsonFilename := "providers.json"
|
||||||
|
outGoFilename := "acmedns.go"
|
||||||
|
if buildForWindowsSeven {
|
||||||
|
outJsonFilename = "providers_nt61.json"
|
||||||
|
outGoFilename = "acmedns_nt61.go"
|
||||||
|
}
|
||||||
|
os.WriteFile(filepath.Join(outputDir, outJsonFilename), js, 0775)
|
||||||
|
os.WriteFile(filepath.Join(outputDir, outGoFilename), []byte(fullCodeSnippet), 0775)
|
||||||
|
fmt.Println("Output written to file")
|
||||||
|
}
|
27
tools/dns_challenge_update/code-gen/update.sh
Normal file
27
tools/dns_challenge_update/code-gen/update.sh
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#/bin/bash
|
||||||
|
|
||||||
|
repo_url="https://github.com/go-acme/lego"
|
||||||
|
|
||||||
|
# Check if the folder "./lego" exists
|
||||||
|
if [ -d "./lego" ]; then
|
||||||
|
# If the folder exists, change into it and perform a git pull
|
||||||
|
echo "Folder './lego' exists. Pulling updates..."
|
||||||
|
cd "./lego" || exit
|
||||||
|
git pull
|
||||||
|
cd ../
|
||||||
|
else
|
||||||
|
# If the folder doesn't exist, clone the repository
|
||||||
|
echo "Folder './lego' does not exist. Cloning the repository..."
|
||||||
|
git clone "$repo_url" "./lego" || exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run the extract.go to get all the config from lego source code
|
||||||
|
echo "Generating code"
|
||||||
|
go run ./extract.go
|
||||||
|
go run ./extract.go -- "win7"
|
||||||
|
|
||||||
|
echo "Cleaning up lego"
|
||||||
|
# Comment the line below if you dont want to pull everytime update
|
||||||
|
# This is to help go compiler to not load all the lego source file when compile
|
||||||
|
#rm -rf ./lego/
|
||||||
|
echo "Config generated"
|
45
tools/dns_challenge_update/providers-scraper-util.js
Normal file
45
tools/dns_challenge_update/providers-scraper-util.js
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// This script is used to scrape the DNS providers from the https://go-acme.github.io/lego/dns/ website
|
||||||
|
// It will fetch the DNS providers and their respective codes and store them in a Map object
|
||||||
|
// You can copy the code into the browser console and run it to get the Map object
|
||||||
|
// Dont forget to remove providers that are not supported by the current acme-lego version that is being used
|
||||||
|
|
||||||
|
const providerArray = [];
|
||||||
|
document.querySelectorAll('table a[href^="/lego/dns/"]').forEach((provider) => {
|
||||||
|
fetch(provider.href)
|
||||||
|
.then(function(response) { return response.text() })
|
||||||
|
.then(function(html) {
|
||||||
|
const parser = new DOMParser();
|
||||||
|
const doc = parser.parseFromString(html, "text/html")
|
||||||
|
|
||||||
|
const providerCodes = Array.from(doc.querySelector('table tbody').querySelectorAll('code')).map(code => code.innerHTML);
|
||||||
|
const providerId = provider.href.match(/.*?\/dns\/(.*?)\//)[1];
|
||||||
|
const providerName = provider.innerHTML;
|
||||||
|
providerArray.push({providerId, providerName, providerCodes});
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
console.log('Failed to fetch page '+provider.href+': ', err);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
// After fetching all the providers, sort them by providerName. You have to run this line in the console after the fetch is done
|
||||||
|
|
||||||
|
providerArray.sort((a,b) => a.providerName.localeCompare(b.providerName))
|
||||||
|
|
||||||
|
|
||||||
|
// Create Dropdown items for the providers
|
||||||
|
|
||||||
|
providerDropdownItems = "";
|
||||||
|
providerArray.forEach(provider => {
|
||||||
|
providerDropdownItems += '<div class="item" data-value="'+provider.providerId+'">'+provider.providerName+'</div>\n'
|
||||||
|
})
|
||||||
|
console.log(providerDropdownItems);
|
||||||
|
|
||||||
|
|
||||||
|
// Create Credential prefill for the providers
|
||||||
|
|
||||||
|
switchCasePrefill = "";
|
||||||
|
providerArray.forEach(provider => {
|
||||||
|
providerCodes = provider.providerCodes.reduce((accumulator,value) => accumulator + value + "=\\n","").slice(0, -2);
|
||||||
|
switchCasePrefill += 'case "'+provider.providerId+'":\n\t$("#dnsCredentials").val("'+providerCodes+'");\n\tbreak;\n'
|
||||||
|
})
|
||||||
|
console.log(switchCasePrefill);
|
Reference in New Issue
Block a user