Skip to content

Commit 317be59

Browse files
authored
[LDAP] Support ldaps scheme (#5934)
1 parent bc07740 commit 317be59

32 files changed

+975
-657
lines changed

ydb/core/driver_lib/run/kikimr_services_initializers.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@
118118
#include <ydb/core/scheme/scheme_type_registry.h>
119119

120120
#include <ydb/core/security/ticket_parser.h>
121-
#include <ydb/core/security/ldap_auth_provider.h>
121+
#include <ydb/core/security/ldap_auth_provider/ldap_auth_provider.h>
122122
#include <ydb/core/security/ticket_parser_settings.h>
123123

124124
#include <ydb/core/sys_view/processor/processor.h>

ydb/core/driver_lib/run/ya.make

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ PEERDIR(
9797
ydb/core/scheme
9898
ydb/core/scheme_types
9999
ydb/core/security
100+
ydb/core/security/ldap_auth_provider
100101
ydb/core/statistics
101102
ydb/core/statistics/aggregator
102103
ydb/core/sys_view/processor

ydb/core/grpc_services/rpc_login.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include <ydb/core/tx/schemeshard/schemeshard.h>
99
#include <ydb/core/tx/scheme_cache/scheme_cache.h>
1010

11-
#include <ydb/core/security/ldap_auth_provider.h>
11+
#include <ydb/core/security/ldap_auth_provider/ldap_auth_provider.h>
1212
#include <ydb/core/security/login_shared_func.h>
1313

1414
#include <ydb/public/api/protos/ydb_auth.pb.h>

ydb/core/grpc_services/ya.make

+1
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ PEERDIR(
126126
ydb/core/util
127127
ydb/core/ydb_convert
128128
ydb/core/security
129+
ydb/core/security/ldap_auth_provider
129130
ydb/library/aclib
130131
ydb/library/binary_json
131132
ydb/library/dynumber

ydb/core/protos/auth.proto

+3-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ message TLdapAuthentication {
102102
optional TCertRequire CertRequire = 3 [default = DEMAND];
103103
}
104104

105-
optional string Host = 1;
105+
optional string Host = 1; // DEPRECATED: Use Hosts instead it
106106
optional uint32 Port = 2;
107107
optional string BaseDn = 3;
108108
optional string BindDn = 4;
@@ -111,4 +111,6 @@ message TLdapAuthentication {
111111
optional string SearchAttribute = 7;
112112
optional TUseTls UseTls = 8;
113113
optional string RequestedGroupAttribute = 9;
114+
repeated string Hosts = 10;
115+
optional string Scheme = 11 [default = "ldap"];
114116
}

ydb/core/security/ldap_auth_provider.cpp renamed to ydb/core/security/ldap_auth_provider/ldap_auth_provider.cpp

+50-17
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include <ydb/library/actors/core/actor_bootstrapped.h>
22
#include <ydb/library/actors/core/log.h>
33
#include <ydb/core/base/ticket_parser.h>
4-
#include "ticket_parser_log.h"
4+
#include <ydb/core/security/ticket_parser_log.h>
55
#include "ldap_auth_provider.h"
66
#include "ldap_utils.h"
77

@@ -156,7 +156,7 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
156156
}
157157

158158
int result = 0;
159-
if (Settings.GetUseTls().GetEnable()) {
159+
if (Settings.GetScheme() != NKikimrLdap::LDAPS_SCHEME && Settings.GetUseTls().GetEnable()) {
160160
result = NKikimrLdap::StartTLS(*ld);
161161
if (!NKikimrLdap::IsSuccess(result)) {
162162
TEvLdapAuthProvider::TError error {
@@ -173,7 +173,7 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
173173
result = NKikimrLdap::Bind(*ld, Settings.GetBindDn(), Settings.GetBindPassword());
174174
if (!NKikimrLdap::IsSuccess(result)) {
175175
TEvLdapAuthProvider::TError error {
176-
.Message = "Could not perform initial LDAP bind for dn " + Settings.GetBindDn() + " on server " + Settings.GetHost() + "\n"
176+
.Message = "Could not perform initial LDAP bind for dn " + Settings.GetBindDn() + " on server " + UrisList + "\n"
177177
+ NKikimrLdap::ErrorToString(result),
178178
.Retryable = NKikimrLdap::IsRetryableError(result)
179179
};
@@ -190,10 +190,8 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
190190
return response;
191191
}
192192

193-
const TString& host = Settings.GetHost();
194-
const ui32 port = Settings.GetPort() != 0 ? Settings.GetPort() : NKikimrLdap::GetPort();
195193
int result = 0;
196-
if (Settings.GetUseTls().GetEnable()) {
194+
if (Settings.GetScheme() == NKikimrLdap::LDAPS_SCHEME || Settings.GetUseTls().GetEnable()) {
197195
const TString& caCertificateFile = Settings.GetUseTls().GetCaCertFile();
198196
result = NKikimrLdap::SetOption(*ld, NKikimrLdap::EOption::TLS_CACERTFILE, caCertificateFile.c_str());
199197
if (!NKikimrLdap::IsSuccess(result)) {
@@ -204,10 +202,12 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
204202
}
205203
}
206204

207-
*ld = NKikimrLdap::Init(host, port);
208-
if (*ld == nullptr) {
205+
const ui32 port = Settings.GetPort() != 0 ? Settings.GetPort() : NKikimrLdap::GetPort(Settings.GetScheme());
206+
UrisList = GetUris(port);
207+
result = NKikimrLdap::Init(ld, Settings.GetScheme(), UrisList, port);
208+
if (!NKikimrLdap::IsSuccess(result)) {
209209
return {{TEvLdapAuthProvider::EStatus::UNAVAILABLE,
210-
{.Message = "Could not initialize LDAP connection for host: " + host + ", port: " + ToString(port) + ". " + NKikimrLdap::LdapError(*ld),
210+
{.Message = "Could not initialize LDAP connection for uris: " + UrisList + ". " + NKikimrLdap::LdapError(*ld),
211211
.Retryable = false}}};
212212
}
213213

@@ -219,7 +219,7 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
219219
.Retryable = NKikimrLdap::IsRetryableError(result)}}};
220220
}
221221

222-
if (Settings.GetUseTls().GetEnable()) {
222+
if (Settings.GetScheme() == NKikimrLdap::LDAPS_SCHEME || Settings.GetUseTls().GetEnable()) {
223223
int requireCert = NKikimrLdap::ConvertRequireCert(Settings.GetUseTls().GetCertRequire());
224224
result = NKikimrLdap::SetOption(*ld, NKikimrLdap::EOption::TLS_REQUIRE_CERT, &requireCert);
225225
if (!NKikimrLdap::IsSuccess(result)) {
@@ -229,21 +229,22 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
229229
.Retryable = NKikimrLdap::IsRetryableError(result)}}};
230230
}
231231
}
232+
232233
return {};
233234
}
234235

235236
TAuthenticateUserResponse AuthenticateUser(const TAuthenticateUserRequest& request) {
236237
char* dn = NKikimrLdap::GetDn(*request.Ld, request.Entry);
237238
if (dn == nullptr) {
238239
return {{TEvLdapAuthProvider::EStatus::UNAUTHORIZED,
239-
{.Message = "Could not get dn for the first entry matching " + FilterCreator.GetFilter(request.Login) + " on server " + Settings.GetHost() + "\n"
240+
{.Message = "Could not get dn for the first entry matching " + FilterCreator.GetFilter(request.Login) + " on server " + UrisList + "\n"
240241
+ NKikimrLdap::LdapError(*request.Ld),
241242
.Retryable = false}}};
242243
}
243244
TEvLdapAuthProvider::TError error;
244245
int result = NKikimrLdap::Bind(*request.Ld, dn, request.Password);
245246
if (!NKikimrLdap::IsSuccess(result)) {
246-
error.Message = "LDAP login failed for user " + TString(dn) + " on server " + Settings.GetHost() + "\n"
247+
error.Message = "LDAP login failed for user " + TString(dn) + " on server " + UrisList + "\n"
247248
+ NKikimrLdap::ErrorToString((result));
248249
error.Retryable = NKikimrLdap::IsRetryableError(result);
249250
}
@@ -265,7 +266,7 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
265266
TSearchUserResponse response;
266267
if (!NKikimrLdap::IsSuccess(result)) {
267268
response.Status = NKikimrLdap::ErrorToStatus(result);
268-
response.Error = {.Message = "Could not search for filter " + searchFilter + " on server " + Settings.GetHost() + "\n"
269+
response.Error = {.Message = "Could not search for filter " + searchFilter + " on server " + UrisList + "\n"
269270
+ NKikimrLdap::ErrorToString(result),
270271
.Retryable = NKikimrLdap::IsRetryableError(result)};
271272
return response;
@@ -274,11 +275,11 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
274275
if (countEntries != 1) {
275276
if (countEntries == 0) {
276277
response.Error = {.Message = "LDAP user " + request.User + " does not exist. "
277-
"LDAP search for filter " + searchFilter + " on server " + Settings.GetHost() + " return no entries",
278+
"LDAP search for filter " + searchFilter + " on server " + UrisList + " return no entries",
278279
.Retryable = false};
279280
} else {
280281
response.Error = {.Message = "LDAP user " + request.User + " is not unique. "
281-
"LDAP search for filter " + searchFilter + " on server " + Settings.GetHost() + " return " + countEntries + " entries",
282+
"LDAP search for filter " + searchFilter + " on server " + UrisList + " return " + countEntries + " entries",
282283
.Retryable = false};
283284
}
284285
response.Status = TEvLdapAuthProvider::EStatus::UNAUTHORIZED;
@@ -290,8 +291,8 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
290291
}
291292

292293
TInitializeLdapConnectionResponse CheckRequiredSettingsParameters() const {
293-
if (Settings.GetHost().empty()) {
294-
return {TEvLdapAuthProvider::EStatus::UNAVAILABLE, {.Message = "Ldap server host is empty", .Retryable = false}};
294+
if (Settings.GetHosts().empty() && Settings.GetHost().empty()) {
295+
return {TEvLdapAuthProvider::EStatus::UNAVAILABLE, {.Message = "List of ldap server hosts is empty", .Retryable = false}};
295296
}
296297
if (Settings.GetBaseDn().empty()) {
297298
return {TEvLdapAuthProvider::EStatus::UNAVAILABLE, {.Message = "Parameter BaseDn is empty", .Retryable = false}};
@@ -305,10 +306,42 @@ class TLdapAuthProvider : public NActors::TActorBootstrapped<TLdapAuthProvider>
305306
return {TEvLdapAuthProvider::EStatus::SUCCESS, {}};
306307
}
307308

309+
TString GetUris(ui32 port) const {
310+
TStringBuilder uris;
311+
if (Settings.HostsSize() > 0) {
312+
for (const auto& host : Settings.GetHosts()) {
313+
uris << CreateUri(host, port) << " ";
314+
}
315+
uris.remove(uris.size() - 1);
316+
} else {
317+
uris << CreateUri(Settings.GetHost(), port);
318+
}
319+
return uris;
320+
}
321+
322+
TString CreateUri(const TString& endpoint, ui32 port) const {
323+
TStringBuilder uri;
324+
uri << Settings.GetScheme() << "://" << endpoint;
325+
if (!HasEndpointPort(endpoint)) {
326+
uri << ':' << port;
327+
}
328+
return uri;
329+
}
330+
331+
static bool HasEndpointPort(const TString& endpoint) {
332+
size_t colonPos = endpoint.rfind(':');
333+
if (colonPos == TString::npos) {
334+
return false;
335+
}
336+
++colonPos;
337+
return (endpoint.size() - colonPos) > 0;
338+
}
339+
308340
private:
309341
const NKikimrProto::TLdapAuthentication Settings;
310342
const TSearchFilterCreator FilterCreator;
311343
char* RequestedAttributes[2];
344+
TString UrisList;
312345
};
313346

314347
IActor* CreateLdapAuthProvider(const NKikimrProto::TLdapAuthentication& settings) {

ydb/core/security/ldap_auth_provider_linux.cpp renamed to ydb/core/security/ldap_auth_provider/ldap_auth_provider_linux.cpp

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include <ydb/library/actors/core/actor_bootstrapped.h>
22
#include <ydb/library/actors/core/log.h>
33
#include <ydb/core/base/ticket_parser.h>
4-
#include "ticket_parser_log.h"
4+
#include <ydb/core/security/ticket_parser_log.h>
55
#include "ldap_auth_provider.h"
66

77
#define LDAP_DEPRECATED 1
@@ -38,6 +38,7 @@ int ConvertOption(const EOption& option) {
3838
}
3939

4040
char* noAttributes[] = {ldapNoAttribute, nullptr};
41+
const TString LDAPS_SCHEME = "ldaps";
4142

4243
int Bind(LDAP* ld, const TString& dn, const TString& password) {
4344
return ldap_simple_bind_s(ld, dn.c_str(), password.c_str());
@@ -47,8 +48,9 @@ int Unbind(LDAP* ld) {
4748
return ldap_unbind(ld);
4849
}
4950

50-
LDAP* Init(const TString& host, ui32 port) {
51-
return ldap_init(host.c_str(), port);
51+
int Init(LDAP** ld, const TString& scheme, const TString& uris, ui32 port) {
52+
Y_UNUSED(scheme, port);
53+
return ldap_initialize(ld, uris.c_str());
5254
}
5355

5456
int Search(LDAP* ld,
@@ -109,7 +111,10 @@ std::vector<TString> GetAllValuesOfAttribute(LDAP* ld, LDAPMessage* entry, char*
109111
return response;
110112
}
111113

112-
ui32 GetPort() {
114+
ui32 GetPort(const TString& scheme) {
115+
if (scheme == LDAPS_SCHEME) {
116+
return LDAPS_PORT;
117+
}
113118
return LDAP_PORT;
114119
}
115120

0 commit comments

Comments
 (0)