Skip to content

Commit 3c87975

Browse files
authored
Merge 8ba2174 into e77b182
2 parents e77b182 + 8ba2174 commit 3c87975

File tree

5 files changed

+108
-76
lines changed

5 files changed

+108
-76
lines changed

ydb/core/security/ldap_auth_provider/ldap_auth_provider.cpp

Lines changed: 82 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <queue>
77
#include "ldap_auth_provider.h"
88
#include "ldap_utils.h"
9+
#include "ldap_auth_provider_log.h"
910

1011
// This temporary solution
1112
// These lines should be declared outside ldap_compat.h
@@ -172,11 +173,12 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
172173

173174
int result = 0;
174175
if (Settings.GetScheme() != NKikimrLdap::LDAPS_SCHEME && Settings.GetUseTls().GetEnable()) {
176+
LDAP_LOG_D("start TLS");
175177
result = NKikimrLdap::StartTLS(*ld);
176178
if (!NKikimrLdap::IsSuccess(result)) {
179+
LDAP_LOG_D("Could not start TLS. " << NKikimrLdap::ErrorToString(result));
177180
TEvLdapAuthProvider::TError error {
178-
.Message = "Could not start TLS\n" + NKikimrLdap::ErrorToString(result),
179-
.Retryable = NKikimrLdap::IsRetryableError(result)
181+
.Message = ERROR_MESSAGE, .Retryable = NKikimrLdap::IsRetryableError(result)
180182
};
181183
// The Unbind operation is not the antithesis of the Bind operation as the name implies.
182184
// Close the LDAP connection, free the resources contained in the LDAP structure
@@ -185,12 +187,13 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
185187
}
186188
}
187189

190+
LDAP_LOG_D("bind: bindDn: " << Settings.GetBindDn());
188191
result = NKikimrLdap::Bind(*ld, Settings.GetBindDn(), Settings.GetBindPassword());
189192
if (!NKikimrLdap::IsSuccess(result)) {
193+
LDAP_LOG_D("Could not perform initial LDAP bind for dn " << Settings.GetBindDn() << " on server " + UrisCreator.GetUris() << ". "
194+
<< NKikimrLdap::ErrorToString(result));
190195
TEvLdapAuthProvider::TError error {
191-
.Message = "Could not perform initial LDAP bind for dn " + Settings.GetBindDn() + " on server " + UrisCreator.GetUris() + "\n"
192-
+ NKikimrLdap::ErrorToString(result),
193-
.Retryable = NKikimrLdap::IsRetryableError(result)
196+
.Message = ERROR_MESSAGE, .Retryable = NKikimrLdap::IsRetryableError(result)
194197
};
195198
// The Unbind operation is not the antithesis of the Bind operation as the name implies.
196199
// Close the LDAP connection, free the resources contained in the LDAP structure
@@ -210,36 +213,37 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
210213
const TString& caCertificateFile = Settings.GetUseTls().GetCaCertFile();
211214
result = NKikimrLdap::SetOption(*ld, NKikimrLdap::EOption::TLS_CACERTFILE, caCertificateFile.c_str());
212215
if (!NKikimrLdap::IsSuccess(result)) {
216+
LDAP_LOG_D("Could not set LDAP ca certificate file \"" << caCertificateFile + "\": " << NKikimrLdap::ErrorToString(result));
213217
NKikimrLdap::Unbind(*ld);
214218
return {{NKikimrLdap::ErrorToStatus(result),
215-
{.Message = "Could not set LDAP ca certificate file \"" + caCertificateFile + "\": " + NKikimrLdap::ErrorToString(result),
216-
.Retryable = NKikimrLdap::IsRetryableError(result)}}};
219+
{.Message = ERROR_MESSAGE, .Retryable = NKikimrLdap::IsRetryableError(result)}}};
217220
}
218221
}
219222

