[release] v0.10.0-unstable2

This commit is contained in:
Yann Stepienik 2023-08-22 15:39:06 +01:00
parent f127e5a146
commit 8e83fde02e
10 changed files with 158 additions and 36 deletions

View file

@ -123,8 +123,9 @@
align-items: center;
}
.loading-image {
.loading-image:empty {
background: url('assets/images/icons/cosmos_gray.png') no-repeat center center;
background-size: contain;
}
.raw-table table {

View file

@ -1,7 +1,7 @@
import * as React from 'react';
import MainCard from '../../../components/MainCard';
import RestartModal from '../users/restart';
import { Chip, Divider, Stack, useMediaQuery } from '@mui/material';
import { Checkbox, Chip, Divider, FormControlLabel, Stack, useMediaQuery } from '@mui/material';
import HostChip from '../../../components/hostChip';
import { RouteMode, RouteSecurity } from '../../../components/routeComponents';
import { getFaviconURL } from '../../../utils/routes';
@ -9,6 +9,8 @@ import * as API from '../../../api';
import { CheckOutlined, ClockCircleOutlined, DashboardOutlined, DeleteOutlined, DownOutlined, LockOutlined, UpOutlined } from "@ant-design/icons";
import IsLoggedIn from '../../../isLoggedIn';
import { redirectToLocal } from '../../../utils/indexs';
import { CosmosCheckbox } from '../users/formShortcuts';
import { Field } from 'formik';
const info = {
backgroundColor: 'rgba(0, 0, 0, 0.1)',

View file

@ -206,7 +206,7 @@ export const CosmosCollapse = ({ children, title }) => {
export function CosmosFormDivider({title}) {
return <Grid item xs={12}>
<Divider>
<Chip label={title} />
{title && <Chip label={title} />}
</Divider>
</Grid>
}

View file

@ -12,20 +12,56 @@ import { PlusCircleFilled } from '@ant-design/icons';
import { Formik } from 'formik';
import * as yup from 'yup';
import * as API from '../../api';
import { CosmosInputText, CosmosSelect } from '../config/users/formShortcuts';
import { CosmosFormDivider, CosmosInputText, CosmosSelect } from '../config/users/formShortcuts';
import { DownloadFile } from '../../api/downloadButton';
import QRCode from 'qrcode';
const AddDeviceModal = ({ config, isAdmin, refreshConfig, devices }) => {
const AddDeviceModal = ({ users, config, isAdmin, refreshConfig, devices }) => {
const [openModal, setOpenModal] = useState(false);
const [isDone, setIsDone] = useState(null);
const canvasRef = React.useRef(null);
let firstIP = "192.168.201.1/24";
if (devices && devices.length > 0) {
const isIpFree = (ip) => {
return devices.filter((d) => d.ip === ip).length === 0;
}
let i = 1;
let j = 201;
while (!isIpFree(firstIP)) {
i++;
if (i > 254) {
i = 0;
j++;
}
firstIP = "192.168." + j + "." + i + "/24";
}
}
const renderCanvas = (data) => {
if (!canvasRef.current) return setTimeout(() => {
renderCanvas(data);
}, 500);
QRCode.toCanvas(canvasRef.current, JSON.stringify(data),
{
width: 600,
color: {
dark: "#000",
light: '#fff'
}
}, function (error) {
if (error) console.error(error)
})
}
return <>
<Dialog open={openModal} onClose={() => setOpenModal(false)}>
<Formik
initialValues={{
nickname: '',
nickname: users[0].nickname,
deviceName: '',
ip: '192.168.201.1/24',
ip: firstIP,
publicKey: '',
}}
@ -36,6 +72,7 @@ const AddDeviceModal = ({ config, isAdmin, refreshConfig, devices }) => {
return API.constellation.addDevice(values).then(({data}) => {
setIsDone(data);
refreshConfig();
renderCanvas(data);
}).catch((err) => {
setErrors(err.response.data);
});
@ -43,16 +80,30 @@ const AddDeviceModal = ({ config, isAdmin, refreshConfig, devices }) => {
>
{(formik) => (
<form onSubmit={formik.handleSubmit}>
<DialogTitle>Manually Add Device</DialogTitle>
<DialogTitle>Add Device</DialogTitle>
{isDone ? <DialogContent>
<DialogContentText>
<p>
Device added successfully!
Download the private and public keys to your device along side the config and network certificate to connect:
Download scan the QR Code from the Cosmos app or download the relevant
files to your device along side the config and network certificate to
connect:
</p>
<Stack spacing={2} direction={"column"}>
<CosmosFormDivider title={"Cosmos Client (QR Code)"} />
<div style={{textAlign: 'center'}}>
<canvas style={{borderRadius: '15px'}} ref={canvasRef} />
</div>
<CosmosFormDivider title={"Cosmos Client (File)"} />
<DownloadFile
filename={isDone.DeviceName + `.constellation`}
content={JSON.stringify(isDone, null, 2)}
label={"Download " + isDone.DeviceName + `.constellation`}
/>
<CosmosFormDivider title={"Nebula Client"} />
<DownloadFile
filename={`config.yml`}
content={isDone.Config}
@ -77,7 +128,7 @@ const AddDeviceModal = ({ config, isAdmin, refreshConfig, devices }) => {
</DialogContentText>
</DialogContent> : <DialogContent>
<DialogContentText>
<p>Manually add a device to the constellation. It is recommended that you use the Cosmos app instead. Use this form to add another Nebula device manually</p>
<p>Add a device to the constellation using either the Cosmos or Nebula client</p>
<div>
<Stack spacing={2} style={{}}>
<CosmosSelect
@ -85,9 +136,11 @@ const AddDeviceModal = ({ config, isAdmin, refreshConfig, devices }) => {
label="Owner"
formik={formik}
// disabled={!isAdmin}
options={[
["admin", "admin"]
]}
options={
users.map((u) => {
return [u.nickname, u.nickname]
})
}
/>
<CosmosInputText
@ -139,7 +192,7 @@ const AddDeviceModal = ({ config, isAdmin, refreshConfig, devices }) => {
variant="contained"
startIcon={<PlusCircleFilled />}
>
Manually Add Device
Add Device
</ResponsiveButton>
</>;
};

View file

@ -6,10 +6,16 @@ import PrettyTableView from "../../components/tableView/prettyTableView";
import { DeleteButton } from "../../components/delete";
import { CloudOutlined, DesktopOutlined, LaptopOutlined, MobileOutlined, TabletOutlined } from "@ant-design/icons";
import IsLoggedIn from "../../isLoggedIn";
import { Button, CircularProgress, Stack } from "@mui/material";
import { CosmosCheckbox, CosmosFormDivider } from "../config/users/formShortcuts";
import MainCard from "../../components/MainCard";
import { Formik } from "formik";
import { LoadingButton } from "@mui/lab";
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 () => {
@ -17,6 +23,7 @@ export const ConstellationIndex = () => {
setConfig(configAsync.data);
setIsAdmin(configAsync.isAdmin);
setDevices((await API.constellation.list()).data || []);
setUsers((await API.users.list()).data || []);
};
useEffect(() => {
@ -40,12 +47,48 @@ export const ConstellationIndex = () => {
return <>
<IsLoggedIn />
{devices && config && <>
{(devices && config && users) ? <>
<Stack spacing={2}>
<div>
<MainCard title={"Constellation Setup"} content={config.constellationIP}>
<Stack spacing={2}>
<Formik
initialValues={{
Enabled: config.ConstellationConfig.Enabled,
}}
onSubmit={(values) => {
let newConfig = { ...config };
newConfig.ConstellationConfig.Enabled = values.Enabled;
return API.config.set(newConfig);
}}
>
{(formik) => (
<form onSubmit={formik.handleSubmit}>
<Stack spacing={2}>
<CosmosCheckbox formik={formik} name="Enabled" label="Constellation Enabled" />
<LoadingButton
disableElevation
loading={formik.isSubmitting}
fullWidth
type="submit"
variant="contained"
color="primary"
>
Save
</LoadingButton>
</Stack>
</form>
)}
</Formik>
</Stack>
</MainCard>
</div>
<CosmosFormDivider title={"Devices"} />
<PrettyTableView
data={devices}
getKey={(r) => r.deviceName}
buttons={[
<AddDeviceModal isAdmin={isAdmin} config={config} refreshConfig={refreshConfig} devices={devices} />
<AddDeviceModal isAdmin={isAdmin} users={users} config={config} refreshConfig={refreshConfig} devices={devices} />
]}
columns={[
{
@ -76,6 +119,9 @@ export const ConstellationIndex = () => {
}
]}
/>
</>}
</Stack>
</> : <center>
<CircularProgress color="inherit" size={20} />
</center>}
</>
};

View file

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

View file

@ -5,6 +5,7 @@ import (
"encoding/json"
"github.com/azukaar/cosmos-server/src/utils"
"github.com/azukaar/cosmos-server/src/authorizationserver"
"github.com/azukaar/cosmos-server/src/constellation"
)
func ConfigApiSet(w http.ResponseWriter, req *http.Request) {
@ -43,6 +44,7 @@ func ConfigApiSet(w http.ResponseWriter, req *http.Request) {
utils.DisconnectDB()
authorizationserver.Init()
utils.RestartHTTPServer()
constellation.RestartNebula()
json.NewEncoder(w).Encode(map[string]interface{}{
"status": "OK",

View file

@ -16,7 +16,6 @@ type DeviceCreateRequestJSON struct {
}
func DeviceCreate(w http.ResponseWriter, req *http.Request) {
if(req.Method == "POST") {
var request DeviceCreateRequestJSON
err1 := json.NewDecoder(req.Body).Decode(&request)
@ -58,7 +57,8 @@ func DeviceCreate(w http.ResponseWriter, req *http.Request) {
}).Decode(&device)
if err2 == mongo.ErrNoDocuments {
cert, key, err := generateNebulaCert(deviceName, request.IP, false)
cert, key, err := generateNebulaCert(deviceName, request.IP, request.PublicKey, false)
if err != nil {
utils.Error("DeviceCreation: Error while creating Device", err)
@ -71,7 +71,6 @@ func DeviceCreate(w http.ResponseWriter, req *http.Request) {
"Nickname": nickname,
"DeviceName": deviceName,
"PublicKey": cert,
"PrivateKey": key,
"IP": request.IP,
})

View file

@ -23,7 +23,7 @@ func Init() {
if _, err := os.Stat(utils.CONFIGFOLDER + "cosmos.crt"); os.IsNotExist(err) {
utils.Log("Constellation: cosmos.crt not found, generating...")
// generate cosmos.crt
generateNebulaCert("cosmos", "192.168.201.0/24", true)
generateNebulaCert("cosmos", "192.168.201.0/24", "", true)
}
// export nebula.yml

View file

@ -58,7 +58,7 @@ func stop() error {
defer processMux.Unlock()
if process == nil {
return errors.New("nebula is not running")
return nil
}
if err := process.Process.Kill(); err != nil {
@ -69,11 +69,9 @@ func stop() error {
return nil
}
func restart() error {
if err := stop(); err != nil {
return err
}
return startNebulaInBackground()
func RestartNebula() {
stop()
Init()
}
func ExportConfigToYAML(overwriteConfig utils.ConstellationConfig, outputPath string) error {
@ -192,15 +190,36 @@ func killAllNebulaInstances() error {
return nil
}
func generateNebulaCert(name, ip string, saveToFile bool) (string, string, error) {
func generateNebulaCert(name, ip, PK string, saveToFile bool) (string, string, error) {
// Run the nebula-cert command
cmd := exec.Command(binaryToRun() + "-cert",
"sign",
"-ca-crt", utils.CONFIGFOLDER + "ca.crt",
"-ca-key", utils.CONFIGFOLDER + "ca.key",
"-name", name,
"-ip", ip,
)
var cmd *exec.Cmd
if(PK == "") {
cmd = exec.Command(binaryToRun() + "-cert",
"sign",
"-ca-crt", utils.CONFIGFOLDER + "ca.crt",
"-ca-key", utils.CONFIGFOLDER + "ca.key",
"-name", name,
"-ip", ip,
)
} else {
// write PK to temp.cert
err := ioutil.WriteFile("./temp.cert", []byte(PK), 0644)
if err != nil {
return "", "", fmt.Errorf("failed to write temp.cert: %s", err)
}
cmd = exec.Command(binaryToRun() + "-cert",
"sign",
"-ca-crt", utils.CONFIGFOLDER + "ca.crt",
"-ca-key", utils.CONFIGFOLDER + "ca.key",
"-name", name,
"-ip", ip,
"-in-pub", "./temp.cert",
)
// delete temp.cert
defer os.Remove("./temp.cert")
}
utils.Debug(cmd.String())
cmd.Stderr = os.Stderr