使用Rust构建Azure IoT Edge安全守护进程
Azure IoT Edge是微软Azure IoT团队开发的开源跨平台软件项目,旨在解决从云到本地网络边缘的计算分发管理问题。本文阐述了选择Rust作为产品中安全守护进程组件实现编程语言的技术依据。
安全守护进程的技术栈选择
安全守护进程(内部称为edgelet)启动Azure IoT Edge运行时,作为运行时与多个主机服务(如容器运行时和基于硬件的加密设备HSM/TPM)之间的通信代理。
在启动edgelet开发时,我们确定了以下核心设计目标:
- 需为原生组件,无需.NET CLR等运行时环境
- 作为访问设备HSM/TPM硬件的通道,必须具备高安全性
- 需通过C应用二进制接口(ABI)与HSM/TPM硬件通信,要求能直接加载共享对象/DLL并调用C函数
这些目标意味着必须选择编译为原生代码的语言如C、C++或Rust。为避免垃圾收集器的运行时开销,Go不是理想选择。而守护进程的安全相关要求使我们希望避免处理内存和并发错误。最终,Rust完全符合这些约束条件。
实践效果
在Azure IoT Edge正式发布前,我们聘请外部安全供应商进行渗透测试。Rust代码库零安全问题的发现验证了我们的语言选择。从项目开始我们就要求编译器将所有警告(包括clippy的lint检查)视为错误。持续集成系统会拒绝未通过rustfmt格式检查的拉取请求,确保代码库格式一致。
Rust编译器更新过程和cargo工具链在Azure IoT Edge中表现良好,升级到新编译器版本几乎总是无缝进行。
Rust的团队采用
与其他流行语言相比,Rust的学习曲线较陡峭。我们团队已有精通C、C++、C#和Java的开发者,幸运的是还有几位对Rust充满热情的成员!我们组织了实践研讨会,帮助团队掌握语言中较难直观理解的部分。
投资培训时间被证明非常有效。4-6周内,团队几乎所有成员都对Rust代码库做出了实质性贡献。
技术挑战
虽然整体体验令人满意,但我们面临一些挑战:
- Rust生态相对较新,经常需要自行构建基础设施组件
- 解析编译器错误消息在处理大量使用Tokio Futures或std::iter::Iterator组合器的代码时偶尔困难
- 习惯C#和Java优秀工具支持的团队认为Rust编辑/调试体验稍逊色,VS Code Rust RLS扩展在实践中不够稳定
- 构建复杂Tokio Future组合器链时产生的复杂类型推理有时很棘手
未来展望
Azure IoT已全面接纳Rust编程语言。自Azure IoT Edge发布后,Rust的使用范围进一步扩大。多个正在积极开发的云服务项目都采用Rust编写。Rust提供的内存安全、数据竞争安全和性能三重优势非常适合Azure IoT的需求。
Raj Vengalil, IoT平台首席软件工程经理