223+
LDAP_LOG_D("init: scheme: " << Settings.GetScheme() << ", uris: " << UrisCreator.GetUris() << ", port: " << UrisCreator.GetConfiguredPort());
220224
result = NKikimrLdap::Init(ld, Settings.GetScheme(), UrisCreator.GetUris(), UrisCreator.GetConfiguredPort());
221225
if (!NKikimrLdap::IsSuccess(result)) {
226+
LDAP_LOG_D("Could not initialize LDAP connection for uris: " << UrisCreator.GetUris() << ". " << NKikimrLdap::LdapError(*ld));
222227
return {{TEvLdapAuthProvider::EStatus::UNAVAILABLE,
223-
{.Message = "Could not initialize LDAP connection for uris: " + UrisCreator.GetUris() + ". " + NKikimrLdap::LdapError(*ld),
224-
.Retryable = false}}};
228+
{.Message = ERROR_MESSAGE, .Retryable = false}}};
225229
}
226230

227231
result = NKikimrLdap::SetProtocolVersion(*ld);
228232
if (!NKikimrLdap::IsSuccess(result)) {
229233
NKikimrLdap::Unbind(*ld);
234+
LDAP_LOG_D("Could not set LDAP protocol version: " << NKikimrLdap::ErrorToString(result));
230235
return {{NKikimrLdap::ErrorToStatus(result),
231-
{.Message = "Could not set LDAP protocol version: " + NKikimrLdap::ErrorToString(result),
232-
.Retryable = NKikimrLdap::IsRetryableError(result)}}};
236+
{.Message = ERROR_MESSAGE, .Retryable = NKikimrLdap::IsRetryableError(result)}}};
233237
}
234238

235239
if (Settings.GetScheme() == NKikimrLdap::LDAPS_SCHEME || Settings.GetUseTls().GetEnable()) {
236240
int requireCert = NKikimrLdap::ConvertRequireCert(Settings.GetUseTls().GetCertRequire());
237241
result = NKikimrLdap::SetOption(*ld, NKikimrLdap::EOption::TLS_REQUIRE_CERT, &requireCert);
238242
if (!NKikimrLdap::IsSuccess(result)) {
239243
NKikimrLdap::Unbind(*ld);
244+
LDAP_LOG_D("Could not set require certificate option: " << NKikimrLdap::ErrorToString(result));
240245
return {{NKikimrLdap::ErrorToStatus(result),
241-
{.Message = "Could not set require certificate option: " + NKikimrLdap::ErrorToString(result),
242-
.Retryable = NKikimrLdap::IsRetryableError(result)}}};
246+
{.Message = ERROR_MESSAGE, .Retryable = NKikimrLdap::IsRetryableError(result)}}};
243247
}
244248
}
245249

@@ -249,16 +253,18 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
249253
TAuthenticateUserResponse AuthenticateUser(const TAuthenticateUserRequest& request) {
250254
char* dn = NKikimrLdap::GetDn(*request.Ld, request.Entry);
251255
if (dn == nullptr) {
256+
LDAP_LOG_D("Could not get dn for the first entry matching " << FilterCreator.GetFilter(request.Login) << " on server " << UrisCreator.GetUris() << ". "
257+
<< NKikimrLdap::LdapError(*request.Ld));
252258
return {{TEvLdapAuthProvider::EStatus::UNAUTHORIZED,
253-
{.Message = "Could not get dn for the first entry matching " + FilterCreator.GetFilter(request.Login) + " on server " + UrisCreator.GetUris() + "\n"
254-
+ NKikimrLdap::LdapError(*request.Ld),
255-
.Retryable = false}}};
259+
{.Message = ERROR_MESSAGE, .Retryable = false}}};
256260
}
257261
TEvLdapAuthProvider::TError error;
262+
LDAP_LOG_D("bind: bindDn: " << dn);
258263
int result = NKikimrLdap::Bind(*request.Ld, dn, request.Password);
259264
if (!NKikimrLdap::IsSuccess(result)) {
260-
error.Message = "LDAP login failed for user " + TString(dn) + " on server " + UrisCreator.GetUris() + "\n"
261-
+ NKikimrLdap::ErrorToString((result));
265+
LDAP_LOG_D("LDAP login failed for user " << TString(dn) << " on server " << UrisCreator.GetUris() << ". "
266+
<< NKikimrLdap::ErrorToString((result)));
267+
error.Message = ERROR_MESSAGE;
262268
error.Retryable = NKikimrLdap::IsRetryableError(result);
263269
}
264270
NKikimrLdap::MemFree(dn);
@@ -269,6 +275,10 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
269275
LDAPMessage* searchMessage = nullptr;
270276
const TString searchFilter = FilterCreator.GetFilter(request.User);
271277

