Skip to content

Commit

Permalink
Merge 5d15b43 into 31dedaa
Browse files Browse the repository at this point in the history
  • Loading branch information
StekPerepolnen authored Nov 27, 2024
2 parents 31dedaa + 5d15b43 commit d22f709
Show file tree
Hide file tree
Showing 32 changed files with 922 additions and 296 deletions.
6 changes: 2 additions & 4 deletions ydb/mvp/oidc_proxy/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
#include "oidc_settings.h"
#include "context.h"

namespace NMVP {
namespace NOIDC {
namespace NMVP::NOIDC {

TContext::TContext(const TInitializer& initializer)
: State(initializer.State)
Expand Down Expand Up @@ -94,5 +93,4 @@ TStringBuf TContext::GetRequestedUrl(const NHttp::THttpIncomingRequestPtr& reque
return requestedUrl;
}

} // NOIDC
} // NMVP
} // NMVP::NOIDC
6 changes: 2 additions & 4 deletions ydb/mvp/oidc_proxy/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ using THttpIncomingRequestPtr = TIntrusivePtr<THttpIncomingRequest>;

}

namespace NMVP {
namespace NOIDC {
namespace NMVP::NOIDC {

class TContext {
public:
Expand Down Expand Up @@ -45,5 +44,4 @@ class TContext {
TString GenerateCookie(const TString& key) const;
};

} // NOIDC
} // NMVP
} // NMVP::NOIDC
7 changes: 3 additions & 4 deletions ydb/mvp/oidc_proxy/mvp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@

NActors::IActor* CreateMemProfiler();

namespace NMVP {
namespace NOIDC {
namespace NMVP::NOIDC {

namespace {

Expand Down Expand Up @@ -233,6 +232,7 @@ void TMVP::TryGetOidcOptionsFromConfig(const YAML::Node& config) {
OpenIdConnectSettings.AuthUrlPath = oidc["auth_url_path"].as<std::string>(OpenIdConnectSettings.DEFAULT_AUTH_URL_PATH);
OpenIdConnectSettings.TokenUrlPath = oidc["token_url_path"].as<std::string>(OpenIdConnectSettings.DEFAULT_TOKEN_URL_PATH);
OpenIdConnectSettings.ExchangeUrlPath = oidc["exchange_url_path"].as<std::string>(OpenIdConnectSettings.DEFAULT_EXCHANGE_URL_PATH);
OpenIdConnectSettings.ImpersonateUrlPath = oidc["impersonate_url_path"].as<std::string>(OpenIdConnectSettings.DEFAULT_IMPERSONATE_URL_PATH);
Cout << "Started processing allowed_proxy_hosts..." << Endl;
for (const std::string& host : oidc["allowed_proxy_hosts"].as<std::vector<std::string>>()) {
Cout << host << " added to allowed_proxy_hosts" << Endl;
Expand Down Expand Up @@ -417,5 +417,4 @@ THolder<NActors::TActorSystemSetup> TMVP::BuildActorSystemSetup(int argc, char**

TAtomic TMVP::Quit = false;

} // NOIDC
} // NMVP
} // NMVP::NOIDC
6 changes: 2 additions & 4 deletions ydb/mvp/oidc_proxy/mvp.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
#include <contrib/libs/yaml-cpp/include/yaml-cpp/yaml.h>
#include "oidc_settings.h"

namespace NMVP {
namespace NOIDC {
namespace NMVP::NOIDC {

const TString& GetEServiceName(NActors::NLog::EComponent component);

Expand Down Expand Up @@ -72,5 +71,4 @@ class TMVP {
int Shutdown();
};

} // namespace NOIDC
} // namespace NMVP
} // NMVP::NOIDC
22 changes: 18 additions & 4 deletions ydb/mvp/oidc_proxy/oidc_client.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#include "oidc_client.h"
#include "oidc_protected_page_handler.h"
#include "oidc_session_create_handler.h"
#include "oidc_impersonate_start_page_nebius.h"
#include "oidc_impersonate_stop_page_nebius.h"

namespace NMVP {
namespace NOIDC {
namespace NMVP::NOIDC {

void InitOIDC(NActors::TActorSystem& actorSystem,
const NActors::TActorId& httpProxyId,
Expand All @@ -14,12 +15,25 @@ void InitOIDC(NActors::TActorSystem& actorSystem,
)
);

if (settings.AccessServiceType == NMvp::nebius_v1) {
actorSystem.Send(httpProxyId, new NHttp::TEvHttpProxy::TEvRegisterHandler(
"/impersonate/start",
actorSystem.Register(new TImpersonateStartPageHandler(httpProxyId, settings))
)
);

actorSystem.Send(httpProxyId, new NHttp::TEvHttpProxy::TEvRegisterHandler(
"/impersonate/stop",
actorSystem.Register(new TImpersonateStopPageHandler(httpProxyId, settings))
)
);
}

actorSystem.Send(httpProxyId, new NHttp::TEvHttpProxy::TEvRegisterHandler(
"/",
actorSystem.Register(new TProtectedPageHandler(httpProxyId, settings))
)
);
}

} // NOIDC
} // NMVP
} // NMVP::NOIDC
6 changes: 2 additions & 4 deletions ydb/mvp/oidc_proxy/oidc_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ class TActorSystem;
struct TActorId;

} // NActors
namespace NMVP {
namespace NOIDC {
namespace NMVP::NOIDC {

struct TOpenIdConnectSettings;

void InitOIDC(NActors::TActorSystem& actorSystem, const NActors::TActorId& httpProxyId, const TOpenIdConnectSettings& settings);

} // NOIDC
} // NMVP
} // NMVP::NOIDC
151 changes: 151 additions & 0 deletions ydb/mvp/oidc_proxy/oidc_impersonate_start_page_nebius.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
#include <library/cpp/string_utils/base64/base64.h>
#include <library/cpp/string_utils/quote/quote.h>
#include <ydb/library/actors/http/http.h>
#include <ydb/library/security/util.h>
#include <ydb/mvp/core/mvp_log.h>
#include <ydb/mvp/core/mvp_tokens.h>
#include "openid_connect.h"
#include "oidc_session_create.h"
#include "oidc_impersonate_start_page_nebius.h"

namespace NMVP::NOIDC {

THandlerImpersonateStart::THandlerImpersonateStart(const NActors::TActorId& sender,
const NHttp::THttpIncomingRequestPtr& request,
const NActors::TActorId& httpProxyId,
const TOpenIdConnectSettings& settings)
: Sender(sender)
, Request(request)
, HttpProxyId(httpProxyId)
, Settings(settings)
{}

void THandlerImpersonateStart::Bootstrap(const NActors::TActorContext& ctx) {
BLOG_D("Start impersonation process");

NHttp::TUrlParameters urlParameters(Request->URL);
TString serviceAccountId = urlParameters["service_account_id"];

NHttp::THeaders headers(Request->Headers);
NHttp::TCookies cookies(headers.Get("Cookie"));

TString sessionCookieName = CreateNameSessionCookie(Settings.ClientId);
TStringBuf sessionCookieValue = cookies.Get(sessionCookieName);
if (!sessionCookieValue.Empty()) {
BLOG_D("Using session cookie (" << sessionCookieName << ": " << NKikimr::MaskTicket(sessionCookieValue) << ")");
}
TString sessionToken = DecodeToken(sessionCookieValue);
TStringBuf impersonatedCookieValue = GetCookie(cookies, CreateNameImpersonatedCookie(Settings.ClientId));

if (sessionToken.empty()) {
return ReplyBadRequestAndPassAway("Wrong impersonate parameter: session cookie not found");
}
if (!impersonatedCookieValue.empty()) {
return ReplyBadRequestAndPassAway("Wrong impersonate parameter: impersonated cookie already exists");
}
if (serviceAccountId.empty()) {
return ReplyBadRequestAndPassAway("Wrong impersonate parameter: service_account_id not found");
}

RequestImpersonatedToken(sessionToken, serviceAccountId, ctx);
}

void THandlerImpersonateStart::RequestImpersonatedToken(TString& sessionToken, TString& serviceAccountId, const NActors::TActorContext& ctx) {
BLOG_D("Request impersonated token");
NHttp::THttpOutgoingRequestPtr httpRequest = NHttp::THttpOutgoingRequest::CreateRequestPost(Settings.GetImpersonateEndpointURL());
httpRequest->Set<&NHttp::THttpRequest::ContentType>("application/x-www-form-urlencoded");

TMvpTokenator* tokenator = MVPAppData()->Tokenator;
TString token = "";
if (tokenator) {
token = tokenator->GetToken(Settings.SessionServiceTokenName);
}
httpRequest->Set("Authorization", token); // Bearer included

TCgiParameters params;
params.InsertEscaped("session", sessionToken);
params.InsertEscaped("service_account_id", serviceAccountId);
httpRequest->Set<&NHttp::THttpRequest::Body>(params());

ctx.Send(HttpProxyId, new NHttp::TEvHttpProxy::TEvHttpOutgoingRequest(httpRequest));
Become(&THandlerImpersonateStart::StateWork);
}

void THandlerImpersonateStart::ProcessImpersonatedToken(const TString& impersonatedToken) {
TString impersonatedCookieName = CreateNameImpersonatedCookie(Settings.ClientId);
TString impersonatedCookieValue = Base64Encode(impersonatedToken);
BLOG_D("Set impersonated cookie: (" << impersonatedCookieName << ": " << NKikimr::MaskTicket(impersonatedCookieValue) << ")");

NHttp::THeadersBuilder responseHeaders;
responseHeaders.Set("Set-Cookie", CreateSecureCookie(impersonatedCookieName, impersonatedCookieValue));
SetCORS(Request, &responseHeaders);
NHttp::THttpOutgoingResponsePtr httpResponse = Request->CreateResponse("200", "OK", responseHeaders);
ReplyAndPassAway(std::move(httpResponse));
}

void THandlerImpersonateStart::Handle(NHttp::TEvHttpProxy::TEvHttpIncomingResponse::TPtr event) {
NHttp::THttpOutgoingResponsePtr httpResponse;
if (event->Get()->Error.empty() && event->Get()->Response) {
NHttp::THttpIncomingResponsePtr response = event->Get()->Response;
BLOG_D("Incoming response from authorization server: " << response->Status);
if (response->Status == "200") {
TStringBuf errorMessage;
NJson::TJsonValue jsonValue;
NJson::TJsonReaderConfig jsonConfig;
if (NJson::ReadJsonTree(response->Body, &jsonConfig, &jsonValue)) {
const NJson::TJsonValue* jsonImpersonatedToken;
if (jsonValue.GetValuePointer("impersonation", &jsonImpersonatedToken)) {
TString impersonatedToken = jsonImpersonatedToken->GetStringRobust();
ProcessImpersonatedToken(impersonatedToken);
return;
} else {
errorMessage = "Wrong OIDC provider response: impersonated token not found";
}
} else {
errorMessage = "Wrong OIDC response";
}
NHttp::THeadersBuilder responseHeaders;
responseHeaders.Set("Content-Type", "text/plain");
SetCORS(Request, &responseHeaders);
return ReplyAndPassAway(Request->CreateResponse("400", "Bad Request", responseHeaders, errorMessage));
} else {
NHttp::THeadersBuilder responseHeaders;
NHttp::THeaders headers(response->Headers);
if (headers.Has("Content-Type")) {
responseHeaders.Set("Content-Type", headers.Get("Content-Type"));
}
SetCORS(Request, &responseHeaders);
return ReplyAndPassAway(Request->CreateResponse(response->Status, response->Message, responseHeaders, response->Body));
}
} else {
NHttp::THeadersBuilder responseHeaders;
responseHeaders.Set("Content-Type", "text/plain");
SetCORS(Request, &responseHeaders);
return ReplyAndPassAway(Request->CreateResponse("400", "Bad Request", responseHeaders, event->Get()->Error));
}
}

void THandlerImpersonateStart::ReplyAndPassAway(NHttp::THttpOutgoingResponsePtr httpResponse) {
Send(Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(std::move(httpResponse)));
PassAway();
}

void THandlerImpersonateStart::ReplyBadRequestAndPassAway(const TString& errorMessage) {
NHttp::THeadersBuilder responseHeaders;
responseHeaders.Set("Content-Type", "text/plain");
SetCORS(Request, &responseHeaders);
NHttp::THttpOutgoingResponsePtr httpResponse = Request->CreateResponse("400", "Bad Request", responseHeaders, errorMessage);
ReplyAndPassAway(std::move(httpResponse));
}

TImpersonateStartPageHandler::TImpersonateStartPageHandler(const NActors::TActorId& httpProxyId, const TOpenIdConnectSettings& settings)
: TBase(&TImpersonateStartPageHandler::StateWork)
, HttpProxyId(httpProxyId)
, Settings(settings)
{}

void TImpersonateStartPageHandler::Handle(NHttp::TEvHttpProxy::TEvHttpIncomingRequest::TPtr event, const NActors::TActorContext& ctx) {
ctx.Register(new THandlerImpersonateStart(event->Sender, event->Get()->Request, HttpProxyId, Settings));
}

} // NMVP::NOIDC
56 changes: 56 additions & 0 deletions ydb/mvp/oidc_proxy/oidc_impersonate_start_page_nebius.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#pragma once

#include "oidc_settings.h"
#include "context.h"
#include <ydb/library/actors/core/events.h>

namespace NMVP::NOIDC {

class THandlerImpersonateStart : public NActors::TActorBootstrapped<THandlerImpersonateStart> {
private:
using TBase = NActors::TActorBootstrapped<THandlerImpersonateStart>;

protected:
const NActors::TActorId Sender;
const NHttp::THttpIncomingRequestPtr Request;
const NActors::TActorId HttpProxyId;
const TOpenIdConnectSettings Settings;

public:
THandlerImpersonateStart(const NActors::TActorId& sender,
const NHttp::THttpIncomingRequestPtr& request,
const NActors::TActorId& httpProxyId,
const TOpenIdConnectSettings& settings);
void Bootstrap(const NActors::TActorContext& ctx);
void RequestImpersonatedToken(TString&, TString&, const NActors::TActorContext&);
void ProcessImpersonatedToken(const TString& impersonatedToken);
void Handle(NHttp::TEvHttpProxy::TEvHttpIncomingResponse::TPtr event);
void ReplyAndPassAway(NHttp::THttpOutgoingResponsePtr httpResponse);
void ReplyBadRequestAndPassAway(const TString& errorMessage);

STFUNC(StateWork) {
switch (ev->GetTypeRewrite()) {
hFunc(NHttp::TEvHttpProxy::TEvHttpIncomingResponse, Handle);
}
}
};

class TImpersonateStartPageHandler : public NActors::TActor<TImpersonateStartPageHandler> {
using TBase = NActors::TActor<TImpersonateStartPageHandler>;

const NActors::TActorId HttpProxyId;
const TOpenIdConnectSettings Settings;

public:
TImpersonateStartPageHandler(const NActors::TActorId& httpProxyId, const TOpenIdConnectSettings& settings);
void Handle(NHttp::TEvHttpProxy::TEvHttpIncomingRequest::TPtr event, const NActors::TActorContext& ctx);

STFUNC(StateWork) {
switch (ev->GetTypeRewrite()) {
HFunc(NHttp::TEvHttpProxy::TEvHttpIncomingRequest, Handle);
cFunc(NActors::TEvents::TEvPoisonPill::EventType, PassAway);
}
}
};

} // NMVP::NOIDC
45 changes: 45 additions & 0 deletions ydb/mvp/oidc_proxy/oidc_impersonate_stop_page_nebius.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include "openid_connect.h"
#include "oidc_session_create.h"
#include "oidc_impersonate_stop_page_nebius.h"

namespace NMVP::NOIDC {

THandlerImpersonateStop::THandlerImpersonateStop(const NActors::TActorId& sender,
const NHttp::THttpIncomingRequestPtr& request,
const NActors::TActorId& httpProxyId,
const TOpenIdConnectSettings& settings)
: Sender(sender)
, Request(request)
, HttpProxyId(httpProxyId)
, Settings(settings)
{}

void THandlerImpersonateStop::Bootstrap() {
TString impersonatedCookieName = CreateNameImpersonatedCookie(Settings.ClientId);
BLOG_D("Clear impersonated cookie: (" << impersonatedCookieName << ")");

NHttp::THeadersBuilder responseHeaders;
responseHeaders.Set("Set-Cookie", ClearSecureCookie(impersonatedCookieName));
SetCORS(Request, &responseHeaders);

NHttp::THttpOutgoingResponsePtr httpResponse;
httpResponse = Request->CreateResponse("200", "OK", responseHeaders);
ReplyAndPassAway(std::move(httpResponse));
}

void THandlerImpersonateStop::ReplyAndPassAway(NHttp::THttpOutgoingResponsePtr httpResponse) {
Send(Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(std::move(httpResponse)));
PassAway();
}

TImpersonateStopPageHandler::TImpersonateStopPageHandler(const NActors::TActorId& httpProxyId, const TOpenIdConnectSettings& settings)
: TBase(&TImpersonateStopPageHandler::StateWork)
, HttpProxyId(httpProxyId)
, Settings(settings)
{}

void TImpersonateStopPageHandler::Handle(NHttp::TEvHttpProxy::TEvHttpIncomingRequest::TPtr event, const NActors::TActorContext& ctx) {
ctx.Register(new THandlerImpersonateStop(event->Sender, event->Get()->Request, HttpProxyId, Settings));
}

} // NMVP::NOIDC
Loading

0 comments on commit d22f709

Please sign in to comment.