Entropic 2.3.8
Local-first agentic inference engine
Loading...
Searching...
No Matches
mcp_authorization.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
10
11#include <nlohmann/json.hpp>
12
13static auto logger = entropic::log::get("mcp.authorization");
14
15namespace entropic {
16
24 const std::string& identity_name) {
25 std::lock_guard<std::mutex> lock(auth_mutex_);
26 key_sets_.try_emplace(identity_name);
27 logger->info("Registered identity: {}", identity_name);
28}
29
38 const std::string& identity_name) const {
39 std::lock_guard<std::mutex> lock(auth_mutex_);
40 return key_sets_.count(identity_name) > 0;
41}
42
53 const std::string& identity_name,
54 const std::string& pattern,
55 MCPAccessLevel level) {
56 std::lock_guard<std::mutex> lock(auth_mutex_);
57 auto it = key_sets_.find(identity_name);
58 if (it == key_sets_.end()) {
60 }
61 it->second.grant(pattern, level);
62 return ENTROPIC_OK;
63}
64
74 const std::string& identity_name,
75 const std::string& pattern) {
76 std::lock_guard<std::mutex> lock(auth_mutex_);
77 auto it = key_sets_.find(identity_name);
78 if (it == key_sets_.end()) {
80 }
81 it->second.revoke(pattern);
82 return ENTROPIC_OK;
83}
84
95 const std::string& identity_name,
96 const std::string& tool_name,
97 MCPAccessLevel required_level) const {
98 std::lock_guard<std::mutex> lock(auth_mutex_);
99 auto it = key_sets_.find(identity_name);
100 if (it == key_sets_.end()) {
101 logger->info("Auth ALLOW: {} on {} (no enforcement)",
102 identity_name, tool_name);
103 return true;
104 }
105 bool allowed = it->second.has_access(tool_name, required_level);
106 logger->info("Auth {}: {} on {} (required={})",
107 allowed ? "ALLOW" : "DENY",
108 identity_name, tool_name,
109 static_cast<int>(required_level));
110 return allowed;
111}
112
124 const std::string& granter_name,
125 const std::string& grantee_name,
126 const std::string& pattern,
127 MCPAccessLevel level) {
128 std::lock_guard<std::mutex> lock(auth_mutex_);
129 auto granter = key_sets_.find(granter_name);
130 auto grantee = key_sets_.find(grantee_name);
131 if (granter == key_sets_.end() ||
132 grantee == key_sets_.end()) {
134 }
135 if (!granter->second.has_access(pattern, level)) {
136 logger->warn("{} lacks {}:{} — cannot grant to {}",
137 granter_name, pattern,
138 mcp_access_level_name(level), grantee_name);
140 }
141 grantee->second.grant(pattern, level);
142 logger->info("{} granted {}:{} to {}", granter_name, pattern,
143 mcp_access_level_name(level), grantee_name);
144 return ENTROPIC_OK;
145}
146
155 const std::string& identity_name) const {
156 std::lock_guard<std::mutex> lock(auth_mutex_);
157 auto it = key_sets_.find(identity_name);
158 if (it == key_sets_.end()) {
159 return {};
160 }
161 return it->second.list();
162}
163
171 std::lock_guard<std::mutex> lock(auth_mutex_);
172 nlohmann::json obj = nlohmann::json::object();
173 for (const auto& [name, key_set] : key_sets_) {
174 auto keys_json = key_set.serialize();
175 obj[name] = nlohmann::json::parse(keys_json);
176 }
177 return obj.dump();
178}
179
188 const std::string& json) {
189 nlohmann::json obj;
190 try {
191 obj = nlohmann::json::parse(json);
192 } catch (const nlohmann::json::exception& e) {
193 logger->warn("Deserialize failed: {}", e.what());
194 return false;
195 }
196 if (!obj.is_object()) {
197 logger->warn("Deserialize: expected JSON object");
198 return false;
199 }
200 std::lock_guard<std::mutex> lock(auth_mutex_);
201 key_sets_.clear();
202 for (const auto& [name, keys_arr] : obj.items()) {
203 auto [it, _] = key_sets_.try_emplace(name);
204 it->second.deserialize(keys_arr.dump());
205 }
206 return true;
207}
208
216 const std::string& identity_name) {
217 std::lock_guard<std::mutex> lock(auth_mutex_);
218 key_sets_.erase(identity_name);
219 logger->info("Unregistered identity: {}", identity_name);
220}
221
222} // namespace entropic
entropic_error_t grant(const std::string &identity_name, const std::string &pattern, MCPAccessLevel level)
Grant a tool key to an identity.
void register_identity(const std::string &identity_name)
Register an empty key set for an identity.
void unregister_identity(const std::string &identity_name)
Remove an identity's key set (disables enforcement).
bool deserialize_all(const std::string &json)
Deserialize all identity key sets from JSON.
bool is_enforced(const std::string &identity_name) const
Check if an identity has authorization enforcement enabled.
entropic_error_t revoke(const std::string &identity_name, const std::string &pattern)
Revoke a tool key from an identity.
std::string serialize_all() const
Serialize all identity key sets to JSON.
std::vector< MCPKey > list_keys(const std::string &identity_name) const
List all keys for an identity.
entropic_error_t grant_from(const std::string &granter_name, const std::string &grantee_name, const std::string &pattern, MCPAccessLevel level)
One identity grants a key to another identity.
bool check_access(const std::string &identity_name, const std::string &tool_name, MCPAccessLevel required_level) const
Check if a tool call is authorized for an identity.
entropic_error_t
Error codes returned by all C API functions.
Definition error.h:35
@ ENTROPIC_OK
Success.
Definition error.h:36
@ ENTROPIC_ERROR_IDENTITY_NOT_FOUND
Identity name not in config (v1.8.9)
Definition error.h:58
@ ENTROPIC_ERROR_PERMISSION_DENIED
Tool call blocked by permission manager.
Definition error.h:44
spdlog initialization and logger access.
ENTROPIC_EXPORT std::shared_ptr< spdlog::logger > get(const std::string &name)
Get or create a named logger.
Definition logging.cpp:211
Per-identity MCP authorization with runtime grant/revoke.
Activate model on GPU (WARM → ACTIVE).
const char * mcp_access_level_name(MCPAccessLevel level)
Convert MCPAccessLevel to string representation.
Definition config.cpp:21
MCPAccessLevel
MCP tool access level for per-identity authorization.
Definition config.h:38