Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 123 additions & 10 deletions cmd/admin/handlers-post.go
Original file line number Diff line number Diff line change
Expand Up @@ -601,21 +601,29 @@ func confPOSTHandler(w http.ResponseWriter, r *http.Request) {
} else {
// Check CSRF Token
if checkCSRFToken(ctx["csrftoken"], c.CSRFToken) {
configuration, err := base64.StdEncoding.DecodeString(c.ConfigurationB64)
if err != nil {
responseMessage = "error decoding configuration"
responseCode = http.StatusInternalServerError
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Printf("DebugService: %s %v", responseMessage, err)
}
} else {
err = envs.UpdateConfiguration(environmentVar, string(configuration))
if c.ConfigurationB64 != "" {
configuration, err := base64.StdEncoding.DecodeString(c.ConfigurationB64)
if err != nil {
responseMessage = "error saving configuration"
responseMessage = "error decoding configuration"
responseCode = http.StatusInternalServerError
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Printf("DebugService: %s %v", responseMessage, err)
}
} else {
err = envs.UpdateConfiguration(environmentVar, string(configuration))
if err != nil {
responseMessage = "error saving configuration"
responseCode = http.StatusInternalServerError
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Printf("DebugService: %s %v", responseMessage, err)
}
}
}
} else {
responseMessage = "empty configuration"
responseCode = http.StatusInternalServerError
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Printf("DebugService: %s %v", responseMessage, err)
}
}
} else {
Expand Down Expand Up @@ -688,6 +696,24 @@ func intervalsPOSTHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("DebugService: %s %v", responseMessage, err)
}
}
// After updating interval, you need to re-generate flags
flags, err := envs.GenerateFlagsEnv(environmentVar, "", "")
if err == nil {
// Update flags in the newly created environment
if err := envs.UpdateFlags(environmentVar, flags); err != nil {
responseMessage = "error updating flags"
responseCode = http.StatusInternalServerError
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Printf("DebugService: %s %v", responseMessage, err)
}
}
} else {
responseMessage = "error re-generating flags"
responseCode = http.StatusInternalServerError
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Printf("DebugService: %s %v", responseMessage, err)
}
}
} else {
responseMessage = "invalid CSRF token"
responseCode = http.StatusInternalServerError
Expand Down Expand Up @@ -1214,3 +1240,90 @@ func usersPOSTHandler(w http.ResponseWriter, r *http.Request) {
log.Println("DebugService: Users response sent")
}
}

// Handler POST requests enroll data
func enrollPOSTHandler(w http.ResponseWriter, r *http.Request) {
responseMessage := "Enroll data saved successfully"
responseCode := http.StatusOK
utils.DebugHTTPDump(r, settingsmgr.DebugHTTP(settings.ServiceAdmin), true)
vars := mux.Vars(r)
// Extract environment and verify
environmentVar, ok := vars["environment"]
if !ok || !envs.Exists(environmentVar) {
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Printf("DebugService: error getting environment")
}
return
}
// Verify environment
if !envs.Exists(environmentVar) {
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Printf("DebugService: error unknown environment (%s)", environmentVar)
}
return
}
var e EnrollRequest
// Get context data
ctx := r.Context().Value(contextKey("session")).(contextValue)
// Parse request JSON body
err := json.NewDecoder(r.Body).Decode(&e)
if err != nil {
responseMessage = "error parsing POST body"
responseCode = http.StatusInternalServerError
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Printf("DebugService: %s %v", responseMessage, err)
}
} else {
// Check CSRF Token
if checkCSRFToken(ctx["csrftoken"], e.CSRFToken) {
if e.CertificateB64 != "" {
certificate, err := base64.StdEncoding.DecodeString(e.CertificateB64)
if err != nil {
responseMessage = "error decoding certificate"
responseCode = http.StatusInternalServerError
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Printf("DebugService: %s %v", responseMessage, err)
}
} else {
err = envs.UpdateCertificate(environmentVar, string(certificate))
if err != nil {
responseMessage = "error saving certificate"
responseCode = http.StatusInternalServerError
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Printf("DebugService: %s %v", responseMessage, err)
}
}
}
} else {
responseMessage = "empty certificate"
responseCode = http.StatusInternalServerError
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Printf("DebugService: %s %v", responseMessage, err)
}
}
} else {
responseMessage = "invalid CSRF token"
responseCode = http.StatusInternalServerError
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Printf("DebugService: %s %v", responseMessage, err)
}
}
}
// Prepare response
response, err := json.Marshal(AdminResponse{Message: responseMessage})
if err != nil {
responseMessage = "error formating response"
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Printf("DebugService: %s %v", responseMessage, err)
}
responseCode = http.StatusInternalServerError
response = []byte(responseMessage)
}
// Send response
w.Header().Set("Content-Type", JSONApplicationUTF8)
w.WriteHeader(responseCode)
_, _ = w.Write(response)
if settingsmgr.DebugService(settings.ServiceAdmin) {
log.Println("DebugService: Configuration response sent")
}
}
6 changes: 3 additions & 3 deletions cmd/admin/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ const JSONApplicationUTF8 string = JSONApplication + "; charset=UTF-8"
// Empty default osquery configuration
const emptyConfiguration string = "data/osquery-empty.json"

