Skip to content

Commit 2274f9e

Browse files
impersonate
1 parent 34dcd14 commit 2274f9e

15 files changed

+332
-108
lines changed

ydb/mvp/oidc_proxy/mvp.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ void TMVP::TryGetOidcOptionsFromConfig(const YAML::Node& config) {
233233
OpenIdConnectSettings.AuthUrlPath = oidc["auth_url_path"].as<std::string>(OpenIdConnectSettings.DEFAULT_AUTH_URL_PATH);
234234
OpenIdConnectSettings.TokenUrlPath = oidc["token_url_path"].as<std::string>(OpenIdConnectSettings.DEFAULT_TOKEN_URL_PATH);
235235
OpenIdConnectSettings.ExchangeUrlPath = oidc["exchange_url_path"].as<std::string>(OpenIdConnectSettings.DEFAULT_EXCHANGE_URL_PATH);
236+
OpenIdConnectSettings.ImpersonateUrlPath = oidc["impersonate_url_path"].as<std::string>(OpenIdConnectSettings.DEFAULT_IMPERSONATE_URL_PATH);
236237
Cout << "Started processing allowed_proxy_hosts..." << Endl;
237238
for (const std::string& host : oidc["allowed_proxy_hosts"].as<std::vector<std::string>>()) {
238239
Cout << host << " added to allowed_proxy_hosts" << Endl;

ydb/mvp/oidc_proxy/oidc_client.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "oidc_client.h"
22
#include "oidc_protected_page_handler.h"
33
#include "oidc_session_create_handler.h"
4+
#include "oidc_impersonate_start_page_nebius.h"
5+
#include "oidc_impersonate_stop_page_nebius.h"
46

57
namespace NMVP {
68
namespace NOIDC {
@@ -14,17 +16,19 @@ void InitOIDC(NActors::TActorSystem& actorSystem,
1416
)
1517
);
1618

17-
actorSystem.Send(httpProxyId, new NHttp::TEvHttpProxy::TEvRegisterHandler(
18-
"/impersonate/start",
19-
actorSystem.Register(new THandlerImpersonateStart(httpProxyId, settings))
20-
)
21-
);
19+
if (settings.AccessServiceType == NMvp::nebius_v1) {
20+
actorSystem.Send(httpProxyId, new NHttp::TEvHttpProxy::TEvRegisterHandler(
21+
"/impersonate/start",
22+
actorSystem.Register(new TImpersonateStartPageHandler(httpProxyId, settings))
23+
)
24+
);
2225

23-
actorSystem.Send(httpProxyId, new NHttp::TEvHttpProxy::TEvRegisterHandler(
24-
"/impersonate/stop",
25-
actorSystem.Register(new THandlerImpersonateStop(httpProxyId, settings))
26-
)
27-
);
26+
actorSystem.Send(httpProxyId, new NHttp::TEvHttpProxy::TEvRegisterHandler(
27+
"/impersonate/stop",
28+
actorSystem.Register(new TImpersonateStopPageHandler(httpProxyId, settings))
29+
)
30+
);
31+
}
2832

2933
actorSystem.Send(httpProxyId, new NHttp::TEvHttpProxy::TEvRegisterHandler(
3034
"/",

ydb/mvp/oidc_proxy/oidc_impersonate_start_page_nebius.cpp

Lines changed: 70 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,75 @@
11
#include <library/cpp/json/json_reader.h>
22
#include <library/cpp/string_utils/base64/base64.h>
33
#include <ydb/library/actors/http/http.h>
4+
#include <ydb/library/security/util.h>
45
#include <ydb/mvp/core/mvp_log.h>
6+
#include <ydb/mvp/core/mvp_tokens.h>
57
#include "openid_connect.h"
68
#include "oidc_session_create.h"
79
#include "oidc_settings.h"
10+
#include "oidc_impersonate_start_page_nebius.h"
811

912
namespace NMVP {
1013
namespace NOIDC {
1114

1215
THandlerImpersonateStart::THandlerImpersonateStart(const NActors::TActorId& sender,
13-
const NHttp::THttpIncomingRequestPtr& request,
14-
const NActors::TActorId& httpProxyId,
15-
const TOpenIdConnectSettings& settings)
16+
const NHttp::THttpIncomingRequestPtr& request,
17+
const NActors::TActorId& httpProxyId,
18+
const TOpenIdConnectSettings& settings)
1619
: Sender(sender)
1720
, Request(request)
1821
, HttpProxyId(httpProxyId)
1922
, Settings(settings)
2023
{}
2124

25+
TString THandlerImpersonateStart::DecodeToken(const TStringBuf& cookie, const NActors::TActorContext& ctx) {
26+
TString token;
27+
try {
28+
Base64StrictDecode(cookie, token);
29+
} catch (std::exception& e) {
30+
LOG_DEBUG_S(ctx, EService::MVP, "Base64Decode " << cookie << " cookie: " << e.what());
31+
token.clear();
32+
}
33+
return token;
34+
}
35+
2236
void THandlerImpersonateStart::Bootstrap(const NActors::TActorContext& ctx) {
37+
LOG_DEBUG_S(ctx, EService::MVP, "Start impersonation process");
2338
NHttp::TUrlParameters urlParameters(Request->URL);
24-
TString serviceAccountId = urlParameters["service_accound_id"];
39+
TString serviceAccountId = urlParameters["service_account_id"];
2540

2641
NHttp::THeaders headers(Request->Headers);
27-
LOG_DEBUG_S(ctx, EService::MVP, "Start impersonation process");
2842
NHttp::TCookies cookies(headers.Get("Cookie"));
29-
TString sessionToken = DecodeToken(cookies, CreateNameSessionCookie(Settings.ClientId));
3043

31-
if (sessionToken && serviceAccountId) {
32-
RequestImpersonatedToken(sessionToken, serviceAccountId, ctx);
33-
} else {
44+
TString sessionCookieName = CreateNameSessionCookie(Settings.ClientId);
45+
TStringBuf sessionCookieValue = cookies.Get(sessionCookieName);
46+
if (!sessionCookieValue.Empty()) {
47+
LOG_DEBUG_S(ctx, EService::MVP, "Using session cookie (" << sessionCookieName << ": " << NKikimr::MaskTicket(sessionCookieValue) << ")");
48+
}
49+
50+
TString sessionToken = DecodeToken(sessionCookieValue, ctx);
51+
52+
TString jsonError;
53+
if (sessionToken.empty()) {
54+
jsonError = "Wrong impersonate parameter: session cookie not found";
55+
} else if (serviceAccountId.empty()) {
56+
jsonError = "Wrong impersonate parameter: account_id not found";
57+
}
58+
59+
if (jsonError) {
3460
NHttp::THeadersBuilder responseHeaders;
3561
responseHeaders.Set("Content-Type", "text/plain");
36-
httpResponse = Request->CreateResponse("400", "Bad Request", responseHeaders, event->Get()->Error);
62+
NHttp::THttpOutgoingResponsePtr httpResponse = Request->CreateResponse("400", "Bad Request", responseHeaders, jsonError);
63+
ctx.Send(Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(httpResponse));
64+
Die(ctx);
65+
} else {
66+
RequestImpersonatedToken(sessionToken, serviceAccountId, ctx);
3767
}
3868
}
3969

40-
void THandlerImpersonateStart::RequestImpersonatedToken(const TString sessionToken, const TString serviceAccountId, const NActors::TActorContext& ctx) {
70+
void THandlerImpersonateStart::RequestImpersonatedToken(const TString& sessionToken, const TString& serviceAccountId, const NActors::TActorContext& ctx) {
4171
LOG_DEBUG_S(ctx, EService::MVP, "Request impersonated token");
42-
NHttp::THttpOutgoingRequestPtr httpRequest = NHttp::THttpOutgoingRequest::CreateRequestPost(Settings.GetExchangeEndpointURL());
72+
NHttp::THttpOutgoingRequestPtr httpRequest = NHttp::THttpOutgoingRequest::CreateRequestPost(Settings.GetImpersonateEndpointURL());
4373
httpRequest->Set<&NHttp::THttpRequest::ContentType>("application/x-www-form-urlencoded");
4474

4575
TMvpTokenator* tokenator = MVPAppData()->Tokenator;
@@ -48,16 +78,27 @@ void THandlerImpersonateStart::RequestImpersonatedToken(const TString sessionTok
4878
token = tokenator->GetToken(Settings.SessionServiceTokenName);
4979
}
5080
httpRequest->Set("Authorization", token); // Bearer included
81+
5182
TStringBuilder body;
52-
body << "grant_type=urn:ietf:params:oauth:grant-type:token-exchange"
53-
<< "&requested_token_type=urn:ietf:params:oauth:token-type:access_token"
54-
<< "&subject_token_type=urn:ietf:params:oauth:token-type:session_token"
55-
<< "&subject_token=" << sessionToken;
83+
body << "session=" << sessionToken
84+
<< "&service_account_id=" << serviceAccountId;
5685
httpRequest->Set<&NHttp::THttpRequest::Body>(body);
5786

5887
ctx.Send(HttpProxyId, new NHttp::TEvHttpProxy::TEvHttpOutgoingRequest(httpRequest));
88+
Become(&THandlerImpersonateStart::StateWork);
89+
}
90+
91+
void THandlerImpersonateStart::ProcessImpersonatedToken(const TString& impersonatedToken, const NActors::TActorContext& ctx) {
92+
TString impersonatedCookieName = CreateNameImpersonatedCookie(Settings.ClientId);
93+
TString impersonatedCookieValue = Base64Encode(impersonatedToken);
94+
LOG_DEBUG_S(ctx, EService::MVP, "Set impersonated cookie: (" << impersonatedCookieName << ": " << NKikimr::MaskTicket(impersonatedCookieValue) << ")");
5995

60-
Become(&THandlerSessionServiceCheckNebius::StateExchange);
96+
NHttp::THeadersBuilder responseHeaders;
97+
responseHeaders.Set("Set-Cookie", CreateSecureCookie(impersonatedCookieName, impersonatedCookieValue));
98+
NHttp::THttpOutgoingResponsePtr httpResponse;
99+
httpResponse = Request->CreateResponse("200", "OK", responseHeaders);
100+
ctx.Send(Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(httpResponse));
101+
Die(ctx);
61102
}
62103

63104
void THandlerImpersonateStart::Handle(NHttp::TEvHttpProxy::TEvHttpIncomingResponse::TPtr event, const NActors::TActorContext& ctx) {
@@ -70,13 +111,13 @@ void THandlerImpersonateStart::Handle(NHttp::TEvHttpProxy::TEvHttpIncomingRespon
70111
NJson::TJsonValue jsonValue;
71112
NJson::TJsonReaderConfig jsonConfig;
72113
if (NJson::ReadJsonTree(response->Body, &jsonConfig, &jsonValue)) {
73-
const NJson::TJsonValue* jsonAccessToken;
74-
if (jsonValue.GetValuePointer("access_token", &jsonAccessToken)) {
75-
TString sessionToken = jsonAccessToken->GetStringRobust();
76-
ProcessSessionToken(sessionToken, ctx);
114+
const NJson::TJsonValue* jsonImpersonatedToken;
115+
if (jsonValue.GetValuePointer("impersonation", &jsonImpersonatedToken)) {
116+
TString impersonatedToken = jsonImpersonatedToken->GetStringRobust();
117+
ProcessImpersonatedToken(impersonatedToken, ctx);
77118
return;
78119
} else {
79-
jsonError = "Wrong OIDC provider response: access_token not found";
120+
jsonError = "Wrong OIDC provider response: impersonated token not found";
80121
}
81122
} else {
82123
jsonError = "Wrong OIDC response";
@@ -98,51 +139,14 @@ void THandlerImpersonateStart::Handle(NHttp::TEvHttpProxy::TEvHttpIncomingRespon
98139
Die(ctx);
99140
}
100141

101-
TString THandlerImpersonateStart::ChangeSameSiteFieldInSessionCookie(const TString& cookie) {
102-
const static TStringBuf SameSiteParameter {"SameSite=Lax"};
103-
size_t n = cookie.find(SameSiteParameter);
104-
if (n == TString::npos) {
105-
return cookie;
106-
}
107-
TStringBuilder cookieBuilder;
108-
cookieBuilder << cookie.substr(0, n);
109-
cookieBuilder << "SameSite=None";
110-
cookieBuilder << cookie.substr(n + SameSiteParameter.size());
111-
return cookieBuilder;
112-
}
113-
114-
void THandlerImpersonateStart::RetryRequestToProtectedResourceAndDie(const NActors::TActorContext& ctx) {
115-
NHttp::THeadersBuilder responseHeaders;
116-
RetryRequestToProtectedResourceAndDie(&responseHeaders, ctx);
117-
}
118-
119-
void THandlerImpersonateStart::RetryRequestToProtectedResourceAndDie(NHttp::THeadersBuilder* responseHeaders, const NActors::TActorContext& ctx) {
120-
SetCORS(Request, responseHeaders);
121-
responseHeaders->Set("Location", Context.GetRequestedAddress());
122-
ctx.Send(Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(Request->CreateResponse("302", "Found", *responseHeaders)));
123-
Die(ctx);
124-
}
142+
TImpersonateStartPageHandler::TImpersonateStartPageHandler(const NActors::TActorId& httpProxyId, const TOpenIdConnectSettings& settings)
143+
: TBase(&TImpersonateStartPageHandler::StateWork)
144+
, HttpProxyId(httpProxyId)
145+
, Settings(settings)
146+
{}
125147

126-
void THandlerImpersonateStart::SendUnknownErrorResponseAndDie(const NActors::TActorContext& ctx) {
127-
NHttp::THeadersBuilder responseHeaders;
128-
responseHeaders.Set("Content-Type", "text/html");
129-
SetCORS(Request, &responseHeaders);
130-
const static TStringBuf BAD_REQUEST_HTML_PAGE = "<html>"
131-
"<head>"
132-
"<title>"
133-
"400 Bad Request"
134-
"</title>"
135-
"</head>"
136-
"<body bgcolor=\"white\">"
137-
"<center>"
138-
"<h1>"
139-
"Unknown error has occurred. Please open the page again"
140-
"</h1>"
141-
"</center>"
142-
"</body>"
143-
"</html>";
144-
ctx.Send(Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(Request->CreateResponse("400", "Bad Request", responseHeaders, BAD_REQUEST_HTML_PAGE)));
145-
Die(ctx);
148+
void TImpersonateStartPageHandler::Handle(NHttp::TEvHttpProxy::TEvHttpIncomingRequest::TPtr event, const NActors::TActorContext& ctx) {
149+
ctx.Register(new THandlerImpersonateStart(event->Sender, event->Get()->Request, HttpProxyId, Settings));
146150
}
147151

148152
} // NOIDC

ydb/mvp/oidc_proxy/oidc_impersonate_start_page_nebius.h

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,39 @@ class THandlerImpersonateStart : public NActors::TActorBootstrapped<THandlerImpe
2424
TContext Context;
2525

2626
public:
27+
TString DecodeToken(const TStringBuf& cookie, const NActors::TActorContext& ctx);
2728
THandlerImpersonateStart(const NActors::TActorId& sender,
28-
const NHttp::THttpIncomingRequestPtr& request,
29-
const NActors::TActorId& httpProxyId,
30-
const TOpenIdConnectSettings& settings);
31-
32-
virtual void RequestSessionToken(const TString&, const NActors::TActorContext&) = 0;
33-
virtual void ProcessSessionToken(const TString& accessToken, const NActors::TActorContext&) = 0;
29+
const NHttp::THttpIncomingRequestPtr& request,
30+
const NActors::TActorId& httpProxyId,
31+
const TOpenIdConnectSettings& settings);
32+
void RequestImpersonatedToken(const TString&, const TString&, const NActors::TActorContext&);
33+
void ProcessImpersonatedToken(const TString& impersonatedToken, const NActors::TActorContext& ctx);
3434

3535
void Bootstrap(const NActors::TActorContext& ctx);
3636
void Handle(NHttp::TEvHttpProxy::TEvHttpIncomingResponse::TPtr event, const NActors::TActorContext& ctx);
3737

38-
protected:
39-
TString ChangeSameSiteFieldInSessionCookie(const TString& cookie);
40-
void RetryRequestToProtectedResourceAndDie(const NActors::TActorContext& ctx);
41-
void RetryRequestToProtectedResourceAndDie(NHttp::THeadersBuilder* responseHeaders, const NActors::TActorContext& ctx);
38+
STFUNC(StateWork) {
39+
switch (ev->GetTypeRewrite()) {
40+
HFunc(NHttp::TEvHttpProxy::TEvHttpIncomingResponse, Handle);
41+
}
42+
}
43+
};
4244

43-
private:
44-
void SendUnknownErrorResponseAndDie(const NActors::TActorContext& ctx);
45+
class TImpersonateStartPageHandler : public NActors::TActor<TImpersonateStartPageHandler> {
46+
using TBase = NActors::TActor<TImpersonateStartPageHandler>;
47+
48+
const NActors::TActorId HttpProxyId;
49+
const TOpenIdConnectSettings Settings;
50+
51+
public:
52+
TImpersonateStartPageHandler(const NActors::TActorId& httpProxyId, const TOpenIdConnectSettings& settings);
53+
void Handle(NHttp::TEvHttpProxy::TEvHttpIncomingRequest::TPtr event, const NActors::TActorContext& ctx);
54+
55+
STFUNC(StateWork) {
56+
switch (ev->GetTypeRewrite()) {
57+
HFunc(NHttp::TEvHttpProxy::TEvHttpIncomingRequest, Handle);
58+
}
59+
}
4560
};
4661

4762
} // NOIDC

ydb/mvp/oidc_proxy/oidc_impersonate_stop_page_nebius.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,44 @@
55
#include "openid_connect.h"
66
#include "oidc_session_create.h"
77
#include "oidc_settings.h"
8+
#include "oidc_impersonate_stop_page_nebius.h"
89

910
namespace NMVP {
1011
namespace NOIDC {
1112

12-
THandlerImpersonateStop::THandlerSessionCreate(const NActors::TActorId& sender,
13-
const NHttp::THttpIncomingRequestPtr& request,
14-
const NActors::TActorId& httpProxyId,
15-
const TOpenIdConnectSettings& settings)
13+
THandlerImpersonateStop::THandlerImpersonateStop(const NActors::TActorId& sender,
14+
const NHttp::THttpIncomingRequestPtr& request,
15+
const NActors::TActorId& httpProxyId,
16+
const TOpenIdConnectSettings& settings)
1617
: Sender(sender)
1718
, Request(request)
1819
, HttpProxyId(httpProxyId)
1920
, Settings(settings)
2021
{}
2122

2223
void THandlerImpersonateStop::Bootstrap(const NActors::TActorContext& ctx) {
23-
NHttp::THeadersBuilder responseHeaders;responseHeaders
24+
TString impersonatedCookieName = CreateNameImpersonatedCookie(Settings.ClientId);
25+
LOG_DEBUG_S(ctx, EService::MVP, "Clear impersonated cookie: (" << impersonatedCookieName << ")");
26+
27+
NHttp::THeadersBuilder responseHeaders;
2428
SetCORS(Request, &responseHeaders);
25-
responseHeaders.Set("Set-Cookie", CreateSecureCookie(Settings.ClientId, sessionToken));
29+
responseHeaders.Set("Set-Cookie", ClearSecureCookie(impersonatedCookieName));
2630

2731
NHttp::THttpOutgoingResponsePtr httpResponse;
2832
httpResponse = Request->CreateResponse("200", "OK", responseHeaders);
2933
ctx.Send(Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(httpResponse));
3034
Die(ctx);
3135
}
3236

37+
TImpersonateStopPageHandler::TImpersonateStopPageHandler(const NActors::TActorId& httpProxyId, const TOpenIdConnectSettings& settings)
38+
: TBase(&TImpersonateStopPageHandler::StateWork)
39+
, HttpProxyId(httpProxyId)
40+
, Settings(settings)
41+
{}
42+
43+
void TImpersonateStopPageHandler::Handle(NHttp::TEvHttpProxy::TEvHttpIncomingRequest::TPtr event, const NActors::TActorContext& ctx) {
44+
ctx.Register(new THandlerImpersonateStop(event->Sender, event->Get()->Request, HttpProxyId, Settings));
45+
}
46+
3347
} // NOIDC
3448
} // NMVP

ydb/mvp/oidc_proxy/oidc_impersonate_stop_page_nebius.h

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,29 @@ class THandlerImpersonateStop : public NActors::TActorBootstrapped<THandlerImper
2525

2626
public:
2727
THandlerImpersonateStop(const NActors::TActorId& sender,
28-
const NHttp::THttpIncomingRequestPtr& request,
29-
const NActors::TActorId& httpProxyId,
30-
const TOpenIdConnectSettings& settings);
28+
const NHttp::THttpIncomingRequestPtr& request,
29+
const NActors::TActorId& httpProxyId,
30+
const TOpenIdConnectSettings& settings);
3131

3232
void Bootstrap(const NActors::TActorContext& ctx);
3333
};
3434

35+
class TImpersonateStopPageHandler : public NActors::TActor<TImpersonateStopPageHandler> {
36+
using TBase = NActors::TActor<TImpersonateStopPageHandler>;
37+
38+
const NActors::TActorId HttpProxyId;
39+
const TOpenIdConnectSettings Settings;
40+
41+
public:
42+
TImpersonateStopPageHandler(const NActors::TActorId& httpProxyId, const TOpenIdConnectSettings& settings);
43+
void Handle(NHttp::TEvHttpProxy::TEvHttpIncomingRequest::TPtr event, const NActors::TActorContext& ctx);
44+
45+
STFUNC(StateWork) {
46+
switch (ev->GetTypeRewrite()) {
47+
HFunc(NHttp::TEvHttpProxy::TEvHttpIncomingRequest, Handle);
48+
}
49+
}
50+
};
51+
3552
} // NOIDC
3653
} // NMVP

0 commit comments

Comments
 (0)