-
Notifications
You must be signed in to change notification settings - Fork 694
Check secret existence #14865
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Check secret existence #14865
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ | |
#include <library/cpp/threading/future/core/future.h> | ||
|
||
#include <util/generic/deque.h> | ||
#include <util/generic/guid.h> | ||
#include <util/generic/hash.h> | ||
#include <util/generic/hash_set.h> | ||
#include <util/generic/maybe.h> | ||
|
@@ -1110,6 +1111,32 @@ TRestoreResult TRestoreClient::RestoreTopic( | |
return Result<TRestoreResult>(dbPath, std::move(result)); | ||
} | ||
|
||
TRestoreResult TRestoreClient::CheckSecretExistence(const TString& secretName) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would like to see a little comment explaining how this is the only way to check the secret existence at the moment, because this approach is very counter intuitive. Possibly in the later PRs |
||
LOG_D("Check existence of the secret " << secretName.Quote()); | ||
|
||
const auto tmpUser = CreateGuidAsString(); | ||
const auto create = std::format("CREATE OBJECT `{}:{}` (TYPE SECRET_ACCESS);", secretName.c_str(), tmpUser.c_str()); | ||
const auto drop = std::format("DROP OBJECT `{}:{}` (TYPE SECRET_ACCESS);", secretName.c_str(), tmpUser.c_str()); | ||
|
||
auto result = QueryClient.RetryQuerySync([&](NQuery::TSession session) { | ||
return session.ExecuteQuery(create, NQuery::TTxControl::NoTx()).ExtractValueSync(); | ||
}); | ||
if (!result.IsSuccess()) { | ||
return Result<TRestoreResult>(EStatus::PRECONDITION_FAILED, TStringBuilder() | ||
<< "Secret " << secretName.Quote() << " does not exist or you do not have access permissions"); | ||
} | ||
|
||
result = QueryClient.RetryQuerySync([&](NQuery::TSession session) { | ||
return session.ExecuteQuery(drop, NQuery::TTxControl::NoTx()).ExtractValueSync(); | ||
}); | ||
if (!result.IsSuccess()) { | ||
return Result<TRestoreResult>(EStatus::INTERNAL_ERROR, TStringBuilder() | ||
<< "Failed to drop temporary secret access " << secretName << ":" << tmpUser); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
TRestoreResult TRestoreClient::RestoreReplication( | ||
const TFsPath& fsPath, | ||
const TString& dbRestoreRoot, | ||
|
@@ -1131,6 +1158,11 @@ TRestoreResult TRestoreClient::RestoreReplication( | |
} | ||
|
||
auto query = ReadAsyncReplicationQuery(fsPath, Log.get()); | ||
if (const auto secretName = GetSecretName(query)) { | ||
if (auto result = CheckSecretExistence(secretName); !result.IsSuccess()) { | ||
return Result<TRestoreResult>(fsPath.GetPath(), std::move(result)); | ||
} | ||
} | ||
|
||
NYql::TIssues issues; | ||
if (!RewriteObjectRefs(query, dbRestoreRoot, issues)) { | ||
|
@@ -1262,6 +1294,11 @@ TRestoreResult TRestoreClient::RestoreExternalDataSource( | |
} | ||
|
||
TString query = ReadExternalDataSourceQuery(fsPath, Log.get()); | ||
if (const auto secretName = GetSecretName(query)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. External data sources can depend on multiple secrets, see TAuth message describing the authorization for a particular data source |
||
if (auto result = CheckSecretExistence(secretName); !result.IsSuccess()) { | ||
return Result<TRestoreResult>(fsPath.GetPath(), std::move(result)); | ||
} | ||
} | ||
|
||
NYql::TIssues issues; | ||
if (!RewriteCreateQuery(query, "CREATE EXTERNAL DATA SOURCE IF NOT EXISTS `{}`", dbPath, issues)) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -190,7 +190,7 @@ struct TTableRefValidator { | |
NYql::TIssues& Issues; | ||
}; | ||
|
||
TString GetOpt(TStringInput query, TStringBuf pattern) { | ||
TString GetToken(TStringInput query, TStringBuf pattern) { | ||
TString line; | ||
while (query.ReadLine(line)) { | ||
StripInPlace(line); | ||
|
@@ -205,11 +205,26 @@ TString GetOpt(TStringInput query, TStringBuf pattern) { | |
} // anonymous | ||
|
||
TString GetBackupRoot(const TString& query) { | ||
return GetOpt(query, R"(-- backup root: ")"); | ||
return GetToken(query, R"(-- backup root: ")"); | ||
} | ||
|
||
TString GetDatabase(const TString& query) { | ||
return GetOpt(query, R"(-- database: ")"); | ||
return GetToken(query, R"(-- database: ")"); | ||
} | ||
|
||
TString GetSecretName(const TString& query) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function has very limited functionality. I guess it is enough to check restorability of an external data source that uses static authorization (login + password), or an authorization by token. However, there are a lot more supported authorization methods, which require different secret names. Moreover, why even bother detecting missing secrets, if an external data source (and I guess an async replication too) will detect the missing secrets themselves on the creation attempt? |
||
TString secretName; | ||
if (auto pwd = GetToken(query, R"(PASSWORD_SECRET_NAME = ')")) { | ||
secretName = std::move(pwd); | ||
} else if (auto token = GetToken(query, R"(TOKEN_SECRET_NAME = ')")) { | ||
secretName = std::move(token); | ||
} | ||
|
||
if (secretName.EndsWith("'")) { | ||
secretName.resize(secretName.size() - 1); | ||
} | ||
|
||
return secretName; | ||
} | ||
|
||
bool SqlToProtoAst(const TString& queryStr, TRule_sql_query& queryProto, NYql::TIssues& issues) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: why 2 spaces and not 4? Isn't the 4 spaces the default formatting?