blob: ec68dac1e3de559f30594efb3b8eb52302d31816 [file] [log] [blame]
#ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_AUTHZ_AUTHZ_SERVER_H_
#define THIRD_PARTY_MILOTIC_EXTERNAL_CC_AUTHZ_AUTHZ_SERVER_H_
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <memory>
#include <string>
#include <string_view>
#include "absl/base/thread_annotations.h"
#include "absl/synchronization/mutex.h"
#include "grpcpp/security/auth_context.h"
#include "grpcpp/server.h"
#include "grpcpp/server_builder.h"
#include "grpcpp/support/status.h"
#include "config_parser.h"
#include "oauth.grpc.pb.h"
#include "oauth.pb.h"
namespace milotic::authz {
// ssh-keygen user certificate sign command template take parameters:
// {0}: port_id
// {1}: life_time_in_seconds
// {2}: the public key file
constexpr std::string_view kHiscCertGenCmd =
R"delim(/usr/bin/ssh-keygen \
-s /run/hiscd/hiscd_ca \
-I "port-{0}@$(hostname)" \
-z "$(date +%s)" \
-n "hisc" \
-V "+{1}s" \
-O clear -O permit-pty \
-O force-command='/usr/libexec/ttf-console.sh -s user port-{0}' \
{2} 2>&1 | /usr/bin/systemd-cat -t hisc_token -p info
)delim";
// The maximum life time in seconds of Host Interactive Serial Console token.
constexpr uint32_t kMaxHiscCertLifeTimeInSeconds = 30 * 60; // 30 mins
// The system dependency of HiscToken RPC
class HiscTokenSystemDependency {
public:
virtual ~HiscTokenSystemDependency() = default;
virtual int LibcMkstemp(char tmpname[]) = 0;
virtual int RunSshKeyGen(const std::string& cmd,
std::string_view input_key_file) = 0;
};
// This class is thread-safe. The thread safety is provided by the system
// functions it calls and the cmd it runs which are thread-safe.
class BMCHiscTokenSystemDependency : public HiscTokenSystemDependency {
public:
int LibcMkstemp(char tmpname[]) override { return mkstemp(tmpname); }
int RunSshKeyGen(const std::string& cmd,
[[maybe_unused]] std::string_view input_key_file) override {
return std::system(cmd.c_str());
}
};
// The AuthorizationServer only works in mutual TLS mode.
struct ServerConfiguration {
int port = 0;
// The credentials used in the gRPC interface.
std::string trust_bundle_path;
std::string server_certificate_path;
std::string server_key_path;
std::string server_fqdn;
std::string authz_configuration_path;
std::string crl_directory;
// The absolute path where Offline Node Entities file is. (Can be left empty)
// This should be the file installed on the node during RRI
// For more information see go/node-entities-api
std::string offline_node_entities_path;
// The path where the Google Machine Identity is. If left empty, machines in
// HWOPS may be configured incorrectly. For more information see
// go/google-machine-identity-token
std::string google_machine_identity_path;
// The path where the server will dump the public key for other processes.
std::string rsa_public_key_path;
};
namespace impl {
class AuthorizationServiceImpl : public ::oauth::AuthorizationService::Service {
public:
explicit AuthorizationServiceImpl(const ServerConfiguration& server_config);
grpc::Status Exchange(::grpc::ServerContext* /*context*/,
const ::oauth::ExchangeRequest* /*request*/,
::oauth::ExchangeResponse* /*response*/) override;
grpc::Status MintToken(::grpc::ServerContext* context,
const ::oauth::MintTokenRequest* request,
::oauth::MintTokenResponse* response) override;
grpc::Status HiscToken(::grpc::ServerContext* context,
const ::oauth::HiscTokenRequest* request,
::oauth::HiscTokenResponse* response) override;
~AuthorizationServiceImpl() override = default;
void LoadAuthzConfig();
std::string GetRsaPrivateKey() const { return rsa_private_key_; }
std::string GetServerFqdn();
void SetServerFqdn(const std::string& server_fqdn);
protected:
grpc::Status AuthorizeMintTokenRpc(const grpc::AuthContext& context);
grpc::Status CheckMintTokenRequest(const ::oauth::MintTokenRequest& request);
std::string GetAndIncreaseTokenCount();
grpc::Status AuthorizeHiscTokenRpc(const grpc::AuthContext& context);
static grpc::Status HiscToken(
const ::oauth::HiscTokenRequest* request,
::oauth::HiscTokenResponse* response,
HiscTokenSystemDependency& hisc_token_system_dependency);
private:
std::unique_ptr<AuthzConfiguration> authz_config_;
std::string rsa_private_key_;
absl::Mutex mutex_;
std::size_t token_count_ ABSL_GUARDED_BY(mutex_);
ServerConfiguration server_config_ ABSL_GUARDED_BY(mutex_);
BMCHiscTokenSystemDependency bmc_hisc_token_system_dependency_;
};
} // namespace impl
// The BMC local authorization server.
// This class is thread-safe.
class AuthorizationServer {
public:
explicit AuthorizationServer(const ServerConfiguration& config);
~AuthorizationServer();
void StartServer();
// Thread safe reload on authz config without updating the RSA key
void ReloadAuthzConfig(const std::string& server_fqdn);
// Blocks until process is killed.
void Wait();
std::string GetRsaPrivateKey() const { return service_->GetRsaPrivateKey(); }
private:
ServerConfiguration server_config_;
std::unique_ptr<impl::AuthorizationServiceImpl> service_;
std::unique_ptr<grpc::Server> server_;
};
} // namespace milotic::authz
#endif // THIRD_PARTY_MILOTIC_EXTERNAL_CC_AUTHZ_AUTHZ_SERVER_H_