Closed diagutierrezro closed 13 minutes ago
Leo la documentación que realizo mi compañero David sobre la apropiación de la libreria.
El archivo donde se van a proponer los cambios es en middleware.go, por eso se hace una descripción de su código.
El archivo middleware.go implementa un middleware para registrar información sobre las solicitudes entrantes. Este middleware recopila información de la petición HTTP, el usuario, y otros metadatos, y genera logs en un formato personalizado.
type Usuario struct {
Sub string json:"sub"
Date time.Time
}
userMap; Un mapa en memoria para almacenar identificadores de usuarios autenticados, indexados por el token de autorización. c; Una caché (proporcionada por la biblioteca go-cache) que almacena temporalmente los datos de usuario para reducir solicitudes repetidas al servicio de autenticación.
var userMap = make(map[string]string) var c = cache.New(60time.Minute, 10time.Minute)
func getUserInfo2(ctx *context.Context) (u string) { var usuario Usuario
if val, ok := userMap[ctx.Request.Header["Authorization"][0]]; ok {
return val
} else {
if err := GetJsonWithHeader("https://autenticacion.portaloas.udistrital.edu.co/oauth2/userinfo", &usuario, ctx); err == nil {
userMap[ctx.Request.Header["Authorization"][0]] = usuario.Sub
return usuario.Sub
} else {
userMap[ctx.Request.Header["Authorization"][0]] = "No user"
return "No user"
}
}
}
func getUserInfo(ctx *context.Context) (u string) { var usuario Usuario if x, found := c.Get(ctx.Request.Header["Authorization"][0]); found { foo := x.(string) return foo } else { if err := GetJsonWithHeader("https://autenticacion.portaloas.udistrital.edu.co/oauth2/userinfo", &usuario, ctx); err == nil { c.Set(ctx.Request.Header["Authorization"][0], usuario.Sub, cache.DefaultExpiration) return usuario.Sub } else { c.Set(ctx.Request.Header["Authorization"][0], "No user", cache.DefaultExpiration) return "No user" } } }
Nombre de la aplicación (app_name). Información del usuario autenticado (user). IP del cliente, agente de usuario, host, endpoint, método y fecha de la solicitud. El cuerpo de la respuesta (data_response).
func ListenRequest(ctx *context.Context) {
/*---- Declaración de variables ---- */
/*---- Información relacionada a la aplicación y la petición ---- */
var app_name string //Nombre del API al que se le hace la petición
var host string //Host del API
var end_point string //End point al que se le realiza la petición
var method string //Método REST de la petición
var date string //Fecha y hora de la operación
/*---- Información relacionada con el usuario ---- */
var ip_user string //IP del usuario <----- pendiente
var user_agent string //Tipo de aplicación, sistema operativo, provedor del software o laversión del software de la petición del agente de usuario
var user string //Nombre de usuario en WSO2 que realiza la petición <----- pendiente
// var access_token string //Access token asignado al usuario que realiza peticion
/*---- Información relacionada con el cuerpo de la petición ---- */
var data_response interface{} //Payload del servicio
/*---- Asignación de variables ----*/
app_name = beego.AppConfig.String("appname")
host = ctx.Request.Host
end_point = ctx.Request.URL.String()
method = ctx.Request.Method
date = time.Now().String()
ip_user = ctx.Input.IP()
if len(ctx.Request.Header["User-Agent"]) > 0 {
user_agent = ctx.Request.Header["User-Agent"][0]
}
data_response = ctx.Input.Data()
//data_response = "ejemplo"
// *--------- Se implementa try y catch para cuando la petición NO viene de WSO2 y no se tiene access_token
//
go func() {
defer func() {
//Catch
if r := recover(); r != nil {
// access_token = "NO WSO2"
user = "NO WSO2 - No user"
var log = fmt.Sprintf(`@&%s@&%s@&%s@&%s@&%s@&%s@&%s@&%s@&%s@$`, app_name, host, end_point, method, date, ip_user, user_agent, user, data_response)
if end_point != "/" {
beego.Info(log)
}
}
}()
// try
// access_token = ctx.Request.Header["Authorization"][0]
/*---- Obtención del usuario ---- */
defer func() {
if r := recover(); r != nil {
// access_token = "Error WSO2"
user = "Error wso2"
var log = fmt.Sprintf(`@&%s@&%s@&%s@&%s@&%s@&%s@&%s@&%s@&%s@$`, app_name, host, end_point, method, date, ip_user, user_agent, user, data_response)
if end_point != "/" {
beego.Info(log)
}
}
}()
user = getUserInfo(ctx)
var log = fmt.Sprintf(`@&%s@&%s@&%s@&%s@&%s@&%s@&%s@&%s@&%s@$`, app_name, host, end_point, method, date, ip_user, user_agent, user, data_response)
if end_point != "/" {
beego.Info(log)
}
}()
}
func InitMiddleware() { beego.InsertFilter("*", beego.AfterExec, ListenRequest, false) }
Para que los logs generados queden en el estilo clave-valor y su data este limpia de carácteres especiales, se puede usar el paquete estándar encoding/json de Go para formatear y serializar los datos antes de registrarlos en los logs. Esto asegura que la información sea legible y compatible con herramientas de análisis JSON.
Implementación:
func ListenRequest(ctx *context.Context) { go func() { defer func() { if r := recover(); r != nil { logData := map[string]interface{}{ "app_name": beego.AppConfig.String("appname"), "host": ctx.Request.Host, "end_point": ctx.Request.URL.String(), "method": ctx.Request.Method, "date": time.Now().Format(time.RFC3339), "ip_user": ctx.Input.IP(), "user_agent": getUserAgent(ctx), "user": "Error WSO2", "data": ctx.Input.Data(), } logAsJSON(logData) } }()
user := getUserInfo(ctx)
logData := map[string]interface{}{
"app_name": beego.AppConfig.String("appname"),
"host": ctx.Request.Host,
"end_point": ctx.Request.URL.String(),
"method": ctx.Request.Method,
"date": time.Now().Format(time.RFC3339),
"ip_user": ctx.Input.IP(),
"user_agent": getUserAgent(ctx),
"user": user,
"data": ctx.Input.Data(),
}
logAsJSON(logData)
}()
}
func logAsJSON(data map[string]interface{}) { jsonLog, err := json.MarshalIndent(data, "", " ") if err != nil { beego.Error("Error al serializar el log a JSON:", err) } else { beego.Info(string(jsonLog)) } }
func getUserAgent(ctx *context.Context) string { if len(ctx.Request.Header["User-Agent"]) > 0 { return ctx.Request.Header["User-Agent"][0] } return "Desconocido" }
Se requiere realizar la apropiación de la librería de auditoría, revisar el documento creado por Andres en #241, analizar principalmente la manera de cambiar los logs cuando se muestran los JSON para que tambien se muestre la clave de este JSON y poder mapear mejor la información.
Sub Tareas
Criterios de aceptación
Requerimientos
No aplica
Definition of Ready - DoR
Definition of Done - DoD - Desarrollo