The Azure IoT Edge open source, cross-platform software project from Microsoft’s Azure IT team aims to address the issue of managing compute distribution from the cloud to the edge of your on-premise network. The selection of Rust as the product’s implementation programming language for the Security Daemon component is explained in some detail in this post.
The Azure IoT Edge runtime is bootstrapped by the Security Daemon. It serves as a middleman between the container runtime, hardware-based cryptography devices Hardware Security Modules ( HSM), and Trusted Platform Moduli ( TPM) and the Azure IoT Edge host service.
selecting the Security Daemon’s tech stack
We identified the following broad design objectives when we first began working on the Security Daemon ( also known as the edgelet ):
- The edgelet must be a native component that can run independently of the.NETCLR.
- The edgelet must be secure because it will act as the device’s channel for accessing the HSM/TPM hardware.
- A C Application Binary Interface ( ABI ) will be used by the edgelet to communicate with HSM/TPM hardware, making it simple to call C functions and load shared objects/DLLs.
Due to these design objectives, we were forced to choose a programming language that could compile native code, such as C, C++, or Rust. Go was n’t a preferred choice because there was no need to pay for the runtime of the garbage collector. We wanted to stay away from memory and concurrency bugs because of the daemon’s security-related requirements. In the end, given these limitations, Rust perfectly suited the bill for us. Many of the advantages we discovered when deciding Rust was the programming language of choice are captured in this earlier post on this blog.
What was successful
We hired an outside security vendor to test the software’s penetration before releasing Azure IoT Edge for general availability. To us, the fact that they found no security flaws in the Rust portion of the codebase supported our decision to use it. We made the decision to treat all warnings as errors, including lints that clippy checked for, right away. In order to ensure consistent code formatting throughout the codebase, our continuous integration system would reject pull requests that failed a test run.
For Azure IoT Edge, the cargo tooling and the Rust compiler update process were successful. It is almost always painless to upgrade to a new compiler version.
adoption of rust
The language needed to be intensified as a next step. We were concerned about how this ramp-up would affect project timelines because Rust has a relatively steep learning curve compared to other well-known programming languages. Developers who were proficient in C, C++, PHP, and Java were already on our team. Fortunately, we also had a few passionate Rust developers on our team! We developed hands-on Rust workshops where we guided the team through the language’s concepts that, in our experience, have been challenging to understand. This investment turned out to be very beneficial. We found that ultimately, learning the language was n’t as difficult as we had thought.
In just 4 to 6 weeks, we discovered that almost every team member had contributed significantly to the Rust section of the codebase.
Challenges
Although shipping some of Microsoft’s first-ever production Rust code has been enjoyable overall, there have been a few difficulties:
- Compared to some of the other, more well-established languages, the Rust ecosystem is still relatively new. As a result, we frequently had to construct infrastructure that we probably would n’t have otherwise needed.
- Parsing compiler error messages would occasionally prove to be difficult especially when dealing with code that made heavy use of combinators from Tokio Futures or
std::iter::Iterator
. - The Rust editing and debugging experience was a little lacking for teams used to excellent tooling support for C# and Java code editing. In actual use, the VS Code Rust RLS extension was infamously unstable.
- When creating intricate Tokio Future combinator chains, it can be challenging to reason about the complex types that are always built.
What comes next?
It would be accurate to say that the Rust programming language is fully compatible with Azure IoT at this point. Since we shipped Azure IoT Edge, Rust usage has only grown even more. Rust is being used to create a number of active cloud service projects. Azure IoT has a great fit for Rust’s trifecta of memory, data race, and performance. In the future, we hope to have more to say about this!
Raj Vengalil, IoT Platform’s principal SWE Manager