address feedback.

* use exceptions when fetching identity key instead of std::optional, will throw on fail
* fix up config options for endpoint auth and add better docs
* add llarp::serive::AuthType enum for controlling what kind of endpoint auth to use
pull/1306/head
Jeff Becker 4 years ago
parent a7c42ab2bd
commit 80919a3b76
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -165,12 +165,16 @@ namespace llarp
conf.defineOption<std::string>("network", "keyfile", false, "", AssignmentAcceptor(m_keyfile));
conf.defineOption<bool>("network", "auth", false, false, AssignmentAcceptor(m_AuthEnabled));
conf.defineOption<std::string>("network", "auth", false, "", [this](std::string arg) {
if (arg.empty())
return;
m_AuthType = service::ParseAuthType(arg);
});
conf.defineOption<std::string>("network", "auth-url", false, "", AssignmentAcceptor(m_AuthUrl));
conf.defineOption<std::string>("network", "auth-lmq", false, "", AssignmentAcceptor(m_AuthUrl));
conf.defineOption<std::string>(
"network", "auth-method", false, "llarp.auth", [this](std::string arg) {
"network", "auth-lmq-method", false, "llarp.auth", [this](std::string arg) {
if (arg.empty())
return;
m_AuthMethod = std::move(arg);
@ -877,7 +881,10 @@ namespace llarp
"network",
"exit-node",
{
"Specify a `.loki` address to use as an exit broker.",
"Specify a `.loki` address and an optional ip range to use as an exit broker.",
"Example:",
"exit-node=whatever.loki # maps all exit traffic to whatever.loki",
"exit-node=stuff.loki:100.0.0.0/24 # maps 100.0.0.0/24 to stuff.loki",
});
def.addOptionComments(
@ -901,21 +908,22 @@ namespace llarp
"network",
"auth",
{
"authenticate remote sessions against a whitelist or an external lmq server",
"true/false",
"Set the endpoint authentication mechanism.",
"none/whitelist/lmq",
});
def.addOptionComments(
"network",
"auth-url",
"auth-lmq",
{
"lmq endpoint to talk to for authenticating new sessions",
"ipc:///var/lib/lokinet/auth.socket",
"tcp://127.0.0.1:5555",
});
def.addOptionComments(
"network",
"auth-method",
"auth-lmq-method",
{
"lmq function to call for authenticating new sessions",
"llarp.auth",

@ -13,6 +13,7 @@
#include <net/net_int.hpp>
#include <net/ip_range_map.hpp>
#include <service/address.hpp>
#include <service/auth.hpp>
#include <cstdlib>
#include <functional>
@ -83,7 +84,7 @@ namespace llarp
net::IPRangeMap<service::Address> m_ExitMap;
std::unordered_map<huint128_t, service::Address> m_mapAddrs;
bool m_AuthEnabled = false;
service::AuthType m_AuthType = service::AuthType::eAuthTypeNone;
std::optional<std::string> m_AuthUrl;
std::optional<std::string> m_AuthMethod;
std::unordered_set<service::Address, service::Address::Hash> m_AuthWhitelist;

@ -93,8 +93,7 @@ namespace llarp
router = std::make_unique<Router>(mainloop, logic);
nodedb = std::make_unique<llarp_nodedb>(
nodedb_dir,
[r = router.get()](std::function<void(void)> call) { r->QueueDiskIO(std::move(call)); });
nodedb_dir, [r = router.get()](auto call) { r->QueueDiskIO(std::move(call)); });
if (!router->Configure(config.get(), opts.isRouter, nodedb.get()))
throw std::runtime_error("Failed to configure router");

@ -117,14 +117,16 @@ namespace llarp
LogInfo(Name(), " setting to be not reachable by default");
}
if (conf.m_AuthUrl.has_value() and conf.m_AuthMethod.has_value())
if (conf.m_AuthType != service::AuthType::eAuthTypeNone)
{
std::string url, method;
if (conf.m_AuthUrl.has_value() and conf.m_AuthMethod.has_value())
{
url = *conf.m_AuthUrl;
method = *conf.m_AuthMethod;
}
auto auth = std::make_shared<rpc::EndpointAuthRPC>(
*conf.m_AuthUrl,
*conf.m_AuthMethod,
conf.m_AuthWhitelist,
Router()->lmq(),
shared_from_this());
url, method, conf.m_AuthWhitelist, Router()->lmq(), shared_from_this());
auth->Start();
m_AuthPolicy = std::move(auth);
}

@ -212,9 +212,7 @@ namespace llarp
return false;
#endif
#endif
const auto maybe = RpcClient()->ObtainIdentityKey();
if (maybe.has_value())
_identity = *maybe;
_identity = RpcClient()->ObtainIdentityKey();
}
else
{
@ -287,7 +285,7 @@ namespace llarp
LogError("RC is invalid, not saving");
return false;
}
QueueDiskIO(std::bind(&Router::HandleSaveRC, this));
QueueDiskIO([&]() { HandleSaveRC(); });
return true;
}

