Secrets
In this tutorial you will learn how to use secrets in Toit projects.
Introduction
Many online services require a secret to be able to access them. For example, a database might require a password, or a service might require an API key. For open-source projects (and often for closed-source ones too) these secrets should not be stored in the source code.
In the remainder of this tutorial we will show a simple way of storing secrets in Toit projects without ending up storing them in the version control system.
Prerequisites
We assume that you have set up your development environment as described in the IDE tutorial.
We also assume that you are familiar with running Toit programs. If not, have a look at the Hello world tutorial.
Note that you can do this tutorial without a device. In that case,
you need to use the -d host
option whenever you invoke
jag run
. The program will then run on your computer instead of on
a device.
The project
We will assume an API key "123456" that we want to use in our program.
A simple program client.toit
that uses this API key could look like this:
To simplify things we simply "use" the API key by printing it.
Storing the secret for devices
A common way of passing secrets to programs is to use environment. However, when flashing a program to a device, the environment is not available.
Instead, we can store the secret in a separate file that isn't checked in.
A secrets file
The most straight-forward way of storing the secret is to create a file
called secrets.toit
with the following content:
The original client.toit
program can then be changed to the following:
import .secrets main: secret-api-key := API-KEY // Imported from secrets. print "Using the API-KEY now: $secret-api-key"
The secrets.toit
file should not be checked into version control.
One problem with this approach is that there isn't a good way to distinguish between secrets for different environments. For example, if we have a development environment and a production environment, we might want to use different secrets in the two environments.
The next section shows a way to solve this problem.
Using a separate entry file
Whereas the previous approach imported the secrets file directly, we can instead create a separate entry file that passes the secret to the main program.
Change the original program to the following:
Then create a file called client-production.toit
with the following content:
The main
function in client-production.toit
simply calls the main
function
in client.toit
with the API key as an argument. The client-production.toit
file
should not be checked into version control.
This approach makes it easy to have different secrets for different
environments. For example, we can create a client-dev.toit
file with
different secrets for the development environment.
Since there is now more boilerplate code, we should create a template
for the client-X.toit
files. For example, a client-template.toit
file
could look like this:
Whenever we want to create a new client-X.toit
file, we can simply
copy the client-template.toit
file and replace <API-KEY>
with the
actual API key.
At this point, we should add the client-template.toit
file to version
control, and then ignore the client-X.toit
files. This can
be done by adding the following line to the .gitignore
file:
Using the environment
When running a program on the desktop, we can use the environment to
pass secrets to the program. In that case we need the
host
package. Install it by running the following command:
See the package tutorial for more information.
The host
package provides the os
library which gives access to
the environment.
We can add a few more lines to the original client.toit
program to
use the environment:
import host.os main: api-key := os.env.get "API_KEY" if not api-key or api-key == "": print "Please set the API_KEY environment variable." return main api-key main api-key: print "Using the API-KEY now: $api-key"
Since we still have a main
function that takes an api-key
argument,
we can still use the client-production.toit
file to run the program
on a device. However, we can now also run the program on the desktop
by setting the API_KEY
environment variable.
Conclusion
In this tutorial we have seen how to use secrets in Toit projects. We have seen how to store secrets in a separate file, and how to use the environment to pass secrets to programs.