blob: 5cba93dd1d9b4c572119248422f17f7f4003814b [file] [log] [blame] [edit]
#include <filesystem>
#include <memory>
#include <string>
#include <system_error>
#include <thread>
#include <boost/asio.hpp>
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/log/log.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "grpc/grpc_security_constants.h"
#include "grpcpp/ext/proto_server_reflection_plugin.h"
#include "grpcpp/security/authorization_policy_provider.h"
#include "grpcpp/security/server_credentials.h"
#include "grpcpp/security/tls_certificate_provider.h"
#include "grpcpp/security/tls_credentials_options.h"
#include "grpcpp/server_builder.h"
#include "grpcpp/server_context.h"
#include "grpcpp/support/status.h"
#include "channel_server.hpp"
using grpc::Server;
using grpc::ServerBuilder;
using ::grpc::experimental::AuthorizationPolicyProviderInterface;
using ::grpc::experimental::FileWatcherAuthorizationPolicyProvider;
using ::grpc::experimental::FileWatcherCertificateProvider;
using ::grpc::experimental::TlsServerCredentials;
using ::grpc::experimental::TlsServerCredentialsOptions;
ABSL_FLAG(std::string, address_uri, "[::]:5124",
"Host address to listen to. Default to [::]:5124");
ABSL_FLAG(bool, start_secure_server, true,
"Start secure server with Zatar credentials. Default to true");
constexpr absl::string_view kZatarCertFilePath =
"/var/volatile/prodid/server.pem";
constexpr absl::string_view kTrustBundleFilePath =
"/var/google/trust_bundle/trust_bundle.pem";
// Order matters in the array. If the policy file is not found in the
// first path, the second path will be checked, and so on. This is to
// give priority to the policy file provided by the merged view from
// the overlay filesystem.
constexpr absl::string_view kStrowgerdCertAuthZPolicyBasePath[] = {"/var/",
"/etc/"};
constexpr absl::string_view kStrowgerdCertAuthZPolicy =
"google/authz_policies/strowgerd_authz_policy.json";
std::shared_ptr<grpc::ServerCredentials> GetCredsInfo() {
std::error_code file_error;
bool file_exist = std::filesystem::exists(kZatarCertFilePath, file_error);
if (file_error) {
LOG(ERROR) << "Zatar file error: " << file_error.message();
return nullptr;
}
std::string keypair_path;
if (file_exist) {
keypair_path = std::string(kZatarCertFilePath);
} else {
// TODO(jorgecardona): Include self sign certificate implementation.
LOG(ERROR) << "Zatar Certificate file: " << kZatarCertFilePath
<< " does not exist.";
return nullptr;
}
auto certificateProvider = std::make_shared<FileWatcherCertificateProvider>(
keypair_path, keypair_path, std::string(kTrustBundleFilePath),
/* refresh_interval_sec */ 30);
TlsServerCredentialsOptions options(certificateProvider);
options.watch_root_certs();
options.set_root_cert_name("Zatar");
options.watch_identity_key_cert_pairs();
options.set_cert_request_type(
GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
// TODO(jorgecardona): Investigate whether certificate verifier is needed.
std::shared_ptr<grpc::ServerCredentials> tlsServerCredentials =
TlsServerCredentials(options);
if (tlsServerCredentials == nullptr) {
LOG(ERROR) << "Error generating TLS Server credentials";
return nullptr;
}
return tlsServerCredentials;
}
std::shared_ptr<AuthorizationPolicyProviderInterface> GetAuthPolicy() {
grpc::Status policyStatus;
std::string policy_path;
for (const auto& prefix : kStrowgerdCertAuthZPolicyBasePath) {
std::string temp_policy_path =
absl::StrCat(prefix, kStrowgerdCertAuthZPolicy);
std::error_code file_error;
if (std::filesystem::exists(temp_policy_path, file_error)) {
policy_path = temp_policy_path;
LOG(INFO) << "Using policy path: " << policy_path;
break;
}
if (file_error) {
LOG(ERROR) << "Error checking policy file: " << file_error.message();
}
}
if (policy_path.empty()) {
LOG(ERROR) << "Policy file not found.";
return nullptr;
}
std::shared_ptr<AuthorizationPolicyProviderInterface> policy =
FileWatcherAuthorizationPolicyProvider::Create(
policy_path,
/* policy refresh_interval_sec = 5 minutes*/ 300, &policyStatus);
if (!policyStatus.ok()) {
return nullptr;
}
return policy;
}
std::shared_ptr<Server> CreateServer(RemoteDebugServiceImpl& service,
std::string address_uri,
bool start_secure_server) {
grpc::reflection::InitProtoReflectionServerBuilderPlugin();
ServerBuilder builder;
std::shared_ptr<grpc::ServerCredentials> creds =
grpc::InsecureServerCredentials();
if (start_secure_server) {
if (auto secure_creds = GetCredsInfo()) {
creds = secure_creds;
if (auto policy = GetAuthPolicy()) {
builder.experimental().SetAuthorizationPolicyProvider(policy);
} else {
LOG(ERROR) << "Failed to get authorization policy.";
return nullptr;
}
} else {
LOG(WARNING)
<< "Failed to get secure credentials. Using insecure server.";
}
}
builder.AddListeningPort(address_uri, creds);
builder.RegisterService(&service);
return builder.BuildAndStart();
}
int main(int argc, char** argv) {
absl::ParseCommandLine(argc, argv);
std::string address_uri = absl::GetFlag(FLAGS_address_uri);
boost::asio::io_context io_context;
boost::asio::executor_work_guard<boost::asio::io_context::executor_type>
work_guard(io_context.get_executor());
RemoteDebugServiceImpl service(io_context);
bool start_secure_server = absl::GetFlag(FLAGS_start_secure_server);
std::shared_ptr<Server> server =
CreateServer(service, address_uri, start_secure_server);
if (server == nullptr) {
return 1;
}
std::thread thread{[&io_context]() { io_context.run(); }};
server->Wait();
return 0;
}