528 lines
18 KiB
C++
528 lines
18 KiB
C++
// ================================================================================================
|
||
// Audio Backend - 沙盒安全测试
|
||
// ================================================================================================
|
||
|
||
#include <gtest/gtest.h>
|
||
#include <gmock/gmock.h>
|
||
#include "plugin_host/sandbox/sandbox_interface.h"
|
||
#include "tests/common/test_fixtures.h"
|
||
#include <thread>
|
||
#include <chrono>
|
||
#include <atomic>
|
||
|
||
using namespace audio_backend;
|
||
using namespace audio_backend::plugin_host;
|
||
using namespace std::chrono_literals;
|
||
|
||
// 创建安全测试用的沙盒实现
|
||
class SecurityTestingSandbox : public SandboxBase {
|
||
public:
|
||
explicit SecurityTestingSandbox() : SandboxBase(SandboxType::ProcessLevelIsolation) {}
|
||
~SecurityTestingSandbox() override = default;
|
||
|
||
// 基本方法实现
|
||
common::ErrorCode do_initialize() override { return common::ErrorCode::Success; }
|
||
common::ErrorCode do_shutdown() override { return common::ErrorCode::Success; }
|
||
|
||
common::ErrorCode do_start_process(
|
||
const std::string& executable_path,
|
||
const std::vector<std::string>& arguments,
|
||
ProcessId& out_process_id) override {
|
||
out_process_id = next_pid_++;
|
||
register_process(out_process_id, executable_path);
|
||
return common::ErrorCode::Success;
|
||
}
|
||
|
||
common::ErrorCode do_stop_process(ProcessId process_id, bool force) override {
|
||
auto* process_info = find_process_info(process_id);
|
||
if (process_info) {
|
||
unregister_process(process_id);
|
||
return common::ErrorCode::Success;
|
||
}
|
||
return common::ErrorCode::InvalidArgument;
|
||
}
|
||
|
||
// 接口方法实现
|
||
common::ErrorCode start_process(
|
||
const std::string& executable_path,
|
||
const std::vector<std::string>& arguments,
|
||
ProcessId& out_process_id) override {
|
||
return SandboxBase::start_process(executable_path, arguments, out_process_id);
|
||
}
|
||
|
||
common::ErrorCode suspend_process(ProcessId process_id) override {
|
||
return common::ErrorCode::Success;
|
||
}
|
||
|
||
common::ErrorCode resume_process(ProcessId process_id) override {
|
||
return common::ErrorCode::Success;
|
||
}
|
||
|
||
common::ErrorCode restart_process(ProcessId process_id) override {
|
||
return common::ErrorCode::Success;
|
||
}
|
||
|
||
common::ErrorCode wait_for_process(
|
||
ProcessId process_id,
|
||
std::chrono::milliseconds timeout,
|
||
int& exit_code) override {
|
||
exit_code = 0;
|
||
return common::ErrorCode::Success;
|
||
}
|
||
|
||
common::ErrorCode set_resource_limits(
|
||
ProcessId process_id,
|
||
const ResourceLimits& limits) override {
|
||
return common::ErrorCode::Success;
|
||
}
|
||
|
||
common::ErrorCode get_resource_usage(
|
||
ProcessId process_id,
|
||
PerformanceMetrics& metrics) override {
|
||
return common::ErrorCode::Success;
|
||
}
|
||
|
||
common::ErrorCode enforce_resource_limits(ProcessId process_id) override {
|
||
return common::ErrorCode::Success;
|
||
}
|
||
|
||
// 安全管理重点方法
|
||
common::ErrorCode apply_security_settings(
|
||
ProcessId process_id,
|
||
const SecuritySettings& settings) override {
|
||
auto* process_info = find_process_info(process_id);
|
||
if (process_info) {
|
||
security_settings_[process_id] = settings;
|
||
return common::ErrorCode::Success;
|
||
}
|
||
return common::ErrorCode::InvalidArgument;
|
||
}
|
||
|
||
bool is_path_accessible(
|
||
ProcessId process_id,
|
||
const std::string& path) const override {
|
||
auto* process_info = find_process_info(process_id);
|
||
if (!process_info) {
|
||
return false;
|
||
}
|
||
|
||
// 获取安全设置
|
||
auto it = security_settings_.find(process_id);
|
||
if (it == security_settings_.end()) {
|
||
// 如果没有特定设置,默认不允许访问
|
||
return false;
|
||
}
|
||
|
||
const SecuritySettings& settings = it->second;
|
||
|
||
// 全局文件访问设置
|
||
if (!settings.allow_file_access) {
|
||
notify_security_violation(process_id, "FileAccess");
|
||
return false;
|
||
}
|
||
|
||
// 检查允许的路径
|
||
for (const auto& allowed_path : settings.allowed_paths) {
|
||
if (path.find(allowed_path) == 0) {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
// 检查禁止的路径
|
||
for (const auto& denied_path : settings.denied_paths) {
|
||
if (path.find(denied_path) == 0) {
|
||
notify_security_violation(process_id, "PathAccess:" + denied_path);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 如果允许列表不为空,但路径不在允许列表中,则拒绝访问
|
||
if (!settings.allowed_paths.empty()) {
|
||
notify_security_violation(process_id, "PathNotAllowed:" + path);
|
||
return false;
|
||
}
|
||
|
||
// 默认允许访问
|
||
return true;
|
||
}
|
||
|
||
bool is_network_accessible(ProcessId process_id) const override {
|
||
auto* process_info = find_process_info(process_id);
|
||
if (!process_info) {
|
||
return false;
|
||
}
|
||
|
||
// 获取安全设置
|
||
auto it = security_settings_.find(process_id);
|
||
if (it == security_settings_.end()) {
|
||
// 如果没有特定设置,默认不允许访问
|
||
return false;
|
||
}
|
||
|
||
const SecuritySettings& settings = it->second;
|
||
|
||
// 全局网络访问设置
|
||
if (!settings.allow_network_access) {
|
||
notify_security_violation(process_id, "NetworkAccess");
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
common::ErrorCode execute_platform_specific_operation(
|
||
const std::string& operation_name,
|
||
const std::vector<std::string>& parameters,
|
||
std::string& result) override {
|
||
// 检查是否是安全敏感操作
|
||
if (operation_name == "AccessRegistry" ||
|
||
operation_name == "ModifySystemFiles" ||
|
||
operation_name == "AccessDevices") {
|
||
|
||
// 获取当前进程ID(假设是从调用上下文中获取的)
|
||
ProcessId current_pid = current_operation_pid_;
|
||
auto* process_info = find_process_info(current_pid);
|
||
|
||
if (process_info) {
|
||
auto it = security_settings_.find(current_pid);
|
||
if (it != security_settings_.end()) {
|
||
const SecuritySettings& settings = it->second;
|
||
|
||
// 检查是否允许系统操作
|
||
if (!settings.allow_system_operations) {
|
||
notify_security_violation(current_pid, "SystemOperation:" + operation_name);
|
||
return common::ErrorCode::SecurityViolation;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 默认实现
|
||
result = "操作执行成功";
|
||
return common::ErrorCode::Success;
|
||
}
|
||
|
||
// 添加测试辅助方法
|
||
const SecuritySettings& get_security_settings(ProcessId process_id) const {
|
||
static SecuritySettings empty_settings;
|
||
|
||
auto it = security_settings_.find(process_id);
|
||
if (it != security_settings_.end()) {
|
||
return it->second;
|
||
}
|
||
|
||
return empty_settings;
|
||
}
|
||
|
||
void set_current_operation_pid(ProcessId pid) {
|
||
current_operation_pid_ = pid;
|
||
}
|
||
|
||
// 获取安全统计信息
|
||
size_t get_security_violations_count() const {
|
||
return stats_.total_security_violations.load();
|
||
}
|
||
|
||
private:
|
||
std::atomic<ProcessId> next_pid_{1000};
|
||
mutable std::map<ProcessId, SecuritySettings> security_settings_;
|
||
ProcessId current_operation_pid_ = 0; // 当前操作的进程ID
|
||
};
|
||
|
||
// 沙盒安全测试固定装置
|
||
class SandboxSecurityTest : public test::PluginSandboxTest {
|
||
protected:
|
||
void SetUp() override {
|
||
test::PluginSandboxTest::SetUp();
|
||
|
||
// 创建沙盒
|
||
sandbox_ = std::make_unique<SecurityTestingSandbox>();
|
||
|
||
// 创建事件回调
|
||
callback_ = std::make_shared<::testing::NiceMock<MockSandboxEventCallback>>();
|
||
|
||
// 初始化沙盒
|
||
SandboxConfig config;
|
||
config.sandbox_type = SandboxType::ProcessLevelIsolation;
|
||
config.enable_security_monitoring = true;
|
||
|
||
ASSERT_EQ(sandbox_->initialize(config), common::ErrorCode::Success);
|
||
|
||
// 设置事件回调
|
||
sandbox_->set_event_callback(callback_);
|
||
}
|
||
|
||
void TearDown() override {
|
||
if (sandbox_->is_initialized()) {
|
||
sandbox_->shutdown();
|
||
}
|
||
|
||
sandbox_.reset();
|
||
callback_.reset();
|
||
|
||
test::PluginSandboxTest::TearDown();
|
||
}
|
||
|
||
// 创建默认安全设置
|
||
SecuritySettings create_default_settings() {
|
||
SecuritySettings settings;
|
||
settings.allow_file_access = true;
|
||
settings.allow_network_access = true;
|
||
settings.allow_system_operations = false;
|
||
settings.allow_registry_access = false;
|
||
settings.allow_process_creation = false;
|
||
settings.allow_device_access = false;
|
||
settings.allowed_paths = {"/app", "./data"};
|
||
settings.denied_paths = {"/system", "./config"};
|
||
return settings;
|
||
}
|
||
|
||
protected:
|
||
std::unique_ptr<SecurityTestingSandbox> sandbox_;
|
||
std::shared_ptr<MockSandboxEventCallback> callback_;
|
||
};
|
||
|
||
// 测试应用安全设置
|
||
TEST_F(SandboxSecurityTest, ApplySecuritySettings) {
|
||
// 启动进程
|
||
ProcessId pid = 0;
|
||
ASSERT_EQ(sandbox_->start_process("test.exe", {}, pid), common::ErrorCode::Success);
|
||
|
||
// 创建安全设置
|
||
SecuritySettings settings = create_default_settings();
|
||
|
||
// 应用安全设置
|
||
ASSERT_EQ(sandbox_->apply_security_settings(pid, settings), common::ErrorCode::Success);
|
||
|
||
// 验证安全设置
|
||
const SecuritySettings& applied_settings = sandbox_->get_security_settings(pid);
|
||
EXPECT_EQ(applied_settings.allow_file_access, settings.allow_file_access);
|
||
EXPECT_EQ(applied_settings.allow_network_access, settings.allow_network_access);
|
||
EXPECT_EQ(applied_settings.allow_system_operations, settings.allow_system_operations);
|
||
EXPECT_EQ(applied_settings.allowed_paths, settings.allowed_paths);
|
||
EXPECT_EQ(applied_settings.denied_paths, settings.denied_paths);
|
||
|
||
// 测试无效的进程ID
|
||
EXPECT_NE(sandbox_->apply_security_settings(999999, settings), common::ErrorCode::Success);
|
||
}
|
||
|
||
// 测试文件访问控制
|
||
TEST_F(SandboxSecurityTest, FileAccessControl) {
|
||
// 启动进程
|
||
ProcessId pid = 0;
|
||
ASSERT_EQ(sandbox_->start_process("test.exe", {}, pid), common::ErrorCode::Success);
|
||
|
||
// 创建安全设置
|
||
SecuritySettings settings = create_default_settings();
|
||
settings.allow_file_access = true;
|
||
settings.allowed_paths = {"/app", "./data"};
|
||
settings.denied_paths = {"/system", "./config"};
|
||
|
||
// 应用安全设置
|
||
ASSERT_EQ(sandbox_->apply_security_settings(pid, settings), common::ErrorCode::Success);
|
||
|
||
// 测试允许的路径
|
||
EXPECT_TRUE(sandbox_->is_path_accessible(pid, "/app/resources"));
|
||
EXPECT_TRUE(sandbox_->is_path_accessible(pid, "./data/user"));
|
||
|
||
// 设置安全事件调用期望
|
||
EXPECT_CALL(*callback_, on_security_violation(pid, ::testing::_))
|
||
.Times(2);
|
||
|
||
// 测试禁止的路径
|
||
EXPECT_FALSE(sandbox_->is_path_accessible(pid, "/system/bin"));
|
||
EXPECT_FALSE(sandbox_->is_path_accessible(pid, "./config/secrets"));
|
||
|
||
// 测试未指定的路径
|
||
EXPECT_TRUE(sandbox_->is_path_accessible(pid, "/tmp/cache"));
|
||
|
||
// 测试完全禁止文件访问
|
||
SecuritySettings no_file_access = settings;
|
||
no_file_access.allow_file_access = false;
|
||
|
||
ASSERT_EQ(sandbox_->apply_security_settings(pid, no_file_access), common::ErrorCode::Success);
|
||
|
||
// 设置安全事件调用期望
|
||
EXPECT_CALL(*callback_, on_security_violation(pid, "FileAccess"))
|
||
.Times(1);
|
||
|
||
// 即使是允许的路径,现在也应该被拒绝
|
||
EXPECT_FALSE(sandbox_->is_path_accessible(pid, "/app/resources"));
|
||
}
|
||
|
||
// 测试网络访问控制
|
||
TEST_F(SandboxSecurityTest, NetworkAccessControl) {
|
||
// 启动进程
|
||
ProcessId pid = 0;
|
||
ASSERT_EQ(sandbox_->start_process("test.exe", {}, pid), common::ErrorCode::Success);
|
||
|
||
// 创建安全设置,默认允许网络访问
|
||
SecuritySettings settings = create_default_settings();
|
||
settings.allow_network_access = true;
|
||
|
||
// 应用安全设置
|
||
ASSERT_EQ(sandbox_->apply_security_settings(pid, settings), common::ErrorCode::Success);
|
||
|
||
// 测试网络访问
|
||
EXPECT_TRUE(sandbox_->is_network_accessible(pid));
|
||
|
||
// 禁用网络访问
|
||
settings.allow_network_access = false;
|
||
ASSERT_EQ(sandbox_->apply_security_settings(pid, settings), common::ErrorCode::Success);
|
||
|
||
// 设置安全事件调用期望
|
||
EXPECT_CALL(*callback_, on_security_violation(pid, "NetworkAccess"))
|
||
.Times(1);
|
||
|
||
// 测试网络访问被拒绝
|
||
EXPECT_FALSE(sandbox_->is_network_accessible(pid));
|
||
}
|
||
|
||
// 测试系统操作访问控制
|
||
TEST_F(SandboxSecurityTest, SystemOperationsControl) {
|
||
// 启动进程
|
||
ProcessId pid = 0;
|
||
ASSERT_EQ(sandbox_->start_process("test.exe", {}, pid), common::ErrorCode::Success);
|
||
|
||
// 创建安全设置,默认禁止系统操作
|
||
SecuritySettings settings = create_default_settings();
|
||
settings.allow_system_operations = false;
|
||
|
||
// 应用安全设置
|
||
ASSERT_EQ(sandbox_->apply_security_settings(pid, settings), common::ErrorCode::Success);
|
||
|
||
// 设置当前操作进程ID
|
||
sandbox_->set_current_operation_pid(pid);
|
||
|
||
// 设置安全事件调用期望
|
||
EXPECT_CALL(*callback_, on_security_violation(pid, ::testing::StartsWith("SystemOperation:")))
|
||
.Times(1);
|
||
|
||
// 尝试执行系统操作
|
||
std::string result;
|
||
auto err = sandbox_->execute_platform_specific_operation("AccessRegistry", {}, result);
|
||
|
||
// 应该被拒绝
|
||
EXPECT_EQ(err, common::ErrorCode::SecurityViolation);
|
||
|
||
// 允许系统操作
|
||
settings.allow_system_operations = true;
|
||
ASSERT_EQ(sandbox_->apply_security_settings(pid, settings), common::ErrorCode::Success);
|
||
|
||
// 再次尝试执行系统操作
|
||
err = sandbox_->execute_platform_specific_operation("AccessRegistry", {}, result);
|
||
|
||
// 现在应该成功
|
||
EXPECT_EQ(err, common::ErrorCode::Success);
|
||
EXPECT_FALSE(result.empty());
|
||
}
|
||
|
||
// 测试安全违规计数
|
||
TEST_F(SandboxSecurityTest, SecurityViolationCounting) {
|
||
// 启动进程
|
||
ProcessId pid = 0;
|
||
ASSERT_EQ(sandbox_->start_process("test.exe", {}, pid), common::ErrorCode::Success);
|
||
|
||
// 创建安全设置
|
||
SecuritySettings settings = create_default_settings();
|
||
settings.allow_file_access = true;
|
||
settings.allow_network_access = false;
|
||
settings.allow_system_operations = false;
|
||
settings.allowed_paths = {"/app"};
|
||
settings.denied_paths = {"/system"};
|
||
|
||
// 应用安全设置
|
||
ASSERT_EQ(sandbox_->apply_security_settings(pid, settings), common::ErrorCode::Success);
|
||
|
||
// 初始违规计数应为0
|
||
EXPECT_EQ(sandbox_->get_security_violations_count(), 0);
|
||
|
||
// 触发网络访问违规
|
||
sandbox_->is_network_accessible(pid);
|
||
|
||
// 违规计数应增加
|
||
EXPECT_EQ(sandbox_->get_security_violations_count(), 1);
|
||
|
||
// 触发文件访问违规
|
||
sandbox_->is_path_accessible(pid, "/system/bin");
|
||
|
||
// 违规计数应再次增加
|
||
EXPECT_EQ(sandbox_->get_security_violations_count(), 2);
|
||
|
||
// 设置当前操作进程ID
|
||
sandbox_->set_current_operation_pid(pid);
|
||
|
||
// 触发系统操作违规
|
||
std::string result;
|
||
sandbox_->execute_platform_specific_operation("AccessRegistry", {}, result);
|
||
|
||
// 违规计数应再次增加
|
||
EXPECT_EQ(sandbox_->get_security_violations_count(), 3);
|
||
}
|
||
|
||
// 测试多进程安全设置
|
||
TEST_F(SandboxSecurityTest, MultiProcessSecuritySettings) {
|
||
// 启动多个进程
|
||
ProcessId pid1 = 0, pid2 = 0;
|
||
ASSERT_EQ(sandbox_->start_process("process1.exe", {}, pid1), common::ErrorCode::Success);
|
||
ASSERT_EQ(sandbox_->start_process("process2.exe", {}, pid2), common::ErrorCode::Success);
|
||
|
||
// 创建不同的安全设置
|
||
SecuritySettings settings1 = create_default_settings();
|
||
settings1.allow_file_access = true;
|
||
settings1.allow_network_access = false;
|
||
|
||
SecuritySettings settings2 = create_default_settings();
|
||
settings2.allow_file_access = false;
|
||
settings2.allow_network_access = true;
|
||
|
||
// 应用安全设置
|
||
ASSERT_EQ(sandbox_->apply_security_settings(pid1, settings1), common::ErrorCode::Success);
|
||
ASSERT_EQ(sandbox_->apply_security_settings(pid2, settings2), common::ErrorCode::Success);
|
||
|
||
// 测试文件访问
|
||
EXPECT_TRUE(sandbox_->is_path_accessible(pid1, "/app/resources"));
|
||
EXPECT_FALSE(sandbox_->is_path_accessible(pid2, "/app/resources"));
|
||
|
||
// 测试网络访问
|
||
EXPECT_FALSE(sandbox_->is_network_accessible(pid1));
|
||
EXPECT_TRUE(sandbox_->is_network_accessible(pid2));
|
||
}
|
||
|
||
// 测试安全设置更新
|
||
TEST_F(SandboxSecurityTest, UpdateSecuritySettings) {
|
||
// 启动进程
|
||
ProcessId pid = 0;
|
||
ASSERT_EQ(sandbox_->start_process("test.exe", {}, pid), common::ErrorCode::Success);
|
||
|
||
// 创建初始安全设置
|
||
SecuritySettings settings = create_default_settings();
|
||
settings.allow_file_access = true;
|
||
settings.allow_network_access = true;
|
||
|
||
// 应用安全设置
|
||
ASSERT_EQ(sandbox_->apply_security_settings(pid, settings), common::ErrorCode::Success);
|
||
|
||
// 测试初始设置
|
||
EXPECT_TRUE(sandbox_->is_path_accessible(pid, "/app/resources"));
|
||
EXPECT_TRUE(sandbox_->is_network_accessible(pid));
|
||
|
||
// 更新安全设置
|
||
settings.allow_file_access = false;
|
||
settings.allow_network_access = false;
|
||
|
||
ASSERT_EQ(sandbox_->apply_security_settings(pid, settings), common::ErrorCode::Success);
|
||
|
||
// 设置安全事件调用期望
|
||
EXPECT_CALL(*callback_, on_security_violation(pid, ::testing::_))
|
||
.Times(2);
|
||
|
||
// 测试更新后的设置
|
||
EXPECT_FALSE(sandbox_->is_path_accessible(pid, "/app/resources"));
|
||
EXPECT_FALSE(sandbox_->is_network_accessible(pid));
|
||
}
|
||
|
||
int main(int argc, char** argv) {
|
||
::testing::InitGoogleTest(&argc, argv);
|
||
return RUN_ALL_TESTS();
|
||
} |