add event log retrieval
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2024-01-17 12:20:01 +11:00
parent 5f63ee235b
commit f68bd9637d
8 changed files with 75 additions and 12 deletions

View File

@@ -92,7 +92,9 @@ Body
``` ```
This API call will return a JWT token that must be present for any other API calls to succeed. The validity duration of this token is based on the configured TOKEN_HOUR_LIFESPAN value. JWT token is returned as value of `access_token`, and must be supplied via a HTTP header in the form `"Authorization: Bearer <JWT_TOKEN>"` for all subsequent API calls. This API call will return a JWT token that must be present for any other API calls to succeed. The validity duration of this token is based on the configured TOKEN_HOUR_LIFESPAN value. JWT token is returned as value of `access_token`, and must be supplied via a HTTP header in the form `"Authorization: Bearer <JWT_TOKEN>"` for all subsequent API calls.
### Unlock #### Admin Only operations
#### Unlock
**POST** `/api/admin/unlock` **POST** `/api/admin/unlock`
Body Body
@@ -106,6 +108,11 @@ If the SECRETS_KEY environment variable is not defined, this API call to unlock
This API call can only be made once after the service has started. Subsequent calls will receive an error until the service is restarted. This API call can only be made once after the service has started. Subsequent calls will receive an error until the service is restarted.
#### Event Logs
**GET** `/api/admin/logs`
This operation can only be performed by a user with that is admin enabled. Lists all event logs.
### User Operations ### User Operations
#### Register User #### Register User

View File

@@ -82,7 +82,7 @@ func DeleteUser(c *gin.Context) {
UserId: RequestingUserId, UserId: RequestingUserId,
EventText: fmt.Sprintf("Deleted User Id %d", testUser.UserId), EventText: fmt.Sprintf("Deleted User Id %d", testUser.UserId),
} }
a.AuditAdd() a.AutidLogAdd()
c.JSON(http.StatusOK, gin.H{"message": "user deletion success"}) c.JSON(http.StatusOK, gin.H{"message": "user deletion success"})
} }
@@ -183,7 +183,7 @@ func AddUser(c *gin.Context) {
UserId: RequestingUserId, UserId: RequestingUserId,
EventText: fmt.Sprintf("Created User Id %d", u.UserId), EventText: fmt.Sprintf("Created User Id %d", u.UserId),
} }
a.AuditAdd() a.AutidLogAdd()
c.JSON(http.StatusOK, gin.H{"message": "user registration success", "data": u}) c.JSON(http.StatusOK, gin.H{"message": "user registration success", "data": u})
} }

View File

@@ -0,0 +1,23 @@
package controllers
import (
"fmt"
"log"
"net/http"
"smt/models"
"github.com/gin-gonic/gin"
)
func GetAuditLogsHandler(c *gin.Context) {
logs, err := models.AuditLogList()
if err != nil {
errString := fmt.Sprintf("error retrieving audit logs : '%s'", err)
log.Printf("GetAuditLogsHandler %s\n", errString)
c.JSON(http.StatusBadRequest, gin.H{"error": errString})
return
}
c.JSON(http.StatusOK, gin.H{"message": "success", "data": logs})
}

View File

@@ -164,7 +164,7 @@ func retrieveSpecifiedSecret(s *models.Secret, c *gin.Context) {
UserId: UserId, UserId: UserId,
EventText: fmt.Sprintf("Retrieved Secret Id %d", results[0].SecretId), EventText: fmt.Sprintf("Retrieved Secret Id %d", results[0].SecretId),
} }
a.AuditAdd() a.AutidLogAdd()
// output results as json // output results as json
c.JSON(http.StatusOK, gin.H{"message": "success", "data": results}) c.JSON(http.StatusOK, gin.H{"message": "success", "data": results})
@@ -210,7 +210,7 @@ func ListSecrets(c *gin.Context) {
UserId: UserId, UserId: UserId,
EventText: fmt.Sprintf("Listed %d secrets, %+v", len(output), s), EventText: fmt.Sprintf("Listed %d secrets, %+v", len(output), s),
} }
a.AuditAdd() a.AutidLogAdd()
// output results as json // output results as json
c.JSON(http.StatusOK, gin.H{"message": "success", "data": output}) c.JSON(http.StatusOK, gin.H{"message": "success", "data": output})

View File

