| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| #pragma once |
| |
| #include <memory> |
| #include <string> |
| #include <unordered_map> |
| #include <unordered_set> |
| #include <utility> |
| |
| #include "kudu/gutil/port.h" |
| #include "kudu/gutil/ref_counted.h" |
| #include "kudu/ranger/ranger.pb.h" |
| #include "kudu/subprocess/server.h" |
| #include "kudu/subprocess/subprocess_proxy.h" |
| #include "kudu/util/metrics.h" |
| #include "kudu/util/status.h" |
| |
| namespace kudu { |
| |
| class Env; |
| |
| namespace ranger { |
| |
| struct ActionHash { |
| public: |
| int operator()(const ActionPB& action) const { |
| return action; |
| } |
| }; |
| |
| struct RangerSubprocessMetrics : public subprocess::SubprocessMetrics { |
| explicit RangerSubprocessMetrics(const scoped_refptr<MetricEntity>& entity); |
| }; |
| |
| typedef subprocess::SubprocessProxy<RangerRequestListPB, RangerResponseListPB, |
| RangerSubprocessMetrics> RangerSubprocess; |
| |
| // A client for the Ranger service that communicates with a Java subprocess. |
| // |
| // The Ranger subprocess itself is configured using xml files, like |
| // core-site.xml and ranger-kudu-security.xml. The only configuration that is |
| // coming from this class are environmental, like Java binary location, location |
| // of config files, and krb5.conf file (setting it doesn't enable Kerberos, that |
| // depends on core-site.xml). |
| // |
| // These methods return non-OK status only if something goes wrong between the |
| // client and the subprocess (e.g. IOError, EndOfFile, Corruption), but they |
| // never return NotAuthorized. The authz provider is responsible to return |
| // NotAuthorized based on RangerClient's out parameters and return Status. |
| class RangerClient { |
| public: |
| // The privilege scope can indicate the hierarchy of authorizables |
| // (e.g. database -> table -> column). For example, authorizable 'db=a' has |
| // database level scope, while authorizable 'db=a->table=b' has table level scope. |
| // Note that COLUMN level scope is not defined in the enum as it is not |
| // used yet in the code (although the concept still apply when |
| // authorizing column level privileges). |
| enum Scope { |
| DATABASE, |
| TABLE |
| }; |
| |
| // Creates a Ranger client. |
| explicit RangerClient(Env* env, const scoped_refptr<MetricEntity>& metric_entity); |
| |
| // Starts the RangerClient, initializes the subprocess server. |
| Status Start() WARN_UNUSED_RESULT; |
| |
| // Authorizes an action on the table. Sets 'authorized' to true if it's |
| // authorized, false otherwise. |
| Status AuthorizeAction(const std::string& user_name, const ActionPB& action, |
| const std::string& database, const std::string& table, bool is_owner, |
| bool requires_delegate_admin, bool* authorized, |
| Scope scope = Scope::TABLE) WARN_UNUSED_RESULT; |
| |
| // Authorizes action on multiple tables. It sets 'table_names' to the |
| // tables the user is authorized to access. |
| Status AuthorizeActionMultipleTables(const std::string& user_name, const ActionPB& action, |
| std::unordered_map<std::string, bool>* tables) |
| WARN_UNUSED_RESULT; |
| |
| // Authorizes action on multiple columns. It sets 'column_names' to the |
| // columns the user is authorized to access. |
| Status AuthorizeActionMultipleColumns(const std::string& user_name, const ActionPB& action, |
| const std::string& database, const std::string& table, |
| bool is_owner, |
| std::unordered_set<std::string>* column_names) |
| WARN_UNUSED_RESULT; |
| |
| // Authorizes multiple table-level actions on a single table. It sets |
| // 'actions' to the actions the user is authorized to perform. |
| Status AuthorizeActions(const std::string& user_name, const std::string& database, |
| const std::string& table, bool is_owner, |
| std::unordered_set<ActionPB, ActionHash>* actions, |
| Scope scope = Scope::TABLE) WARN_UNUSED_RESULT; |
| |
| // Refreshes policies in the Ranger subprocess. This does not invalidate the |
| // existing cache and doesn't fail if Ranger service is unavailable, it simply |
| // tries to refresh the policies from the server on a best effort basis. |
| Status RefreshPolicies() WARN_UNUSED_RESULT; |
| |
| // Replaces the subprocess server in the subprocess proxy. |
| void ReplaceServerForTests(std::unique_ptr<subprocess::SubprocessServer> server) { |
| // Creates a dummy RangerSubprocess if it is not initialized. |
| if (!subprocess_) { |
| subprocess_.reset(new RangerSubprocess(env_, "", {""}, metric_entity_)); |
| } |
| subprocess_->ReplaceServerForTests(std::move(server)); |
| } |
| |
| private: |
| Env* env_; |
| std::unique_ptr<RangerSubprocess> subprocess_; |
| scoped_refptr<MetricEntity> metric_entity_; |
| }; |
| |
| } // namespace ranger |
| } // namespace kudu |