-
Notifications
You must be signed in to change notification settings - Fork 128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
acra_configui #111
acra_configui #111
Changes from 6 commits
cb33b7c
52433be
3d8eec4
a35f445
0df305d
7812add
846b14f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
package main | ||
|
||
// TODO: errors output, | ||
|
||
// sdfsdf | ||
|
||
import ( | ||
//"io/ioutil" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we remove this lines? https://godoc.org/golang.org/x/tools/cmd/goimports - this tool drop unnecessary imports and add missing. it help to not care about commenting some imports. (golang IDE can run it for every .go file on save) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cleaned. Tip: IDE can manage this using "Reformat Code" action |
||
//"html/template" | ||
"net/http" | ||
"log" | ||
"html/template" | ||
"path/filepath" | ||
"gopkg.in/yaml.v2" | ||
"io/ioutil" | ||
"time" | ||
"encoding/json" | ||
"strconv" | ||
"bytes" | ||
"os" | ||
"fmt" | ||
"flag" | ||
) | ||
|
||
func check(e error) { | ||
if e != nil { | ||
panic(e) | ||
} | ||
} | ||
|
||
type paramYAML struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought how we can avoid duplicating and remembered that we can operate with interface{} or map values and convert to/from json/yaml. But when I tried use struct directly I took correct converting without hacks
So I think better to use one struct instead two and avoid problem with synchronization There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It fails for me in go1.5.4 with struct tags to make input/output more json/yaml convenient and compatible to current configs |
||
Name string `yaml:"name"` | ||
Title string `yaml:"title"` | ||
Value_type string `yaml:"value_type"` | ||
Input_type string `yaml:"input_type"` | ||
Values []string `yaml:"values,flow"` | ||
Labels []string `yaml:"labels,flow"` | ||
} | ||
|
||
type paramJSON struct { | ||
Name string `json:"name"` | ||
Title string `json:"title"` | ||
Value_type string `json:"value_type"` | ||
Input_type string `json:"input_type"` | ||
Values []string `json:"values,flow"` | ||
Labels []string `json:"labels,flow"` | ||
} | ||
|
||
type configParamsYAML struct { | ||
Config []paramYAML | ||
} | ||
|
||
type configParamsJSON struct { | ||
Config []paramJSON | ||
} | ||
|
||
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"` | ||
} | ||
|
||
type JsonResponse struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where is this struct used? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed |
||
Success bool `json:"success"` | ||
} | ||
|
||
func nop_map(map[string][]string) {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is it used anywhere? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nop, removed |
||
func nop_string(string) {} | ||
|
||
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 { | ||
panic(err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think better to log error and exit. Then we can collect logs and do some processing, count errors, etc. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree to log, but it's request processing and we should continue with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can panic and log together. panic to process error as it expected by framework and add log record to process it in a future with our format, not with format of panic messages. Human message like "can't parse post form in 'getConfig' api methid" will be better than something like "incorrect url parameters format" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
} | ||
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 { | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
req, err := http.NewRequest("POST", "http://localhost:9292/setConfig", bytes.NewBuffer(jsonToServer)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. better to change hardcoded string in code to some const or read from config There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
req.Header.Set("Content-Type", "application/json") | ||
client := &http.Client{} | ||
resp, err := client.Do(req) | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
defer resp.Body.Close() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. code below can't fail (as I see, they don't return any error) so better to just call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
||
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") | ||
ip := filepath.Join("static", "index.html") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. refactored |
||
tmpl, _ := template.ParseFiles(ip) | ||
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("http://localhost:9292/getConfig") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the same as above with hardcoded url There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
if err != nil { | ||
log.Printf("ERROR: api error - %s", err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in previous PR I changed all logs to using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed to github.com/sirupsen/logrus |
||
} | ||
serverConfigDataJsonString, err := ioutil.ReadAll(serverResponse.Body) | ||
defer serverResponse.Body.Close() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
var serverConfigData ConfigAcraServer | ||
err = json.Unmarshal(serverConfigDataJsonString, &serverConfigData) | ||
if err != nil { | ||
log.Printf("ERROR: json.Unmarshal error - %s", err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
} | ||
// log.Println(serverConfigData) | ||
// end get current config | ||
|
||
yaml.Unmarshal(configParamsYAML, &outConfigParams) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. check error? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. checked |
||
|
||
var configParams configParamsJSON | ||
for _, item := range outConfigParams.Config { | ||
c := paramJSON{ | ||
Name: item.Name, | ||
Title: item.Title, | ||
Value_type: item.Value_type, | ||
Input_type: item.Input_type, | ||
Values: item.Values, | ||
Labels: item.Labels, | ||
} | ||
configParams.Config = append(configParams.Config, c) | ||
} | ||
// log.Println(configParams) | ||
|
||
res, err := json.Marshal(configParams) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. check error? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
|
||
tmpl.Execute(w, struct { | ||
ConfigParams string | ||
ConfigAcraServer | ||
}{ | ||
string(res), | ||
serverConfigData, | ||
}) | ||
} | ||
|
||
func main() { | ||
port := flag.Int("port", 8000, "Port for configUI HTTP endpoint") | ||
flag.Parse() | ||
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.Println(fmt.Sprintf("AcraConfigUI is listening @ :%d with PID %d", *port, os.Getpid())) | ||
err := http.ListenAndServe(fmt.Sprintf(":%d", *port), nil) | ||
check(err) | ||
} |
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 |
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" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we place blocking javascript resources before There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need this to use jQuery and see rendered layout with styles applied. |
||
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> |
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"); | ||
}); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cleaned