@ -158,44 +158,42 @@ namespace llarp
LogicCall(m_Router->logic(), [r = m_Router, nodeList]() { r->SetRouterWhitelist(nodeList); });
}
std::optional<SecretKey>
SecretKey
LokidRpcClient::ObtainIdentityKey()
{
std::promise<std::optional<SecretKey>> promise;
std::promise<SecretKey> promise;
Request(
"admin.get_service_privkeys",
[self = shared_from_this(), &promise](bool success, std::vector<std::string> data) {
if (not success)
{
LogError("failed to get private key");
promise.set_value(std::nullopt);
return;
}
if (data.empty())
{
LogError("failed to get private key, no response");
promise.set_value(std::nullopt);
return;
}
try
{
auto j = nlohmann::json::parse(data[0]);
if (not success)
{
throw std::runtime_error(
"failed to get private key request "
"failed");
}
if (data.empty())
{
throw std::runtime_error(
"failed to get private key request "
"data empty");
}
const auto j = nlohmann::json::parse(data[0]);
SecretKey k;
if (not k.FromHex(j.at("service_node_ed25519_privkey").get<std::string>()))
{
promise.set_value(std::nullopt);
return;
throw std::runtime_error("failed to parse private key");
}
promise.set_value(k);
}
catch (std::exception& ex)
catch (...)
{
LogError("failed to get private key: ", ex.what());
promise.set_value(std::nullopt);
promise.set_exception(std::current_exception());
}
});
return promise.get_future().get();
auto ftr = promise.get_future();
return ftr.get();
}
} // namespace rpc

@ -26,7 +26,8 @@ namespace llarp
ConnectAsync(lokimq::address url);
/// blocking request identity key from lokid
std::optional<SecretKey>
/// throws on failure
SecretKey
ObtainIdentityKey();
private:

@ -7,7 +7,7 @@ namespace llarp::service
std::optional<AuthResult>
ParseAuthResult(std::string data)
{
static thread_local std::unordered_map<std::string, AuthResult> values = {
static std::unordered_map<std::string, AuthResult> values = {
{"OKAY", AuthResult::eAuthAccepted},
{"REJECT", AuthResult::eAuthRejected},
{"PAYME", AuthResult::eAuthPaymentRequired},
@ -17,4 +17,17 @@ namespace llarp::service
return std::nullopt;
return itr->second;
}
AuthType
ParseAuthType(std::string data)
{
static std::unordered_map<std::string, AuthType> values = {
{"lmq", AuthType::eAuthTypeLMQ},
{"whitelist", AuthType::eAuthTypeWhitelist},
{"none", AuthType::eAuthTypeNone}};
const auto itr = values.find(data);
if (itr == values.end())
throw std::invalid_argument("no such auth type: " + data);
return itr->second;
}
} // namespace llarp::service

@ -45,4 +45,20 @@ namespace llarp::service
std::string token;
};
/// what kind of backend to use for auth
enum class AuthType
{
/// no authentication
eAuthTypeNone,
/// manual whitelist
eAuthTypeWhitelist,
/// LMQ server
eAuthTypeLMQ
};
/// get an auth type from a string
/// throws std::invalid_argument if arg is invalid
AuthType
ParseAuthType(std::string arg);
} // namespace llarp::service

Loading…
Cancel
Save