#include "agent_auth.h" #include "core/crypto/crypto_core.h" #include "core/os/os.h" #include "core/string/print_string.h" AgentAuth *AgentAuth::singleton = nullptr; AgentAuth::AgentAuth() { singleton = this; } AgentAuth::~AgentAuth() { singleton = nullptr; } void AgentAuth::_bind_methods() { ClassDB::bind_method(D_METHOD("register_agent", "name", "permissions"), &AgentAuth::register_agent, DEFVAL(PERM_ALL)); ClassDB::bind_method(D_METHOD("unregister_agent", "token"), &AgentAuth::unregister_agent); ClassDB::bind_method(D_METHOD("validate_token", "token"), &AgentAuth::validate_token); ClassDB::bind_method(D_METHOD("check_permission", "token", "perm"), &AgentAuth::check_permission); ClassDB::bind_method(D_METHOD("get_agents"), &AgentAuth::get_agents); ClassDB::bind_method(D_METHOD("get_audit_log", "count"), &AgentAuth::get_audit_log, DEFVAL(100)); ClassDB::bind_method(D_METHOD("get_agent_info", "token"), &AgentAuth::get_agent_info); ClassDB::bind_method(D_METHOD("set_max_requests_per_minute", "max"), &AgentAuth::set_max_requests_per_minute); BIND_ENUM_CONSTANT(PERM_READ); BIND_ENUM_CONSTANT(PERM_WRITE); BIND_ENUM_CONSTANT(PERM_EXECUTE); BIND_ENUM_CONSTANT(PERM_ALL); } Dictionary AgentAuth::register_agent(const String &p_name, uint32_t p_permissions) { MutexLock lock(auth_mutex); AgentSession session; session.agent_id = vformat("agent_%d", OS::get_singleton()->get_ticks_msec()); session.agent_name = p_name; session.token = _generate_token(); session.permissions = p_permissions; session.connected_at = OS::get_singleton()->get_ticks_msec(); session.last_activity = session.connected_at; sessions[session.token] = session; Dictionary result; result["agent_id"] = session.agent_id; result["token"] = session.token; result["permissions"] = session.permissions; print_line(vformat("AgentAuth: Registered agent '%s' (id: %s)", p_name, session.agent_id)); return result; } void AgentAuth::unregister_agent(const String &p_token) { MutexLock lock(auth_mutex); if (sessions.has(p_token)) { print_line(vformat("AgentAuth: Unregistered agent '%s'", sessions[p_token].agent_name)); sessions.erase(p_token); } } bool AgentAuth::validate_token(const String &p_token) { MutexLock lock(auth_mutex); return sessions.has(p_token); } bool AgentAuth::check_permission(const String &p_token, Permission p_perm) { MutexLock lock(auth_mutex); if (!sessions.has(p_token)) { return false; } return (sessions[p_token].permissions & (uint32_t)p_perm) != 0; } void AgentAuth::record_activity(const String &p_token, const String &p_method, const String &p_path, int p_status) { MutexLock lock(auth_mutex); // Update session activity. if (sessions.has(p_token)) { sessions[p_token].last_activity = OS::get_singleton()->get_ticks_msec(); sessions[p_token].request_count++; } // Add to audit log. AuditEntry entry; entry.timestamp_msec = OS::get_singleton()->get_ticks_msec(); entry.agent_id = sessions.has(p_token) ? sessions[p_token].agent_id : "unknown"; entry.method = p_method; entry.path = p_path; entry.status_code = p_status; audit_log.push_back(entry); if (audit_log.size() > MAX_AUDIT) { audit_log.remove_at(0); } } bool AgentAuth::check_rate_limit(const String &p_token) { MutexLock lock(auth_mutex); if (!sessions.has(p_token)) { return false; } // Simple rate limiting: check requests in the last minute. // For a proper implementation, use a sliding window counter. // This simplified version just checks total requests. const AgentSession &session = sessions[p_token]; uint64_t elapsed = OS::get_singleton()->get_ticks_msec() - session.connected_at; if (elapsed == 0) { return true; } float minutes = (float)elapsed / 60000.0f; float rate = (float)session.request_count / MAX(minutes, 0.01f); return rate <= (float)max_requests_per_minute; } Array AgentAuth::get_agents() const { Array result; for (const KeyValue &kv : sessions) { Dictionary dict; dict["agent_id"] = kv.value.agent_id; dict["name"] = kv.value.agent_name; dict["permissions"] = kv.value.permissions; dict["connected_at"] = kv.value.connected_at; dict["last_activity"] = kv.value.last_activity; dict["request_count"] = kv.value.request_count; result.push_back(dict); } return result; } Array AgentAuth::get_audit_log(int p_count) const { Array result; int start = MAX(0, audit_log.size() - p_count); for (int i = start; i < audit_log.size(); i++) { Dictionary dict; dict["timestamp_msec"] = audit_log[i].timestamp_msec; dict["agent_id"] = audit_log[i].agent_id; dict["method"] = audit_log[i].method; dict["path"] = audit_log[i].path; dict["status_code"] = audit_log[i].status_code; result.push_back(dict); } return result; } Dictionary AgentAuth::get_agent_info(const String &p_token) const { Dictionary dict; if (sessions.has(p_token)) { const AgentSession &s = sessions[p_token]; dict["agent_id"] = s.agent_id; dict["name"] = s.agent_name; dict["permissions"] = s.permissions; dict["connected_at"] = s.connected_at; dict["last_activity"] = s.last_activity; dict["request_count"] = s.request_count; } return dict; } String AgentAuth::_generate_token() { // Generate a random hex token. uint8_t bytes[32]; for (int i = 0; i < 32; i++) { bytes[i] = (uint8_t)(Math::rand() % 256); } String token; for (int i = 0; i < 32; i++) { token += vformat("%02x", bytes[i]); } return "agent_" + token; }