Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Populating a static/const with an environment variable at runtime in Rust

I'm trying to load passwords and sensitive data from the system's environment when my service starts up. I've tried a number of different ways but can't seem to figure out the right way to do this in Rust.

const PASSWORD: String = var("PASSWORD").unwrap();

Doesn't work because method calls in constants are limited to constant inherent methods. The same applies to static (except the error says statics, obviously).

The other way I've seen to do it is

const PASSWORD: &'static str = env!("PASSWORD");

But the problem with that is it will be defined at compile time as env! is a macro (at least that is my understanding).

I also considered simply wrapping the call to var("...").unwrap() in a function but that solution doesn't really sit right with me, and would also allow the values to change throughout runtime AND not validate them when the service starts.

As you can tell I'm new to Rust. I'd really appreciate if in your answer you could not just explain how to load the const/static at runtime but also explain why what I'm doing is dumb and wrong :)

like image 426
dave Avatar asked May 24 '16 06:05

dave


1 Answers

const and static fill different roles in Rust.

const does not only mean a constant, it means a compile-time constant, a value determined at compile-time and inscribed in the read-only memory of the program. It is not suitable for your usecase.

static means a global variable, with a lifetime that will span the entire program. It may be mutable, in which case it must be Sync to avoid concurrent modifications. A static variable must be initialized from a constant, in order to be available from the start of the program.

So, how to read a variable at run-time and have it available? Well, a clean solution would be to avoid globals altogether...

... but since it can be convenient, there is a crate for it: lazy_static!.

use std::env::var;
use lazy_static::lazy_static;

lazy_static! {
    static ref PASSWORD: String = var("PASSWORD").unwrap();
}

fn main() {
    println!("{:?}", *PASSWORD);
}

On first access to the variable, the expression is executed to load its value, the value is then memoized and available until the end of the program.

like image 158
Matthieu M. Avatar answered Nov 07 '22 06:11

Matthieu M.