Browse Source

shared secrets have been supported (#9553)

Oleg Doronin 5 months ago
parent
commit
5807f623fc

+ 61 - 1
ydb/core/external_sources/s3/ut/s3_aws_credentials_ut.cpp

@@ -61,7 +61,9 @@ Y_UNIT_TEST_SUITE(S3AwsCredentials) {
                 AWS_ACCESS_KEY_ID_SECRET_NAME="id",
                 AWS_SECRET_ACCESS_KEY_SECRET_NAME="key",
                 AWS_REGION="ru-central-1"
-            );)",
+            );
+            GRANT ALL ON `{external_source}` TO `root1@builtin`;
+            )",
             "external_source"_a = externalDataSourceName,
             "location"_a = "localhost:" + GetExternalPort("minio", "9000") + "/datalake/"
             );
@@ -125,6 +127,64 @@ Y_UNIT_TEST_SUITE(S3AwsCredentials) {
             UNIT_ASSERT_VALUES_EQUAL(resultSet.ColumnParser(0).GetUtf8(), "2");
             UNIT_ASSERT_VALUES_EQUAL(resultSet.ColumnParser(1).GetUtf8(), "hello world");
         }
+
+        {
+            auto db = kikimr->GetQueryClient(NYdb::NQuery::TClientSettings().AuthToken("root1@builtin"));
+            {
+                auto scriptExecutionOperation = db.ExecuteScript(fmt::format(R"(
+                    SELECT * FROM `{external_source}`.`/a/` WITH (
+                        format="json_each_row",
+                        schema(
+                            key Utf8 NOT NULL,
+                            value Utf8 NOT NULL
+                        )
+                    )
+                )", "external_source"_a = externalDataSourceName)).ExtractValueSync();
+                UNIT_ASSERT_VALUES_EQUAL_C(scriptExecutionOperation.Status().GetStatus(), EStatus::SUCCESS, scriptExecutionOperation.Status().GetIssues().ToString());
+                UNIT_ASSERT(scriptExecutionOperation.Metadata().ExecutionId);
+
+                NYdb::NQuery::TScriptExecutionOperation readyOp = WaitScriptExecutionOperation(scriptExecutionOperation.Id(), kikimr->GetDriver());
+                UNIT_ASSERT_EQUAL_C(readyOp.Metadata().ExecStatus, EExecStatus::Failed, readyOp.Status().GetIssues().ToString());
+                UNIT_ASSERT_STRING_CONTAINS_C(readyOp.Status().GetIssues().ToString(), "secret with name 'id' not found", readyOp.Status().GetIssues().ToString());
+            }
+            {
+                const TString query = R"(
+                    CREATE OBJECT `id:root1@builtin` (TYPE SECRET_ACCESS);
+                    CREATE OBJECT `key:root1@builtin` (TYPE SECRET_ACCESS);
+                    )";
+                auto result = session.ExecuteSchemeQuery(query).GetValueSync();
+                UNIT_ASSERT_C(result.GetStatus() == NYdb::EStatus::SUCCESS, result.GetIssues().ToString());
+            }
+            {
+                auto scriptExecutionOperation = db.ExecuteScript(fmt::format(R"(
+                    SELECT * FROM `{external_source}`.`/a/` WITH (
+                        format="json_each_row",
+                        schema(
+                            key Utf8 NOT NULL,
+                            value Utf8 NOT NULL
+                        )
+                    )
+                )", "external_source"_a = externalDataSourceName)).ExtractValueSync();
+                UNIT_ASSERT_VALUES_EQUAL_C(scriptExecutionOperation.Status().GetStatus(), EStatus::SUCCESS, scriptExecutionOperation.Status().GetIssues().ToString());
+                UNIT_ASSERT(scriptExecutionOperation.Metadata().ExecutionId);
+
+                NYdb::NQuery::TScriptExecutionOperation readyOp = WaitScriptExecutionOperation(scriptExecutionOperation.Id(), kikimr->GetDriver());
+                UNIT_ASSERT_EQUAL_C(readyOp.Metadata().ExecStatus, EExecStatus::Completed, readyOp.Status().GetIssues().ToString());
+                TFetchScriptResultsResult results = db.FetchScriptResults(scriptExecutionOperation.Id(), 0).ExtractValueSync();
+                UNIT_ASSERT_C(results.IsSuccess(), results.GetIssues().ToString());
+
+                TResultSetParser resultSet(results.ExtractResultSet());
+                UNIT_ASSERT_VALUES_EQUAL(resultSet.ColumnsCount(), 2);
+                UNIT_ASSERT_VALUES_EQUAL(resultSet.RowsCount(), 2);
+                UNIT_ASSERT(resultSet.TryNextRow());
+                UNIT_ASSERT_VALUES_EQUAL(resultSet.ColumnParser(0).GetUtf8(), "1");
+                UNIT_ASSERT_VALUES_EQUAL(resultSet.ColumnParser(1).GetUtf8(), "trololo");
+                UNIT_ASSERT(resultSet.TryNextRow());
+                UNIT_ASSERT_VALUES_EQUAL(resultSet.ColumnParser(0).GetUtf8(), "2");
+                UNIT_ASSERT_VALUES_EQUAL(resultSet.ColumnParser(1).GetUtf8(), "hello world");
+            }
+        }
+        
     }
 }
 

