[release] v0.10.0-unstable7

This commit is contained in:
Yann Stepienik 2023-08-27 15:21:13 +01:00
parent ff90bdf51e
commit 735874006c
10 changed files with 277 additions and 42 deletions

View file

@ -19,7 +19,37 @@ function addDevice(device) {
}))
}
function restart() {
return wrap(fetch('/cosmos/api/constellation/restart', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}))
}
function getConfig() {
return wrap(fetch('/cosmos/api/constellation/config', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}))
}
function getLogs() {
return wrap(fetch('/cosmos/api/constellation/logs', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}))
}
export {
list,
addDevice,
restart,
getConfig,
getLogs,
};

View file

@ -0,0 +1,94 @@
// material-ui
import { LoadingButton } from '@mui/lab';
import { Button } from '@mui/material';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
import * as React from 'react';
import { useEffect, useState } from 'react';
const preStyle = {
backgroundColor: '#000',
color: '#fff',
padding: '10px',
borderRadius: '5px',
overflow: 'auto',
maxHeight: '500px',
maxWidth: '100%',
width: '100%',
margin: '0',
position: 'relative',
fontSize: '12px',
fontFamily: 'monospace',
whiteSpace: 'pre-wrap',
wordWrap: 'break-word',
wordBreak: 'break-all',
lineHeight: '1.5',
boxShadow: '0 0 10px rgba(0,0,0,0.5)',
border: '1px solid rgba(255,255,255,0.1)',
boxSizing: 'border-box',
marginBottom: '10px',
marginTop: '10px',
marginLeft: '0',
marginRight: '0',
display: 'block',
textAlign: 'left',
verticalAlign: 'baseline',
opacity: '1',
}
const ApiModal = ({ callback, label }) => {
const [openModal, setOpenModal] = useState(false);
const [content, setContent] = useState("");
const [loading, setLoading] = useState(true);
const getContent = async () => {
setLoading(true);
let content = await callback();
setContent(content.data);
setLoading(false);
};
useEffect(() => {
if (openModal)
getContent();
}, [openModal]);
return <>
<Dialog open={openModal} onClose={() => setOpenModal(false)}>
<DialogTitle>Refresh Page</DialogTitle>
<DialogContent>
<DialogContentText>
<pre style={preStyle}>
{content}
</pre>
</DialogContentText>
</DialogContent>
<DialogActions>
<LoadingButton
loading={loading}
onClick={() => {
getContent();
}}>Refresh</LoadingButton>
<Button onClick={() => {
setOpenModal(false);
}}>Close</Button>
</DialogActions>
</Dialog>
<Button
disableElevation
variant="outlined"
color="primary"
onClick={() => {
setOpenModal(true);
}}
>
{label}
</Button>
</>
};
export default ApiModal;

View file

