create audit module

This commit is contained in:
yuli
2024-12-28 21:39:51 +02:00
parent 4c62cad36b
commit 6e1dbf4f14
27 changed files with 357 additions and 356 deletions

View File

@@ -5,7 +5,7 @@ FROM golang:alpine AS builder
RUN apk update && apk add --no-cache git gcc libc-dev openssl && go install github.com/gobuffalo/packr/packr@latest
WORKDIR /go/src/securitybunker/databunker/src/
COPY src/go.mod ./deps
RUN cat ./deps | grep -v storage | grep -v utils > ./go.mod && go mod download
RUN cat ./deps | grep -v storage | grep -v utils | grep -v audit > ./go.mod && go mod download
COPY . /go/src/securitybunker/databunker/
WORKDIR /go/src/securitybunker/databunker/
#RUN echo "tidy " && go get -u && go mod tidy && cat ./go.mod

View File

@@ -1,5 +1,5 @@
#!/bin/sh
VERSION=$(cat ./version.txt)
docker build -t securitybunker/databunker:$VERSION .
docker build --progress=plain -t securitybunker/databunker:$VERSION .
docker tag securitybunker/databunker:$VERSION securitybunker/databunker:latest

View File

@@ -7,6 +7,7 @@ import (
"reflect"
"github.com/julienschmidt/httprouter"
"github.com/securitybunker/databunker/src/audit"
"github.com/securitybunker/databunker/src/utils"
//"go.mongodb.org/mongo-driver/bson"
)
@@ -15,35 +16,35 @@ func (e mainEnv) agreementAccept(w http.ResponseWriter, r *http.Request, ps http
identity := ps.ByName("identity")
brief := ps.ByName("brief")
mode := ps.ByName("mode")
event := audit("accept agreement by "+brief, identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("accept agreement by "+brief, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false {
ReturnError(w, r, "bad mode", 405, nil, event)
utils.ReturnError(w, r, "bad mode", 405, nil, event)
return
}
brief = utils.NormalizeBrief(brief)
if utils.CheckValidBrief(brief) == false {
ReturnError(w, r, "bad brief format", 405, nil, event)
utils.ReturnError(w, r, "bad brief format", 405, nil, event)
return
}
exists, err := e.db.checkLegalBasis(brief)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if exists == false {
ReturnError(w, r, "not found", 404, nil, event)
utils.ReturnError(w, r, "not found", 404, nil, event)
return
}
userTOKEN := ""
if mode == "token" {
if EnforceUUID(w, identity, event) == false {
if utils.EnforceUUID(w, identity, event) == false {
return
}
userBson, err := e.db.lookupUserRecord(identity)
if err != nil || userBson == nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if e.EnforceAuth(w, r, event) == "" {
@@ -53,7 +54,7 @@ func (e mainEnv) agreementAccept(w http.ResponseWriter, r *http.Request, ps http
} else {
userBson, err := e.db.lookupUserRecordByIndex(mode, identity, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if userBson != nil {
@@ -61,7 +62,7 @@ func (e mainEnv) agreementAccept(w http.ResponseWriter, r *http.Request, ps http
event.Record = userTOKEN
} else {
if mode == "login" {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
// else user not found - we allow to save consent for unlinked users!
@@ -70,7 +71,7 @@ func (e mainEnv) agreementAccept(w http.ResponseWriter, r *http.Request, ps http
records, err := utils.GetJSONPostMap(r)
if err != nil {
ReturnError(w, r, "failed to decode request body", 405, err, event)
utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return
}
starttime := int32(0)
@@ -129,37 +130,37 @@ func (e mainEnv) agreementWithdraw(w http.ResponseWriter, r *http.Request, ps ht
identity := ps.ByName("identity")
brief := ps.ByName("brief")
mode := ps.ByName("mode")
event := audit("withdraw agreement by "+brief, identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("withdraw agreement by "+brief, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false {
ReturnError(w, r, "bad mode", 405, nil, event)
utils.ReturnError(w, r, "bad mode", 405, nil, event)
return
}
brief = utils.NormalizeBrief(brief)
if utils.CheckValidBrief(brief) == false {
ReturnError(w, r, "bad brief format", 405, nil, event)
utils.ReturnError(w, r, "bad brief format", 405, nil, event)
return
}
lbasis, err := e.db.getLegalBasis(brief)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if lbasis == nil {
ReturnError(w, r, "not found", 405, nil, event)
utils.ReturnError(w, r, "not found", 405, nil, event)
return
}
userTOKEN := ""
authResult := ""
if mode == "token" {
if EnforceUUID(w, identity, event) == false {
if utils.EnforceUUID(w, identity, event) == false {
return
}
userBson, _ := e.db.lookupUserRecord(identity)
if userBson == nil {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
authResult = e.EnforceAuth(w, r, event)
@@ -175,7 +176,7 @@ func (e mainEnv) agreementWithdraw(w http.ResponseWriter, r *http.Request, ps ht
event.Record = userTOKEN
} else {
if mode == "login" {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
// else user not found - we allow to save consent for unlinked users!
@@ -183,7 +184,7 @@ func (e mainEnv) agreementWithdraw(w http.ResponseWriter, r *http.Request, ps ht
}
records, err := utils.GetJSONPostMap(r)
if err != nil {
ReturnError(w, r, "failed to decode request body", 405, err, event)
utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return
}
lastmodifiedby := utils.GetStringValue(records["lastmodifiedby"])
@@ -210,7 +211,7 @@ func (e mainEnv) agreementWithdraw(w http.ResponseWriter, r *http.Request, ps ht
if authResult == "login" && selfService == false {
rtoken, rstatus, err := e.db.saveUserRequest("agreement-withdraw", userTOKEN, "", brief, nil, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -243,16 +244,16 @@ func (e mainEnv) agreementRevokeAll(w http.ResponseWriter, r *http.Request, ps h
}
brief = utils.NormalizeBrief(brief)
if utils.CheckValidBrief(brief) == false {
ReturnError(w, r, "bad brief format", 405, nil, nil)
utils.ReturnError(w, r, "bad brief format", 405, nil, nil)
return
}
exists, err := e.db.checkLegalBasis(brief)
if err != nil {
ReturnError(w, r, "internal error", 405, nil, nil)
utils.ReturnError(w, r, "internal error", 405, nil, nil)
return
}
if exists == false {
ReturnError(w, r, "not found", 405, nil, nil)
utils.ReturnError(w, r, "not found", 405, nil, nil)
return
}
e.db.revokeLegalBasis(brief)
@@ -264,22 +265,22 @@ func (e mainEnv) agreementRevokeAll(w http.ResponseWriter, r *http.Request, ps h
func (e mainEnv) getUserAgreements(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := audit("privacy agreements for "+mode, identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("privacy agreements for "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false {
ReturnError(w, r, "bad mode", 405, nil, event)
utils.ReturnError(w, r, "bad mode", 405, nil, event)
return
}
userTOKEN := ""
if mode == "token" {
if EnforceUUID(w, identity, event) == false {
if utils.EnforceUUID(w, identity, event) == false {
return
}
userBson, _ := e.db.lookupUserRecord(identity)
if userBson == nil {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
if e.EnforceAuth(w, r, event) == "" {
@@ -297,7 +298,7 @@ func (e mainEnv) getUserAgreements(w http.ResponseWriter, r *http.Request, ps ht
}
} else {
if mode == "login" {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
// else user not found - we allow to save consent for unlinked users!
@@ -317,7 +318,7 @@ func (e mainEnv) getUserAgreements(w http.ResponseWriter, r *http.Request, ps ht
resultJSON, numRecords, err = e.db.listAgreementRecordsByIdentity(identity)
}
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -330,35 +331,35 @@ func (e mainEnv) getUserAgreement(w http.ResponseWriter, r *http.Request, ps htt
identity := ps.ByName("identity")
brief := ps.ByName("brief")
mode := ps.ByName("mode")
event := audit("privacy agreements for "+mode, identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("privacy agreements for "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false {
ReturnError(w, r, "bad mode", 405, nil, event)
utils.ReturnError(w, r, "bad mode", 405, nil, event)
return
}
brief = utils.NormalizeBrief(brief)
if utils.CheckValidBrief(brief) == false {
ReturnError(w, r, "bad brief format", 405, nil, event)
utils.ReturnError(w, r, "bad brief format", 405, nil, event)
return
}
exists, err := e.db.checkLegalBasis(brief)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if exists == false {
ReturnError(w, r, "not found", 404, nil, event)
utils.ReturnError(w, r, "not found", 404, nil, event)
return
}
userTOKEN := ""
if mode == "token" {
if EnforceUUID(w, identity, event) == false {
if utils.EnforceUUID(w, identity, event) == false {
return
}
userBson, _ := e.db.lookupUserRecord(identity)
if userBson == nil {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
if e.EnforceAuth(w, r, event) == "" {
@@ -376,7 +377,7 @@ func (e mainEnv) getUserAgreement(w http.ResponseWriter, r *http.Request, ps htt
}
} else {
if mode == "login" {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
// else user not found - we allow to save consent for unlinked users!
@@ -389,11 +390,11 @@ func (e mainEnv) getUserAgreement(w http.ResponseWriter, r *http.Request, ps htt
var resultJSON []byte
resultJSON, err = e.db.viewAgreementRecord(userTOKEN, brief)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if resultJSON == nil {
ReturnError(w, r, "not found", 405, err, event)
utils.ReturnError(w, r, "not found", 405, err, event)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -407,16 +408,16 @@ func (e mainEnv) consentUserRecord(w http.ResponseWriter, r *http.Request, ps ht
identity := ps.ByName("identity")
brief := ps.ByName("brief")
mode := ps.ByName("mode")
event := audit("consent record for "+brief, identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("consent record for "+brief, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false {
ReturnError(w, r, "bad mode", 405, nil, event)
utils.ReturnError(w, r, "bad mode", 405, nil, event)
return
}
brief = utils.NormalizeBrief(brief)
if utils.CheckValidBrief(brief) == false {
ReturnError(w, r, "bad brief format", 405, nil, event)
utils.ReturnError(w, r, "bad brief format", 405, nil, event)
return
}
userTOKEN := identity
@@ -434,7 +435,7 @@ func (e mainEnv) consentUserRecord(w http.ResponseWriter, r *http.Request, ps ht
}
}
if userBson == nil {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
// make sure that user is logged in here, unless he wants to cancel emails
@@ -443,11 +444,11 @@ func (e mainEnv) consentUserRecord(w http.ResponseWriter, r *http.Request, ps ht
}
resultJSON, err := e.db.viewConsentRecord(userTOKEN, brief)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if resultJSON == nil {
ReturnError(w, r, "not found", 405, nil, event)
utils.ReturnError(w, r, "not found", 405, nil, event)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -460,8 +461,8 @@ func (e mainEnv) consentUserRecord(w http.ResponseWriter, r *http.Request, ps ht
/*
func (e mainEnv) consentFilterRecords(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
brief := ps.ByName("brief")
event := audit("consent get all for "+brief, brief, "brief", brief)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("consent get all for "+brief, brief, "brief", brief)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if e.EnforceAuth(w, r, event) == "" {
return
}
@@ -476,7 +477,7 @@ func (e mainEnv) consentFilterRecords(w http.ResponseWriter, r *http.Request, ps
}
resultJSON, numRecords, err := e.db.filterConsentRecords(brief, offset, limit)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
log.Printf("Total count of rows: %d\n", numRecords)

View File

@@ -6,43 +6,11 @@ import (
"net/http"
"github.com/julienschmidt/httprouter"
"github.com/securitybunker/databunker/src/audit"
"github.com/securitybunker/databunker/src/utils"
)
func ReturnError(w http.ResponseWriter, r *http.Request, message string, code int, err error, event *auditEvent) {
log.Printf("[%d] %s %s -> Return error\n", code, r.Method, r.URL.Path)
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(code)
fmt.Fprintf(w, `{"status":"error","message":%q}`, message)
if event != nil {
event.Status = "error"
event.Msg = message
if err != nil {
event.Debug = err.Error()
log.Printf("Generate error response: %s, Error: %s\n", message, err.Error())
} else {
log.Printf("Generate error response: %s\n", message)
}
}
//http.Error(w, http.StatusText(405), 405)
}
func EnforceUUID(w http.ResponseWriter, uuidCode string, event *auditEvent) bool {
if utils.CheckValidUUID(uuidCode) == false {
//fmt.Printf("405 bad uuid in : %s\n", uuidCode)
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(405)
fmt.Fprintf(w, `{"status":"error","message":"bad uuid"}`)
if event != nil {
event.Status = "error"
event.Msg = "bad uuid"
}
return false
}
return true
}
func (e mainEnv) EnforceAuth(w http.ResponseWriter, r *http.Request, event *auditEvent) string {
func (e mainEnv) EnforceAuth(w http.ResponseWriter, r *http.Request, event *audit.AuditEvent) string {
/*
for key, value := range r.Header {
fmt.Printf("%s => %s\n", key, value)
@@ -81,7 +49,7 @@ func (e mainEnv) EnforceAuth(w http.ResponseWriter, r *http.Request, event *audi
return ""
}
func (e mainEnv) EnforceAdmin(w http.ResponseWriter, r *http.Request, event *auditEvent) string {
func (e mainEnv) EnforceAdmin(w http.ResponseWriter, r *http.Request, event *audit.AuditEvent) string {
if token, ok := r.Header["X-Bunker-Token"]; ok {
authResult, err := e.db.checkUserAuthXToken(token[0])
//fmt.Printf("error in auth? error %s - %s\n", err, token[0])
@@ -102,9 +70,9 @@ func (e mainEnv) EnforceAdmin(w http.ResponseWriter, r *http.Request, event *aud
func (e mainEnv) getAuditEvents(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
userTOKEN := ps.ByName("token")
event := audit("view audit events", userTOKEN, "token", userTOKEN)
defer func() { event.submit(e.db, e.conf) }()
if EnforceUUID(w, userTOKEN, event) == false {
event := audit.CreateAuditEvent("view audit events", userTOKEN, "token", userTOKEN)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.EnforceUUID(w, userTOKEN, event) == false {
return
}
if e.EnforceAuth(w, r, event) == "" {
@@ -121,7 +89,7 @@ func (e mainEnv) getAuditEvents(w http.ResponseWriter, r *http.Request, ps httpr
}
resultJSON, counter, err := e.db.getAuditEvents(userTOKEN, offset, limit)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
//fmt.Printf("Total count of events: %d\n", counter)
@@ -146,7 +114,7 @@ func (e mainEnv) getAdminAuditEvents(w http.ResponseWriter, r *http.Request, ps
}
resultJSON, counter, err := e.db.getAdminAuditEvents(offset, limit)
if err != nil {
ReturnError(w, r, "internal error", 405, err, nil)
utils.ReturnError(w, r, "internal error", 405, err, nil)
return
}
//fmt.Printf("Total count of events: %d\n", counter)
@@ -158,16 +126,16 @@ func (e mainEnv) getAdminAuditEvents(w http.ResponseWriter, r *http.Request, ps
func (e mainEnv) getAuditEvent(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
atoken := ps.ByName("atoken")
event := audit("view audit event", atoken, "token", atoken)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("view audit event", atoken, "token", atoken)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
//fmt.Println("error code")
if EnforceUUID(w, atoken, event) == false {
if utils.EnforceUUID(w, atoken, event) == false {
return
}
userTOKEN, resultJSON, err := e.db.getAuditEvent(atoken)
log.Printf("extracted user token: %s", userTOKEN)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
event.Record = userTOKEN

View File

@@ -6,41 +6,18 @@ import (
"fmt"
//"log"
"time"
uuid "github.com/hashicorp/go-uuid"
"github.com/securitybunker/databunker/src/audit"
"github.com/securitybunker/databunker/src/storage"
"github.com/securitybunker/databunker/src/utils"
"go.mongodb.org/mongo-driver/bson"
)
type auditEvent struct {
When int32 `json:"when"`
Who string `json:"who"`
Mode string `json:"mode"`
Identity string `json:"identity"`
Record string `json:"record"`
App string `json:"app"`
Title string `json:"title"`
Status string `json:"status"`
Msg string `json:"msg"`
Debug string `json:"debug"`
Before string `json:"before"`
After string `json:"after"`
Atoken string `json:"atoken"`
}
func audit(title string, record string, mode string, identity string) *auditEvent {
//fmt.Printf("/%s : %s\n", title, record)
return &auditEvent{Title: title, Mode: mode, Who: identity, Record: record, Status: "ok", When: int32(time.Now().Unix())}
}
func auditApp(title string, record string, app string, mode string, identity string) *auditEvent {
//fmt.Printf("/%s : %s : %s\n", title, app, record)
return &auditEvent{Title: title, Mode: mode, Who: identity, Record: record, Status: "ok", When: int32(time.Now().Unix())}
}
func (event auditEvent) submit(db *dbcon, conf Config) {
func SaveAuditEvent(event *audit.AuditEvent, db *dbcon, conf Config) {
if event == nil {
return
}
if conf.Generic.DisableAudit == true {
return
}

View File

@@ -18,6 +18,7 @@ import (
"github.com/kelseyhightower/envconfig"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/securitybunker/databunker/src/audit"
"github.com/securitybunker/databunker/src/autocontext"
"github.com/securitybunker/databunker/src/storage"
"github.com/securitybunker/databunker/src/utils"
@@ -383,15 +384,15 @@ func (e mainEnv) dbCleanup() {
}
// helper function to load user details by idex name
func (e mainEnv) loadUserToken(w http.ResponseWriter, r *http.Request, mode string, identity string, event *auditEvent) string {
func (e mainEnv) loadUserToken(w http.ResponseWriter, r *http.Request, mode string, identity string, event *audit.AuditEvent) string {
var err error
if utils.ValidateMode(mode) == false {
ReturnError(w, r, "bad mode", 405, nil, event)
utils.ReturnError(w, r, "bad mode", 405, nil, event)
return ""
}
var userBson bson.M
if mode == "token" {
if EnforceUUID(w, identity, event) == false {
if utils.EnforceUUID(w, identity, event) == false {
return ""
}
userBson, err = e.db.lookupUserRecord(identity)
@@ -399,7 +400,7 @@ func (e mainEnv) loadUserToken(w http.ResponseWriter, r *http.Request, mode stri
userBson, err = e.db.lookupUserRecordByIndex(mode, identity, e.conf)
}
if userBson == nil || err != nil {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return ""
}
event.Record = userBson["token"].(string)

View File

@@ -28,19 +28,19 @@ func (e mainEnv) showCaptcha(w http.ResponseWriter, r *http.Request, ps httprout
code := ps.ByName("code")
if len(code) == 0 {
err := errors.New("Bad code")
ReturnError(w, r, "bad code", 405, err, nil)
utils.ReturnError(w, r, "bad code", 405, err, nil)
return
}
s, err := decryptCaptcha(code)
if err != nil {
ReturnError(w, r, err.Error(), 405, err, nil)
utils.ReturnError(w, r, err.Error(), 405, err, nil)
return
}
log.Printf("Decoded captcha: %s", s)
//box := packr.NewBox("../ui")
//comic, err := box.Find("site/fonts/comic.ttf")
//if err != nil {
// ReturnError(w, r, err.Error(), 405, err, nil)
// utils.ReturnError(w, r, err.Error(), 405, err, nil)
// return
//}
cap := captcha.New()

View File

@@ -7,6 +7,7 @@ import (
"github.com/julienschmidt/httprouter"
"github.com/securitybunker/databunker/src/autocontext"
"github.com/securitybunker/databunker/src/utils"
)
func (e mainEnv) setupConfRouter(router *httprouter.Router) *httprouter.Router {
@@ -23,7 +24,7 @@ func (e mainEnv) initContext(r *http.Request) {
func (e mainEnv) cookieSettings(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
resultJSON, scriptsJSON, _, err := e.db.getLegalBasisCookieConf()
if err != nil {
ReturnError(w, r, "internal error", 405, err, nil)
utils.ReturnError(w, r, "internal error", 405, err, nil)
return
}
resultUIConfJSON, _ := json.Marshal(e.conf.UI)

View File

@@ -6,6 +6,7 @@ import (
uuid "github.com/hashicorp/go-uuid"
"github.com/julienschmidt/httprouter"
"github.com/securitybunker/databunker/src/audit"
"github.com/securitybunker/databunker/src/storage"
"github.com/securitybunker/databunker/src/utils"
"go.mongodb.org/mongo-driver/bson"
@@ -31,16 +32,16 @@ func (e mainEnv) expUsers() error {
func (e mainEnv) expGetStatus(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := audit("get expiration status by "+mode, identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("get expiration status by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
var err error
if utils.ValidateMode(mode) == false {
ReturnError(w, r, "bad mode", 405, nil, event)
utils.ReturnError(w, r, "bad mode", 405, nil, event)
return
}
var userBson bson.M
if mode == "token" {
if EnforceUUID(w, identity, event) == false {
if utils.EnforceUUID(w, identity, event) == false {
return
}
userBson, err = e.db.lookupUserRecord(identity)
@@ -48,7 +49,7 @@ func (e mainEnv) expGetStatus(w http.ResponseWriter, r *http.Request, ps httprou
userBson, err = e.db.lookupUserRecordByIndex(mode, identity, e.conf)
}
if userBson == nil || err != nil {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
userTOKEN := userBson["token"].(string)
@@ -67,16 +68,16 @@ func (e mainEnv) expCancel(w http.ResponseWriter, r *http.Request, ps httprouter
var err error
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := audit("clear user expiration by "+mode, identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("clear user expiration by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false {
ReturnError(w, r, "bad mode", 405, nil, event)
utils.ReturnError(w, r, "bad mode", 405, nil, event)
return
}
userTOKEN := identity
var userBson bson.M
if mode == "token" {
if EnforceUUID(w, identity, event) == false {
if utils.EnforceUUID(w, identity, event) == false {
return
}
userBson, err = e.db.lookupUserRecord(identity)
@@ -88,13 +89,13 @@ func (e mainEnv) expCancel(w http.ResponseWriter, r *http.Request, ps httprouter
}
}
if userBson == nil || err != nil {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
status := ""
err = e.db.updateUserExpStatus(userTOKEN, status)
if err != nil {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
finalJSON := `{"status":"ok"}`
@@ -106,14 +107,14 @@ func (e mainEnv) expCancel(w http.ResponseWriter, r *http.Request, ps httprouter
func (e mainEnv) expRetainData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
identity := ps.ByName("exptoken")
mode := "exptoken"
event := audit("retain user data by exptoken", identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
if EnforceUUID(w, identity, event) == false {
event := audit.CreateAuditEvent("retain user data by exptoken", identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.EnforceUUID(w, identity, event) == false {
return
}
userBson, err := e.db.lookupUserRecordByIndex(mode, identity, e.conf)
if userBson == nil || err != nil {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
userTOKEN := userBson["token"].(string)
@@ -121,7 +122,7 @@ func (e mainEnv) expRetainData(w http.ResponseWriter, r *http.Request, ps httpro
status := "retain"
err = e.db.updateUserExpStatus(userTOKEN, status)
if err != nil {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
w.WriteHeader(200)
@@ -131,14 +132,14 @@ func (e mainEnv) expRetainData(w http.ResponseWriter, r *http.Request, ps httpro
func (e mainEnv) expDeleteData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
identity := ps.ByName("exptoken")
mode := "exptoken"
event := audit("delete user data by exptoken", identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
if EnforceUUID(w, identity, event) == false {
event := audit.CreateAuditEvent("delete user data by exptoken", identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.EnforceUUID(w, identity, event) == false {
return
}
userJSON, userTOKEN, userBSON, err := e.db.getUserByIndex(identity, mode, e.conf)
if userJSON == nil || err != nil {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
event.Record = userTOKEN
@@ -148,7 +149,7 @@ func (e mainEnv) expDeleteData(w http.ResponseWriter, r *http.Request, ps httpro
}
_, err = e.db.deleteUserRecord(userJSON, userTOKEN, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
e.db.updateUserExpStatus(userTOKEN, "expired")
@@ -160,8 +161,8 @@ func (e mainEnv) expStart(w http.ResponseWriter, r *http.Request, ps httprouter.
var err error
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := audit("initiate user record expiration by "+mode, identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("initiate user record expiration by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if e.EnforceAdmin(w, r, event) == "" {
return
@@ -172,7 +173,7 @@ func (e mainEnv) expStart(w http.ResponseWriter, r *http.Request, ps httprouter.
}
records, err := utils.GetJSONPostMap(r)
if err != nil {
ReturnError(w, r, "failed to decode request body", 405, err, event)
utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return
}
expirationStr := utils.GetStringValue(records["expiration"])
@@ -184,11 +185,11 @@ func (e mainEnv) expStart(w http.ResponseWriter, r *http.Request, ps httprouter.
}
expToken, err := uuid.GenerateUUID()
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
}
err = e.db.initiateUserExpiration(userTOKEN, endtime, status, expToken)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
finalJSON := fmt.Sprintf(`{"status":"ok","exptoken":"%s"}`, expToken)

View File

@@ -8,6 +8,8 @@ replace github.com/securitybunker/databunker/src/storage => ./storage
replace github.com/securitybunker/databunker/src/utils => ./utils
replace github.com/securitybunker/databunker/src/audit => ./audit
require (
github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868
github.com/evanphx/json-patch v5.9.0+incompatible
@@ -18,6 +20,7 @@ require (
github.com/oschwald/geoip2-golang v1.11.0
github.com/prometheus/client_golang v1.20.5
github.com/qri-io/jsonpointer v0.1.1
github.com/securitybunker/databunker/src/audit v0.0.0
github.com/securitybunker/databunker/src/storage v0.0.0
github.com/securitybunker/databunker/src/utils v0.0.0
github.com/securitybunker/jsonschema v0.2.1-0.20201128224651-d77c1a3cb787
@@ -62,7 +65,7 @@ require (
google.golang.org/protobuf v1.36.1 // indirect
modernc.org/gc/v3 v3.0.0-20241223112719-96e2e1e4408d // indirect
modernc.org/libc v1.61.5 // indirect
modernc.org/mathutil v1.7.0 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.8.0 // indirect
modernc.org/sqlite v1.34.4 // indirect
modernc.org/strutil v1.2.0 // indirect

View File

@@ -18,18 +18,18 @@ func (e mainEnv) createLegalBasis(w http.ResponseWriter, r *http.Request, ps htt
}
brief = utils.NormalizeBrief(brief)
if utils.CheckValidBrief(brief) == false {
ReturnError(w, r, "bad brief format", 405, nil, nil)
utils.ReturnError(w, r, "bad brief format", 405, nil, nil)
return
}
records, err := utils.GetJSONPostMap(r)
if err != nil {
ReturnError(w, r, "failed to decode request body", 405, err, nil)
utils.ReturnError(w, r, "failed to decode request body", 405, err, nil)
return
}
newbrief := utils.GetStringValue(records["brief"])
if len(newbrief) > 0 && newbrief != brief {
if utils.CheckValidBrief(newbrief) == false {
ReturnError(w, r, "bad brief format", 405, nil, nil)
utils.ReturnError(w, r, "bad brief format", 405, nil, nil)
return
}
}
@@ -88,7 +88,7 @@ func (e mainEnv) deleteLegalBasis(w http.ResponseWriter, r *http.Request, ps htt
}
brief = utils.NormalizeBrief(brief)
if utils.CheckValidBrief(brief) == false {
ReturnError(w, r, "bad brief format", 405, nil, nil)
utils.ReturnError(w, r, "bad brief format", 405, nil, nil)
return
}
e.db.unlinkProcessingActivityBrief(brief)
@@ -104,7 +104,7 @@ func (e mainEnv) listLegalBasisRecords(w http.ResponseWriter, r *http.Request, p
}
resultJSON, numRecords, err := e.db.getLegalBasisRecords()
if err != nil {
ReturnError(w, r, "internal error", 405, err, nil)
utils.ReturnError(w, r, "internal error", 405, err, nil)
return
}
log.Printf("Total count of rows: %d\n", numRecords)

View File

@@ -4,7 +4,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"log"
"net/http"
@@ -80,7 +80,7 @@ func notify(notifyURL string, host interface{}, requestBody []byte) {
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Printf("error in body read: %s", err)
return

View File

@@ -18,12 +18,12 @@ func (e mainEnv) pactivityCreate(w http.ResponseWriter, r *http.Request, ps http
}
activity = utils.NormalizeBrief(activity)
if utils.CheckValidBrief(activity) == false {
ReturnError(w, r, "bad activity format", 405, nil, nil)
utils.ReturnError(w, r, "bad activity format", 405, nil, nil)
return
}
records, err := utils.GetJSONPostMap(r)
if err != nil {
ReturnError(w, r, "failed to decode request body", 405, err, nil)
utils.ReturnError(w, r, "failed to decode request body", 405, err, nil)
return
}
defer func() {
@@ -76,7 +76,7 @@ func (e mainEnv) pactivityDelete(w http.ResponseWriter, r *http.Request, ps http
}
activity = utils.NormalizeBrief(activity)
if utils.CheckValidBrief(activity) == false {
ReturnError(w, r, "bad activity format", 405, nil, nil)
utils.ReturnError(w, r, "bad activity format", 405, nil, nil)
return
}
e.db.deleteProcessingActivity(activity)
@@ -93,26 +93,26 @@ func (e mainEnv) pactivityLink(w http.ResponseWriter, r *http.Request, ps httpro
}
activity = utils.NormalizeBrief(activity)
if utils.CheckValidBrief(activity) == false {
ReturnError(w, r, "bad activity format", 405, nil, nil)
utils.ReturnError(w, r, "bad activity format", 405, nil, nil)
return
}
brief = utils.NormalizeBrief(brief)
if utils.CheckValidBrief(brief) == false {
ReturnError(w, r, "bad brief format", 405, nil, nil)
utils.ReturnError(w, r, "bad brief format", 405, nil, nil)
return
}
exists, err := e.db.checkLegalBasis(brief)
if err != nil {
ReturnError(w, r, "internal error", 405, nil, nil)
utils.ReturnError(w, r, "internal error", 405, nil, nil)
return
}
if exists == false {
ReturnError(w, r, "not found", 405, nil, nil)
utils.ReturnError(w, r, "not found", 405, nil, nil)
return
}
_, err = e.db.linkProcessingActivity(activity, brief)
if err != nil {
ReturnError(w, r, "internal error", 405, err, nil)
utils.ReturnError(w, r, "internal error", 405, err, nil)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -128,17 +128,17 @@ func (e mainEnv) pactivityUnlink(w http.ResponseWriter, r *http.Request, ps http
}
activity = utils.NormalizeBrief(activity)
if utils.CheckValidBrief(activity) == false {
ReturnError(w, r, "bad activity format", 405, nil, nil)
utils.ReturnError(w, r, "bad activity format", 405, nil, nil)
return
}
brief = utils.NormalizeBrief(brief)
if utils.CheckValidBrief(brief) == false {
ReturnError(w, r, "bad brief format", 405, nil, nil)
utils.ReturnError(w, r, "bad brief format", 405, nil, nil)
return
}
_, err := e.db.unlinkProcessingActivity(activity, brief)
if err != nil {
ReturnError(w, r, "internal error", 405, err, nil)
utils.ReturnError(w, r, "internal error", 405, err, nil)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -152,7 +152,7 @@ func (e mainEnv) pactivityList(w http.ResponseWriter, r *http.Request, ps httpro
}
resultJSON, numRecords, err := e.db.listProcessingActivities()
if err != nil {
ReturnError(w, r, "internal error", 405, err, nil)
utils.ReturnError(w, r, "internal error", 405, err, nil)
return
}
log.Printf("Total count of rows: %d\n", numRecords)

View File

@@ -7,6 +7,7 @@ import (
"strings"
"github.com/julienschmidt/httprouter"
"github.com/securitybunker/databunker/src/audit"
"github.com/securitybunker/databunker/src/utils"
)
@@ -30,7 +31,7 @@ func (e mainEnv) getUserRequests(w http.ResponseWriter, r *http.Request, ps http
}
resultJSON, counter, err := e.db.getRequests(status, offset, limit)
if err != nil {
ReturnError(w, r, "internal error", 405, err, nil)
utils.ReturnError(w, r, "internal error", 405, err, nil)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -43,8 +44,8 @@ func (e mainEnv) getUserRequests(w http.ResponseWriter, r *http.Request, ps http
func (e mainEnv) getCustomUserRequests(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := audit("get user privacy requests", identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("get user privacy requests", identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if e.EnforceAuth(w, r, event) == "" {
return
@@ -64,7 +65,7 @@ func (e mainEnv) getCustomUserRequests(w http.ResponseWriter, r *http.Request, p
}
resultJSON, counter, err := e.db.getUserRequests(userTOKEN, offset, limit)
if err != nil {
ReturnError(w, r, "internal error", 405, err, nil)
utils.ReturnError(w, r, "internal error", 405, err, nil)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -75,19 +76,19 @@ func (e mainEnv) getCustomUserRequests(w http.ResponseWriter, r *http.Request, p
func (e mainEnv) getUserRequest(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
request := ps.ByName("request")
event := audit("get user request by request token", request, "request", request)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("get user request by request token", request, "request", request)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if EnforceUUID(w, request, event) == false {
if utils.EnforceUUID(w, request, event) == false {
return
}
requestInfo, err := e.db.getRequest(request)
if err != nil {
ReturnError(w, r, "internal error", 405, err, nil)
utils.ReturnError(w, r, "internal error", 405, err, nil)
return
}
if len(requestInfo) == 0 {
ReturnError(w, r, "not found", 405, err, event)
utils.ReturnError(w, r, "not found", 405, err, event)
return
}
var resultJSON []byte
@@ -113,11 +114,11 @@ func (e mainEnv) getUserRequest(w http.ResponseWriter, r *http.Request, ps httpr
resultJSON, err = e.db.getUserJSON(userTOKEN)
}
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if resultJSON == nil {
ReturnError(w, r, "not found", 405, err, event)
utils.ReturnError(w, r, "not found", 405, err, event)
return
}
//fmt.Printf("Full json: %s\n", resultJSON)
@@ -143,10 +144,10 @@ func (e mainEnv) getUserRequest(w http.ResponseWriter, r *http.Request, ps httpr
func (e mainEnv) approveUserRequest(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
request := ps.ByName("request")
event := audit("approve user request", request, "request", request)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("approve user request", request, "request", request)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if EnforceUUID(w, request, event) == false {
if utils.EnforceUUID(w, request, event) == false {
return
}
authResult := e.EnforceAdmin(w, r, event)
@@ -155,17 +156,17 @@ func (e mainEnv) approveUserRequest(w http.ResponseWriter, r *http.Request, ps h
}
records, err := utils.GetJSONPostMap(r)
if err != nil {
ReturnError(w, r, "failed to decode request body", 405, err, event)
utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return
}
reason := utils.GetStringValue(records["reason"])
requestInfo, err := e.db.getRequest(request)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if len(requestInfo) == 0 {
ReturnError(w, r, "not found", 405, err, event)
utils.ReturnError(w, r, "not found", 405, err, event)
return
}
userTOKEN := utils.GetStringValue(requestInfo["token"])
@@ -175,16 +176,16 @@ func (e mainEnv) approveUserRequest(w http.ResponseWriter, r *http.Request, ps h
action := utils.GetStringValue(requestInfo["action"])
status := utils.GetStringValue(requestInfo["status"])
if status != "open" {
ReturnError(w, r, "wrong status: "+status, 405, err, event)
utils.ReturnError(w, r, "wrong status: "+status, 405, err, event)
return
}
userJSON, userBSON, err := e.db.getUser(userTOKEN)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if userJSON == nil {
ReturnError(w, r, "not found", 405, err, event)
utils.ReturnError(w, r, "not found", 405, err, event)
return
}
if action == "forget-me" {
@@ -199,7 +200,7 @@ func (e mainEnv) approveUserRequest(w http.ResponseWriter, r *http.Request, ps h
event.Msg = "failed to delete"
}
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
notifyURL := e.conf.Notification.NotificationURL
@@ -207,11 +208,11 @@ func (e mainEnv) approveUserRequest(w http.ResponseWriter, r *http.Request, ps h
} else if action == "change-profile" {
oldJSON, newJSON, lookupErr, err := e.db.updateUserRecord(requestInfo["change"].([]uint8), userTOKEN, userBSON, event, e.conf)
if lookupErr {
ReturnError(w, r, "internal error", 405, errors.New("not found"), event)
utils.ReturnError(w, r, "internal error", 405, errors.New("not found"), event)
return
}
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
utils.ReturnUUID(w, userTOKEN)
@@ -221,7 +222,7 @@ func (e mainEnv) approveUserRequest(w http.ResponseWriter, r *http.Request, ps h
app := requestInfo["app"].(string)
_, err = e.db.updateAppRecord(requestInfo["change"].([]uint8), userTOKEN, app, event, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
} else if action == "agreement-withdraw" {
@@ -241,25 +242,25 @@ func (e mainEnv) approveUserRequest(w http.ResponseWriter, r *http.Request, ps h
func (e mainEnv) cancelUserRequest(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
request := ps.ByName("request")
event := audit("cancel user request", request, "request", request)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("cancel user request", request, "request", request)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if EnforceUUID(w, request, event) == false {
if utils.EnforceUUID(w, request, event) == false {
return
}
records, err := utils.GetJSONPostMap(r)
if err != nil {
ReturnError(w, r, "failed to decode request body", 405, err, event)
utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return
}
reason := utils.GetStringValue(records["reason"])
requestInfo, err := e.db.getRequest(request)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if len(requestInfo) == 0 {
ReturnError(w, r, "not found", 405, err, event)
utils.ReturnError(w, r, "not found", 405, err, event)
return
}
userTOKEN := utils.GetStringValue(requestInfo["token"])
@@ -271,16 +272,16 @@ func (e mainEnv) cancelUserRequest(w http.ResponseWriter, r *http.Request, ps ht
return
}
if requestInfo["status"].(string) != "open" {
ReturnError(w, r, "wrong status: "+requestInfo["status"].(string), 405, err, event)
utils.ReturnError(w, r, "wrong status: "+requestInfo["status"].(string), 405, err, event)
return
}
resultJSON, err := e.db.getUserJSON(userTOKEN)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if resultJSON == nil {
ReturnError(w, r, "not found", 405, err, event)
utils.ReturnError(w, r, "not found", 405, err, event)
return
}
if len(reason) == 0 && authResult == "login" {

View File

@@ -5,7 +5,6 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -51,7 +50,7 @@ func loadUserSchema(cfg Config, confFile *string) error {
if os.IsNotExist(err) {
return err
}
schemaData, err := ioutil.ReadFile(fileSchema)
schemaData, err := os.ReadFile(fileSchema)
if err != nil {
return err
}

View File

@@ -9,6 +9,7 @@ import (
uuid "github.com/hashicorp/go-uuid"
"github.com/julienschmidt/httprouter"
"github.com/securitybunker/databunker/src/audit"
"github.com/securitybunker/databunker/src/storage"
"github.com/securitybunker/databunker/src/utils"
"go.mongodb.org/mongo-driver/bson"
@@ -16,14 +17,14 @@ import (
func (e mainEnv) createSession(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
session := ps.ByName("session")
var event *auditEvent
var event *audit.AuditEvent
defer func() {
if event != nil {
event.submit(e.db, e.conf)
SaveAuditEvent(event, e.db, e.conf)
}
}()
if EnforceUUID(w, session, event) == false {
//ReturnError(w, r, "bad session format", nil, event)
if utils.EnforceUUID(w, session, event) == false {
//utils.ReturnError(w, r, "bad session format", nil, event)
return
}
if e.EnforceAdmin(w, r, event) == "" {
@@ -31,11 +32,11 @@ func (e mainEnv) createSession(w http.ResponseWriter, r *http.Request, ps httpro
}
records, err := utils.GetJSONPostMap(r)
if err != nil {
ReturnError(w, r, "failed to decode request body", 405, err, event)
utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return
}
if len(records) == 0 {
ReturnError(w, r, "empty body", 405, nil, event)
utils.ReturnError(w, r, "empty body", 405, nil, event)
return
}
expirationStr := utils.GetStringValue(records["expiration"])
@@ -60,23 +61,23 @@ func (e mainEnv) createSession(w http.ResponseWriter, r *http.Request, ps httpro
userBson, err = e.db.lookupUserRecord(userToken)
}
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
userTOKEN := ""
if userBson != nil {
event = audit("create session", session, "session", session)
event = audit.CreateAuditEvent("create session", session, "session", session)
userTOKEN = userBson["token"].(string)
event.Record = userTOKEN
}
jsonData, err := json.Marshal(records)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
session, err = e.db.createSessionRecord(session, userTOKEN, expiration, jsonData)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -86,10 +87,10 @@ func (e mainEnv) createSession(w http.ResponseWriter, r *http.Request, ps httpro
func (e mainEnv) deleteSession(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
session := ps.ByName("session")
event := audit("delete session", session, "session", session)
defer func() { event.submit(e.db, e.conf) }()
if EnforceUUID(w, session, event) == false {
//ReturnError(w, r, "bad session format", nil, event)
event := audit.CreateAuditEvent("delete session", session, "session", session)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.EnforceUUID(w, session, event) == false {
//utils.ReturnError(w, r, "bad session format", nil, event)
return
}
if e.EnforceAdmin(w, r, event) == "" {
@@ -105,8 +106,8 @@ func (e mainEnv) deleteSession(w http.ResponseWriter, r *http.Request, ps httpro
func (e mainEnv) newUserSession(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := audit("create user session by "+mode, identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("create user session by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
userTOKEN := e.loadUserToken(w, r, mode, identity, event)
if userTOKEN == "" {
@@ -117,11 +118,11 @@ func (e mainEnv) newUserSession(w http.ResponseWriter, r *http.Request, ps httpr
}
records, err := utils.GetJSONPostMap(r)
if err != nil {
ReturnError(w, r, "failed to decode request body", 405, err, event)
utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return
}
if len(records) == 0 {
ReturnError(w, r, "empty body", 405, nil, event)
utils.ReturnError(w, r, "empty body", 405, nil, event)
return
}
expirationStr := utils.GetStringValue(records["expiration"])
@@ -129,17 +130,17 @@ func (e mainEnv) newUserSession(w http.ResponseWriter, r *http.Request, ps httpr
log.Printf("Record expiration: %s", expiration)
jsonData, err := json.Marshal(records)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
sessionUUID, err := uuid.GenerateUUID()
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
sessionID, err := e.db.createSessionRecord(sessionUUID, userTOKEN, expiration, jsonData)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -150,8 +151,8 @@ func (e mainEnv) newUserSession(w http.ResponseWriter, r *http.Request, ps httpr
func (e mainEnv) getUserSessions(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := audit("get all user sessions", identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("get all user sessions", identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
userTOKEN := e.loadUserToken(w, r, mode, identity, event)
if userTOKEN == "" {
@@ -172,7 +173,7 @@ func (e mainEnv) getUserSessions(w http.ResponseWriter, r *http.Request, ps http
}
records, count, err := e.db.getUserSessionsByToken(userTOKEN, offset, limit)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
data := strings.Join(records, ",")
@@ -183,10 +184,10 @@ func (e mainEnv) getUserSessions(w http.ResponseWriter, r *http.Request, ps http
func (e mainEnv) getSession(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
session := ps.ByName("session")
event := audit("get session", session, "session", session)
event := audit.CreateAuditEvent("get session", session, "session", session)
defer func() {
if event != nil {
event.submit(e.db, e.conf)
SaveAuditEvent(event, e.db, e.conf)
}
}()
when, record, userTOKEN, err := e.db.getSession(session)
@@ -195,7 +196,7 @@ func (e mainEnv) getSession(w http.ResponseWriter, r *http.Request, ps httproute
e.db.store.DeleteExpired(storage.TblName.Sessions, "token", userTOKEN)
}
if err != nil {
ReturnError(w, r, err.Error(), 405, err, event)
utils.ReturnError(w, r, err.Error(), 405, err, event)
return
}

View File

@@ -9,6 +9,7 @@ import (
"strings"
"github.com/julienschmidt/httprouter"
"github.com/securitybunker/databunker/src/audit"
"github.com/securitybunker/databunker/src/utils"
"github.com/tidwall/gjson"
)
@@ -16,8 +17,8 @@ import (
func (e mainEnv) newSharedRecord(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := audit("create shareable record by "+mode, identity, "token", identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("create shareable record by "+mode, identity, "token", identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
userTOKEN := e.loadUserToken(w, r, mode, identity, event)
if userTOKEN == "" {
@@ -28,7 +29,7 @@ func (e mainEnv) newSharedRecord(w http.ResponseWriter, r *http.Request, ps http
}
records, err := utils.GetJSONPostMap(r)
if err != nil {
ReturnError(w, r, "failed to decode request body", 405, err, event)
utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return
}
fields := ""
@@ -55,7 +56,7 @@ func (e mainEnv) newSharedRecord(w http.ResponseWriter, r *http.Request, ps http
if reflect.TypeOf(value) == reflect.TypeOf("string") {
expiration = utils.SetExpiration(e.conf.Policy.MaxShareableRecordRetentionPeriod, value.(string))
} else {
ReturnError(w, r, "failed to parse expiration field", 405, err, event)
utils.ReturnError(w, r, "failed to parse expiration field", 405, err, event)
return
}
}
@@ -63,11 +64,11 @@ func (e mainEnv) newSharedRecord(w http.ResponseWriter, r *http.Request, ps http
if reflect.TypeOf(value) == reflect.TypeOf("string") {
appName = strings.ToLower(value.(string))
if len(appName) > 0 && utils.CheckValidApp(appName) == false {
ReturnError(w, r, "unknown app name", 405, nil, event)
utils.ReturnError(w, r, "unknown app name", 405, nil, event)
}
} else {
// type is different
ReturnError(w, r, "failed to parse app field", 405, nil, event)
utils.ReturnError(w, r, "failed to parse app field", 405, nil, event)
}
}
if len(expiration) == 0 {
@@ -76,7 +77,7 @@ func (e mainEnv) newSharedRecord(w http.ResponseWriter, r *http.Request, ps http
}
recordUUID, err := e.db.saveSharedRecord(userTOKEN, fields, expiration, session, appName, partner, e.conf)
if err != nil {
ReturnError(w, r, err.Error(), 405, err, event)
utils.ReturnError(w, r, err.Error(), 405, err, event)
return
}
event.Record = userTOKEN
@@ -88,10 +89,10 @@ func (e mainEnv) newSharedRecord(w http.ResponseWriter, r *http.Request, ps http
func (e mainEnv) getRecord(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
record := ps.ByName("record")
event := audit("get shareable record by token", record, "record", record)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("get shareable record by token", record, "record", record)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if EnforceUUID(w, record, event) == false {
if utils.EnforceUUID(w, record, event) == false {
return
}
recordInfo, err := e.db.getSharedRecord(record)
@@ -115,11 +116,11 @@ func (e mainEnv) getRecord(w http.ResponseWriter, r *http.Request, ps httprouter
resultJSON, err = e.db.getUserJSON(recordInfo.token)
}
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if resultJSON == nil {
ReturnError(w, r, "not found", 405, err, event)
utils.ReturnError(w, r, "not found", 405, err, event)
return
}
log.Printf("Full json: %s\n", resultJSON)

View File

@@ -5,7 +5,6 @@ package storage
import (
"database/sql"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
@@ -42,7 +41,7 @@ func (dbobj MySQLDB) getConnectionString(dbname *string) string {
dbnameString = *dbname
}
if len(os.Getenv("MYSQL_USER_PASS_FILE")) > 0 {
content, err := ioutil.ReadFile(os.Getenv("MYSQL_USER_PASS_FILE"))
content, err := os.ReadFile(os.Getenv("MYSQL_USER_PASS_FILE"))
if err != nil {
return ""
}

View File

@@ -5,7 +5,6 @@ package storage
import (
"database/sql"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
@@ -42,7 +41,7 @@ func (dbobj PGSQLDB) getConnectionString(dbname *string) string {
dbnameString = *dbname
}
if len(os.Getenv("PGSQL_USER_PASS_FILE")) > 0 {
content, err := ioutil.ReadFile(os.Getenv("PGSQL_USER_PASS_FILE"))
content, err := os.ReadFile(os.Getenv("PGSQL_USER_PASS_FILE"))
if err != nil {
return ""
}

View File

@@ -7,6 +7,7 @@ import (
"strings"
"github.com/julienschmidt/httprouter"
"github.com/securitybunker/databunker/src/audit"
"github.com/securitybunker/databunker/src/utils"
)
@@ -14,8 +15,8 @@ func (e mainEnv) userappNew(w http.ResponseWriter, r *http.Request, ps httproute
appName := strings.ToLower(ps.ByName("appname"))
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := auditApp("create user app record by "+mode, identity, appName, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditAppEvent("create user app record by "+mode, identity, appName, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
userTOKEN := e.loadUserToken(w, r, mode, identity, event)
if userTOKEN == "" {
@@ -25,31 +26,31 @@ func (e mainEnv) userappNew(w http.ResponseWriter, r *http.Request, ps httproute
return
}
if utils.CheckValidApp(appName) == false {
ReturnError(w, r, "bad appname", 405, nil, event)
utils.ReturnError(w, r, "bad appname", 405, nil, event)
return
}
if e.db.store.ValidateNewApp("app_"+appName) == false {
ReturnError(w, r, "db limitation", 405, nil, event)
utils.ReturnError(w, r, "db limitation", 405, nil, event)
return
}
data, err := utils.GetJSONPostMap(r)
if err != nil {
ReturnError(w, r, "failed to decode request body", 405, err, event)
utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return
}
if len(data) == 0 {
ReturnError(w, r, "empty body", 405, nil, event)
utils.ReturnError(w, r, "empty body", 405, nil, event)
return
}
jsonData, err := json.Marshal(data)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
_, err = e.db.createAppRecord(jsonData, userTOKEN, appName, event, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
utils.ReturnUUID(w, userTOKEN)
@@ -60,8 +61,8 @@ func (e mainEnv) userappChange(w http.ResponseWriter, r *http.Request, ps httpro
appName := strings.ToLower(ps.ByName("appname"))
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := auditApp("change user app record by "+mode, identity, appName, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditAppEvent("change user app record by "+mode, identity, appName, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
userTOKEN := e.loadUserToken(w, r, mode, identity, event)
if userTOKEN == "" {
return
@@ -71,32 +72,32 @@ func (e mainEnv) userappChange(w http.ResponseWriter, r *http.Request, ps httpro
return
}
if utils.CheckValidApp(appName) == false {
ReturnError(w, r, "bad appname", 405, nil, event)
utils.ReturnError(w, r, "bad appname", 405, nil, event)
return
}
jsonData, err := utils.GetJSONPostData(r)
if err != nil {
ReturnError(w, r, "failed to decode request body", 405, err, event)
utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return
}
if jsonData == nil {
ReturnError(w, r, "empty body", 405, nil, event)
utils.ReturnError(w, r, "empty body", 405, nil, event)
return
}
// make sure userapp exists
resultJSON, err := e.db.getUserApp(userTOKEN, appName, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if resultJSON == nil {
ReturnError(w, r, "not found", 405, nil, event)
utils.ReturnError(w, r, "not found", 405, nil, event)
return
}
if authResult != "login" {
_, err = e.db.updateAppRecord(jsonData, userTOKEN, appName, event, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
utils.ReturnUUID(w, userTOKEN)
@@ -107,7 +108,7 @@ func (e mainEnv) userappChange(w http.ResponseWriter, r *http.Request, ps httpro
if utils.StringPatternMatch(strings.ToLower(name), appName) {
_, err = e.db.updateAppRecord(jsonData, userTOKEN, appName, event, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
utils.ReturnUUID(w, userTOKEN)
@@ -117,7 +118,7 @@ func (e mainEnv) userappChange(w http.ResponseWriter, r *http.Request, ps httpro
}
rtoken, rstatus, err := e.db.saveUserRequest("change-app-data", userTOKEN, appName, "", jsonData, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -128,8 +129,8 @@ func (e mainEnv) userappChange(w http.ResponseWriter, r *http.Request, ps httpro
func (e mainEnv) userappList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := audit("get user app list by "+mode, identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("get user app list by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
userTOKEN := e.loadUserToken(w, r, mode, identity, event)
if userTOKEN == "" {
return
@@ -139,7 +140,7 @@ func (e mainEnv) userappList(w http.ResponseWriter, r *http.Request, ps httprout
}
result, err := e.db.listUserApps(userTOKEN, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -151,8 +152,8 @@ func (e mainEnv) userappGet(w http.ResponseWriter, r *http.Request, ps httproute
appName := strings.ToLower(ps.ByName("appname"))
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := auditApp("get user app record by "+mode, identity, appName, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditAppEvent("get user app record by "+mode, identity, appName, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
userTOKEN := e.loadUserToken(w, r, mode, identity, event)
if userTOKEN == "" {
return
@@ -161,16 +162,16 @@ func (e mainEnv) userappGet(w http.ResponseWriter, r *http.Request, ps httproute
return
}
if utils.CheckValidApp(appName) == false {
ReturnError(w, r, "bad appname", 405, nil, event)
utils.ReturnError(w, r, "bad appname", 405, nil, event)
return
}
resultJSON, err := e.db.getUserApp(userTOKEN, appName, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if resultJSON == nil {
ReturnError(w, r, "not found", 405, nil, event)
utils.ReturnError(w, r, "not found", 405, nil, event)
return
}
finalJSON := fmt.Sprintf(`{"status":"ok","token":"%s","data":%s}`, userTOKEN, resultJSON)
@@ -183,8 +184,8 @@ func (e mainEnv) userappDelete(w http.ResponseWriter, r *http.Request, ps httpro
appName := strings.ToLower(ps.ByName("appname"))
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := auditApp("delete user app record by "+mode, identity, appName, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditAppEvent("delete user app record by "+mode, identity, appName, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
userTOKEN := e.loadUserToken(w, r, mode, identity, event)
if userTOKEN == "" {
return
@@ -193,7 +194,7 @@ func (e mainEnv) userappDelete(w http.ResponseWriter, r *http.Request, ps httpro
return
}
if utils.CheckValidApp(appName) == false {
ReturnError(w, r, "bad appname", 405, nil, event)
utils.ReturnError(w, r, "bad appname", 405, nil, event)
return
}
@@ -211,7 +212,7 @@ func (e mainEnv) appList(w http.ResponseWriter, r *http.Request, ps httprouter.P
}
result, err := e.db.listAllApps(e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, nil)
utils.ReturnError(w, r, "internal error", 405, err, nil)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")

View File

@@ -8,6 +8,7 @@ import (
"strings"
jsonpatch "github.com/evanphx/json-patch"
"github.com/securitybunker/databunker/src/audit"
"github.com/securitybunker/databunker/src/storage"
"github.com/securitybunker/databunker/src/utils"
"go.mongodb.org/mongo-driver/bson"
@@ -54,7 +55,7 @@ func (dbobj dbcon) deleteUserApps(userTOKEN string, conf Config) {
}
}
func (dbobj dbcon) createAppRecord(jsonData []byte, userTOKEN string, appName string, event *auditEvent, conf Config) (string, error) {
func (dbobj dbcon) createAppRecord(jsonData []byte, userTOKEN string, appName string, event *audit.AuditEvent, conf Config) (string, error) {
appNameFull := "app_" + appName
//log.Printf("Going to create app record: %s\n", appName)
encodedStr, err := dbobj.userEncrypt(userTOKEN, jsonData)
@@ -103,7 +104,7 @@ func (dbobj dbcon) createAppRecord(jsonData []byte, userTOKEN string, appName st
return userTOKEN, err
}
func (dbobj dbcon) updateAppRecord(jsonDataPatch []byte, userTOKEN string, appName string, event *auditEvent, conf Config) (string, error) {
func (dbobj dbcon) updateAppRecord(jsonDataPatch []byte, userTOKEN string, appName string, event *audit.AuditEvent, conf Config) (string, error) {
//_, err = collection.InsertOne(context.TODO(), bson.M{"name": "The Go Language2", "genre": "Coding", "authorId": "4"})
appNameFull := "app_" + appName
userBson, err := dbobj.lookupUserRecord(userTOKEN)

View File

@@ -7,14 +7,15 @@ import (
"net/http"
"github.com/julienschmidt/httprouter"
"github.com/securitybunker/databunker/src/audit"
"github.com/securitybunker/databunker/src/storage"
"github.com/securitybunker/databunker/src/utils"
"go.mongodb.org/mongo-driver/bson"
)
func (e mainEnv) userCreate(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
event := audit("create user record", "", "", "")
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("create user record", "", "", "")
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if e.conf.Generic.CreateUserWithoutAccessToken == false {
// anonymous user can not create user record, check token
@@ -25,60 +26,60 @@ func (e mainEnv) userCreate(w http.ResponseWriter, r *http.Request, ps httproute
}
userJSON, err := utils.GetUserJSONStruct(r, e.conf.Sms.DefaultCountry)
if err != nil {
ReturnError(w, r, "failed to decode request body", 405, err, event)
utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return
}
if len(userJSON.JsonData) == 0 {
ReturnError(w, r, "empty request body", 405, nil, event)
utils.ReturnError(w, r, "empty request body", 405, nil, event)
return
}
err = validateUserRecord(userJSON.JsonData)
if err != nil {
ReturnError(w, r, "user schema error: "+err.Error(), 405, err, event)
utils.ReturnError(w, r, "user schema error: "+err.Error(), 405, err, event)
return
}
// make sure that login, email and phone are unique
if len(userJSON.LoginIdx) > 0 {
otherUserBson, err := e.db.lookupUserRecordByIndex("login", userJSON.LoginIdx, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if otherUserBson != nil {
ReturnError(w, r, "duplicate index: login", 405, nil, event)
utils.ReturnError(w, r, "duplicate index: login", 405, nil, event)
return
}
}
if len(userJSON.EmailIdx) > 0 {
otherUserBson, err := e.db.lookupUserRecordByIndex("email", userJSON.EmailIdx, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if otherUserBson != nil {
ReturnError(w, r, "duplicate index: email", 405, nil, event)
utils.ReturnError(w, r, "duplicate index: email", 405, nil, event)
return
}
}
if len(userJSON.PhoneIdx) > 0 {
otherUserBson, err := e.db.lookupUserRecordByIndex("phone", userJSON.PhoneIdx, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if otherUserBson != nil {
ReturnError(w, r, "duplicate index: phone", 405, nil, event)
utils.ReturnError(w, r, "duplicate index: phone", 405, nil, event)
return
}
}
if len(userJSON.CustomIdx) > 0 {
otherUserBson, err := e.db.lookupUserRecordByIndex("custom", userJSON.CustomIdx, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if otherUserBson != nil {
ReturnError(w, r, "duplicate index: custom", 405, nil, event)
utils.ReturnError(w, r, "duplicate index: custom", 405, nil, event)
return
}
}
@@ -86,13 +87,13 @@ func (e mainEnv) userCreate(w http.ResponseWriter, r *http.Request, ps httproute
len(userJSON.EmailIdx) == 0 &&
len(userJSON.PhoneIdx) == 0 &&
len(userJSON.CustomIdx) == 0 {
ReturnError(w, r, "failed to create user, all user lookup fields are missing", 405, err, event)
utils.ReturnError(w, r, "failed to create user, all user lookup fields are missing", 405, err, event)
return
}
userTOKEN, err := e.db.createUserRecord(userJSON, event)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
encPhoneIdx := ""
@@ -127,17 +128,17 @@ func (e mainEnv) userGet(w http.ResponseWriter, r *http.Request, ps httprouter.P
var resultJSON []byte
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := audit("get user record by "+mode, identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("get user record by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false {
ReturnError(w, r, "bad mode", 405, nil, event)
utils.ReturnError(w, r, "bad mode", 405, nil, event)
return
}
userTOKEN := ""
authResult := ""
if mode == "token" {
if EnforceUUID(w, identity, event) == false {
if utils.EnforceUUID(w, identity, event) == false {
return
}
resultJSON, err = e.db.getUserJSON(identity)
@@ -147,7 +148,7 @@ func (e mainEnv) userGet(w http.ResponseWriter, r *http.Request, ps httprouter.P
event.Record = userTOKEN
}
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
authResult = e.EnforceAuth(w, r, event)
@@ -155,7 +156,7 @@ func (e mainEnv) userGet(w http.ResponseWriter, r *http.Request, ps httprouter.P
return
}
if resultJSON == nil {
ReturnError(w, r, "record not found", 405, nil, event)
utils.ReturnError(w, r, "record not found", 405, nil, event)
return
}
finalJSON := fmt.Sprintf(`{"status":"ok","token":"%s","data":%s}`, userTOKEN, resultJSON)
@@ -171,7 +172,7 @@ func (e mainEnv) userList(w http.ResponseWriter, r *http.Request, ps httprouter.
return
}
if e.conf.Generic.ListUsers == false {
ReturnError(w, r, "access denied", 403, nil, nil)
utils.ReturnError(w, r, "access denied", 403, nil, nil)
return
}
var offset int32 = 0
@@ -199,28 +200,28 @@ func (e mainEnv) userList(w http.ResponseWriter, r *http.Request, ps httprouter.
func (e mainEnv) userChange(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := audit("change user record by "+mode, identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("change user record by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false {
ReturnError(w, r, "bad index", 405, nil, event)
utils.ReturnError(w, r, "bad index", 405, nil, event)
return
}
jsonData, err := utils.GetJSONPostData(r)
if err != nil {
ReturnError(w, r, "failed to decode request body", 405, err, event)
utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return
}
if jsonData == nil {
ReturnError(w, r, "empty request body", 405, nil, event)
utils.ReturnError(w, r, "empty request body", 405, nil, event)
return
}
userTOKEN := ""
var userJSON []byte
var userBSON bson.M
if mode == "token" {
if EnforceUUID(w, identity, event) == false {
if utils.EnforceUUID(w, identity, event) == false {
return
}
userTOKEN = identity
@@ -230,11 +231,11 @@ func (e mainEnv) userChange(w http.ResponseWriter, r *http.Request, ps httproute
event.Record = userTOKEN
}
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if userJSON == nil {
ReturnError(w, r, "user record not found", 405, nil, event)
utils.ReturnError(w, r, "user record not found", 405, nil, event)
return
}
authResult := e.EnforceAuth(w, r, event)
@@ -245,7 +246,7 @@ func (e mainEnv) userChange(w http.ResponseWriter, r *http.Request, ps httproute
if UserSchemaEnabled() {
adminRecordChanged, err = e.db.validateUserRecordChange(userJSON, jsonData, userTOKEN, authResult)
if err != nil {
ReturnError(w, r, "schema validation error: "+err.Error(), 405, err, event)
utils.ReturnError(w, r, "schema validation error: "+err.Error(), 405, err, event)
return
}
}
@@ -254,7 +255,7 @@ func (e mainEnv) userChange(w http.ResponseWriter, r *http.Request, ps httproute
if e.conf.SelfService.UserRecordChange == false || adminRecordChanged == true {
rtoken, rstatus, err := e.db.saveUserRequest("change-profile", userTOKEN, "", "", jsonData, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -265,11 +266,11 @@ func (e mainEnv) userChange(w http.ResponseWriter, r *http.Request, ps httproute
}
oldJSON, newJSON, lookupErr, err := e.db.updateUserRecord(jsonData, userTOKEN, userBSON, event, e.conf)
if lookupErr {
ReturnError(w, r, "record not found", 405, errors.New("record not found"), event)
utils.ReturnError(w, r, "record not found", 405, errors.New("record not found"), event)
return
}
if err != nil {
ReturnError(w, r, "error updating user", 405, err, event)
utils.ReturnError(w, r, "error updating user", 405, err, event)
return
}
utils.ReturnUUID(w, userTOKEN)
@@ -281,11 +282,11 @@ func (e mainEnv) userChange(w http.ResponseWriter, r *http.Request, ps httproute
func (e mainEnv) userDelete(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := audit("delete user record by "+mode, identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("delete user record by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false {
ReturnError(w, r, "bad mode", 405, nil, event)
utils.ReturnError(w, r, "bad mode", 405, nil, event)
return
}
var err error
@@ -293,7 +294,7 @@ func (e mainEnv) userDelete(w http.ResponseWriter, r *http.Request, ps httproute
var userJSON []byte
userTOKEN := identity
if mode == "token" {
if EnforceUUID(w, identity, event) == false {
if utils.EnforceUUID(w, identity, event) == false {
return
}
userJSON, userBSON, err = e.db.getUser(identity)
@@ -302,7 +303,7 @@ func (e mainEnv) userDelete(w http.ResponseWriter, r *http.Request, ps httproute
event.Record = userTOKEN
}
if err != nil {
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
authResult := e.EnforceAuth(w, r, event)
@@ -316,7 +317,7 @@ func (e mainEnv) userDelete(w http.ResponseWriter, r *http.Request, ps httproute
w.WriteHeader(200)
fmt.Fprintf(w, `{"status":"ok","result":"done"}`)
}
ReturnError(w, r, "record not found", 405, nil, event)
utils.ReturnError(w, r, "record not found", 405, nil, event)
return
}
@@ -325,7 +326,7 @@ func (e mainEnv) userDelete(w http.ResponseWriter, r *http.Request, ps httproute
if e.conf.SelfService.ForgetMe == false {
rtoken, rstatus, err := e.db.saveUserRequest("forget-me", userTOKEN, "", "", nil, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -341,7 +342,7 @@ func (e mainEnv) userDelete(w http.ResponseWriter, r *http.Request, ps httproute
//fmt.Printf("deleting user %s\n", userTOKEN)
_, err = e.db.deleteUserRecord(userJSON, userTOKEN, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -356,8 +357,8 @@ func (e mainEnv) userPrelogin(w http.ResponseWriter, r *http.Request, ps httprou
code := ps.ByName("code")
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := audit("user prelogin by "+mode, identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("user prelogin by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
code0, err := decryptCaptcha(captcha)
if err != nil || code0 != code {
@@ -367,12 +368,12 @@ func (e mainEnv) userPrelogin(w http.ResponseWriter, r *http.Request, ps httprou
return
}
if mode != "phone" && mode != "email" {
ReturnError(w, r, "bad mode", 405, nil, event)
utils.ReturnError(w, r, "bad mode", 405, nil, event)
return
}
userBson, err := e.db.lookupUserRecordByIndex(mode, identity, e.conf)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if userBson != nil {
@@ -395,7 +396,7 @@ func (e mainEnv) userPrelogin(w http.ResponseWriter, r *http.Request, ps httprou
//notifyURL := e.conf.Notification.NotificationURL
//notifyBadLogin(notifyURL, mode, identity)
e.pluginUserLookup(identity)
//ReturnError(w, r, "record not found", 405, errors.New("record not found"), event)
//utils.ReturnError(w, r, "record not found", 405, errors.New("record not found"), event)
captcha, _ := generateCaptcha()
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(403)
@@ -413,17 +414,17 @@ func (e mainEnv) userLogin(w http.ResponseWriter, r *http.Request, ps httprouter
tmp := utils.Atoi(ps.ByName("tmp"))
identity := ps.ByName("identity")
mode := ps.ByName("mode")
event := audit("user login by "+mode, identity, mode, identity)
defer func() { event.submit(e.db, e.conf) }()
event := audit.CreateAuditEvent("user login by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if mode != "phone" && mode != "email" {
ReturnError(w, r, "bad mode", 405, nil, event)
utils.ReturnError(w, r, "bad mode", 405, nil, event)
return
}
userBson, err := e.db.lookupUserRecordByIndex(mode, identity, e.conf)
if userBson == nil || err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
@@ -439,7 +440,7 @@ func (e mainEnv) userLogin(w http.ResponseWriter, r *http.Request, ps httprouter
xtoken, hashedToken, err := e.db.generateUserLoginXtoken(userTOKEN)
//fmt.Printf("generate user access token: %s\n", xtoken)
if err != nil {
ReturnError(w, r, "internal error", 405, err, event)
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
event.Msg = "generated: " + hashedToken
@@ -448,5 +449,5 @@ func (e mainEnv) userLogin(w http.ResponseWriter, r *http.Request, ps httprouter
fmt.Fprintf(w, `{"status":"ok","xtoken":"%s","token":"%s"}`, xtoken, userTOKEN)
return
}
ReturnError(w, r, "internal error", 405, nil, event)
utils.ReturnError(w, r, "internal error", 405, nil, event)
}

View File

@@ -11,12 +11,13 @@ import (
jsonpatch "github.com/evanphx/json-patch"
uuid "github.com/hashicorp/go-uuid"
"github.com/securitybunker/databunker/src/audit"
"github.com/securitybunker/databunker/src/storage"
"github.com/securitybunker/databunker/src/utils"
"go.mongodb.org/mongo-driver/bson"
)
func (dbobj dbcon) createUserRecord(parsedData utils.UserJSONStruct, event *auditEvent) (string, error) {
func (dbobj dbcon) createUserRecord(parsedData utils.UserJSONStruct, event *audit.AuditEvent) (string, error) {
var userTOKEN string
//var bdoc interface{}
bdoc := bson.M{}
@@ -139,7 +140,7 @@ func (dbobj dbcon) validateUserRecordChange(oldUserJSON []byte, jsonDataPatch []
return validateUserRecordChange(oldUserJSON, newJSON, authResult)
}
func (dbobj dbcon) updateUserRecord(jsonDataPatch []byte, userTOKEN string, userBSON bson.M, event *auditEvent, conf Config) ([]byte, []byte, bool, error) {
func (dbobj dbcon) updateUserRecord(jsonDataPatch []byte, userTOKEN string, userBSON bson.M, event *audit.AuditEvent, conf Config) ([]byte, []byte, bool, error) {
oldJSON, newJSON, lookupErr, err := dbobj.updateUserRecordDo(jsonDataPatch, userTOKEN, userBSON, event, conf)
if lookupErr == true {
return oldJSON, newJSON, lookupErr, err
@@ -162,7 +163,7 @@ func (dbobj dbcon) updateUserRecord(jsonDataPatch []byte, userTOKEN string, user
return nil, nil, false, err
}
func (dbobj dbcon) updateUserRecordDo(jsonDataPatch []byte, userTOKEN string, oldUserBson bson.M, event *auditEvent, conf Config) ([]byte, []byte, bool, error) {
func (dbobj dbcon) updateUserRecordDo(jsonDataPatch []byte, userTOKEN string, oldUserBson bson.M, event *audit.AuditEvent, conf Config) ([]byte, []byte, bool, error) {
// get user key
userKey := oldUserBson["key"].(string)

42
src/utils/checks.go Normal file
View File

@@ -0,0 +1,42 @@
package utils
import (
"fmt"
"log"
"net/http"
"github.com/securitybunker/databunker/src/audit"
)
func ReturnError(w http.ResponseWriter, r *http.Request, message string, code int, err error, event *audit.AuditEvent) {
log.Printf("[%d] %s %s -> Return error\n", code, r.Method, r.URL.Path)
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(code)
fmt.Fprintf(w, `{"status":"error","message":%q}`, message)
if event != nil {
event.Status = "error"
event.Msg = message
if err != nil {
event.Debug = err.Error()
log.Printf("Generate error response: %s, Error: %s\n", message, err.Error())
} else {
log.Printf("Generate error response: %s\n", message)
}
}
//http.Error(w, http.StatusText(405), 405)
}
func EnforceUUID(w http.ResponseWriter, uuidCode string, event *audit.AuditEvent) bool {
if CheckValidUUID(uuidCode) == false {
//fmt.Printf("405 bad uuid in : %s\n", uuidCode)
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(405)
fmt.Fprintf(w, `{"status":"error","message":"bad uuid"}`)
if event != nil {
event.Status = "error"
event.Msg = "bad uuid"
}
return false
}
return true
}

View File

@@ -4,7 +4,10 @@ go 1.21
toolchain go1.23.2
replace github.com/securitybunker/databunker/src/audit => ../audit
require (
github.com/securitybunker/databunker/src/audit v0.0.0
github.com/ttacon/libphonenumber v1.2.1
golang.org/x/sys v0.28.0
)

View File

@@ -6,7 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"io"
"log"
"math/rand"
"mime"
@@ -387,7 +387,7 @@ func GetJSONPostMap(r *http.Request) (map[string]interface{}, error) {
// otherwise data is not parsed!
r.Method = "PATCH"
}
body0, err := ioutil.ReadAll(r.Body)
body0, err := io.ReadAll(r.Body)
if err != nil {
return nil, err
}
@@ -446,7 +446,7 @@ func GetJSONPostData(r *http.Request) ([]byte, error) {
// otherwise data is not parsed!
r.Method = "PATCH"
}
body0, err := ioutil.ReadAll(r.Body)
body0, err := io.ReadAll(r.Body)
if err != nil {
return nil, err
}

View File

@@ -2,7 +2,7 @@ package main
import (
"fmt"
"io/ioutil"
"io"
"log"
"net/http"
"net/http/httptest"
@@ -99,7 +99,7 @@ func TestUtilSMS(t *testing.T) {
rw.Header().Set("Content-Type", "application/json")
rw.WriteHeader(200)
defer req.Body.Close()
bodyBytes, _ := ioutil.ReadAll(req.Body)
bodyBytes, _ := io.ReadAll(req.Body)
log.Printf("body: %s\n", string(bodyBytes))
if string(bodyBytes) != "Body=Data+Bunker+code+1234&From=from1234&To=4444" {
t.Fatalf("bad request: %s", string(bodyBytes))
@@ -119,7 +119,7 @@ func TestUtilNotifyConsentChange(t *testing.T) {
rw.Header().Set("Content-Type", "application/json")
rw.WriteHeader(200)
defer req.Body.Close()
bodyBytes, _ := ioutil.ReadAll(req.Body)
bodyBytes, _ := io.ReadAll(req.Body)
log.Printf("body: %s\n", string(bodyBytes))
if string(bodyBytes) != `{"action":"consentchange","brief":"brief","identity":"user3@user3.com","mode":"email","status":"no"}` {
q <- fmt.Sprintf("bad request in notifyConsentChange: %s", string(bodyBytes))
@@ -142,7 +142,7 @@ func TestUtilNotifyProfileNew(t *testing.T) {
rw.Header().Set("Content-Type", "application/json")
rw.WriteHeader(200)
defer req.Body.Close()
bodyBytes, _ := ioutil.ReadAll(req.Body)
bodyBytes, _ := io.ReadAll(req.Body)
log.Printf("body: %s\n", string(bodyBytes))
if string(bodyBytes) != `{"action":"profilenew","identity":"user3@user3.com","mode":"email","profile":{"name":"alex"}}` {
q <- fmt.Sprintf("bad request in notifyConsentChange: %s", string(bodyBytes))
@@ -166,7 +166,7 @@ func TestUtilNotifyForgetMe(t *testing.T) {
rw.Header().Set("Content-Type", "application/json")
rw.WriteHeader(200)
defer req.Body.Close()
bodyBytes, _ := ioutil.ReadAll(req.Body)
bodyBytes, _ := io.ReadAll(req.Body)
log.Printf("body: %s\n", string(bodyBytes))
if string(bodyBytes) != `{"action":"forgetme","identity":"user3@user3.com","mode":"email","profile":{"name":"alex"}}` {
q <- fmt.Sprintf("bad request in notifyConsentChange: %s", string(bodyBytes))
@@ -190,7 +190,7 @@ func TestUtilNotifyProfileChange(t *testing.T) {
rw.Header().Set("Content-Type", "application/json")
rw.WriteHeader(200)
defer req.Body.Close()
bodyBytes, _ := ioutil.ReadAll(req.Body)
bodyBytes, _ := io.ReadAll(req.Body)
log.Printf("body: %s\n", string(bodyBytes))
if string(bodyBytes) != `{"action":"profilechange","identity":"user3@user3.com","mode":"email","old":{"name":"alex2"},"profile":{"name":"alex3"}}` {
q <- fmt.Sprintf("bad request in notifyConsentChange: %s", string(bodyBytes))