Secrets
Give functions API keys and passwords without putting them in code or showing them to the people who run them.
Secrets give functions API keys, passwords and tokens without putting them in code or showing them to the people who run them.
Declare what a function needs
List the environment variables in secrets, and read them inside the function:
import os
import stripe
from callables import deploy
@deploy(title="Refund a charge", secrets=["STRIPE_KEY"])
def refund(charge_id: str) -> str:
stripe.api_key = os.environ["STRIPE_KEY"]
stripe.Refund.create(charge=charge_id)
return f"Refunded {charge_id}."The code only names the secret. The value never appears in the repo.
Set the value
After you push, set the value in the web app. Values are stored encrypted and injected as environment variables each time the function runs. A function only receives the secrets it declares.
Each secret can be set at one of three levels:
| Level | Applies to |
|---|---|
| Team | Every function on the team |
| Project | Every function in one project |
| Function | One function |
When the same name is set at more than one level, the most specific wins: function, then project, then team. Builders set and change secrets. People who only run a function never see the values.
Missing secrets
A declared secret that nobody has set doesn't block the run. The variable is simply missing, and builders see a "missing secrets" warning on the project. For an optional secret, read it with os.environ.get("NAME") and handle it being missing.
Groups
A group can declare secrets once for every action in it:
from callables import Group
billing = Group("billing", title="Billing", secrets=["STRIPE_KEY"])Key files
Each secret is a single value. For a .pem file or a service account JSON, paste the file's contents as the secret, and have your code read it from the variable.
Locally
call local and call <function> read the same variables from your environment, so a .env file works well. Keep it in .gitignore.
Rules
- Never hard-code a key, even for testing.
- Never take a key as a form input.
- Read secrets inside the function, never at module level: modules are imported at build time, when secrets aren't set.
- Give each function the narrowest key that works, such as a restricted Stripe key.