// Handle testing requests
func testingHTTPHandler(w http.ResponseWriter, r *http.Request) {
// Handle health requests
func healthHTTPHandler(w http.ResponseWriter, r *http.Request) {
utils.DebugHTTPDump(r, settingsmgr.DebugHTTP(settings.ServiceAdmin), true)
// Send response
w.Header().Set("Content-Type", JSONApplicationUTF8)
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("test"))
_, _ = w.Write([]byte(""))
}

// Handle error requests
Expand Down
25 changes: 12 additions & 13 deletions cmd/admin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ const (
serviceDescription string = "Admin service for osctrl"
// Application description
appDescription string = serviceDescription + ", a fast and efficient osquery management"
// Default endpoint to handle HTTP testing
testingPath string = "/testing"
// Default endpoint to handle HTTP health
healthPath string = "/health"
// Default endpoint to handle HTTP errors
errorPath string = "/error"
// Default service configuration file
Expand Down Expand Up @@ -95,7 +95,7 @@ var validAuth = map[string]bool{
settings.AuthJSON: true,
}
var validLogging = map[string]bool{
settings.LoggingDB: true,
settings.LoggingDB: true,
}

// Function to load the configuration file
Expand Down Expand Up @@ -256,8 +256,8 @@ func main() {
routerAdmin.HandleFunc("/login", loginGETHandler).Methods("GET")
routerAdmin.HandleFunc("/login", loginPOSTHandler).Methods("POST")
}
// Admin: testing
routerAdmin.HandleFunc(testingPath, testingHTTPHandler).Methods("GET")
// Admin: health of service
routerAdmin.HandleFunc(healthPath, healthHTTPHandler).Methods("GET")
// Admin: error
routerAdmin.HandleFunc(errorPath, errorHTTPHandler).Methods("GET")
// Admin: favicon
Expand Down Expand Up @@ -324,23 +324,22 @@ func main() {
routerAdmin.Handle("/intervals/{environment}", handlerAuthCheck(http.HandlerFunc(intervalsPOSTHandler))).Methods("POST")
// Admin: nodes enroll
routerAdmin.Handle("/enroll/{environment}", handlerAuthCheck(http.HandlerFunc(enrollGETHandler))).Methods("GET")
routerAdmin.Handle("/enroll/{environment}", handlerAuthCheck(http.HandlerFunc(enrollPOSTHandler))).Methods("POST")
routerAdmin.Handle("/expiration/{environment}", handlerAuthCheck(http.HandlerFunc(expirationPOSTHandler))).Methods("POST")
// Admin: server settings
routerAdmin.Handle("/settings/{service}", handlerAuthCheck(http.HandlerFunc(settingsGETHandler))).Methods("GET")
routerAdmin.Handle("/settings/{service}", handlerAuthCheck(http.HandlerFunc(settingsPOSTHandler))).Methods("POST")
// Admin: manage environments
routerAdmin.Handle("/environments", handlerAuthCheck(http.HandlerFunc(envsGETHandler))).Methods("GET")
routerAdmin.Handle("/environments", handlerAuthCheck(http.HandlerFunc(envsPOSTHandler))).Methods("POST")
// Admin: manage users if authentication is enabled
if adminConfig.Auth != settings.AuthNone {
routerAdmin.Handle("/users", handlerAuthCheck(http.HandlerFunc(usersGETHandler))).Methods("GET")
routerAdmin.Handle("/users", handlerAuthCheck(http.HandlerFunc(usersPOSTHandler))).Methods("POST")
// logout
routerAdmin.Handle("/logout", handlerAuthCheck(http.HandlerFunc(logoutHandler))).Methods("POST")
}
// Admin: manage users
routerAdmin.Handle("/users", handlerAuthCheck(http.HandlerFunc(usersGETHandler))).Methods("GET")
routerAdmin.Handle("/users", handlerAuthCheck(http.HandlerFunc(usersPOSTHandler))).Methods("POST")
// logout
routerAdmin.Handle("/logout", handlerAuthCheck(http.HandlerFunc(logoutHandler))).Methods("POST")

// SAML ACS
if adminConfig.Auth == settings.AuthNone {
if adminConfig.Auth == settings.AuthSAML {
routerAdmin.PathPrefix("/saml/").Handler(samlMiddleware)
}

Expand Down
22 changes: 22 additions & 0 deletions cmd/admin/static/js/enrolls.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,25 @@ function extendRemoveLink() {
function expireRemoveLink() {
genericLinkAction('remove', 'expire');
}

function confirmUploadCertificate() {
$('#certificate_action').click(function () {
$('#certificateModal').modal('hide');
uploadCertificate();
});
$("#certificateModal").modal();
}

function uploadCertificate() {
var _csrftoken = $("#csrftoken").val();
var _blob = $('#certificate').data('CodeMirrorInstance');
var _certificate = _blob.getValue();

var _url = window.location.pathname;

var data = {
csrftoken: _csrftoken,
certificate: btoa(_certificate),
};
sendPostRequest(data, _url, window.location.pathname, false);
}
23 changes: 23 additions & 0 deletions cmd/admin/templates/components/page-modals.html
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,27 @@ <h4 class="modal-title">Action can not be completed</h4>
</div>
<!-- /.modal -->

<div class="modal fade" id="certificateModal" tabindex="-1" role="dialog" aria-labelledby="certificateModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dark modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Upload new certificate</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<textarea id="certificate" name="certificate"></textarea>
</div>
<div class="modal-footer">
<button id="certificate_action" type="button" class="btn btn-dark" data-dismiss="modal">Upload</button>
<button type="button" class="btn btn-danger" data-dismiss="modal">Cancel</button>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->

{{ end }}
20 changes: 18 additions & 2 deletions cmd/admin/templates/enroll.html
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,16 @@
<hr>

<div class="row mb-4">
<div class="col-md-12">
Enrollment certificate:
<div class="row col-md-12">
<div class="col-md-10">
Enrollment certificate:
</div>
<div class="col-md-2">
<button id="" class="btn btn-sm btn-block btn-dark"
data-tooltip="true" data-placement="bottom" title="Upload new certificate" onclick="confirmUploadCertificate();">
<i class="fas fa-upload"></i>
</button>
</div>
</div>
</div>
<div class="row mb-4">
Expand Down Expand Up @@ -262,6 +270,14 @@
hljs.initHighlightingOnLoad();

$(document).ready(function() {
// Codemirror editor for configuration
var certificateBlob = CodeMirror.fromTextArea(document.getElementById("certificate"), {
mode: 'text/plain',
lineNumbers: true
});
$('#certificate').data('CodeMirrorInstance', certificateBlob);
certificateBlob.setSize("100%", "100%");

// Highlight.js code element initialization
$('code').each(function(i, block) {
hljs.highlightBlock(block);
Expand Down
6 changes: 6 additions & 0 deletions cmd/admin/types-requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ type ConfigurationRequest struct {
ConfigurationB64 string `json:"configuration"`
}

// EnrollRequest to receive changes to enroll certificates
type EnrollRequest struct {
CSRFToken string `json:"csrftoken"`
CertificateB64 string `json:"certificate"`
}

// IntervalsRequest to receive changes to intervals
type IntervalsRequest struct {
CSRFToken string `json:"csrftoken"`
Expand Down
6 changes: 3 additions & 3 deletions cmd/tls/handlers-tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ func okHTTPHandler(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte("💥"))
}

// Handle testing requests
func testingHTTPHandler(w http.ResponseWriter, r *http.Request) {
// Handle health requests
func healthHTTPHandler(w http.ResponseWriter, r *http.Request) {
// Send response
w.Header().Set("Content-Type", JSONApplicationUTF8)
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("test"))
_, _ = w.Write([]byte(""))
}

// Handle error requests
Expand Down
6 changes: 3 additions & 3 deletions cmd/tls/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ const (
serviceDescription string = "TLS service for osctrl"
// Application description
appDescription string = serviceDescription + ", a fast and efficient osquery management"
// Default endpoint to handle HTTP testing
testingPath string = "/testing"
// Default endpoint to handle HTTP health
healthPath string = "/health"
// Default endpoint to handle HTTP errors
errorPath string = "/error"
// Default service configuration file
Expand Down Expand Up @@ -168,7 +168,7 @@ func main() {
// TLS: root
routerTLS.HandleFunc("/", okHTTPHandler)
// TLS: testing
routerTLS.HandleFunc(testingPath, testingHTTPHandler).Methods("GET")
routerTLS.HandleFunc(healthPath, healthHTTPHandler).Methods("GET")
// TLS: error
routerTLS.HandleFunc(errorPath, errorHTTPHandler).Methods("GET")
// TLS: Specific routes for osquery nodes
Expand Down
Loading