278+
LDAP_LOG_D("search: baseDn: " << Settings.GetBaseDn()
279+
<< ", scope: " << ConvertSearchScopeToString(NKikimrLdap::EScope::SUBTREE)
280+
<< ", filter: " << searchFilter
281+
<< ", attributes: " << GetStringOfRequestedAttributes(request.RequestedAttributes));
272282
int result = NKikimrLdap::Search(request.Ld,
273283
Settings.GetBaseDn(),
274284
NKikimrLdap::EScope::SUBTREE,
@@ -278,23 +288,22 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
278288
&searchMessage);
279289
TSearchUserResponse response;
280290
if (!NKikimrLdap::IsSuccess(result)) {
291+
LDAP_LOG_D("Could not search for filter " << searchFilter << " on server " << UrisCreator.GetUris() << ". "
292+
<< NKikimrLdap::ErrorToString(result));
281293
response.Status = NKikimrLdap::ErrorToStatus(result);
282-
response.Error = {.Message = "Could not search for filter " + searchFilter + " on server " + UrisCreator.GetUris() + "\n"
283-
+ NKikimrLdap::ErrorToString(result),
284-
.Retryable = NKikimrLdap::IsRetryableError(result)};
294+
response.Error = {.Message = ERROR_MESSAGE, .Retryable = NKikimrLdap::IsRetryableError(result)};
285295
return response;
286296
}
287297
const int countEntries = NKikimrLdap::CountEntries(request.Ld, searchMessage);
288298
if (countEntries != 1) {
289299
if (countEntries == 0) {
290-
response.Error = {.Message = "LDAP user " + request.User + " does not exist. "
291-
"LDAP search for filter " + searchFilter + " on server " + UrisCreator.GetUris() + " return no entries",
292-
.Retryable = false};
300+
LDAP_LOG_D("LDAP user " << request.User << " does not exist. "
301+
"LDAP search for filter " << searchFilter << " on server " << UrisCreator.GetUris() << " return no entries");
293302
} else {
294-
response.Error = {.Message = "LDAP user " + request.User + " is not unique. "
295-
"LDAP search for filter " + searchFilter + " on server " + UrisCreator.GetUris() + " return " + countEntries + " entries",
296-
.Retryable = false};
303+
LDAP_LOG_D("LDAP user " << request.User << " is not unique. "
304+
"LDAP search for filter " << searchFilter << " on server " << UrisCreator.GetUris() << " return " << countEntries << " entries");
297305
}
306+
response.Error = {.Message = ERROR_MESSAGE, .Retryable = false};
298307
response.Status = TEvLdapAuthProvider::EStatus::UNAUTHORIZED;
299308
NKikimrLdap::MsgFree(searchMessage);
300309
return response;
@@ -306,7 +315,14 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
306315
std::vector<TString> TryToGetGroupsUseMatchingRuleInChain(LDAP* ld, LDAPMessage* entry) const {
307316
static const TString matchingRuleInChain = "1.2.840.113556.1.4.1941"; // Only Active Directory supports
308317
TStringBuilder filter;
309-
filter << "(member:" << matchingRuleInChain << ":=" << NKikimrLdap::GetDn(ld, entry) << ')';
318+
char* dn = NKikimrLdap::GetDn(ld, entry);
319+
filter << "(member:" << matchingRuleInChain << ":=" << dn << ')';
320+
NKikimrLdap::MemFree(dn);
321+
dn = nullptr;
322+
LDAP_LOG_D("search: baseDn: " << Settings.GetBaseDn()
323+
<< ", scope: " << ConvertSearchScopeToString(NKikimrLdap::EScope::SUBTREE)
324+
<< ", filter: " << filter
325+
<< ", attributes: " << GetStringOfRequestedAttributes(NKikimrLdap::noAttributes));
310326
LDAPMessage* searchMessage = nullptr;
311327
int result = NKikimrLdap::Search(ld, Settings.GetBaseDn(), NKikimrLdap::EScope::SUBTREE, filter, NKikimrLdap::noAttributes, 0, &searchMessage);
312328
if (!NKikimrLdap::IsSuccess(result)) {
@@ -320,13 +336,18 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
320336
std::vector<TString> groups;
321337
groups.reserve(countEntries);
322338
for (LDAPMessage* groupEntry = NKikimrLdap::FirstEntry(ld, searchMessage); groupEntry != nullptr; groupEntry = NKikimrLdap::NextEntry(ld, groupEntry)) {
323-
groups.push_back(NKikimrLdap::GetDn(ld, groupEntry));
339+
dn = NKikimrLdap::GetDn(ld, groupEntry);
340+
groups.push_back(dn);
341+
NKikimrLdap::MemFree(dn);
342+
dn = nullptr;
324343
}
325344
NKikimrLdap::MsgFree(searchMessage);
326345
return groups;
327346
}
328347

329348
void GetNestedGroups(LDAP* ld, std::vector<TString>* groups) {
349+
LDAP_LOG_D("Try to get nested groups - tree traversal");
350+
330351
std::unordered_set<TString> viewedGroups(groups->cbegin(), groups->cend());
331352
std::queue<TString> queue;
332353
for (const auto& group : *groups) {
@@ -344,6 +365,10 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
344365
queue.pop();
345366
}
346367
filter << ')';
368+
LDAP_LOG_D("search: baseDn: " << Settings.GetBaseDn()
369+
<< ", scope: " << ConvertSearchScopeToString(NKikimrLdap::EScope::SUBTREE)
370+
<< ", filter: " << filter
371+
<< ", attributes: " << GetStringOfRequestedAttributes(RequestedAttributes));
347372
LDAPMessage* searchMessage = nullptr;
348373
int result = NKikimrLdap::Search(ld, Settings.GetBaseDn(), NKikimrLdap::EScope::SUBTREE, filter, RequestedAttributes, 0, &searchMessage);
349374
if (!NKikimrLdap::IsSuccess(result)) {
@@ -392,7 +417,35 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
392417
return {TEvLdapAuthProvider::EStatus::SUCCESS, {}};
393418
}
394419

420+
static TString ConvertSearchScopeToString(const NKikimrLdap::EScope& scope) {
421+
switch (scope) {
422+
case NKikimrLdap::EScope::BASE:
423+
return "base";
424+
case NKikimrLdap::EScope::ONE_LEVEL:
425+
return "one level";
426+
case NKikimrLdap::EScope::SUBTREE:
427+
return "subtree";
428+
}
429+
}
430+
431+
static TString GetStringOfRequestedAttributes(char** attributes) {
432+
if (!attributes) {
433+
return "";
434+
}
435+
TStringBuilder result;
436+
char* firstAttribute = *attributes;
437+
if (firstAttribute) {
438+
result << firstAttribute;
439+
for (char* currentAttribute = *(++attributes); currentAttribute != nullptr; currentAttribute = *(++attributes)) {
440+
result << ", " << currentAttribute;
441+
}
442+
}
443+
return result;
444+
}
445+
395446
private:
447+
static constexpr const char* ERROR_MESSAGE = "User is unauthorized in LDAP server";
448+
396449
const NKikimrProto::TLdapAuthentication Settings;
397450
const TSearchFilterCreator FilterCreator;
398451
const TLdapUrisCreator UrisCreator;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
3+
#include <ydb/library/actors/core/log.h>
4+
5+
#if defined LDAP_LOG_D || defined LDAP_LOG_W || defined LDAP_LOG_ERROR || defined LDAP_LOG_TRACE
6+
#error log macro definition clash
7+
#endif
8+
9+
#define LDAP_LOG_D(stream) LOG_DEBUG_S(*TlsActivationContext, NKikimrServices::LDAP_AUTH_PROVIDER, stream)
10+
#define LDAP_LOG_TRACE(stream) LOG_TRACE_S(*TlsActivationContext, NKikimrServices::LDAP_AUTH_PROVIDER, stream)
11+
#define LDAP_LOG_ERROR(stream) LOG_ERROR_S(*TlsActivationContext, NKikimrServices::LDAP_AUTH_PROVIDER, stream)
12+
#define LDAP_LOG_W(stream) LOG_WARN_S(*TlsActivationContext, NKikimrServices::LDAP_AUTH_PROVIDER, stream)

0 commit comments

Comments
 (0)