-
Notifications
You must be signed in to change notification settings - Fork 128
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* config-ui init * golang 1.5.4+ compatibily explicit struct conversion * Acraserver test param fix * Refactored
- Loading branch information
Showing
10 changed files
with
451 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
package main | ||
|
||
import ( | ||
"io/ioutil" | ||
"html/template" | ||
"net/http" | ||
"path/filepath" | ||
"gopkg.in/yaml.v2" | ||
"time" | ||
"encoding/json" | ||
"strconv" | ||
"bytes" | ||
"os" | ||
"fmt" | ||
"flag" | ||
log "github.com/sirupsen/logrus" | ||
"github.com/cossacklabs/acra/utils" | ||
"github.com/cossacklabs/acra/cmd" | ||
) | ||
|
||
var acraHost *string | ||
var acraPort *int | ||
var debug *bool | ||
|
||
func check(e error) { | ||
if e != nil { | ||
panic(e) | ||
} | ||
} | ||
|
||
type paramItem struct { | ||
Name string `yaml:"name" json:"name"` | ||
Title string `yaml:"title" json:"title"` | ||
ValueType string `yaml:"value_type" json:"value_type"` | ||
InputType string `yaml:"input_type" json:"input_type"` | ||
Values []string `yaml:"values,flow" json:"values,flow"` | ||
Labels []string `yaml:"labels,flow" json:"labels,flow"` | ||
} | ||
|
||
type configParamsYAML struct { | ||
Config []paramItem | ||
} | ||
|
||
type ConfigAcraServer struct { | ||
ProxyHost string `json:"host"` | ||
ProxyPort int `json:"port"` | ||
DbHost string `json:"db_host"` | ||
DbPort int `json:"db_port"` | ||
ProxyCommandsPort int `json:"commands_port"` | ||
Debug bool `json:"debug"` | ||
ScriptOnPoison string `json:"poisonscript"` | ||
StopOnPoison bool `json:"poisonshutdown"` | ||
WithZone bool `json:"zonemode"` | ||
} | ||
|
||
func SubmitSettings(w http.ResponseWriter, r *http.Request) { | ||
if r.Method != "POST" { | ||
http.Error(w, "Invalid request method", http.StatusMethodNotAllowed) | ||
return | ||
} | ||
|
||
err := r.ParseForm() | ||
if err != nil { | ||
log.WithError(err).Errorln("Request parsing failed") | ||
http.Error(w, "Bad request", http.StatusBadRequest) | ||
return | ||
} | ||
var db_port, _ = strconv.Atoi(r.Form.Get("db_port")) | ||
var commands_port, _ = strconv.Atoi(r.Form.Get("commands_port")) | ||
var debug, _ = strconv.ParseBool(r.Form.Get("debug")) | ||
var zonemode, _ = strconv.ParseBool(r.Form.Get("zonemode")) | ||
var poisonshutdown, _ = strconv.ParseBool(r.Form.Get("poisonshutdown")) | ||
config := ConfigAcraServer{ | ||
DbHost: r.Form.Get("db_host"), | ||
DbPort: db_port, | ||
ProxyCommandsPort: commands_port, | ||
Debug: debug, | ||
ScriptOnPoison: r.Form.Get("poisonscript"), | ||
StopOnPoison: poisonshutdown, | ||
WithZone: zonemode, | ||
} | ||
jsonToServer, err := json.Marshal(config) | ||
if err != nil { | ||
log.WithError(err).Errorln("/setConfig json.Marshal failed") | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
req, err := http.NewRequest("POST", fmt.Sprintf("http://%v:%v/setConfig", *acraHost, *acraPort), bytes.NewBuffer(jsonToServer)) | ||
if err != nil { | ||
log.WithError(err).Errorln("/setConfig http.NewRequest failed") | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
req.Header.Set("Content-Type", "application/json") | ||
client := &http.Client{} | ||
resp, err := client.Do(req) | ||
if err != nil { | ||
log.WithError(err).Errorln("/setConfig client.Do failed") | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
resp.Body.Close() | ||
|
||
w.Header().Set("Content-Type", "application/json") | ||
w.Write(jsonToServer) | ||
} | ||
|
||
func index(w http.ResponseWriter, r *http.Request) { | ||
w.Header().Set("Content-Security-Policy", "require-sri-for script style") | ||
parsedTemplate, _ := template.ParseFiles(filepath.Join("static", "index.html")) | ||
var outConfigParams configParamsYAML | ||
configParamsYAML, err := ioutil.ReadFile("acraserver_config_vars.yaml") | ||
check(err) | ||
|
||
// get current config | ||
var netClient = &http.Client{ | ||
Timeout: time.Second * 5, | ||
} | ||
serverResponse, err := netClient.Get(fmt.Sprintf("http://%v:%v/getConfig", *acraHost, *acraPort)) | ||
if err != nil { | ||
log.WithError(err).Errorln("AcraServer api error") | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
serverConfigDataJsonString, err := ioutil.ReadAll(serverResponse.Body) | ||
if err != nil { | ||
log.Fatal(err.Error()) | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
var serverConfigData ConfigAcraServer | ||
err = json.Unmarshal(serverConfigDataJsonString, &serverConfigData) | ||
if err != nil { | ||
log.WithError(err).Errorln("json.Unmarshal error") | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
// end get current config | ||
|
||
err = yaml.Unmarshal(configParamsYAML, &outConfigParams) | ||
if err != nil { | ||
log.Errorf("%v", utils.ErrorMessage("yaml.Unmarshal error", err)) | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
res, err := json.Marshal(outConfigParams) | ||
if err != nil { | ||
log.Errorf("%v", utils.ErrorMessage("json.Marshal error", err)) | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
parsedTemplate.Execute(w, struct { | ||
ConfigParams string | ||
ConfigAcraServer | ||
}{ | ||
string(res), | ||
serverConfigData, | ||
}) | ||
} | ||
|
||
func main() { | ||
port := flag.Int("port", 8000, "Port for configUI HTTP endpoint") | ||
acraHost = flag.String("acraHost", "localhost", "Host for Acraserver HTTP endpoint or proxy") | ||
acraPort = flag.Int("acraPort", 9292, "Port for Acraserver HTTP endpoint or proxy") | ||
debug = flag.Bool("d", false, "Turn on debug logging") | ||
flag.Parse() | ||
|
||
if *debug { | ||
cmd.SetLogLevel(cmd.LOG_DEBUG) | ||
} else { | ||
cmd.SetLogLevel(cmd.LOG_VERBOSE) | ||
} | ||
|
||
http.HandleFunc("/index.html", index) | ||
http.HandleFunc("/", index) | ||
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static")))) | ||
http.HandleFunc("/acraserver/submit_setting", SubmitSettings) | ||
log.Info(fmt.Sprintf("AcraConfigUI is listening @ :%d with PID %d", *port, os.Getpid())) | ||
err := http.ListenAndServe(fmt.Sprintf(":%d", *port), nil) | ||
check(err) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
config: | ||
# - | ||
# name: host | ||
# title: Host network address to listen for incoming connections from AcraProxy or via SSL | ||
# value_type: string | ||
# input_type: text | ||
# - | ||
# name: port | ||
# title: Port for AcraServer to listen for incoming connections from AcraProxy or via SSL | ||
# value_type: int8 | ||
# input_type: number | ||
- | ||
name: db_host | ||
title: Host for destination Postgres | ||
value_type: string | ||
input_type: text | ||
- | ||
name: db_port | ||
title: Port for destination Postgres | ||
value_type: int8 | ||
input_type: number | ||
- | ||
name: commands_port | ||
title: Port for AcraServer's HTTP API | ||
value_type: int8 | ||
input_type: number | ||
- | ||
name: debug | ||
title: Turn on debug logging | ||
value_type: bool | ||
input_type: radio | ||
values: [true, false] | ||
labels: [Yes, No] | ||
- | ||
name: poisonscript | ||
title: Execute script on detecting poison record | ||
value_type: string | ||
input_type: text | ||
- | ||
name: poisonshutdown | ||
title: Stop on detecting poison record | ||
value_type: bool | ||
values: [true, false] | ||
labels: [Yes, No] | ||
input_type: radio | ||
|
||
- | ||
name: server_id | ||
title: ID to be sent in secure session | ||
value_type: string | ||
input_type: text | ||
- | ||
name: zonemode | ||
title: Turn on zone mode | ||
value_type: bool | ||
values: [true, false] | ||
labels: [Yes, No] | ||
input_type: radio |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | ||
<meta charset="utf-8"> | ||
<title>ACRA ConfigUI</title> | ||
<link rel="shortcut icon" type="image/x-icon" href="/static/img/favicon.ico"/> | ||
|
||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" | ||
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> | ||
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" | ||
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> | ||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.bundle.min.js" | ||
integrity="sha384-feJI7QwhOS+hwpX2zkaeJQjeiwlhOP+SdQDqhgvvo1DsjtiSQByFdThsxO669S2D" crossorigin="anonymous"></script> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsrender/0.9.90/jsrender.js" | ||
integrity="sha256-vnIot7uxN4jRvM5P1QDlpy3M8eiR0KwODT0QFKHDhq8=" crossorigin="anonymous"></script> | ||
<script type="text/javascript" src="/static/js/main.js"></script> | ||
<script type="text/javascript"> | ||
configParams = JSON.parse({{.ConfigParams}}); | ||
currentConfig = {{.ConfigAcraServer}}; | ||
</script> | ||
|
||
<style type="text/css"> | ||
html { | ||
font-size: 0.9rem; | ||
} | ||
body{ | ||
padding: 1em; | ||
} | ||
.template{ | ||
display: none; | ||
} | ||
</style> | ||
|
||
<script id="settingsTplRow" type="text/x-jsrender" class="template"> | ||
<table class="table"> | ||
<thead> | ||
<tr> | ||
<th scope="col">#</th> | ||
<th scope="col">Value</th> | ||
<th scope="col">Description</th> | ||
<th scope="col">Alias</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{-for options itemVar="~options"-} | ||
<tr> | ||
<th scope="row">{-:#getIndex()+1-}</th> | ||
<td> | ||
{-if input_type == 'number'-} | ||
<input type="number" name="{-:name-}" value=""> | ||
{-else input_type == 'radio'-} | ||
{-for labels-} | ||
<input type="radio" name="{-:~options.name-}" value="{-:~options.values[#index]-}" id="{-:~options.name-}_{->#data-}"> | ||
<label for="{-:~options.name-}_{->#data-}">{->#data-}</label> | ||
{-/for-} | ||
{-else-} | ||
<input type="text" name="{-:name-}" value=""> | ||
{-/if-} | ||
</td> | ||
<td>{-:title-}</td> | ||
<td>{-:name-}</td> | ||
</tr> | ||
{-/for-} | ||
</tbody> | ||
</table> | ||
<button onclick="javascript: save();">Save</button> | ||
</script> | ||
|
||
</head> | ||
|
||
<body> | ||
|
||
<div class="row"> | ||
<div class="col-3"> | ||
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical"> | ||
<a class="nav-link active show" id="v-pills-settings-tab" data-toggle="pill" href="#v-pills-settings" role="tab" aria-controls="v-pills-settings" aria-selected="false">AcraServer Settings</a> | ||
<a class="nav-link" id="v-pills-profile-tab" data-toggle="pill" href="#v-pills-profile" role="tab" aria-controls="v-pills-profile" aria-selected="true">Intrusion detection</a> | ||
<a class="nav-link" id="v-pills-messages-tab" data-toggle="pill" href="#v-pills-messages" role="tab" aria-controls="v-pills-messages" aria-selected="false">Zones</a> | ||
</div> | ||
</div> | ||
<div class="col-9"> | ||
<div class="tab-content" id="v-pills-tabContent"> | ||
<div class="tab-pane fade active show" id="v-pills-settings" role="tabpanel" aria-labelledby="v-pills-settings-tab"> | ||
|
||
</div> | ||
<div class="tab-pane fade" id="v-pills-profile" role="tabpanel" aria-labelledby="v-pills-profile-tab"> | ||
<p>Coming soon...</p> | ||
</div> | ||
<div class="tab-pane fade" id="v-pills-messages" role="tabpanel" aria-labelledby="v-pills-messages-tab"> | ||
<p>Coming soon...</p> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
$(document).ready(function () { | ||
$.views.settings.delimiters("{-", "-}"); | ||
var options = []; | ||
$.each(configParams.Config, function (i, item) { | ||
options.push(item); | ||
}); | ||
var tpl = $($.templates('#settingsTplRow').render({ | ||
options: options | ||
})); | ||
tpl.appendTo($('#v-pills-settings')); | ||
|
||
// set checkox values | ||
$.each(configParams['Config'], function (i, item) { | ||
if (item.input_type == 'radio') { | ||
if (currentConfig[item.name] == undefined) { | ||
$('#v-pills-settings').find('input[type="radio"][name="' + item.name + '"][value="' + item.value + '"]').attr('checked', 'checked'); | ||
} | ||
else { | ||
var v = currentConfig[item.name] ? 1 : 0; | ||
$('#v-pills-settings').find('input[type="radio"][name="' + item.name + '"][value="' + currentConfig[item.name] + '"]').attr('checked', 'checked'); | ||
} | ||
} | ||
else { | ||
$('#v-pills-settings').find('input[name="' + item.name + '"]').val(currentConfig[item.name]); | ||
} | ||
}); | ||
|
||
$('#v-pills-tab a').on('click', function (e) { | ||
e.preventDefault(); | ||
$(this).tab('show'); | ||
}) | ||
}); | ||
|
||
var save = function () { | ||
var data = {}; | ||
$.each(configParams['Config'], function (i, item) { | ||
if (item.input_type == 'radio') { | ||
data[item.name] = $('#v-pills-settings').find('input:checked[type="radio"][name="' + item.name + '"]').val(); | ||
} | ||
else { | ||
data[item.name] = $('#v-pills-settings').find('input[name="' + item.name + '"]').val(); | ||
} | ||
}); | ||
|
||
$.ajax({ | ||
method: 'POST', | ||
url: "/acraserver/submit_setting", | ||
data: data | ||
}).done(function () { | ||
$(this).addClass("done"); | ||
}); | ||
}; |
Oops, something went wrong.