[release] v0.10.0-unstable16

This commit is contained in:
Yann Stepienik 2023-10-02 16:22:18 +01:00
parent a6b96bc42a
commit 9b033696e3
18 changed files with 738 additions and 248 deletions

View file

@ -66,6 +66,18 @@ function connect(file) {
}))
}
function block(nickname, devicename, block) {
return wrap(fetch(`/cosmos/api/constellation/block`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
nickname, devicename, block
}),
}))
}
export {
list,
addDevice,
@ -74,4 +86,5 @@ export {
getLogs,
reset,
connect,
block,
};

View file

@ -27,26 +27,33 @@ import { strengthColor, strengthIndicator } from '../../../utils/password-streng
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons';
export const CosmosInputText = ({ name, style, multiline, type, placeholder, onChange, label, formik }) => {
export const CosmosInputText = ({ name, style, value, errors, multiline, type, placeholder, onChange, label, formik }) => {
return <Grid item xs={12}>
<Stack spacing={1} style={style}>
<InputLabel htmlFor={name}>{label}</InputLabel>
{label && <InputLabel htmlFor={name}>{label}</InputLabel>}
<OutlinedInput
id={name}
type={type ? type : 'text'}
value={formik.values[name]}
value={value || (formik && formik.values[name])}
name={name}
multiline={multiline}
onBlur={formik.handleBlur}
onBlur={(...ar) => {
return formik && formik.handleBlur(...ar);
}}
onChange={(...ar) => {
onChange && onChange(...ar);
return formik.handleChange(...ar);
return formik && formik.handleChange(...ar);
}}
placeholder={placeholder}
fullWidth
error={Boolean(formik.touched[name] && formik.errors[name])}
error={Boolean(formik && formik.touched[name] && formik.errors[name])}
/>
{formik.touched[name] && formik.errors[name] && (
{formik && formik.touched[name] && formik.errors[name] && (
<FormHelperText error id="standard-weight-helper-text-name-login">
{formik.errors[name]}
</FormHelperText>
)}
{errors && (
<FormHelperText error id="standard-weight-helper-text-name-login">
{formik.errors[name]}
</FormHelperText>

View file

@ -0,0 +1,174 @@
import React from "react";
import { useEffect, useState } from "react";
import * as API from "../../api";
import AddDeviceModal from "./addDevice";
import PrettyTableView from "../../components/tableView/prettyTableView";
import { DeleteButton } from "../../components/delete";
import { CloudOutlined, CloudServerOutlined, CompassOutlined, DesktopOutlined, LaptopOutlined, MobileOutlined, TabletOutlined } from "@ant-design/icons";
import IsLoggedIn from "../../isLoggedIn";
import { Alert, Button, CircularProgress, InputLabel, Stack } from "@mui/material";
import { CosmosCheckbox, CosmosFormDivider, CosmosInputText } from "../config/users/formShortcuts";
import MainCard from "../../components/MainCard";
import { Formik } from "formik";
import { LoadingButton } from "@mui/lab";
import ApiModal from "../../components/apiModal";
import { isDomain } from "../../utils/indexs";
import ConfirmModal from "../../components/confirmModal";
import UploadButtons from "../../components/fileUpload";
export const ConstellationDNS = () => {
const [isAdmin, setIsAdmin] = useState(false);
const [config, setConfig] = useState(null);
const refreshConfig = async () => {
let configAsync = await API.config.get();
setConfig(configAsync.data);
setIsAdmin(configAsync.isAdmin);
};
useEffect(() => {
refreshConfig();
}, []);
return <>
<IsLoggedIn />
{(config) ? <>
<Stack spacing={2} style={{maxWidth: "1000px"}}>
<div>
<MainCard title={"Constellation Internal DNS"} content={config.constellationIP}>
<Stack spacing={2}>
<Formik
initialValues={{
Enabled: config.ConstellationConfig.DNS,
Port: config.ConstellationConfig.DNSPort,
Fallback: config.ConstellationConfig.DNSFallback,
DNSBlockBlacklist: config.ConstellationConfig.DNSBlockBlacklist,
DNSAdditionalBlocklists: config.ConstellationConfig.DNSAdditionalBlocklists,
CustomDNSEntries: config.ConstellationConfig.CustomDNSEntries,
}}
onSubmit={(values) => {
let newConfig = { ...config };
newConfig.ConstellationConfig.DNS = values.Enabled;
newConfig.ConstellationConfig.DNSPort = values.Port;
newConfig.ConstellationConfig.DNSFallback = values.Fallback;
newConfig.ConstellationConfig.DNSBlockBlacklist = values.DNSBlockBlacklist;
newConfig.ConstellationConfig.DNSAdditionalBlocklists = values.DNSAdditionalBlocklists;
newConfig.ConstellationConfig.CustomDNSEntries = values.CustomDNSEntries;
return API.config.set(newConfig);
}}
>
{(formik) => (
<form onSubmit={formik.handleSubmit}>
<Stack spacing={2}>
<CosmosCheckbox formik={formik} name="Enabled" label="Constellation DNS Server Enabled" />
<CosmosInputText formik={formik} name="Port" label="DNS Port" />
<CosmosInputText formik={formik} name="Fallback" label="DNS Fallback" placeholder={'8.8.8.8:53'} />
<CosmosFormDivider title={"DNS Blocklists"} />
<CosmosCheckbox formik={formik} name="DNSBlockBlacklist" label="Use Blacklists to block domains" />
<InputLabel>DNS Blocklist URLs</InputLabel>
{formik.values.DNSAdditionalBlocklists.map((item, index) => (
<Stack direction={"row"} spacing={2} key={`DNSAdditionalBlocklists${item}`} width={"100%"}>
<DeleteButton onDelete={() => {
formik.setFieldValue("DNSAdditionalBlocklists", [...formik.values.DNSAdditionalBlocklists.slice(0, index), ...formik.values.DNSAdditionalBlocklists.slice(index + 1)]);
}} />
<div style={{flexGrow: 1}}>
<CosmosInputText
value={item}
name={`DNSAdditionalBlocklists${index}`}
placeholder={'https://example.com/blocklist.txt'}
onChange={(e) => {
formik.setFieldValue("DNSAdditionalBlocklists", [...formik.values.DNSAdditionalBlocklists.slice(0, index), e.target.value, ...formik.values.DNSAdditionalBlocklists.slice(index + 1)]);
}}
/>
</div>
</Stack>
))}
<Stack direction="row" spacing={2}>
<Button variant="outlined" onClick={() => {
formik.setFieldValue("DNSAdditionalBlocklists", [...formik.values.DNSAdditionalBlocklists, ""]);
}}>Add</Button>
<Button variant="outlined" onClick={() => {
formik.setFieldValue("DNSAdditionalBlocklists", [
"https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt",
"https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt",
"https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts",
"https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/fakenews-only/hosts"
]);
}}>Reset Default</Button>
</Stack>
<CosmosFormDivider title={"DNS Custom Entries"} />
<InputLabel>DNS Custom Entries</InputLabel>
{formik.values.CustomDNSEntries.map((item, index) => (
<Stack direction={"row"} spacing={2} key={`CustomDNSEntries${item}`} width={"100%"}>
<DeleteButton onDelete={() => {
formik.setFieldValue("CustomDNSEntries", [...formik.values.CustomDNSEntries.slice(0, index), ...formik.values.CustomDNSEntries.slice(index + 1)]);
}} />
<div style={{flexGrow: 1}}>
<CosmosInputText
value={item.Key}
name={`CustomDNSEntries${index}-key`}
placeholder={'domain.com'}
onChange={(e) => {
const updatedCustomDNSEntries = [...formik.values.CustomDNSEntries];
updatedCustomDNSEntries[index].Key = e.target.value;
formik.setFieldValue("CustomDNSEntries", updatedCustomDNSEntries);
}}
/>
</div>
<div style={{flexGrow: 1}}>
<CosmosInputText
value={item.Value}
name={`CustomDNSEntries${index}-value`}
placeholder={'1213.123.123.123'}
onChange={(e) => {
const updatedCustomDNSEntries = [...formik.values.CustomDNSEntries];
updatedCustomDNSEntries[index].Value = e.target.value;
formik.setFieldValue("CustomDNSEntries", updatedCustomDNSEntries);
}}
/>
</div>
</Stack>
))}
<Stack direction="row" spacing={2}>
<Button variant="outlined" onClick={() => {
formik.setFieldValue("CustomDNSEntries", [...formik.values.CustomDNSEntries, {
Key: "",
Value: "",
Type: "A"
}]);
}}>Add</Button>
<Button variant="outlined" onClick={() => {
formik.setFieldValue("CustomDNSEntries", [
]);
}}>Reset</Button>
</Stack>
<LoadingButton
disableElevation
loading={formik.isSubmitting}
type="submit"
variant="contained"
color="primary"
>
Save
</LoadingButton>
</Stack>
</form>
)}
</Formik>
</Stack>
</MainCard>
</div>
</Stack>
</> : <center>
<CircularProgress color="inherit" size={20} />
</center>}
</>
};

View file

@ -1,199 +1,35 @@
import React from "react";
import { useEffect, useState } from "react";
import * as API from "../../api";
import AddDeviceModal from "./addDevice";
import PrettyTableView from "../../components/tableView/prettyTableView";
import { DeleteButton } from "../../components/delete";
import { CloudOutlined, CloudServerOutlined, CompassOutlined, DesktopOutlined, LaptopOutlined, MobileOutlined, TabletOutlined } from "@ant-design/icons";
import IsLoggedIn from "../../isLoggedIn";
import { Alert, Button, CircularProgress, Stack } from "@mui/material";
import { CosmosCheckbox, CosmosFormDivider, CosmosInputText } from "../config/users/formShortcuts";
import MainCard from "../../components/MainCard";
import { Formik } from "formik";
import { LoadingButton } from "@mui/lab";
import ApiModal from "../../components/apiModal";
import { isDomain } from "../../utils/indexs";
import ConfirmModal from "../../components/confirmModal";
import UploadButtons from "../../components/fileUpload";
import * as React from 'react';
import MainCard from '../../components/MainCard';
import { Chip, Divider, Stack, useMediaQuery } from '@mui/material';
import HostChip from '../../components/hostChip';
import { RouteMode, RouteSecurity } from '../../components/routeComponents';
import { getFaviconURL } from '../../utils/routes';
import * as API from '../../api';
import { CheckOutlined, ClockCircleOutlined, DashboardOutlined, DeleteOutlined, DownOutlined, LockOutlined, UpOutlined } from "@ant-design/icons";
import IsLoggedIn from '../../isLoggedIn';
import PrettyTabbedView from '../../components/tabbedView/tabbedView';
const getDefaultConstellationHostname = (config) => {
// if domain is set, use it
if(isDomain(config.HTTPConfig.Hostname)) {
return "vpn." + config.HTTPConfig.Hostname;
} else {
return config.HTTPConfig.Hostname;
}
import { ConstellationVPN } from './vpn';
import { ConstellationDNS } from './dns';
const ConstellationIndex = () => {
return <div>
<IsLoggedIn />
<PrettyTabbedView path="/cosmos-ui/constellation/:tab" tabs={[
{
title: 'VPN',
children: <ConstellationVPN />,
path: 'vpn'
},
{
title: 'DNS',
children: <ConstellationDNS />,
path: 'dns'
},
]}/>
</div>;
}
export const ConstellationIndex = () => {
const [isAdmin, setIsAdmin] = useState(false);
const [config, setConfig] = useState(null);
const [users, setUsers] = useState(null);
const [devices, setDevices] = useState(null);
const refreshConfig = async () => {
let configAsync = await API.config.get();
setConfig(configAsync.data);
setIsAdmin(configAsync.isAdmin);
setDevices((await API.constellation.list()).data || []);
setUsers((await API.users.list()).data || []);
};
useEffect(() => {
refreshConfig();
}, []);
const getIcon = (r) => {
if (r.deviceName.toLowerCase().includes("mobile") || r.deviceName.toLowerCase().includes("phone")) {
return <MobileOutlined />
}
else if (r.deviceName.toLowerCase().includes("laptop") || r.deviceName.toLowerCase().includes("computer")) {
return <LaptopOutlined />
} else if (r.deviceName.toLowerCase().includes("desktop")) {
return <DesktopOutlined />
} else if (r.deviceName.toLowerCase().includes("tablet")) {
return <TabletOutlined />
} else if (r.deviceName.toLowerCase().includes("lighthouse") || r.deviceName.toLowerCase().includes("server")) {
return <CompassOutlined />
} else {
return <CloudOutlined />
}
}
return <>
<IsLoggedIn />
{(devices && config && users) ? <>
<Stack spacing={2} style={{maxWidth: "1000px"}}>
<div>
<MainCard title={"Constellation Setup"} content={config.constellationIP}>
<Stack spacing={2}>
{config.ConstellationConfig.Enabled && config.ConstellationConfig.SlaveMode && <>
<Alert severity="info">
You are currently connected to an external constellation network. Use your main Cosmos server to manage your constellation network and devices.
</Alert>
</>}
<Formik
initialValues={{
Enabled: config.ConstellationConfig.Enabled,
IsRelay: config.ConstellationConfig.NebulaConfig.Relay.AMRelay,
ConstellationHostname: (config.ConstellationConfig.ConstellationHostname && config.ConstellationConfig.ConstellationHostname != "") ? config.ConstellationConfig.ConstellationHostname :
getDefaultConstellationHostname(config)
}}
onSubmit={(values) => {
let newConfig = { ...config };
newConfig.ConstellationConfig.Enabled = values.Enabled;
newConfig.ConstellationConfig.NebulaConfig.Relay.AMRelay = values.IsRelay;
newConfig.ConstellationConfig.ConstellationHostname = values.ConstellationHostname;
return API.config.set(newConfig);
}}
>
{(formik) => (
<form onSubmit={formik.handleSubmit}>
<Stack spacing={2}>
{formik.values.Enabled && <Stack spacing={2} direction="row">
<Button
disableElevation
variant="outlined"
color="primary"
onClick={async () => {
await API.constellation.restart();
}}
>
Restart VPN Service
</Button>
<ApiModal callback={API.constellation.getLogs} label={"Show VPN logs"} />
<ApiModal callback={API.constellation.getConfig} label={"Show VPN Config"} />
<ConfirmModal
variant="outlined"
color="warning"
label={"Reset Network"}
content={"This will completely reset the network, and disconnect all the clients. You will need to reconnect them. This cannot be undone."}
callback={async () => {
await API.constellation.reset();
refreshConfig();
}}
/>
</Stack>}
<CosmosCheckbox formik={formik} name="Enabled" label="Constellation Enabled" />
{config.ConstellationConfig.Enabled && !config.ConstellationConfig.SlaveMode && <>
{formik.values.Enabled && <>
<CosmosCheckbox formik={formik} name="IsRelay" label="Relay requests via this Node" />
<Alert severity="info">This is your Constellation hostname, that you will use to connect. If you are using a domain name, this needs to be different from your server's hostname. Whatever the domain you choose, it is very important that you make sure there is a A entry in your domain DNS pointing to this server. <strong>If you change this value, you will need to reset your network and reconnect all the clients!</strong></Alert>
<CosmosInputText formik={formik} name="ConstellationHostname" label="Constellation Hostname" />
</>}
</>}
<UploadButtons
accept=".yml,.yaml"
label={"Upload Nebula Config"}
variant="outlined"
fullWidth
OnChange={async (e) => {
let file = e.target.files[0];
await API.constellation.connect(file);
refreshConfig();
}}
/>
<LoadingButton
disableElevation
loading={formik.isSubmitting}
type="submit"
variant="contained"
color="primary"
>
Save
</LoadingButton>
</Stack>
</form>
)}
</Formik>
</Stack>
</MainCard>
</div>
{config.ConstellationConfig.Enabled && !config.ConstellationConfig.SlaveMode && <>
<CosmosFormDivider title={"Devices"} />
<PrettyTableView
data={devices}
getKey={(r) => r.deviceName}
buttons={[
<AddDeviceModal isAdmin={isAdmin} users={users} config={config} refreshConfig={refreshConfig} devices={devices} />,
]}
columns={[
{
title: '',
field: getIcon,
},
{
title: 'Device Name',
field: (r) => <strong>{r.deviceName}</strong>,
},
{
title: 'Owner',
field: (r) => <strong>{r.nickname}</strong>,
},
{
title: 'Type',
field: (r) => <strong>{r.isLighthouse ? "Lighthouse" : "Client"}</strong>,
},
{
title: 'Constellation IP',
screenMin: 'md',
field: (r) => r.ip,
},
{
title: '',
clickable: true,
field: (r) => {
return <DeleteButton onDelete={async () => {
alert("caca")
}}></DeleteButton>
}
}
]}
/>
</>}
</Stack>
</> : <center>
<CircularProgress color="inherit" size={20} />
</center>}
</>
};
export default ConstellationIndex;

View file

@ -0,0 +1,205 @@
import React from "react";
import { useEffect, useState } from "react";
import * as API from "../../api";
import AddDeviceModal from "./addDevice";
import PrettyTableView from "../../components/tableView/prettyTableView";
import { DeleteButton } from "../../components/delete";
import { CloudOutlined, CloudServerOutlined, CompassOutlined, DesktopOutlined, LaptopOutlined, MobileOutlined, TabletOutlined } from "@ant-design/icons";
import IsLoggedIn from "../../isLoggedIn";
import { Alert, Button, CircularProgress, Stack } from "@mui/material";
import { CosmosCheckbox, CosmosFormDivider, CosmosInputText } from "../config/users/formShortcuts";
import MainCard from "../../components/MainCard";
import { Formik } from "formik";
import { LoadingButton } from "@mui/lab";
import ApiModal from "../../components/apiModal";
import { isDomain } from "../../utils/indexs";
import ConfirmModal from "../../components/confirmModal";
import UploadButtons from "../../components/fileUpload";
const getDefaultConstellationHostname = (config) => {
// if domain is set, use it
if(isDomain(config.HTTPConfig.Hostname)) {
return "vpn." + config.HTTPConfig.Hostname;
} else {
return config.HTTPConfig.Hostname;
}
}
export const ConstellationVPN = () => {
const [isAdmin, setIsAdmin] = useState(false);
const [config, setConfig] = useState(null);
const [users, setUsers] = useState(null);
const [devices, setDevices] = useState(null);
const refreshConfig = async () => {
let configAsync = await API.config.get();
setConfig(configAsync.data);
setIsAdmin(configAsync.isAdmin);
setDevices((await API.constellation.list()).data || []);
setUsers((await API.users.list()).data || []);
};
useEffect(() => {
refreshConfig();
}, []);
const getIcon = (r) => {
if (r.deviceName.toLowerCase().includes("mobile") || r.deviceName.toLowerCase().includes("phone")) {
return <MobileOutlined />
}
else if (r.deviceName.toLowerCase().includes("laptop") || r.deviceName.toLowerCase().includes("computer")) {
return <LaptopOutlined />
} else if (r.deviceName.toLowerCase().includes("desktop")) {
return <DesktopOutlined />
} else if (r.deviceName.toLowerCase().includes("tablet")) {
return <TabletOutlined />
} else if (r.deviceName.toLowerCase().includes("lighthouse") || r.deviceName.toLowerCase().includes("server")) {
return <CompassOutlined />
} else {
return <CloudOutlined />
}
}
return <>
<IsLoggedIn />
{(devices && config && users) ? <>
<Stack spacing={2} style={{maxWidth: "1000px"}}>
<div>
<MainCard title={"Constellation Setup"} content={config.constellationIP}>
<Stack spacing={2}>
{config.ConstellationConfig.Enabled && config.ConstellationConfig.SlaveMode && <>
<Alert severity="info">
You are currently connected to an external constellation network. Use your main Cosmos server to manage your constellation network and devices.
</Alert>
</>}
<Formik
initialValues={{
Enabled: config.ConstellationConfig.Enabled,
PrivateNode: config.ConstellationConfig.PrivateNode,
IsRelay: config.ConstellationConfig.NebulaConfig.Relay.AMRelay,
ConstellationHostname: (config.ConstellationConfig.ConstellationHostname && config.ConstellationConfig.ConstellationHostname != "") ? config.ConstellationConfig.ConstellationHostname :
getDefaultConstellationHostname(config)
}}
onSubmit={(values) => {
let newConfig = { ...config };
newConfig.ConstellationConfig.Enabled = values.Enabled;
newConfig.ConstellationConfig.PrivateNode = values.PrivateNode;
newConfig.ConstellationConfig.NebulaConfig.Relay.AMRelay = values.IsRelay;
newConfig.ConstellationConfig.ConstellationHostname = values.ConstellationHostname;
return API.config.set(newConfig);
}}
>
{(formik) => (
<form onSubmit={formik.handleSubmit}>
<Stack spacing={2}>
{formik.values.Enabled && <Stack spacing={2} direction="row">
<Button
disableElevation
variant="outlined"
color="primary"
onClick={async () => {
await API.constellation.restart();
}}
>
Restart VPN Service
</Button>
<ApiModal callback={API.constellation.getLogs} label={"Show VPN logs"} />
<ApiModal callback={API.constellation.getConfig} label={"Show VPN Config"} />
<ConfirmModal
variant="outlined"
color="warning"
label={"Reset Network"}
content={"This will completely reset the network, and disconnect all the clients. You will need to reconnect them. This cannot be undone."}
callback={async () => {
await API.constellation.reset();
refreshConfig();
}}
/>
</Stack>}
<CosmosCheckbox formik={formik} name="Enabled" label="Constellation Enabled" />
{config.ConstellationConfig.Enabled && !config.ConstellationConfig.SlaveMode && <>
{formik.values.Enabled && <>
<CosmosCheckbox formik={formik} name="IsRelay" label="Relay requests via this Node" />
<CosmosCheckbox formik={formik} name="PrivateNode" label="This node is Private (no public IP)" />
{!formik.values.PrivateNode && <>
<Alert severity="info">This is your Constellation hostname, that you will use to connect. If you are using a domain name, this needs to be different from your server's hostname. Whatever the domain you choose, it is very important that you make sure there is a A entry in your domain DNS pointing to this server. <strong>If you change this value, you will need to reset your network and reconnect all the clients!</strong></Alert>
<CosmosInputText formik={formik} name="ConstellationHostname" label="Constellation Hostname" />
</>}
</>}
</>}
<LoadingButton
disableElevation
loading={formik.isSubmitting}
type="submit"
variant="contained"
color="primary"
>
Save
</LoadingButton>
<UploadButtons
accept=".yml,.yaml"
label={"Upload External Constellation Network File"}
variant="outlined"
fullWidth
OnChange={async (e) => {
let file = e.target.files[0];
await API.constellation.connect(file);
refreshConfig();
}}
/>
</Stack>
</form>
)}
</Formik>
</Stack>
</MainCard>
</div>
{config.ConstellationConfig.Enabled && !config.ConstellationConfig.SlaveMode && <>
<CosmosFormDivider title={"Devices"} />
<PrettyTableView
data={devices.filter((d) => !d.blocked)}
getKey={(r) => r.deviceName}
buttons={[
<AddDeviceModal isAdmin={isAdmin} users={users} config={config} refreshConfig={refreshConfig} devices={devices} />,
]}
columns={[
{
title: '',
field: getIcon,
},
{
title: 'Device Name',
field: (r) => <strong>{r.deviceName}</strong>,
},
{
title: 'Owner',
field: (r) => <strong>{r.nickname}</strong>,
},
{
title: 'Type',
field: (r) => <strong>{r.isLighthouse ? "Lighthouse" : "Client"}</strong>,
},
{
title: 'Constellation IP',
screenMin: 'md',
field: (r) => r.ip,
},
{
title: '',
clickable: true,
field: (r) => {
return <DeleteButton onDelete={async () => {
await API.constellation.block(r.nickname, r.deviceName, true);
refreshConfig();
}}></DeleteButton>
}
}
]}
/>
</>}
</Stack>
</> : <center>
<CircularProgress color="inherit" size={20} />
</center>}
</>
};

View file

@ -15,7 +15,7 @@ import ContainerIndex from '../pages/servapps/containers';
import NewDockerServiceForm from '../pages/servapps/containers/newServiceForm';
import OpenIdList from '../pages/openid/openid-list';
import MarketPage from '../pages/market/listing';
import { ConstellationIndex } from '../pages/constellation';
import ConstellationIndex from '../pages/constellation';
// render - dashboard

27
go.mod
View file

@ -8,7 +8,7 @@ require (
github.com/docker/docker v23.0.3+incompatible
github.com/docker/go-connections v0.4.0
github.com/foomo/tlsconfig v0.0.0-20180418120404-b67861b076c9
github.com/go-acme/lego/v4 v4.13.3
github.com/go-acme/lego/v4 v4.14.2
github.com/go-chi/chi v4.0.2+incompatible
github.com/go-chi/httprate v0.7.1
github.com/go-playground/validator/v10 v10.14.0
@ -16,7 +16,9 @@ require (
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0
github.com/jasonlvhit/gocron v0.0.1
github.com/miekg/dns v1.1.55
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/ory/fosite v0.44.0
github.com/oschwald/geoip2-golang v1.8.0
github.com/pquerna/otp v1.4.0
@ -27,6 +29,7 @@ require (
golang.org/x/crypto v0.10.0
golang.org/x/net v0.11.0
golang.org/x/sys v0.9.0
gopkg.in/yaml.v2 v2.4.0
)
require (
@ -57,7 +60,20 @@ require (
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
github.com/andybalholm/cascadia v1.1.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
github.com/aws/aws-sdk-go v1.39.0 // indirect
github.com/aws/aws-sdk-go-v2 v1.19.0 // indirect
github.com/aws/aws-sdk-go-v2/config v1.18.28 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.13.27 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 // indirect
github.com/aws/aws-sdk-go-v2/service/lightsail v1.27.2 // indirect
github.com/aws/aws-sdk-go-v2/service/route53 v1.28.4 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.19.3 // indirect
github.com/aws/smithy-go v1.13.5 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
@ -126,7 +142,6 @@ require (
github.com/magiconair/properties v1.8.4 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/goveralls v0.0.6 // indirect
github.com/miekg/dns v1.1.55 // 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
@ -137,6 +152,7 @@ require (
github.com/montanaflynn/stats v0.7.0 // 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
@ -153,7 +169,7 @@ require (
github.com/ory/viper v1.7.5 // indirect
github.com/ory/x v0.0.214 // indirect
github.com/oschwald/maxminddb-golang v1.10.0 // indirect
github.com/ovh/go-ovh v1.4.1 // indirect
github.com/ovh/go-ovh v1.4.2 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pborman/uuid v1.2.0 // indirect
github.com/pelletier/go-toml v1.8.1 // indirect
@ -167,7 +183,6 @@ require (
github.com/sacloud/packages-go v0.0.9 // indirect
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.17 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/simplesurance/bunny-go v0.0.0-20221115111006-e11d9dc91f04 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect
github.com/softlayer/softlayer-go v1.1.2 // indirect
@ -210,9 +225,9 @@ require (
google.golang.org/grpc v1.53.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/ns1/ns1-go.v2 v2.7.6 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.4.0 // indirect
)

48
go.sum
View file

@ -60,6 +60,7 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp
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/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/DataDog/datadog-go v4.0.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
@ -107,9 +108,35 @@ github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/aws/aws-sdk-go v1.23.19/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
github.com/aws/aws-sdk-go v1.39.0 h1:74BBwkEmiqBbi2CGflEh34l0YNtIibTjZsibGarkNjo=
github.com/aws/aws-sdk-go v1.39.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go-v2 v1.19.0 h1:klAT+y3pGFBU/qVf1uzwttpBbiuozJYWzNLHioyDJ+k=
github.com/aws/aws-sdk-go-v2 v1.19.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
github.com/aws/aws-sdk-go-v2/config v1.18.28 h1:TINEaKyh1Td64tqFvn09iYpKiWjmHYrG1fa91q2gnqw=
github.com/aws/aws-sdk-go-v2/config v1.18.28/go.mod h1:nIL+4/8JdAuNHEjn/gPEXqtnS02Q3NXB/9Z7o5xE4+A=
github.com/aws/aws-sdk-go-v2/credentials v1.13.27 h1:dz0yr/yR1jweAnsCx+BmjerUILVPQ6FS5AwF/OyG1kA=
github.com/aws/aws-sdk-go-v2/credentials v1.13.27/go.mod h1:syOqAek45ZXZp29HlnRS/BNgMIW6uiRmeuQsz4Qh2UE=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 h1:kP3Me6Fy3vdi+9uHd7YLr6ewPxRL+PU6y15urfTaamU=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5/go.mod h1:Gj7tm95r+QsDoN2Fhuz/3npQvcZbkEf5mL70n3Xfluc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 h1:hMUCiE3Zi5AHrRNGf5j985u0WyqI6r2NULhUfo0N/No=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35/go.mod h1:ipR5PvpSPqIqL5Mi82BxLnfMkHVbmco8kUwO2xrCi0M=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 h1:yOpYx+FTBdpk/g+sBU6Cb1H0U/TLEcYYp66mYqsPpcc=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29/go.mod h1:M/eUABlDbw2uVrdAn+UsI6M727qp2fxkp8K0ejcBDUY=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 h1:8r5m1BoAWkn0TDC34lUculryf7nUF25EgIMdjvGCkgo=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36/go.mod h1:Rmw2M1hMVTwiUhjwMoIBFWFJMhvJbct06sSidxInkhY=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 h1:IiDolu/eLmuB18DRZibj77n1hHQT7z12jnGO7Ze3pLc=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29/go.mod h1:fDbkK4o7fpPXWn8YAPmTieAMuB9mk/VgvW64uaUqxd4=
github.com/aws/aws-sdk-go-v2/service/lightsail v1.27.2 h1:PwNeYoonBzmTdCztKiiutws3U24KrnDBuabzRfIlZY4=
github.com/aws/aws-sdk-go-v2/service/lightsail v1.27.2/go.mod h1:gQhLZrTEath4zik5ixIe6axvgY5jJrgSBDJ360Fxnco=
github.com/aws/aws-sdk-go-v2/service/route53 v1.28.4 h1:p4mTxJfCAyiTT4Wp6p/mOPa6j5MqCSRGot8qZwFs+Z0=
github.com/aws/aws-sdk-go-v2/service/route53 v1.28.4/go.mod h1:VBLWpaHvhQNeu7N9rMEf00SWeOONb/HvaDUxe/7b44k=
github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 h1:sWDv7cMITPcZ21QdreULwxOOAmE05JjEsT6fCDtDA9k=
github.com/aws/aws-sdk-go-v2/service/sso v1.12.13/go.mod h1:DfX0sWuT46KpcqbMhJ9QWtxAIP1VozkDWf8VAkByjYY=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 h1:BFubHS/xN5bjl818QaroN6mQdjneYQ+AOx44KNXlyH4=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13/go.mod h1:BzqsVVFduubEmzrVtUFQQIQdFqvUItF8XUq2EnS8Wog=
github.com/aws/aws-sdk-go-v2/service/sts v1.19.3 h1:e5mnydVdCVWxP+5rPAGi2PYxC7u2OZgH1ypC114H04U=
github.com/aws/aws-sdk-go-v2/service/sts v1.19.3/go.mod h1:yVGZA1CPkmUhBdA039jXNJJG7/6t+G+EBWmFq23xqnY=
github.com/aws/aws-xray-sdk-go v0.9.4/go.mod h1:XtMKdBQfpVut+tJEwI7+dJFRxxRdxHDyVNp2tHXRq04=
github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8=
github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
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=
@ -259,8 +286,8 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm
github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/go-acme/lego/v4 v4.13.3 h1:aZ1S9FXIkCWG3Uw/rZKSD+MOuO8ZB1t6p9VCg6jJiNY=
github.com/go-acme/lego/v4 v4.13.3/go.mod h1:c/iodVGMeBXG/+KiQczoNkySo3YLWTVa0kiyeVd/FHc=
github.com/go-acme/lego/v4 v4.14.2 h1:/D/jqRgLi8Cbk33sLGtu2pX2jEg3bGJWHyV8kFuUHGM=
github.com/go-acme/lego/v4 v4.14.2/go.mod h1:kBXxbeTg0x9AgaOYjPSwIeJy3Y33zTz+tMD16O4MO6c=
github.com/go-bindata/go-bindata v3.1.1+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo=
github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs=
github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
@ -672,6 +699,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/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.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
@ -1024,11 +1052,15 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
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/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q=
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=
@ -1124,8 +1156,8 @@ github.com/oschwald/geoip2-golang v1.8.0 h1:KfjYB8ojCEn/QLqsDU0AzrJ3R5Qa9vFlx3z6
github.com/oschwald/geoip2-golang v1.8.0/go.mod h1:R7bRvYjOeaoenAp9sKRS8GX5bJWcZ0laWO5+DauEktw=
github.com/oschwald/maxminddb-golang v1.10.0 h1:Xp1u0ZhqkSuopaKmk1WwHtjF0H9Hd9181uj2MQ5Vndg=
github.com/oschwald/maxminddb-golang v1.10.0/go.mod h1:Y2ELenReaLAZ0b400URyGwvYxHV1dLIxBuyOsyYjHK0=
github.com/ovh/go-ovh v1.4.1 h1:VBGa5wMyQtTP7Zb+w97zRCh9sLtM/2YKRyy+MEJmWaM=
github.com/ovh/go-ovh v1.4.1/go.mod h1:6bL6pPyUT7tBfI0pqOegJgRjgjuO+mOo+MyXd1EEC0M=
github.com/ovh/go-ovh v1.4.2 h1:ub4jVK6ERbiBTo4y5wbLCjeKCjGY+K36e7BviW+MaAU=
github.com/ovh/go-ovh v1.4.2/go.mod h1:AkPXVtgwB6xlKblMjRKJJmjRp+ogrE7fz2lVgcQY8SY=
github.com/parnurzeal/gorequest v0.2.15/go.mod h1:3Kh2QUMJoqw3icWAecsyzkpY7UzRfDhbRdTjtNwNiUE=
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=
@ -1241,8 +1273,6 @@ github.com/shurcooL/highlight_go v0.0.0-20170515013102-78fb10f4a5f8/go.mod h1:UD
github.com/shurcooL/octicon v0.0.0-20180602230221-c42b0e3b24d9/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/simplesurance/bunny-go v0.0.0-20221115111006-e11d9dc91f04 h1:ZTzdx88+AcnjqUfJwnz89UBrMSBQ1NEysg9u5d+dU9c=
github.com/simplesurance/bunny-go v0.0.0-20221115111006-e11d9dc91f04/go.mod h1:5KS21fpch8TIMyAUv/qQqTa3GZfBDYgjaZbd2KXKYfg=
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.1.0/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A=
@ -1877,6 +1907,8 @@ 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/mail.v2 v2.0.0-20180731213649-a0242b2233b4/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/ns1/ns1-go.v2 v2.7.6 h1:mCPl7q0jbIGACXvGBljAuuApmKZo3rRi4tlRIEbMvjA=
gopkg.in/ns1/ns1-go.v2 v2.7.6/go.mod h1:GMnKY+ZuoJ+lVLL+78uSTjwTz2jMazq6AfGKQOYhsPk=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=

View file

@ -1,6 +1,6 @@
{
"name": "cosmos-server",
"version": "0.10.0-unstable15",
"version": "0.10.0-unstable16",
"description": "",
"main": "test-server.js",
"bugs": {

View file

@ -8,7 +8,7 @@
<a href="https://github.com/soldier1"><img src="https://avatars.githubusercontent.com/soldier1" style="border-radius:48px" width="48" height="48" alt="null" title="null" /></a>
<a href="https://github.com/devcircus"><img src="https://avatars.githubusercontent.com/devcircus" style="border-radius:48px" width="48" height="48" alt="Clayton Stone" title="Clayton Stone" /></a>
<a href="https://github.com/BlackrazorNZ"><img src="https://avatars.githubusercontent.com/BlackrazorNZ" style="border-radius:48px" width="48" height="48" alt="null" title="null" /></a>
<a href="https://github.com/bleibdirtroy"><img src="https://avatars.githubusercontent.com/bleibdirtroy" style="border-radius:48px" width="48" height="48" alt="Adrian Germeck" title="Adrian Germeck" /></a>
<a href="https://github.com/bleibdirtroy"><img src="https://avatars.githubusercontent.com/bleibdirtroy" style="border-radius:48px" width="48" height="48" alt="Adrian" title="Adrian" /></a>
</p><!-- /sponsors -->
---

View file

@ -46,7 +46,10 @@ func handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
// Overwrite local hostnames with custom entries
for _, q := range r.Question {
for hostname, ip := range customDNSEntries {
for _, entry := range customDNSEntries {
hostname := entry.Key
ip := entry.Value
if strings.HasSuffix(q.Name, hostname + ".") && q.Qtype == dns.TypeA {
utils.Debug("DNS Overwrite " + hostname + " with " + ip)
rr, _ := dns.NewRR(q.Name + " A " + ip)

View file

@ -0,0 +1,99 @@
package constellation
import (
"net/http"
"encoding/json"
"github.com/azukaar/cosmos-server/src/utils"
)
type DeviceBlockRequestJSON struct {
Nickname string `json:"nickname",validate:"required,min=3,max=32,alphanum"`
DeviceName string `json:"deviceName",validate:"required,min=3,max=32,alphanum"`
Block bool `json:"block",omitempty`
}
func DeviceBlock(w http.ResponseWriter, req *http.Request) {
if(req.Method == "POST") {
var request DeviceBlockRequestJSON
err1 := json.NewDecoder(req.Body).Decode(&request)
if err1 != nil {
utils.Error("ConstellationDeviceBlocking: Invalid User Request", err1)
utils.HTTPError(w, "Device Creation Error",
http.StatusInternalServerError, "DB001")
return
}
errV := utils.Validate.Struct(request)
if errV != nil {
utils.Error("DeviceBlocking: Invalid User Request", errV)
utils.HTTPError(w, "Device Creation Error: " + errV.Error(),
http.StatusInternalServerError, "DB002")
return
}
nickname := utils.Sanitize(request.Nickname)
deviceName := utils.Sanitize(request.DeviceName)
if utils.AdminOrItselfOnly(w, req, nickname) != nil {
return
}
c, errCo := utils.GetCollection(utils.GetRootAppId(), "devices")
if errCo != nil {
utils.Error("Database Connect", errCo)
utils.HTTPError(w, "Database", http.StatusInternalServerError, "DB001")
return
}
device := utils.Device{}
utils.Debug("ConstellationDeviceBlocking: Blocking Device " + deviceName)
err2 := c.FindOne(nil, map[string]interface{}{
"DeviceName": deviceName,
"Nickname": nickname,
"Blocked": false,
}).Decode(&device)
if err2 == nil {
utils.Debug("ConstellationDeviceBlocking: Found Device " + deviceName)
_, err3 := c.UpdateOne(nil, map[string]interface{}{
"DeviceName": deviceName,
"Nickname": nickname,
}, map[string]interface{}{
"$set": map[string]interface{}{
"Blocked": request.Block,
},
})
if err3 != nil {
utils.Error("DeviceBlocking: Error while updating device", err3)
utils.HTTPError(w, "Device Creation Error: " + err3.Error(),
http.StatusInternalServerError, "DB001")
return
}
if request.Block {
utils.Log("ConstellationDeviceBlocking: Device " + deviceName + " blocked")
} else {
utils.Log("ConstellationDeviceBlocking: Device " + deviceName + " unblocked")
}
} else {
utils.Error("DeviceBlocking: Error while finding device", err2)
utils.HTTPError(w, "Device Creation Error: " + err2.Error(),
http.StatusInternalServerError, "DB001")
return
}
json.NewEncoder(w).Encode(map[string]interface{}{
"status": "OK",
})
} else {
utils.Error("DeviceBlocking: Method not allowed" + req.Method, nil)
utils.HTTPError(w, "Method not allowed", http.StatusMethodNotAllowed, "HTTP001")
return
}
}

View file

@ -4,7 +4,7 @@ import (
"net/http"
"encoding/json"
"go.mongodb.org/mongo-driver/mongo"
"github.com/azukaar/cosmos-server/src/utils"
)
@ -62,11 +62,12 @@ func DeviceCreate(w http.ResponseWriter, req *http.Request) {
err2 := c.FindOne(nil, map[string]interface{}{
"DeviceName": deviceName,
"Blocked": false,
}).Decode(&device)
if err2 == mongo.ErrNoDocuments {
cert, key, err := generateNebulaCert(deviceName, request.IP, request.PublicKey, false)
cert, key, fingerprint, err := generateNebulaCert(deviceName, request.IP, request.PublicKey, false)
if err != nil {
utils.Error("DeviceCreation: Error while creating Device", err)
@ -82,6 +83,13 @@ func DeviceCreate(w http.ResponseWriter, req *http.Request) {
return
}
if err != nil {
utils.Error("DeviceCreation: Error while getting fingerprint", err)
utils.HTTPError(w, "Device Creation Error: " + err.Error(),
http.StatusInternalServerError, "DC007")
return
}
_, err3 := c.InsertOne(nil, map[string]interface{}{
"Nickname": nickname,
"DeviceName": deviceName,
@ -91,6 +99,7 @@ func DeviceCreate(w http.ResponseWriter, req *http.Request) {
"IsRelay": request.IsRelay,
"PublicHostname": request.PublicHostname,
"Port": request.Port,
"Fingerprint": fingerprint,
})
if err3 != nil {

View file

@ -4,7 +4,7 @@ import (
"net/http"
"encoding/json"
"io/ioutil"
"os"
"github.com/azukaar/cosmos-server/src/utils"
)
@ -81,11 +81,15 @@ func API_GetLogs(w http.ResponseWriter, req *http.Request) {
}
if(req.Method == "GET") {
logs, err := os.ReadFile(utils.CONFIGFOLDER+"nebula.log")
if err != nil {
utils.Error("Error reading file:", err)
return
}
json.NewEncoder(w).Encode(map[string]interface{}{
"status": "OK",
"data": logBuffer.String(),
"data": string(logs),
})
} else {
utils.Error("SettingGet: Method not allowed" + req.Method, nil)

View file

@ -12,11 +12,12 @@ import (
"strings"
"io/ioutil"
"strconv"
"encoding/json"
"io"
"bytes"
"github.com/natefinch/lumberjack"
)
var logBuffer bytes.Buffer
var logBuffer *lumberjack.Logger
var (
process *exec.Cmd
@ -38,16 +39,24 @@ func startNebulaInBackground() error {
return errors.New("nebula is already running")
}
logBuffer = &lumberjack.Logger{
Filename: utils.CONFIGFOLDER+"nebula.log",
MaxSize: 1, // megabytes
MaxBackups: 1,
MaxAge: 15, //days
Compress: false,
}
process = exec.Command(binaryToRun(), "-config", utils.CONFIGFOLDER+"nebula.yml")
// Set up multi-writer for stderr
process.Stderr = io.MultiWriter(&logBuffer, os.Stderr)
process.Stderr = io.MultiWriter(logBuffer, os.Stderr)
if utils.LoggingLevelLabels[utils.GetMainConfig().LoggingLevel] == utils.DEBUG {
// Set up multi-writer for stdout if in debug mode
process.Stdout = io.MultiWriter(&logBuffer, os.Stdout)
process.Stdout = io.MultiWriter(logBuffer, os.Stdout)
} else {
process.Stdout = io.MultiWriter(&logBuffer)
process.Stdout = io.MultiWriter(logBuffer)
}
// Start the process in the background
@ -125,6 +134,26 @@ func GetAllLightHouses() ([]utils.ConstellationDevice, error) {
return devices, nil
}
func GetBlockedDevices() ([]utils.ConstellationDevice, error) {
c, err := utils.GetCollection(utils.GetRootAppId(), "devices")
if err != nil {
return []utils.ConstellationDevice{}, err
}
var devices []utils.ConstellationDevice
cursor, err := c.Find(nil, map[string]interface{}{
"Blocked": true,
})
cursor.All(nil, &devices)
if err != nil {
return []utils.ConstellationDevice{}, err
}
return devices, nil
}
func cleanIp(ip string) string {
return strings.Split(ip, "/")[0]
}
@ -133,10 +162,14 @@ func ExportConfigToYAML(overwriteConfig utils.ConstellationConfig, outputPath st
// Combine defaultConfig and overwriteConfig
finalConfig := NebulaDefaultConfig
finalConfig.StaticHostMap = map[string][]string{
"192.168.201.1": []string{
utils.GetMainConfig().ConstellationConfig.ConstellationHostname + ":4242",
},
if !overwriteConfig.PrivateNode {
finalConfig.StaticHostMap = map[string][]string{
"192.168.201.1": []string{
utils.GetMainConfig().ConstellationConfig.ConstellationHostname + ":4242",
},
}
} else {
finalConfig.StaticHostMap = map[string][]string{}
}
// for each lighthouse
@ -150,6 +183,16 @@ func ExportConfigToYAML(overwriteConfig utils.ConstellationConfig, outputPath st
l.PublicHostname + ":" + l.Port,
}
}
// add blocked devices
blockedDevices, err := GetBlockedDevices()
if err != nil {
return err
}
for _, d := range blockedDevices {
finalConfig.PKI.Blocklist = append(finalConfig.PKI.Blocklist, d.Fingerprint)
}
// add other lighthouses
finalConfig.Lighthouse.Hosts = []string{}
@ -334,7 +377,40 @@ func killAllNebulaInstances() error {
return nil
}
func generateNebulaCert(name, ip, PK string, saveToFile bool) (string, string, error) {
func GetCertFingerprint(certPath string) (string, error) {
// nebula-cert print -json
var cmd *exec.Cmd
cmd = exec.Command(binaryToRun() + "-cert",
"print",
"-json",
"-path", certPath,
)
// capture and parse output
output, err := cmd.CombinedOutput()
if err != nil {
utils.Error("Error while printing cert", err)
}
var certInfo map[string]interface{}
err = json.Unmarshal(output, &certInfo)
if err != nil {
utils.Error("Error while unmarshalling cert information", err)
return "", err
}
// Extract fingerprint, replace "fingerprint" with the actual key where the fingerprint is stored in the JSON output
fingerprint, ok := certInfo["fingerprint"].(string)
if !ok {
utils.Error("Fingerprint not found or not a string", nil)
return "", errors.New("fingerprint not found or not a string")
}
return fingerprint, nil
}
func generateNebulaCert(name, ip, PK string, saveToFile bool) (string, string, string, error) {
// Run the nebula-cert command
var cmd *exec.Cmd
@ -348,9 +424,9 @@ func generateNebulaCert(name, ip, PK string, saveToFile bool) (string, string, e
)
} else {
// write PK to temp.cert
err := ioutil.WriteFile("./temp.cert", []byte(PK), 0644)
err := ioutil.WriteFile("./temp.key", []byte(PK), 0644)
if err != nil {
return "", "", fmt.Errorf("failed to write temp.cert: %s", err)
return "", "", "", fmt.Errorf("failed to write temp.key: %s", err)
}
cmd = exec.Command(binaryToRun() + "-cert",
"sign",
@ -358,10 +434,10 @@ func generateNebulaCert(name, ip, PK string, saveToFile bool) (string, string, e
"-ca-key", utils.CONFIGFOLDER + "ca.key",
"-name", name,
"-ip", ip,
"-in-pub", "./temp.cert",
"-in-pub", "./temp.key",
)
// delete temp.cert
defer os.Remove("./temp.cert")
// delete temp.key
defer os.Remove("./temp.key")
}
utils.Debug(cmd.String())
@ -377,7 +453,7 @@ func generateNebulaCert(name, ip, PK string, saveToFile bool) (string, string, e
cmd.Run()
if cmd.ProcessState.ExitCode() != 0 {
return "", "", fmt.Errorf("nebula-cert exited with an error, check the Cosmos logs")
return "", "", "", fmt.Errorf("nebula-cert exited with an error, check the Cosmos logs")
}
// Read the generated certificate and key files
@ -387,14 +463,19 @@ func generateNebulaCert(name, ip, PK string, saveToFile bool) (string, string, e
utils.Debug("Reading certificate from " + certPath)
utils.Debug("Reading key from " + keyPath)
fingerprint, err := GetCertFingerprint(certPath)
if err != nil {
return "", "", "", fmt.Errorf("failed to get certificate fingerprint: %s", err)
}
certContent, errCert := ioutil.ReadFile(certPath)
if errCert != nil {
return "", "", fmt.Errorf("failed to read certificate file: %s", errCert)
return "", "", "", fmt.Errorf("failed to read certificate file: %s", errCert)
}
keyContent, errKey := ioutil.ReadFile(keyPath)
if errKey != nil {
return "", "", fmt.Errorf("failed to read key file: %s", errKey)
return "", "", "", fmt.Errorf("failed to read key file: %s", errKey)
}
if saveToFile {
@ -407,15 +488,15 @@ func generateNebulaCert(name, ip, PK string, saveToFile bool) (string, string, e
} else {
// Delete the generated certificate and key files
if err := os.Remove(certPath); err != nil {
return "", "", fmt.Errorf("failed to delete certificate file: %s", err)
return "", "", "", fmt.Errorf("failed to delete certificate file: %s", err)
}
if err := os.Remove(keyPath); err != nil {
return "", "", fmt.Errorf("failed to delete key file: %s", err)
return "", "", "", fmt.Errorf("failed to delete key file: %s", err)
}
}
return string(certContent), string(keyContent), nil
return string(certContent), string(keyContent), fingerprint, nil
}
func generateNebulaCACert(name string) (error) {

View file

@ -12,10 +12,12 @@ func InitConfig() {
CA string `yaml:"ca"`
Cert string `yaml:"cert"`
Key string `yaml:"key"`
Blocklist []string `yaml:"blocklist"`
}{
CA: utils.CONFIGFOLDER + "ca.crt",
Cert: utils.CONFIGFOLDER + "cosmos.crt",
Key: utils.CONFIGFOLDER + "cosmos.key",
Blocklist: []string{},
},
StaticHostMap: map[string][]string{

View file

@ -338,6 +338,7 @@ func InitServer() *mux.Router {
srapi.HandleFunc("/api/constellation/connect", constellation.API_ConnectToExisting)
srapi.HandleFunc("/api/constellation/config", constellation.API_GetConfig)
srapi.HandleFunc("/api/constellation/logs", constellation.API_GetLogs)
srapi.HandleFunc("/api/constellation/block", constellation.DeviceBlock)
if(!config.HTTPConfig.AcceptAllInsecureHostname) {
srapi.Use(utils.EnsureHostname)

View file

@ -212,16 +212,22 @@ type MarketSource struct {
type ConstellationConfig struct {
Enabled bool
SlaveMode bool
PrivateNode bool
DNS bool
DNSPort string
DNSFallback string
DNSBlockBlacklist bool
DNSAdditionalBlocklists []string
CustomDNSEntries map[string]string
CustomDNSEntries []ConstellationDNSEntry
NebulaConfig NebulaConfig
ConstellationHostname string
}
type ConstellationDNSEntry struct {
Type string
Key string
Value string
}
type ConstellationDevice struct {
Nickname string `json:"nickname"`
DeviceName string `json:"deviceName"`
@ -231,6 +237,8 @@ type ConstellationDevice struct {
IsRelay bool `json:"isRelay"`
PublicHostname string `json:"publicHostname"`
Port string `json:"port"`
Blocked bool `json:"blocked"`
Fingerprint string `json:"fingerprint"`
}
type NebulaFirewallRule struct {
@ -251,6 +259,7 @@ type NebulaConfig struct {
CA string `yaml:"ca"`
Cert string `yaml:"cert"`
Key string `yaml:"key"`
Blocklist []string `yaml:"blocklist"`
} `yaml:"pki"`
StaticHostMap map[string][]string `yaml:"static_host_map"`