@ -11,6 +11,7 @@ import { CosmosCheckbox, CosmosFormDivider } from "../config/users/formShortcuts
import MainCard from "../../components/MainCard";
import { Formik } from "formik";
import { LoadingButton } from "@mui/lab";
import ApiModal from "../../components/apiModal";
export const ConstellationIndex = () => {
const [isAdmin, setIsAdmin] = useState(false);
@ -48,28 +49,45 @@ export const ConstellationIndex = () => {
return <>
<IsLoggedIn />
{(devices && config && users) ? <>
<Stack spacing={2}>
<Stack spacing={2} style={{maxWidth: "1000px"}}>
<div>
<MainCard title={"Constellation Setup"} content={config.constellationIP}>
<Stack spacing={2}>
<Formik
initialValues={{
Enabled: config.ConstellationConfig.Enabled,
IsRelay: config.ConstellationConfig.NebulaConfig.Relay.AMRelay,
}}
onSubmit={(values) => {
let newConfig = { ...config };
newConfig.ConstellationConfig.Enabled = values.Enabled;
newConfig.ConstellationConfig.NebulaConfig.Relay.AMRelay = values.IsRelay;
return API.config.set(newConfig);
}}
>
{(formik) => (
<form onSubmit={formik.handleSubmit}>
<Stack spacing={2}>
<Stack spacing={2} direction="row">
<Button
disableElevation
variant="outlined"
color="primary"
onClick={async () => {
await API.constellation.restart();
}}
>
Restart Nebula
</Button>
<ApiModal callback={API.constellation.getLogs} label={"Show Nebula logs"} />
<ApiModal callback={API.constellation.getConfig} label={"Render Nebula Config"} />
</Stack>
<CosmosCheckbox formik={formik} name="Enabled" label="Constellation Enabled" />
<CosmosCheckbox formik={formik} name="IsRelay" label="Relay requests via this Node" />
<LoadingButton
disableElevation
loading={formik.isSubmitting}
fullWidth
type="submit"
variant="contained"
color="primary"

View file

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

View file

@ -150,7 +150,7 @@ docker run -d -p 80:80 -p 443:443 --privileged --name cosmos-server -h cosmos-s
in this command, `-v /:/mnt/host` is optional and allow to manage folders from Cosmos, you can remove it if you don't want it but you will have to create your container's bind folders manually.
`--privileged` is also optional, but it is required if you use hardening software like AppArmor or SELinux, as they restrict access to the docker socket.
`--privileged` is also optional, but it is required to use Constellation. It is also required if you use hardening software like AppArmor or SELinux, as they restrict access to the docker socket.
Once installed, simply go to `http://your-server-ip` and follow the instructions of the setup wizard.

View file

@ -0,0 +1,75 @@
package constellation
import (
"net/http"
"encoding/json"
"io/ioutil"
"github.com/azukaar/cosmos-server/src/utils"
)
func API_GetConfig(w http.ResponseWriter, req *http.Request) {
if utils.AdminOnly(w, req) != nil {
return
}
if(req.Method == "GET") {
// read utils.CONFIGFOLDER + "nebula.yml"
config, err := ioutil.ReadFile(utils.CONFIGFOLDER + "nebula.yml")
if err != nil {
utils.Error("SettingGet: error while reading nebula.yml", err)
utils.HTTPError(w, "Error while reading nebula.yml", http.StatusInternalServerError, "HTTP002")
return
}
json.NewEncoder(w).Encode(map[string]interface{}{
"status": "OK",
"data": string(config),
})
} else {
utils.Error("SettingGet: Method not allowed" + req.Method, nil)
utils.HTTPError(w, "Method not allowed", http.StatusMethodNotAllowed, "HTTP001")
return
}
}
func API_Restart(w http.ResponseWriter, req *http.Request) {
if utils.AdminOnly(w, req) != nil {
return
}
if(req.Method == "GET") {
RestartNebula()
utils.Log("Constellation: nebula restarted")
json.NewEncoder(w).Encode(map[string]interface{}{
"status": "OK",
})
} else {
utils.Error("SettingGet: Method not allowed" + req.Method, nil)
utils.HTTPError(w, "Method not allowed", http.StatusMethodNotAllowed, "HTTP001")
return
}
}
func API_GetLogs(w http.ResponseWriter, req *http.Request) {
if utils.AdminOnly(w, req) != nil {
return
}
if(req.Method == "GET") {
json.NewEncoder(w).Encode(map[string]interface{}{
"status": "OK",
"data": logBuffer.String(),
})
} else {
utils.Error("SettingGet: Method not allowed" + req.Method, nil)
utils.HTTPError(w, "Method not allowed", http.StatusMethodNotAllowed, "HTTP001")
return
}
}

View file

@ -12,8 +12,12 @@ import (
"strings"
"io/ioutil"
"strconv"
"io"
"bytes"
)
var logBuffer bytes.Buffer
var (
process *exec.Cmd
processMux sync.Mutex
@ -36,12 +40,14 @@ func startNebulaInBackground() error {
process = exec.Command(binaryToRun(), "-config", utils.CONFIGFOLDER+"nebula.yml")
process.Stderr = os.Stderr
// Set up multi-writer for stderr
process.Stderr = io.MultiWriter(&logBuffer, os.Stderr)
if utils.LoggingLevelLabels[utils.GetMainConfig().LoggingLevel] == utils.DEBUG {
process.Stdout = os.Stdout
// Set up multi-writer for stdout if in debug mode
process.Stdout = io.MultiWriter(&logBuffer, os.Stdout)
} else {
process.Stdout = nil
process.Stdout = io.MultiWriter(&logBuffer)
}
// Start the process in the background
@ -82,12 +88,19 @@ func ExportConfigToYAML(overwriteConfig utils.ConstellationConfig, outputPath st
"192.168.201.0": []string{utils.GetMainConfig().HTTPConfig.Hostname + ":4242"},
}
finalConfig.Relay.AMRelay = overwriteConfig.NebulaConfig.Relay.AMRelay
// Marshal the combined config to YAML
yamlData, err := yaml.Marshal(finalConfig)
if err != nil {
return err
}
// delete nebula.yml if exists
if _, err := os.Stat(outputPath); err == nil {
os.Remove(outputPath)
}
// Write YAML data to the specified file
yamlFile, err := os.Create(outputPath)
if err != nil {

View file

@ -46,9 +46,11 @@ func InitConfig() {
Relay: struct {
AMRelay bool `yaml:"am_relay"`
UseRelays bool `yaml:"use_relays"`
Relays []string `yaml:"relays"`
}{
AMRelay: true,
UseRelays: true,
Relays: []string{},
},
TUN: struct {
Disabled bool `yaml:"disabled"`

View file

@ -333,6 +333,9 @@ func InitServer() *mux.Router {
srapi.HandleFunc("/api/background/{ext}", GetBackground)
srapi.HandleFunc("/api/constellation/devices", constellation.ConstellationAPIDevices)
srapi.HandleFunc("/api/constellation/restart", constellation.API_Restart)
srapi.HandleFunc("/api/constellation/config", constellation.API_GetConfig)
srapi.HandleFunc("/api/constellation/logs", constellation.API_GetLogs)
if(!config.HTTPConfig.AcceptAllInsecureHostname) {
srapi.Use(utils.EnsureHostname)

View file

@ -254,7 +254,7 @@ type NebulaConfig struct {
Relay struct {
AMRelay bool `yaml:"am_relay"`
UseRelays bool `yaml:"use_relays"`
relays []string `yaml:"relays"`
Relays []string `yaml:"relays"`
} `yaml:"relay"`
TUN struct {