+ 26 - 10
ydb/core/kqp/federated_query/kqp_federated_query_actors.cpp

@@ -20,17 +20,31 @@ class TDescribeSecretsActor: public NActors::TActorBootstrapped<TDescribeSecrets
         secretValues.reserve(SecretIds.size());
         for (const auto& secretId: SecretIds) {
             TString secretValue;
-            const bool isFound = snapshot->GetSecretValue(NMetadata::NSecret::TSecretIdOrValue::BuildAsId(secretId), secretValue);
-            if (!isFound) {
-                if (!AskSent) {
-                    AskSent = true;
-                    Send(NMetadata::NProvider::MakeServiceId(SelfId().NodeId()), new NMetadata::NProvider::TEvAskSnapshot(GetSecretsSnapshotParser()));
-                } else {
-                    CompleteAndPassAway(TEvDescribeSecretsResponse::TDescription(Ydb::StatusIds::BAD_REQUEST, { NYql::TIssue("secret with name '" + secretId.GetSecretId() + "' not found") }));
-                }
+            bool isFound = snapshot->GetSecretValue(NMetadata::NSecret::TSecretIdOrValue::BuildAsId(secretId), secretValue);
+            if (isFound) {
+                secretValues.push_back(secretValue);
+                continue;
+            }
+
+            auto secretIds = snapshot->GetSecretIds(UserToken, secretId.GetSecretId());
+            if (secretIds.size() > 1) {
+                CompleteAndPassAway(TEvDescribeSecretsResponse::TDescription(Ydb::StatusIds::BAD_REQUEST, { NYql::TIssue("several secrets with name '" + secretId.GetSecretId() + "' were found") }));
                 return;
             }
-            secretValues.push_back(secretValue);
+
+            isFound = !secretIds.empty() && snapshot->GetSecretValue(NMetadata::NSecret::TSecretIdOrValue::BuildAsId(secretIds[0]), secretValue);
+            if (isFound) {
+                secretValues.push_back(secretValue);
+                continue;
+            }
+
+            if (!AskSent) {
+                AskSent = true;
+                Send(NMetadata::NProvider::MakeServiceId(SelfId().NodeId()), new NMetadata::NProvider::TEvAskSnapshot(GetSecretsSnapshotParser()));
+            } else {
+                CompleteAndPassAway(TEvDescribeSecretsResponse::TDescription(Ydb::StatusIds::BAD_REQUEST, { NYql::TIssue("secret with name '" + secretId.GetSecretId() + "' not found") }));
+            }
+            return;
         }
 
         CompleteAndPassAway(TEvDescribeSecretsResponse::TDescription(secretValues));
@@ -49,7 +63,8 @@ class TDescribeSecretsActor: public NActors::TActorBootstrapped<TDescribeSecrets
 
 public:
     TDescribeSecretsActor(const TString& ownerUserId, const std::vector<TString>& secretIds, NThreading::TPromise<TEvDescribeSecretsResponse::TDescription> promise)
-        : SecretIds(CreateSecretIds(ownerUserId, secretIds))
+        : UserToken(NACLib::TUserToken{ownerUserId, TVector<NACLib::TSID>{}})
+        , SecretIds(CreateSecretIds(ownerUserId, secretIds))
         , Promise(promise)
     {}
 
@@ -74,6 +89,7 @@ private:
     }
 
 private:
+    std::optional<NACLib::TUserToken> UserToken;
     const std::vector<NMetadata::NSecret::TSecretId> SecretIds;
     NThreading::TPromise<TEvDescribeSecretsResponse::TDescription> Promise;
     bool AskSent = false;

+ 14 - 0
ydb/services/metadata/secret/snapshot.cpp

@@ -75,4 +75,18 @@ bool TSnapshot::GetSecretValue(const TSecretIdOrValue& sId, TString& result) con
     return true;
 }
 
+std::vector<TSecretId> TSnapshot::GetSecretIds(const std::optional<NACLib::TUserToken>& userToken, const TString& secretId) const {
+    std::vector<TSecretId> secretIds;
+    for (const auto& [key, value]: Secrets) {
+        if (key.GetSecretId() != secretId) {
+            continue;
+        }
+        if (!CheckSecretAccess(NMetadata::NSecret::TSecretIdOrValue::BuildAsId(key), userToken)) {
+            continue;
+        }
+        secretIds.push_back(key);
+    }
+    return secretIds;
+}
+
 }

+ 1 - 0
ydb/services/metadata/secret/snapshot.h

@@ -21,6 +21,7 @@ public:
     bool CheckSecretAccess(const TSecretIdOrValue& sIdOrValue, const std::optional<NACLib::TUserToken>& userToken) const;
     bool PatchString(TString& stringForPath) const;
     bool GetSecretValue(const TSecretIdOrValue& secretId, TString& result) const;
+    std::vector<TSecretId> GetSecretIds(const std::optional<NACLib::TUserToken>& userToken, const TString& secretId) const;
 };
 
 }