You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/recipes/secret-provider.md
+186-13
Original file line number
Diff line number
Diff line change
@@ -23,9 +23,9 @@ Lucee 7 introduces built-in support for secrets management, allowing you to secu
23
23
24
24
In Lucee 7, secret providers can be configured similarly to datasources, caches, or AI connections, either in the Lucee Administrator (work in progress) or directly in `.CFConfig.json`. Here are sample configurations:
25
25
26
-
**Environment Variables Example:**
26
+
### Environment Variables Provider
27
27
28
-
Read the secret directly from the environment variables.
28
+
Read the secret directly from the environment variables:
29
29
30
30
```json
31
31
"secretProviders": {
@@ -38,9 +38,9 @@ Read the secret directly from the environment variables.
38
38
}
39
39
```
40
40
41
-
**File Example:**
41
+
### File Provider
42
42
43
-
Read the secrets from a file, format can be json or env.
43
+
Read the secrets from a file, format can be json or env:
44
44
45
45
```json
46
46
"secretProviders": {
@@ -55,9 +55,9 @@ Read the secrets from a file, format can be json or env.
55
55
}
56
56
```
57
57
58
-
**Combined Providers Example:**
58
+
### Combined Providers
59
59
60
-
The `AndSecretProvider` allows you to combine multiple providers, checking each one in the order specified until a secret is found.
60
+
The `AndSecretProvider` allows you to combine multiple providers, checking each one in the order specified until a secret is found:
61
61
62
62
```json
63
63
"secretProviders": {
@@ -70,18 +70,95 @@ The `AndSecretProvider` allows you to combine multiple providers, checking each
70
70
}
71
71
```
72
72
73
+
### Using External Classes
74
+
75
+
Similar to other Lucee features, you can specify external classes for your secret providers using various methods:
This allows you to specify one or more comma-separated Maven dependencies in gradle-style format.
111
+
112
+
#### CFML Components (Lucee 7+)
113
+
114
+
You can implement your own secret provider as a CFML component:
115
+
116
+
```json
117
+
"secretProviders": {
118
+
"myCustom": {
119
+
"component": "path.to.MySecretProviderComponent",
120
+
"custom": {
121
+
"configParam1": "value1"
122
+
}
123
+
}
124
+
}
125
+
```
126
+
127
+
The component must implement `lucee.runtime.secrets.SecretProvider` via `implementsJava="lucee.runtime.secrets.SecretProvider"` annotation.
128
+
73
129
## Supported Providers
74
130
75
131
Lucee includes several built-in secret providers:
76
132
77
-
-**EnvVarSecretProvider**: Reads secrets from environment variables
78
-
-**FileSecretProvider**: Reads secrets from a .json or .env file (more formats following)
79
-
-**AndSecretProvider**: Combines multiple providers into one
133
+
-**lucee.runtime.secrets.EnvVarSecretProvider**: Reads secrets from environment variables
134
+
-**lucee.runtime.security.FileSecretProvider**: Reads secrets from a .json or .env file (more formats following)
135
+
-**lucee.runtime.security.AndSecretProvider**: Combines multiple providers into one
80
136
-**AWSSecretsManagerProvider**: Connects to AWS Secrets Manager (coming soon)
81
137
-**GoogleSecretManagerProvider**: Uses Google Cloud Secret Manager (coming soon)
82
138
-**DockerSecretsProvider**: Reads secrets from Docker secrets (coming soon)
83
139
84
-
Each provider has specific configuration options as seen above.
140
+
## Provider Configuration Options
141
+
142
+
### EnvVarSecretProvider
143
+
144
+
| Option | Description | Default | Notes |
145
+
|--------|-------------|---------|-------|
146
+
|`caseSensitive`| Determines if environment variable names are case-sensitive |`true`| Set to `false` to allow case-insensitive lookups |
147
+
148
+
### FileSecretProvider
149
+
150
+
| Option | Description | Default | Notes |
151
+
|--------|-------------|---------|-------|
152
+
|`type`| File format |`env`| Supported values: `env`, `json`|
153
+
|`file`| Path to the secrets file | None (Required) | Can use any Lucee-supported resource path (local, S3, HTTP, etc.) |
154
+
|`caseSensitive`| Determines if secret keys are case-sensitive |`true`| Set to `false` to allow case-insensitive lookups |
155
+
|`refreshInterval`| How often to check for file changes (in milliseconds) |`60000` (1 minute) | Set to `0` to disable auto-refresh |
156
+
157
+
### AndSecretProvider
158
+
159
+
| Option | Description | Default | Notes |
160
+
|--------|-------------|---------|-------|
161
+
|`providers`| Comma-separated list of provider names to check | None (Required) | Providers are checked in the specified order |
85
162
86
163
## Using Secrets in Your Application
87
164
@@ -170,6 +247,70 @@ The `AndSecretProvider` allows you to chain multiple providers together, checkin
170
247
apiKey = GetSecret("API_KEY", "combined");
171
248
```
172
249
250
+
## Creating Custom Secret Providers
251
+
252
+
You can create your own secret provider by implementing the `lucee.runtime.secrets.SecretProvider` interface. This can be done either in Java (compiled into a JAR and loaded via OSGi or Maven) or directly in CFML.
// Initialize the provider with custom configuration
261
+
function init(struct config) {
262
+
variables.config = config;
263
+
return this;
264
+
}
265
+
266
+
// Get a secret by key
267
+
function getSecret(string key) {
268
+
// Implementation to retrieve the secret
269
+
// Return null if the secret doesn't exist
270
+
271
+
// Example implementation (database-stored secrets)
272
+
var q = queryExecute(
273
+
"SELECT value FROM app_secrets WHERE key = :key",
274
+
{key: key},
275
+
{datasource: config.datasource}
276
+
);
277
+
278
+
if (q.recordCount) {
279
+
return q.value;
280
+
}
281
+
282
+
return javaNull();
283
+
}
284
+
285
+
// Check if a secret exists
286
+
function hasSecret(string key) {
287
+
// Return true if the secret exists, false otherwise
288
+
289
+
// Example implementation
290
+
var q = queryExecute(
291
+
"SELECT COUNT(*) as count FROM app_secrets WHERE key = :key",
292
+
{key: key},
293
+
{datasource: config.datasource}
294
+
);
295
+
296
+
return q.count > 0;
297
+
}
298
+
}
299
+
```
300
+
301
+
To use this custom provider, configure it in your `.CFConfig.json`:
302
+
303
+
```json
304
+
"secretProviders": {
305
+
"database": {
306
+
"component": "path.to.MySecretProvider",
307
+
"custom": {
308
+
"datasource": "secretsDB"
309
+
}
310
+
}
311
+
}
312
+
```
313
+
173
314
## Security Considerations
174
315
175
316
### Secret Rotation
@@ -186,21 +327,23 @@ Each provider has its own security considerations. For example:
186
327
187
328
- AWS Secrets Manager requires proper IAM roles and permissions
188
329
- Environment variables should be set securely through the operating system
330
+
- File-based secrets need strict file permissions
189
331
190
332
## Troubleshooting
191
333
192
334
### Debugging
193
335
194
336
Lucee logs every use of every key to the `application` log with the log level `trace`, this includes the stacktrace, the key used and the name of the secret provider itself.
195
-
So when yu enable that log level you will see how and where you secrets get used (not set).
337
+
When you enable that log level, you will see how and where your secrets get used (not the values themselves).
196
338
197
-
In addition Lucee also logs in case it fails to load a secret provider.
339
+
In addition, Lucee also logs in case it fails to load a secret provider.
198
340
199
341
### Common Issues
200
342
201
343
1.**Secret not found**: Ensure the secret exists in the provider and that the key is correct.
202
344
2.**Provider configuration**: Verify that the provider is correctly configured and accessible.
203
345
3.**Permission issues**: Check that the application has the necessary permissions to access the secrets.
346
+
4.**Class not found**: When using external providers, ensure all required dependencies are available.
204
347
205
348
## Best Practices
206
349
@@ -209,6 +352,8 @@ In addition Lucee also logs in case it fails to load a secret provider.
209
352
3.**Implement least privilege**: Only grant access to the specific secrets an application needs.
210
353
4.**Monitor usage**: Regularly audit secret access and usage patterns.
211
354
5.**Layer providers**: Use the `AndSecretProvider` to implement fallback mechanisms.
355
+
6.**Environment segregation**: Use different secret providers for development, staging, and production environments.
356
+
7.**Regular rotation**: Rotate secrets regularly and verify that your application handles rotation gracefully.
212
357
213
358
## Reference
214
359
@@ -221,4 +366,32 @@ GetSecret(key [, name])
221
366
-**key**: Key to read from the Secret Provider
222
367
-**name**: (Optional) Name of the Secret Provider to read from. If not provided, all configured providers are checked in order.
223
368
224
-
Returns a reference to the secret value that is automatically resolved when used in a context requiring a simple value.
369
+
Returns a reference to the secret value that is automatically resolved when used in a context requiring a simple value.
370
+
371
+
### SecretProvider Interface
372
+
373
+
```java
374
+
packagelucee.runtime.secrets;
375
+
376
+
publicinterfaceSecretProvider {
377
+
/**
378
+
* Initialize the provider with the given configuration
0 commit comments