diff --git a/cmd/audit-service/audit_service_fx.go b/cmd/audit-service/audit_service_fx.go index da787a5..b73833c 100644 --- a/cmd/audit-service/audit_service_fx.go +++ b/cmd/audit-service/audit_service_fx.go @@ -5,6 +5,7 @@ package main import ( "context" "fmt" + "math" "net" "time" @@ -275,9 +276,13 @@ func (s *auditServerImpl) Query(ctx context.Context, req *auditv1.QueryRequest) }) } + total := len(protoEntries) + if total > math.MaxInt32 { + total = math.MaxInt32 + } return &auditv1.QueryResponse{ Entries: protoEntries, - Total: int32(len(protoEntries)), + Total: int32(total), }, nil } diff --git a/cmd/identity-service/identity_service_fx.go b/cmd/identity-service/identity_service_fx.go index 065ff9b..9f48cc0 100644 --- a/cmd/identity-service/identity_service_fx.go +++ b/cmd/identity-service/identity_service_fx.go @@ -8,6 +8,7 @@ import ( "crypto/subtle" "encoding/base64" "fmt" + "math" "net" "strings" "time" @@ -72,7 +73,11 @@ func verifyPassword(password, hash string) (bool, error) { if err != nil { return false, err } - actualHash := argon2.IDKey([]byte(password), salt, 3, 64*1024, 4, uint32(len(expectedHash))) + hashLen := len(expectedHash) + if hashLen < 0 || hashLen > math.MaxUint32 { + return false, fmt.Errorf("invalid hash length: %d", hashLen) + } + actualHash := argon2.IDKey([]byte(password), salt, 3, 64*1024, 4, uint32(hashLen)) return subtle.ConstantTimeCompare(expectedHash, actualHash) == 1, nil } diff --git a/internal/client/grpc/audit_client.go b/internal/client/grpc/audit_client.go index e4384d4..7bc5f0c 100644 --- a/internal/client/grpc/audit_client.go +++ b/internal/client/grpc/audit_client.go @@ -4,6 +4,7 @@ package grpc import ( "context" "fmt" + "math" auditv1 "git.dcentral.systems/toolz/goplt/api/proto/generated/audit/v1" "git.dcentral.systems/toolz/goplt/pkg/registry" @@ -86,9 +87,17 @@ func (c *AuditClient) Query(ctx context.Context, filters *services.AuditLogFilte return nil, err } + limit := filters.Limit + if limit > math.MaxInt32 { + limit = math.MaxInt32 + } + offset := filters.Offset + if offset > math.MaxInt32 { + offset = math.MaxInt32 + } req := &auditv1.QueryRequest{ - Limit: int32(filters.Limit), - Offset: int32(filters.Offset), + Limit: int32(limit), + Offset: int32(offset), } if filters.UserID != nil { diff --git a/internal/config/config.go b/internal/config/config.go index fed7764..c29c60f 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -100,9 +100,15 @@ func LoadConfig(env string) (config.ConfigProvider, error) { // e.g., DATABASE_DSN -> database.dsn, SERVER_PORT -> server.port v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) // Bind specific environment variables to config keys - v.BindEnv("database.dsn", "DATABASE_DSN") - v.BindEnv("registry.consul.address", "REGISTRY_CONSUL_ADDRESS") - v.BindEnv("registry.type", "REGISTRY_TYPE") + if err := v.BindEnv("database.dsn", "DATABASE_DSN"); err != nil { + return nil, fmt.Errorf("failed to bind DATABASE_DSN: %w", err) + } + if err := v.BindEnv("registry.consul.address", "REGISTRY_CONSUL_ADDRESS"); err != nil { + return nil, fmt.Errorf("failed to bind REGISTRY_CONSUL_ADDRESS: %w", err) + } + if err := v.BindEnv("registry.type", "REGISTRY_TYPE"); err != nil { + return nil, fmt.Errorf("failed to bind REGISTRY_TYPE: %w", err) + } return NewViperConfig(v), nil } diff --git a/services/audit/internal/api/server.go b/services/audit/internal/api/server.go index 3e67362..396f5f7 100644 --- a/services/audit/internal/api/server.go +++ b/services/audit/internal/api/server.go @@ -2,6 +2,7 @@ package api import ( + "math" "context" auditv1 "git.dcentral.systems/toolz/goplt/api/proto/generated/audit/v1" @@ -118,8 +119,12 @@ func (s *Server) Query(ctx context.Context, req *auditv1.QueryRequest) (*auditv1 }) } + total := len(protoEntries) + if total > math.MaxInt32 { + total = math.MaxInt32 + } return &auditv1.QueryResponse{ Entries: protoEntries, - Total: int32(len(protoEntries)), // Note: This is a simplified total, actual total would require a count query + Total: int32(total), // Note: This is a simplified total, actual total would require a count query }, nil } diff --git a/services/identity/internal/password/password.go b/services/identity/internal/password/password.go index 7b1f4d7..81b51aa 100644 --- a/services/identity/internal/password/password.go +++ b/services/identity/internal/password/password.go @@ -7,6 +7,7 @@ import ( "encoding/base64" "errors" "fmt" + "math" "strings" "golang.org/x/crypto/argon2" @@ -77,7 +78,11 @@ func Verify(password, hash string) (bool, error) { } // Compute hash with same parameters - actualHash := argon2.IDKey([]byte(password), salt, uint32(t), uint32(m), uint8(p), uint32(len(expectedHash))) + hashLen := len(expectedHash) + if hashLen < 0 || hashLen > math.MaxUint32 { + return false, fmt.Errorf("invalid hash length: %d", hashLen) + } + actualHash := argon2.IDKey([]byte(password), salt, uint32(t), uint32(m), uint8(p), uint32(hashLen)) // Constant-time comparison if subtle.ConstantTimeCompare(expectedHash, actualHash) == 1 { diff --git a/services/identity/internal/password/password_test.go b/services/identity/internal/password/password_test.go index 7886eb9..8166343 100644 --- a/services/identity/internal/password/password_test.go +++ b/services/identity/internal/password/password_test.go @@ -209,33 +209,3 @@ func TestHash_Uniqueness(t *testing.T) { } } -// Helper functions for test -func splitHash(hash string) []string { - parts := make([]string, 0, 6) - current := "" - for _, char := range hash { - if char == '$' { - if current != "" { - parts = append(parts, current) - current = "" - } - } else { - current += string(char) - } - } - if current != "" { - parts = append(parts, current) - } - return parts -} - -func joinHash(parts []string) string { - result := "" - for i, part := range parts { - if i > 0 { - result += "$" - } - result += part - } - return result -}