Cloudflare operates one of the world’s largest networks, providing network and cloud services to improve website and application security and performance. A critical security aspect of building applications and solutions integrating with Cloudflare involves the management of sensitive data, commonly known as secrets. Cloudflare has a secure mechanism for handling secrets, offering tools for storing, accessing, and managing confidential information in the cloud.
What is a Cloudflare secret?
Cloudflare secrets are sensitive information stored as encrypted environment variables for Cloudflare Workers (execution environments for serverless applications). Secrets include but are not limited to database credentials, API keys, and other confidential data. There is no need to hard-code sensitive information in plain text.
Key features
- Secure and encrypted storage: Secrets in Cloudflare are encrypted during transit and at rest, ensuring high security.
- Native application integration: Cloudflare secrets integrate directly with Cloudflare Workers, eliminating the need for complex setup. This built-in solution provides automatic retrieval and management of credentials.
- Environment variable flexibility: Cloudflare secrets are easily referenced as environment variables across Workers.
Creating Cloudflare secrets via the CLI
You can create secrets via Wrangler, the Cloudflare Workers CLI.
Prerequisites
Install Wrangler
Sign up for a free Cloudflare account
Create a new project and navigate to its directory:
$ npx wrangler init secrets-demo # Select "Hello World" Worker # Confirm "Yes" to using Typescript # Confirm "Yes" to using Git # Select "No" to deploy the application $ cd secrets-demoLogin to your Cloudflare account and authorize Wrangler:
$ npx wrangler login # Confirm authorization to Wrangler
Create a secret
You can create a secret by running the command:
$ npx wrangler secret put MY_SECRET_NAME_KEY
Next, you will be prompted to input the secret’s value, type:
⛅️ wrangler 3.19.0
-------------------
? Enter a secret value: › dragons and unicorns are real
Press Enter to save the secret. You’ll see output similar to the following:
✔ Enter a secret value: … *****************************
🌀 Creating the secret for the Worker "secrets-demo"
✨ Success! Uploaded secret MY_SECRET_NAME_KEY
Verify the secret was created:
$ npx wrangler secret list
[
{
"name": "MY_SECRET_NAME_KEY",
"type": "secret_text"
}
]
Accessing the secret from a Cloudflare Worker
Now that you have created a secret, your application can access it by referencing it in the Worker code.
For example, in TypeScript you might use code that looks something like this to retrieve and return the value of the Cloudflare secret:
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
return new Response(`Secret: ${env.MY_SECRET_NAME_KEY}`);
},
};
Deploy the changes.
$ npx wrangler deploy
⛅️ wrangler 3.19.0
-------------------
Total Upload: 0.21 KiB / gzip: 0.18 KiB
Uploaded secrets-demo (0.92 sec)
Published secrets-demo (3.61 sec)
https://secrets-demo.diana-247.workers.dev
Current Deployment ID: e7c2b8e7-e13a-4a11-9667-024eed3cce05
Here’s an example of using curl against a Cloudflare Worker serverless application using the code above to retrieve and return a Cloudflare secret value:
$ curl https://secrets-demo.diana-247.workers.dev
Secret: dragons and unicorns are real
Best practices
- Rotate secrets regularly: Implement a routine for periodically rotating secrets to enhance security.
- Provide least-privilege access: Employ policies for granular access control to secrets.
- Audit and monitor secret access: Use monitoring tools to track access and modifications to your secrets.
Challenges and considerations
Using Cloudflare secrets comes with particular challenges and considerations:
- Management of secrets overhead: As the number of secrets and contexts grows, managing them can become challenging. Teams must actively track and monitor the usage of secrets, identifying where and by whom they are employed.
- Access control complexity: Setting up fine-grained access controls is crucial but can become complex as teams and projects scale. Defining and maintaining access permissions for different roles and responsibilities can be challenging. Clearly define roles and duties to determine who needs access to specific secrets. Use role-based access control (RBAC) principles to simplify and organize permissions.
- Integration with external secret management systems: Organizations may already have established processes for secrets management using external tools, and integrating these with Cloudflare secrets can be complex. Evaluate whether integrating with an external secrets management system is necessary for your organization. If required, explore solutions that integrate with Cloudflare and provide a unified approach to secrets management. Ensure that the chosen solution aligns with your security and compliance requirements. Two popular secret management systems include AWS Secrets Manager and Google Cloud Secret Manager.
Addressing these challenges and considerations requires a thoughtful approach to secrets management, clear communication within the development team, and a commitment to maintaining security best practices. A beta product to facilitate secrets management and tackle the above challenges is available for Cloudflare as the Cloudflare Secrets Store.
Conclusion
The thing to notice about Cloudflare secrets is that their convenience is also their boundary: they are encrypted environment variables scoped to a Worker, which makes them convenient but ties each secret to a single execution context. The hard part of secrets management isn’t storing one value safely, it’s governing many of them across Workers, teams, and other clouds without losing track of who can read what. If you’re integrating Cloudflare into a larger estate, treat the Worker secret as one storage backend among others and decide early how rotation, access control, and external secret stores fit together, rather than retrofitting that structure once the number of secrets has already grown.
To manage Cloudflare secrets alongside the rest of your infrastructure as code, see the Cloudflare Provider documentation. Below are examples of how to create a Cloudflare secret in the supported programming languages:
$ pulumi config set secrets-demo --secret
value: ****
import * as pulumi from "@pulumi/pulumi";
import * as cloudflare from "@pulumi/cloudflare";
import * as fs from "fs";
const config = new pulumi.Config();
const accountId = config.require("accountId");
const secret = config.require("secrets-demo"); // mark as required
const myScript = new cloudflare.WorkerScript("myScript", {
accountId: accountId,
name: "script_1",
content: fs.readFileSync("script.js", "utf8"),
secretTextBindings: [{
name: "MY_SECRET_NAME_KEY", // secret key
text: secret, // secret value
}],
});
"""A Python Pulumi program"""
import pulumi
import pulumi_cloudflare as cloudflare
config = pulumi.Config()
account_id = config.require("accountId")
secret = config.require("secrets-demo")
# Sets the script with the name "script_1"
my_script = cloudflare.WorkerScript("myScript",
account_id=account_id,
name="script_1",
content=(lambda path: open(path).read())("script.js"),
secret_text_bindings=[cloudflare.WorkerScriptSecretTextBindingArgs(
name="MY_SECRET_NAME_KEY",
text=secret,
)],
)
package main
import (
"os"
"github.com/pulumi/pulumi-cloudflare/sdk/v5/go/cloudflare"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
)
func readFileOrPanic(path string) pulumi.StringInput {
data, err := os.ReadFile(path)
if err != nil {
panic(err.Error())
}
return pulumi.String(string(data))
}
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
conf := config.New(ctx, "")
accountId := conf.Require("accountId")
secret := conf.Require("secrets-demo")
_, err := cloudflare.NewWorkerScript(ctx, "myScript", &cloudflare.WorkerScriptArgs{
AccountId: pulumi.String(accountId),
Name: pulumi.String("script_1"),
Content: readFileOrPanic("script.js"),
SecretTextBindings: cloudflare.WorkerScriptSecretTextBindingArray{
&cloudflare.WorkerScriptSecretTextBindingArgs{
Name: pulumi.String("MY_SECRET_NAME_KEY"),
Text: pulumi.String(secret),
},
},
})
if err != nil {
return err
}
return nil
})
}
- Get started tutorial: Follow a simple tutorial to deploy a Hello World web application using Cloudflare Workers and Pulumi
- Advanced secrets management: For organizations that use more than one secrets manager or store configuration data in multiple locations, Pulumi ESC (Environments, Secrets, and Configuration) offers a centralized solution for managing secrets and configurations across various environments. Moreover, Pulumi ESC integrates with OIDC to allow the dynamic generation of credentials, elevating its utility in scenarios where secrets need to be frequently rotated or updated. Dive deeper into how Pulumi ESC can streamline your secrets management workflows by visiting the Pulumi ESC documentation for the AWS Secrets provider.
The Pulumi community on Slack is open for questions and discussion.
Get started today
Get started today
Pulumi is open source and free to get started. Deploy your first stack today.
Get started