@@ -149,7 +149,7 @@ func StoreSecret(c *gin.Context) {
UserId: UserId, UserId: UserId,
EventText: fmt.Sprintf("Created Secret Id %d", s.SecretId), EventText: fmt.Sprintf("Created Secret Id %d", s.SecretId),
} }
a.AuditAdd() a.AutidLogAdd()
c.JSON(http.StatusOK, gin.H{"message": "secret stored successfully", "data": models.SecretRestricted(s)}) c.JSON(http.StatusOK, gin.H{"message": "secret stored successfully", "data": models.SecretRestricted(s)})
} }
@@ -370,7 +370,7 @@ func UpdateSecret(c *gin.Context) {
UserId: UserId, UserId: UserId,
EventText: fmt.Sprintf("Updated Secret Id %d", s.SecretId), EventText: fmt.Sprintf("Updated Secret Id %d", s.SecretId),
} }
a.AuditAdd() a.AutidLogAdd()
c.JSON(http.StatusOK, gin.H{"message": "secret updated successfully", "data": models.SecretRestricted(s)}) c.JSON(http.StatusOK, gin.H{"message": "secret updated successfully", "data": models.SecretRestricted(s)})
} else { } else {
@@ -460,7 +460,7 @@ func DeleteSecret(c *gin.Context) {
UserId: UserId, UserId: UserId,
EventText: fmt.Sprintf("Deleted Secret Id %d", s.SecretId), EventText: fmt.Sprintf("Deleted Secret Id %d", s.SecretId),
} }
a.AuditAdd() a.AutidLogAdd()
c.JSON(http.StatusOK, gin.H{"message": "secret deleted successfully"}) c.JSON(http.StatusOK, gin.H{"message": "secret deleted successfully"})
} else { } else {

View File

@@ -269,6 +269,7 @@ func main() {
// Other functions for admin // Other functions for admin
adminOnly.POST("/unlock", controllers.Unlock) adminOnly.POST("/unlock", controllers.Unlock)
adminOnly.GET("/logs", controllers.GetAuditLogsHandler)
// Get secrets // Get secrets
secretRoutes := router.Group("/api/secret") secretRoutes := router.Group("/api/secret")

View File

@@ -14,8 +14,8 @@ type Audit struct {
EventTime time.Time `db:"EventTime" json:"eventTime"` EventTime time.Time `db:"EventTime" json:"eventTime"`
} }
// AuditAdd adds a new audit record to the database // AutidLogAdd adds a new audit record to the database
func (a *Audit) AuditAdd() (*Audit, error) { func (a *Audit) AutidLogAdd() (*Audit, error) {
var err error var err error
// Populate timestamp field if not already set // Populate timestamp field if not already set
@@ -26,14 +26,42 @@ func (a *Audit) AuditAdd() (*Audit, error) {
result, err := db.NamedExec(("INSERT INTO audit (UserId, SecretId, EventText, EventTime) VALUES (:UserId, :SecretId, :EventText, :EventTime);"), a) result, err := db.NamedExec(("INSERT INTO audit (UserId, SecretId, EventText, EventTime) VALUES (:UserId, :SecretId, :EventText, :EventTime);"), a)
if err != nil { if err != nil {
log.Printf("AuditAdd error executing sql record : '%s'\n", err) log.Printf("AutidLogAdd error executing sql record : '%s'\n", err)
return &Audit{}, err return &Audit{}, err
} else { } else {
affected, _ := result.RowsAffected() affected, _ := result.RowsAffected()
id, _ := result.LastInsertId() id, _ := result.LastInsertId()
a.AuditId = int(id) a.AuditId = int(id)
log.Printf("AuditAdd insert returned result id '%d' affecting %d row(s).\n", id, affected) log.Printf("AutidLogAdd insert returned result id '%d' affecting %d row(s).\n", id, affected)
} }
return a, nil return a, nil
} }
// AuditList returns a list of all audit logs in database
func AuditLogList() ([]Audit, error) {
var results []Audit
// Query database for groups
rows, err := db.Queryx("SELECT * FROM audit")
if err != nil {
log.Printf("AuditLogList error executing sql record : '%s'\n", err)
return results, err
} else {
// parse all the results into a slice
for rows.Next() {
var a Audit
err = rows.StructScan(&a)
if err != nil {
log.Printf("AuditLogList error parsing sql record : '%s'\n", err)
return results, err
}
results = append(results, a)
}
log.Printf("AuditLogList retrieved '%d' results\n", len(results))
}
return results, nil
}

View File

@@ -261,6 +261,10 @@ func UserLdapNewLoginCheck(username string, password string) (User, error) {
matchFound := false matchFound := false
for _, group := range groupList { for _, group := range groupList {
// Skip any groups that aren't LDAP groups
if len(group.LdapDn) == 0 {
continue
}
for _, lg := range ldapGroups { for _, lg := range ldapGroups {
if group.LdapDn == lg { if group.LdapDn == lg {
log.Printf("Found match with groupname '%s' and LDAP group DN '%s', user is a member of group ID '%d'\n", group.GroupName, group.LdapDn, group.GroupId) log.Printf("Found match with groupname '%s' and LDAP group DN '%s', user is a member of group ID '%d'\n", group.GroupName, group.LdapDn, group.GroupId)