From 9b033696e35932ce60d17f4b26092fcd70b892f6 Mon Sep 17 00:00:00 2001 From: Yann Stepienik Date: Mon, 2 Oct 2023 16:22:18 +0100 Subject: [PATCH] [release] v0.10.0-unstable16 --- client/src/api/constellation.tsx | 13 + .../src/pages/config/users/formShortcuts.jsx | 21 +- client/src/pages/constellation/dns.jsx | 174 +++++++++++++ client/src/pages/constellation/index.jsx | 228 +++--------------- client/src/pages/constellation/vpn.jsx | 205 ++++++++++++++++ client/src/routes/MainRoutes.jsx | 2 +- go.mod | 27 ++- go.sum | 48 +++- package.json | 2 +- readme.md | 2 +- src/constellation/DNS.go | 5 +- src/constellation/api_devices_block.go | 99 ++++++++ src/constellation/api_devices_create.go | 13 +- src/constellation/api_nebula.go | 10 +- src/constellation/nebula.go | 123 ++++++++-- src/constellation/nebula_default.go | 2 + src/httpServer.go | 1 + src/utils/types.go | 11 +- 18 files changed, 738 insertions(+), 248 deletions(-) create mode 100644 client/src/pages/constellation/dns.jsx create mode 100644 client/src/pages/constellation/vpn.jsx create mode 100644 src/constellation/api_devices_block.go diff --git a/client/src/api/constellation.tsx b/client/src/api/constellation.tsx index 375aabe..261362d 100644 --- a/client/src/api/constellation.tsx +++ b/client/src/api/constellation.tsx @@ -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, }; \ No newline at end of file diff --git a/client/src/pages/config/users/formShortcuts.jsx b/client/src/pages/config/users/formShortcuts.jsx index 850bf8e..4419ebb 100644 --- a/client/src/pages/config/users/formShortcuts.jsx +++ b/client/src/pages/config/users/formShortcuts.jsx @@ -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 - {label} + {label && {label}} { + 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] && ( + + {formik.errors[name]} + + )} + {errors && ( {formik.errors[name]} diff --git a/client/src/pages/constellation/dns.jsx b/client/src/pages/constellation/dns.jsx new file mode 100644 index 0000000..6e39761 --- /dev/null +++ b/client/src/pages/constellation/dns.jsx @@ -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 <> + + {(config) ? <> + +
+ + + + { + 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) => ( +
+ + + + + + + + + + DNS Blocklist URLs + {formik.values.DNSAdditionalBlocklists.map((item, index) => ( + + { + formik.setFieldValue("DNSAdditionalBlocklists", [...formik.values.DNSAdditionalBlocklists.slice(0, index), ...formik.values.DNSAdditionalBlocklists.slice(index + 1)]); + }} /> +
+ { + formik.setFieldValue("DNSAdditionalBlocklists", [...formik.values.DNSAdditionalBlocklists.slice(0, index), e.target.value, ...formik.values.DNSAdditionalBlocklists.slice(index + 1)]); + }} + /> +
+
+ ))} + + + + + + + + DNS Custom Entries + {formik.values.CustomDNSEntries.map((item, index) => ( + + { + formik.setFieldValue("CustomDNSEntries", [...formik.values.CustomDNSEntries.slice(0, index), ...formik.values.CustomDNSEntries.slice(index + 1)]); + }} /> +
+ { + const updatedCustomDNSEntries = [...formik.values.CustomDNSEntries]; + updatedCustomDNSEntries[index].Key = e.target.value; + formik.setFieldValue("CustomDNSEntries", updatedCustomDNSEntries); + }} + /> +
+
+ { + const updatedCustomDNSEntries = [...formik.values.CustomDNSEntries]; + updatedCustomDNSEntries[index].Value = e.target.value; + formik.setFieldValue("CustomDNSEntries", updatedCustomDNSEntries); + }} + /> +
+
+ ))} + + + + + + + Save + +
+
+ )} +
+
+
+
+
+ :
+ +
} + +}; \ No newline at end of file diff --git a/client/src/pages/constellation/index.jsx b/client/src/pages/constellation/index.jsx index d4d0518..dea63ec 100644 --- a/client/src/pages/constellation/index.jsx +++ b/client/src/pages/constellation/index.jsx @@ -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
+ + + , + path: 'vpn' + }, + { + title: 'DNS', + children: , + path: 'dns' + }, + ]}/> + +
; } -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 - } - else if (r.deviceName.toLowerCase().includes("laptop") || r.deviceName.toLowerCase().includes("computer")) { - return - } else if (r.deviceName.toLowerCase().includes("desktop")) { - return - } else if (r.deviceName.toLowerCase().includes("tablet")) { - return - } else if (r.deviceName.toLowerCase().includes("lighthouse") || r.deviceName.toLowerCase().includes("server")) { - return - } else { - return - } - } - - return <> - - {(devices && config && users) ? <> - -
- - - {config.ConstellationConfig.Enabled && config.ConstellationConfig.SlaveMode && <> - - You are currently connected to an external constellation network. Use your main Cosmos server to manage your constellation network and devices. - - } - { - 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) => ( -
- - {formik.values.Enabled && - - - - { - await API.constellation.reset(); - refreshConfig(); - }} - /> - } - - {config.ConstellationConfig.Enabled && !config.ConstellationConfig.SlaveMode && <> - {formik.values.Enabled && <> - - 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. If you change this value, you will need to reset your network and reconnect all the clients! - - } - } - { - let file = e.target.files[0]; - await API.constellation.connect(file); - refreshConfig(); - }} - /> - - Save - - -
- )} -
-
-
-
- {config.ConstellationConfig.Enabled && !config.ConstellationConfig.SlaveMode && <> - - r.deviceName} - buttons={[ - , - ]} - columns={[ - { - title: '', - field: getIcon, - }, - { - title: 'Device Name', - field: (r) => {r.deviceName}, - }, - { - title: 'Owner', - field: (r) => {r.nickname}, - }, - { - title: 'Type', - field: (r) => {r.isLighthouse ? "Lighthouse" : "Client"}, - }, - { - title: 'Constellation IP', - screenMin: 'md', - field: (r) => r.ip, - }, - { - title: '', - clickable: true, - field: (r) => { - return { - alert("caca") - }}> - } - } - ]} - /> - } -
- :
- -
} - -}; \ No newline at end of file +export default ConstellationIndex; \ No newline at end of file diff --git a/client/src/pages/constellation/vpn.jsx b/client/src/pages/constellation/vpn.jsx new file mode 100644 index 0000000..65e7b9f --- /dev/null +++ b/client/src/pages/constellation/vpn.jsx @@ -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 + } + else if (r.deviceName.toLowerCase().includes("laptop") || r.deviceName.toLowerCase().includes("computer")) { + return + } else if (r.deviceName.toLowerCase().includes("desktop")) { + return + } else if (r.deviceName.toLowerCase().includes("tablet")) { + return + } else if (r.deviceName.toLowerCase().includes("lighthouse") || r.deviceName.toLowerCase().includes("server")) { + return + } else { + return + } + } + + return <> + + {(devices && config && users) ? <> + +
+ + + {config.ConstellationConfig.Enabled && config.ConstellationConfig.SlaveMode && <> + + You are currently connected to an external constellation network. Use your main Cosmos server to manage your constellation network and devices. + + } + { + 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) => ( +
+ + {formik.values.Enabled && + + + + { + await API.constellation.reset(); + refreshConfig(); + }} + /> + } + + {config.ConstellationConfig.Enabled && !config.ConstellationConfig.SlaveMode && <> + {formik.values.Enabled && <> + + + {!formik.values.PrivateNode && <> + 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. If you change this value, you will need to reset your network and reconnect all the clients! + + } + } + } + + Save + + { + let file = e.target.files[0]; + await API.constellation.connect(file); + refreshConfig(); + }} + /> + +
+ )} +
+
+
+
+ {config.ConstellationConfig.Enabled && !config.ConstellationConfig.SlaveMode && <> + + !d.blocked)} + getKey={(r) => r.deviceName} + buttons={[ + , + ]} + columns={[ + { + title: '', + field: getIcon, + }, + { + title: 'Device Name', + field: (r) => {r.deviceName}, + }, + { + title: 'Owner', + field: (r) => {r.nickname}, + }, + { + title: 'Type', + field: (r) => {r.isLighthouse ? "Lighthouse" : "Client"}, + }, + { + title: 'Constellation IP', + screenMin: 'md', + field: (r) => r.ip, + }, + { + title: '', + clickable: true, + field: (r) => { + return { + await API.constellation.block(r.nickname, r.deviceName, true); + refreshConfig(); + }}> + } + } + ]} + /> + } +
+ :
+ +
} + +}; \ No newline at end of file diff --git a/client/src/routes/MainRoutes.jsx b/client/src/routes/MainRoutes.jsx index 5c67c26..84b7f49 100644 --- a/client/src/routes/MainRoutes.jsx +++ b/client/src/routes/MainRoutes.jsx @@ -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 diff --git a/go.mod b/go.mod index 4e40dd9..7c1de41 100644 --- a/go.mod +++ b/go.mod @@ -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 ) diff --git a/go.sum b/go.sum index ae94432..39b642d 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/package.json b/package.json index f5bc0e2..6a39eec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cosmos-server", - "version": "0.10.0-unstable15", + "version": "0.10.0-unstable16", "description": "", "main": "test-server.js", "bugs": { diff --git a/readme.md b/readme.md index 8d00e7d..ad32c52 100644 --- a/readme.md +++ b/readme.md @@ -8,7 +8,7 @@ null Clayton Stone null -Adrian Germeck +Adrian

