mirror of https://github.com/grpc/grpc.git
Static policy provider implementation. (#26134)
parent
304262e135
commit
b9a643a817
41 changed files with 868 additions and 39 deletions
@ -0,0 +1,67 @@ |
||||
// Copyright 2021 gRPC authors.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
#ifndef GRPCPP_SECURITY_AUTHORIZATION_POLICY_PROVIDER_H |
||||
#define GRPCPP_SECURITY_AUTHORIZATION_POLICY_PROVIDER_H |
||||
|
||||
#include <grpc/status.h> |
||||
#include <grpcpp/impl/codegen/grpc_library.h> |
||||
|
||||
#include <memory> |
||||
|
||||
// TODO(yihuazhang): remove the forward declaration here and include
|
||||
// <grpc/grpc_security.h> directly once the insecure builds are cleaned up.
|
||||
typedef struct grpc_authorization_policy_provider |
||||
grpc_authorization_policy_provider; |
||||
|
||||
namespace grpc { |
||||
namespace experimental { |
||||
|
||||
// Wrapper around C-core grpc_authorization_policy_provider. Internally, it
|
||||
// handles creating and updating authorization engine objects, using SDK
|
||||
// authorization policy.
|
||||
class AuthorizationPolicyProviderInterface { |
||||
public: |
||||
virtual ~AuthorizationPolicyProviderInterface() = default; |
||||
virtual grpc_authorization_policy_provider* c_provider() = 0; |
||||
}; |
||||
|
||||
// Implementation obtains authorization policy from static string. This provider
|
||||
// will always return the same authorization engines.
|
||||
class StaticDataAuthorizationPolicyProvider |
||||
: public AuthorizationPolicyProviderInterface { |
||||
public: |
||||
static std::shared_ptr<StaticDataAuthorizationPolicyProvider> Create( |
||||
const std::string& authz_policy, grpc::Status* status); |
||||
|
||||
// Use factory method "Create" to create an instance of
|
||||
// StaticDataAuthorizationPolicyProvider.
|
||||
explicit StaticDataAuthorizationPolicyProvider( |
||||
grpc_authorization_policy_provider* provider) |
||||
: c_provider_(provider) {} |
||||
|
||||
~StaticDataAuthorizationPolicyProvider() override; |
||||
|
||||
grpc_authorization_policy_provider* c_provider() override { |
||||
return c_provider_; |
||||
} |
||||
|
||||
private: |
||||
grpc_authorization_policy_provider* c_provider_ = nullptr; |
||||
}; |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPCPP_SECURITY_AUTHORIZATION_POLICY_PROVIDER_H
|
@ -0,0 +1,32 @@ |
||||
// Copyright 2021 gRPC authors.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
#ifndef GRPC_CORE_LIB_SECURITY_AUTHORIZATION_AUTHORIZATION_POLICY_PROVIDER_H |
||||
#define GRPC_CORE_LIB_SECURITY_AUTHORIZATION_AUTHORIZATION_POLICY_PROVIDER_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/lib/gprpp/dual_ref_counted.h" |
||||
#include "src/core/lib/security/authorization/authorization_engine.h" |
||||
|
||||
struct grpc_authorization_policy_provider |
||||
: public grpc_core::DualRefCounted<grpc_authorization_policy_provider> { |
||||
public: |
||||
virtual grpc_core::RefCountedPtr<grpc_core::AuthorizationEngine> |
||||
allow_engine() const = 0; |
||||
virtual grpc_core::RefCountedPtr<grpc_core::AuthorizationEngine> deny_engine() |
||||
const = 0; |
||||
}; |
||||
|
||||
#endif // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_AUTHORIZATION_POLICY_PROVIDER_H
|
@ -0,0 +1,24 @@ |
||||
// Copyright 2021 gRPC authors.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <grpc/grpc.h> |
||||
|
||||
// Wrapper API declared in grpc.h
|
||||
|
||||
// Required only for insecure build targets.
|
||||
const grpc_arg_pointer_vtable* grpc_authorization_policy_provider_arg_vtable() { |
||||
return nullptr; |
||||
} |
@ -0,0 +1,46 @@ |
||||
// Copyright 2021 gRPC authors.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <grpc/grpc.h> |
||||
|
||||
#include "src/core/lib/security/authorization/authorization_policy_provider.h" |
||||
|
||||
namespace { |
||||
|
||||
void* ProviderArgCopy(void* p) { |
||||
grpc_authorization_policy_provider* provider = |
||||
static_cast<grpc_authorization_policy_provider*>(p); |
||||
provider->Ref().release(); |
||||
return provider; |
||||
} |
||||
|
||||
void ProviderArgDestroy(void* p) { |
||||
grpc_authorization_policy_provider* provider = |
||||
static_cast<grpc_authorization_policy_provider*>(p); |
||||
provider->Unref(); |
||||
} |
||||
|
||||
int ProviderArgCmp(void* p, void* q) { return GPR_ICMP(p, q); } |
||||
|
||||
} // namespace
|
||||
|
||||
// Wrapper API declared in grpc.h
|
||||
|
||||
const grpc_arg_pointer_vtable* grpc_authorization_policy_provider_arg_vtable() { |
||||
static const grpc_arg_pointer_vtable vtable = { |
||||
ProviderArgCopy, ProviderArgDestroy, ProviderArgCmp}; |
||||
return &vtable; |
||||
} |
@ -0,0 +1,67 @@ |
||||
// Copyright 2021 gRPC authors.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <grpc/grpc_security.h> |
||||
#include <grpc/support/string_util.h> |
||||
|
||||
#include "src/core/lib/security/authorization/grpc_authorization_engine.h" |
||||
#include "src/core/lib/security/authorization/grpc_authorization_policy_provider.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
absl::StatusOr<RefCountedPtr<grpc_authorization_policy_provider>> |
||||
StaticDataAuthorizationPolicyProvider::Create(absl::string_view authz_policy) { |
||||
auto policies_or = GenerateRbacPolicies(authz_policy); |
||||
if (!policies_or.ok()) { |
||||
return policies_or.status(); |
||||
} |
||||
return MakeRefCounted<StaticDataAuthorizationPolicyProvider>( |
||||
std::move(*policies_or)); |
||||
} |
||||
|
||||
StaticDataAuthorizationPolicyProvider::StaticDataAuthorizationPolicyProvider( |
||||
RbacPolicies policies) |
||||
: allow_engine_(MakeRefCounted<GrpcAuthorizationEngine>( |
||||
std::move(policies.allow_policy))), |
||||
deny_engine_(MakeRefCounted<GrpcAuthorizationEngine>( |
||||
std::move(policies.deny_policy))) {} |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
// Wrapper APIs declared in grpc_security.h
|
||||
|
||||
grpc_authorization_policy_provider* |
||||
grpc_authorization_policy_provider_static_data_create( |
||||
const char* authz_policy, grpc_status_code* code, |
||||
const char** error_details) { |
||||
GPR_ASSERT(authz_policy != nullptr); |
||||
auto provider_or = |
||||
grpc_core::StaticDataAuthorizationPolicyProvider::Create(authz_policy); |
||||
if (!provider_or.ok()) { |
||||
*code = static_cast<grpc_status_code>(provider_or.status().code()); |
||||
*error_details = |
||||
gpr_strdup(std::string(provider_or.status().message()).c_str()); |
||||
return nullptr; |
||||
} |
||||
*code = GRPC_STATUS_OK; |
||||
*error_details = nullptr; |
||||
return provider_or->release(); |
||||
} |
||||
|
||||
void grpc_authorization_policy_provider_release( |
||||
grpc_authorization_policy_provider* provider) { |
||||
if (provider != nullptr) provider->Unref(); |
||||
} |
@ -0,0 +1,60 @@ |
||||
// Copyright 2021 gRPC authors.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
#ifndef GRPC_CORE_LIB_SECURITY_AUTHORIZATION_GRPC_AUTHORIZATION_POLICY_PROVIDER_H |
||||
#define GRPC_CORE_LIB_SECURITY_AUTHORIZATION_GRPC_AUTHORIZATION_POLICY_PROVIDER_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <memory> |
||||
|
||||
#include "absl/status/statusor.h" |
||||
|
||||
#include "src/core/lib/security/authorization/authorization_policy_provider.h" |
||||
#include "src/core/lib/security/authorization/rbac_translator.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
// Provider class will get SDK Authorization policy from string during
|
||||
// initialization. This policy will be translated to Envoy RBAC policies and
|
||||
// used to initialize allow and deny AuthorizationEngine objects. This provider
|
||||
// will return the same authorization engines everytime.
|
||||
class StaticDataAuthorizationPolicyProvider |
||||
: public grpc_authorization_policy_provider { |
||||
public: |
||||
static absl::StatusOr<RefCountedPtr<grpc_authorization_policy_provider>> |
||||
Create(absl::string_view authz_policy); |
||||
|
||||
explicit StaticDataAuthorizationPolicyProvider(RbacPolicies policies); |
||||
|
||||
RefCountedPtr<AuthorizationEngine> allow_engine() const override { |
||||
return allow_engine_; |
||||
} |
||||
RefCountedPtr<AuthorizationEngine> deny_engine() const override { |
||||
return deny_engine_; |
||||
} |
||||
|
||||
void Orphan() override {} |
||||
|
||||
private: |
||||
RefCountedPtr<AuthorizationEngine> allow_engine_; |
||||
RefCountedPtr<AuthorizationEngine> deny_engine_; |
||||
}; |
||||
|
||||
// TODO(ashithasantosh): Add implementation for file watcher authorization
|
||||
// policy provider.
|
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_GRPC_AUTHORIZATION_POLICY_PROVIDER_H
|
@ -0,0 +1,45 @@ |
||||
// Copyright 2021 gRPC authors.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
#include <grpc/grpc_security.h> |
||||
#include <grpc/support/alloc.h> |
||||
#include <grpcpp/security/authorization_policy_provider.h> |
||||
|
||||
namespace grpc { |
||||
namespace experimental { |
||||
|
||||
std::shared_ptr<StaticDataAuthorizationPolicyProvider> |
||||
StaticDataAuthorizationPolicyProvider::Create(const std::string& authz_policy, |
||||
grpc::Status* status) { |
||||
grpc_status_code code; |
||||
const char* error_details; |
||||
grpc_authorization_policy_provider* provider = |
||||
grpc_authorization_policy_provider_static_data_create( |
||||
authz_policy.c_str(), &code, &error_details); |
||||
if (code != GRPC_STATUS_OK) { |
||||
*status = grpc::Status(static_cast<grpc::StatusCode>(code), error_details); |
||||
gpr_free(const_cast<char*>(error_details)); |
||||
return nullptr; |
||||
} |
||||
*status = grpc::Status(); |
||||
return std::make_shared<StaticDataAuthorizationPolicyProvider>(provider); |
||||
} |
||||
|
||||
StaticDataAuthorizationPolicyProvider:: |
||||
~StaticDataAuthorizationPolicyProvider() { |
||||
grpc_authorization_policy_provider_release(c_provider_); |
||||
} |
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc
|
@ -0,0 +1,62 @@ |
||||
// Copyright 2021 gRPC authors.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <gmock/gmock.h> |
||||
#include <grpc/grpc_security.h> |
||||
#include <gtest/gtest.h> |
||||
|
||||
#include "src/core/lib/security/authorization/grpc_authorization_engine.h" |
||||
#include "src/core/lib/security/authorization/grpc_authorization_policy_provider.h" |
||||
#include "test/core/util/test_config.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
TEST(AuthorizationPolicyProviderTest, StaticDataInitializationSuccessful) { |
||||
const char* authz_policy = |
||||
"{" |
||||
" \"name\": \"authz\"," |
||||
" \"allow_rules\": [" |
||||
" {" |
||||
" \"name\": \"allow_policy\"" |
||||
" }" |
||||
" ]" |
||||
"}"; |
||||
auto provider = StaticDataAuthorizationPolicyProvider::Create(authz_policy); |
||||
ASSERT_TRUE(provider.ok()); |
||||
auto* allow_engine = |
||||
dynamic_cast<GrpcAuthorizationEngine*>((*provider)->allow_engine().get()); |
||||
ASSERT_NE(allow_engine, nullptr); |
||||
EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow); |
||||
auto* deny_engine = |
||||
dynamic_cast<GrpcAuthorizationEngine*>((*provider)->deny_engine().get()); |
||||
ASSERT_NE(deny_engine, nullptr); |
||||
EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny); |
||||
} |
||||
|
||||
TEST(AuthorizationPolicyProviderTest, |
||||
StaticDataInitializationFailedInvalidPolicy) { |
||||
const char* authz_policy = "{}"; |
||||
auto provider = StaticDataAuthorizationPolicyProvider::Create(authz_policy); |
||||
EXPECT_EQ(provider.status().code(), absl::StatusCode::kInvalidArgument); |
||||
EXPECT_EQ(provider.status().message(), "\"name\" field is not present."); |
||||
} |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
int main(int argc, char** argv) { |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
return RUN_ALL_TESTS(); |
||||
} |
@ -0,0 +1,57 @@ |
||||
// Copyright 2021 gRPC authors.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
#include <grpcpp/security/authorization_policy_provider.h> |
||||
#include <gtest/gtest.h> |
||||
|
||||
#include "test/core/util/test_config.h" |
||||
|
||||
namespace grpc { |
||||
|
||||
TEST(AuthorizationPolicyProviderTest, StaticDataCreateReturnsProvider) { |
||||
const char* authz_policy = |
||||
"{" |
||||
" \"name\": \"authz\"," |
||||
" \"allow_rules\": [" |
||||
" {" |
||||
" \"name\": \"allow_policy\"" |
||||
" }" |
||||
" ]" |
||||
"}"; |
||||
grpc::Status status; |
||||
auto provider = experimental::StaticDataAuthorizationPolicyProvider::Create( |
||||
authz_policy, &status); |
||||
ASSERT_NE(provider, nullptr); |
||||
EXPECT_NE(provider->c_provider(), nullptr); |
||||
EXPECT_TRUE(status.ok()); |
||||
EXPECT_TRUE(status.error_message().empty()); |
||||
} |
||||
|
||||
TEST(AuthorizationPolicyProviderTest, StaticDataCreateReturnsErrorStatus) { |
||||
const char* authz_policy = "{}"; |
||||
grpc::Status status; |
||||
auto provider = experimental::StaticDataAuthorizationPolicyProvider::Create( |
||||
authz_policy, &status); |
||||
ASSERT_EQ(provider, nullptr); |
||||
EXPECT_EQ(status.error_code(), grpc::StatusCode::INVALID_ARGUMENT); |
||||
EXPECT_EQ(status.error_message(), "\"name\" field is not present."); |
||||
} |
||||
|
||||
} // namespace grpc
|
||||
|
||||
int main(int argc, char** argv) { |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
grpc::testing::TestEnvironment env(argc, argv); |
||||
return RUN_ALL_TESTS(); |
||||
} |
Loading…
Reference in new issue