forked from baron/baron-sso
감사로그 조회 에러 수정
This commit is contained in:
@@ -437,7 +437,7 @@ func (h *DevHandler) auditClientIDsByPermit(c *fiber.Ctx, profile *domain.UserPr
|
|||||||
clientFilter = strings.TrimSpace(clientFilter)
|
clientFilter = strings.TrimSpace(clientFilter)
|
||||||
if clientFilter != "" {
|
if clientFilter != "" {
|
||||||
summary, err := h.loadClientSummary(c.Context(), clientFilter)
|
summary, err := h.loadClientSummary(c.Context(), clientFilter)
|
||||||
if err == nil && h.canOperateClientByPermit(c, profile, summary, "view_audit_logs") {
|
if err == nil && h.canOperateClientByPermit(c, profile, summary, "audit_viewer") {
|
||||||
ids[summary.ID] = struct{}{}
|
ids[summary.ID] = struct{}{}
|
||||||
}
|
}
|
||||||
return ids
|
return ids
|
||||||
@@ -453,7 +453,7 @@ func (h *DevHandler) auditClientIDsByPermit(c *fiber.Ctx, profile *domain.UserPr
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
summary := h.mapClientSummary(client)
|
summary := h.mapClientSummary(client)
|
||||||
if h.canOperateClientByPermit(c, profile, summary, "view_audit_logs") {
|
if h.canOperateClientByPermit(c, profile, summary, "audit_viewer") {
|
||||||
ids[summary.ID] = struct{}{}
|
ids[summary.ID] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2243,6 +2243,9 @@ func (h *DevHandler) ListAuditLogs(c *fiber.Ctx) error {
|
|||||||
if tenantFilter == "" {
|
if tenantFilter == "" {
|
||||||
tenantFilter = h.resolveDevTenantScope(c)
|
tenantFilter = h.resolveDevTenantScope(c)
|
||||||
}
|
}
|
||||||
|
if role != domain.RoleSuperAdmin && len(allowedClientIDs) > 0 {
|
||||||
|
tenantFilter = ""
|
||||||
|
}
|
||||||
if role != domain.RoleSuperAdmin && tenantFilter == "" && len(allowedClientIDs) == 0 {
|
if role != domain.RoleSuperAdmin && tenantFilter == "" && len(allowedClientIDs) == 0 {
|
||||||
tenantFilter = tenantIDFromProfile(profile)
|
tenantFilter = tenantIDFromProfile(profile)
|
||||||
}
|
}
|
||||||
@@ -2641,6 +2644,34 @@ func normalizeAuditAction(eventType string, details map[string]any) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func devAuditClientIDFromEventType(eventType string) string {
|
||||||
|
parts := strings.Split(strings.TrimSpace(eventType), " ")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
path := strings.Trim(parts[1], "/")
|
||||||
|
segments := strings.Split(path, "/")
|
||||||
|
for idx := 0; idx+1 < len(segments); idx++ {
|
||||||
|
if segments[idx] == "clients" {
|
||||||
|
return strings.TrimSpace(segments[idx+1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveDevAuditClientID(logItem domain.AuditLog, details map[string]any) string {
|
||||||
|
targetID, _ := details["target_id"].(string)
|
||||||
|
clientID, _ := details["client_id"].(string)
|
||||||
|
resolvedID := strings.TrimSpace(targetID)
|
||||||
|
if resolvedID == "" {
|
||||||
|
resolvedID = strings.TrimSpace(clientID)
|
||||||
|
}
|
||||||
|
if resolvedID == "" {
|
||||||
|
resolvedID = devAuditClientIDFromEventType(logItem.EventType)
|
||||||
|
}
|
||||||
|
return resolvedID
|
||||||
|
}
|
||||||
|
|
||||||
func resolveStatusFromMetadata(metadata map[string]interface{}) string {
|
func resolveStatusFromMetadata(metadata map[string]interface{}) string {
|
||||||
if metadata != nil {
|
if metadata != nil {
|
||||||
if value, ok := metadata["status"].(string); ok && strings.ToLower(strings.TrimSpace(value)) == "inactive" {
|
if value, ok := metadata["status"].(string); ok && strings.ToLower(strings.TrimSpace(value)) == "inactive" {
|
||||||
@@ -2676,19 +2707,12 @@ func (h *DevHandler) matchesDevAuditFilter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if clientFilter != "" {
|
if clientFilter != "" {
|
||||||
targetID, _ := details["target_id"].(string)
|
if resolveDevAuditClientID(logItem, details) != clientFilter {
|
||||||
clientID, _ := details["client_id"].(string)
|
|
||||||
if strings.TrimSpace(targetID) != clientFilter && strings.TrimSpace(clientID) != clientFilter {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(allowedClientIDs) > 0 {
|
if len(allowedClientIDs) > 0 {
|
||||||
targetID, _ := details["target_id"].(string)
|
resolvedID := resolveDevAuditClientID(logItem, details)
|
||||||
clientID, _ := details["client_id"].(string)
|
|
||||||
resolvedID := strings.TrimSpace(targetID)
|
|
||||||
if resolvedID == "" {
|
|
||||||
resolvedID = strings.TrimSpace(clientID)
|
|
||||||
}
|
|
||||||
if resolvedID == "" {
|
if resolvedID == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1604,6 +1604,13 @@ func TestListAuditLogs_UserAllowedByRPAuditPermission(t *testing.T) {
|
|||||||
Timestamp: time.Now().UTC(),
|
Timestamp: time.Now().UTC(),
|
||||||
Details: `{"target_id":"client-allowed","tenant_id":"tenant-a","action":"ROTATE_SECRET"}`,
|
Details: `{"target_id":"client-allowed","tenant_id":"tenant-a","action":"ROTATE_SECRET"}`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
EventID: "evt-allowed-path",
|
||||||
|
EventType: "GET /api/v1/dev/clients/client-allowed/relations",
|
||||||
|
Status: "success",
|
||||||
|
Timestamp: time.Now().UTC().Add(-30 * time.Second),
|
||||||
|
Details: `{"request_id":"req-1"}`,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
EventID: "evt-denied",
|
EventID: "evt-denied",
|
||||||
EventType: "POST /api/v1/dev/clients/client-denied/secret/rotate",
|
EventType: "POST /api/v1/dev/clients/client-denied/secret/rotate",
|
||||||
@@ -1624,8 +1631,8 @@ func TestListAuditLogs_UserAllowedByRPAuditPermission(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
mockKeto := new(devMockKetoService)
|
mockKeto := new(devMockKetoService)
|
||||||
mockKeto.On("CheckPermission", mock.Anything, "User:user-1", "RelyingParty", "client-allowed", "view_audit_logs").Return(true, nil)
|
mockKeto.On("CheckPermission", mock.Anything, "User:user-1", "RelyingParty", "client-allowed", "audit_viewer").Return(true, nil)
|
||||||
mockKeto.On("CheckPermission", mock.Anything, "User:user-1", "RelyingParty", "client-denied", "view_audit_logs").Return(false, nil)
|
mockKeto.On("CheckPermission", mock.Anything, "User:user-1", "RelyingParty", "client-denied", "audit_viewer").Return(false, nil)
|
||||||
|
|
||||||
h := &DevHandler{
|
h := &DevHandler{
|
||||||
Hydra: &service.HydraAdminService{
|
Hydra: &service.HydraAdminService{
|
||||||
@@ -1654,8 +1661,9 @@ func TestListAuditLogs_UserAllowedByRPAuditPermission(t *testing.T) {
|
|||||||
|
|
||||||
var result devAuditListResponse
|
var result devAuditListResponse
|
||||||
_ = json.NewDecoder(resp.Body).Decode(&result)
|
_ = json.NewDecoder(resp.Body).Decode(&result)
|
||||||
if assert.Len(t, result.Items, 1) {
|
if assert.Len(t, result.Items, 2) {
|
||||||
assert.Equal(t, "evt-allowed", result.Items[0].EventID)
|
assert.Equal(t, "evt-allowed", result.Items[0].EventID)
|
||||||
|
assert.Equal(t, "evt-allowed-path", result.Items[1].EventID)
|
||||||
}
|
}
|
||||||
mockKeto.AssertExpectations(t)
|
mockKeto.AssertExpectations(t)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,6 +179,7 @@ func AuditMiddleware(config AuditConfig) fiber.Handler {
|
|||||||
EventID: reqID,
|
EventID: reqID,
|
||||||
Timestamp: start,
|
Timestamp: start,
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
|
TenantID: tenantID,
|
||||||
SessionID: sessionID,
|
SessionID: sessionID,
|
||||||
EventType: fmt.Sprintf("%s %s", c.Method(), c.Path()),
|
EventType: fmt.Sprintf("%s %s", c.Method(), c.Path()),
|
||||||
Status: statusText,
|
Status: statusText,
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ func TestAuditMiddleware(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
app.Post("/test", func(c *fiber.Ctx) error {
|
app.Post("/test", func(c *fiber.Ctx) error {
|
||||||
|
c.Locals("tenant_id", "tenant-a")
|
||||||
c.Locals("audit_details_extra", map[string]any{
|
c.Locals("audit_details_extra", map[string]any{
|
||||||
"client_id": "rp-1",
|
"client_id": "rp-1",
|
||||||
"client_name": "Demo App",
|
"client_name": "Demo App",
|
||||||
@@ -145,6 +146,9 @@ func TestAuditMiddleware(t *testing.T) {
|
|||||||
if details["client_name"] != "Demo App" {
|
if details["client_name"] != "Demo App" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if log.TenantID != "tenant-a" || details["tenant_id"] != "tenant-a" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
skip, ok := details["auth_timeline_skip"].(bool)
|
skip, ok := details["auth_timeline_skip"].(bool)
|
||||||
return ok && skip
|
return ok && skip
|
||||||
})).Return(nil)
|
})).Return(nil)
|
||||||
|
|||||||
@@ -118,8 +118,8 @@ func (r *ClickHouseRepository) FindPage(ctx context.Context, limit int, cursor *
|
|||||||
args := make([]any, 0, 5)
|
args := make([]any, 0, 5)
|
||||||
|
|
||||||
if tenantID != "" {
|
if tenantID != "" {
|
||||||
query += " AND tenant_id = ?"
|
query += " AND (tenant_id = ? OR (tenant_id = '' AND JSONExtractString(details, 'tenant_id') = ?))"
|
||||||
args = append(args, tenantID)
|
args = append(args, tenantID, tenantID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if cursor != nil {
|
if cursor != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user