--- diff --git a/src/constellation/DNS.go b/src/constellation/DNS.go index 1f303ae..c7f23ac 100644 --- a/src/constellation/DNS.go +++ b/src/constellation/DNS.go @@ -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) diff --git a/src/constellation/api_devices_block.go b/src/constellation/api_devices_block.go new file mode 100644 index 0000000..9465c76 --- /dev/null +++ b/src/constellation/api_devices_block.go @@ -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 + } +} \ No newline at end of file diff --git a/src/constellation/api_devices_create.go b/src/constellation/api_devices_create.go index f7ea61d..bc81754 100644 --- a/src/constellation/api_devices_create.go +++ b/src/constellation/api_devices_create.go @@ -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 { diff --git a/src/constellation/api_nebula.go b/src/constellation/api_nebula.go index 1d67c2f..0374760 100644 --- a/src/constellation/api_nebula.go +++ b/src/constellation/api_nebula.go @@ -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) diff --git a/src/constellation/nebula.go b/src/constellation/nebula.go index 7645e57..e4cc6e9 100644 --- a/src/constellation/nebula.go +++ b/src/constellation/nebula.go @@ -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) { diff --git a/src/constellation/nebula_default.go b/src/constellation/nebula_default.go index 8b3abe8..d36b850 100644 --- a/src/constellation/nebula_default.go +++ b/src/constellation/nebula_default.go @@ -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{ diff --git a/src/httpServer.go b/src/httpServer.go index 845fd66..066a212 100644 --- a/src/httpServer.go +++ b/src/httpServer.go @@ -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) diff --git a/src/utils/types.go b/src/utils/types.go index 8d4460a..0a6bcc7 100644 --- a/src/utils/types.go +++ b/src/utils/types.go @@ -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"`