Connection-String Sources
JD.Efcpt.Build can resolve the build-time database connection string from a pluggable
source instead of a project-local file (appsettings.json/app.config) or an explicit
EfcptConnectionString value. This lets you keep real credentials out of source control and
out of MSBuild logs entirely, pulling them from an environment variable, Azure Key Vault, or
AWS Secrets Manager at build time.
Overview
Set EfcptConnectionStringSource to a source key to opt in:
<PropertyGroup>
<EfcptConnectionStringSource>env</EfcptConnectionStringSource>
</PropertyGroup>
| Source key | Package | Network-backed |
|---|---|---|
env |
Built into JD.Efcpt.Build (no extra install) |
No |
azure-keyvault |
JD.Efcpt.Build.ConnectionStrings.AzureKeyVault |
Yes |
aws-secrets |
JD.Efcpt.Build.ConnectionStrings.AwsSecretsManager |
Yes |
When EfcptConnectionStringSource is empty (the default), behavior is unchanged from
today: the existing EfcptConnectionString / EfcptAppSettings / EfcptAppConfig /
auto-discovered file / .sqlproj resolution chain runs exactly as documented in
Connection String Mode.
Fail-closed semantics
Selecting a source is an all-or-nothing switch. Once EfcptConnectionStringSource is set,
the build resolves the connection string from that source only - it never silently falls
back to a file or .sqlproj if the source fails. If the source can't produce a connection
string for any reason, the build fails with an actionable, JD-coded error (see
Error Codes below) instead of continuing with a stale or wrong connection
string.
This is deliberate: once you've opted into a secret store, a silent fallback to a local file would be a worse outcome than a loud failure - it could mean the build quietly used a developer's local database instead of the one your secret store actually points at.
Offline-gated
azure-keyvault and aws-secrets are network-backed. When offline mode is enabled
(EfcptOfflineMode=true or the EFCPT_OFFLINE environment variable - see
Offline / Air-Gapped Builds), both sources are blocked before any network
request is attempted - the build fails with JD0032 rather than hanging or intermittently
timing out. The env source is never network-backed and always works offline.
For air-gapped or secure builds, use the env source - pre-provision the connection
string into an environment variable ahead of time, and offline builds can still resolve it
without any network access.
The env source
Reads the connection string from an environment variable. Ships in the core package - no extra install needed.
<PropertyGroup>
<EfcptConnectionStringSource>env</EfcptConnectionStringSource>
<!-- Optional: defaults to EFCPT_CONNECTION_STRING -->
<EfcptConnectionStringEnvVar>MY_APP_CONNECTION_STRING</EfcptConnectionStringEnvVar>
</PropertyGroup>
set EFCPT_CONNECTION_STRING=Server=localhost;Database=MyDb;Integrated Security=True;
dotnet build
If the variable is unset or empty, the build fails with JD0031.
Azure Key Vault
dotnet add package JD.Efcpt.Build.ConnectionStrings.AzureKeyVault
<PropertyGroup>
<EfcptConnectionStringSource>azure-keyvault</EfcptConnectionStringSource>
<EfcptKeyVaultUri>https://my-vault.vault.azure.net/</EfcptKeyVaultUri>
<EfcptKeyVaultSecretName>MyAppConnectionString</EfcptKeyVaultSecretName>
<!-- Optional: pin a specific secret version -->
<EfcptKeyVaultSecretVersion></EfcptKeyVaultSecretVersion>
</PropertyGroup>
Authentication uses DefaultAzureCredential (the standard Azure SDK credential chain -
environment variables, managed identity, Visual Studio/Azure CLI login, etc.). No credentials
are configured through JD.Efcpt.Build properties; use whichever DefaultAzureCredential leg
fits your environment (a managed identity on a build agent, az login locally, etc.).
Least privilege: grant the build identity only the Get permission on secrets for the
specific vault (Key Vault RBAC role Key Vault Secrets User, or a legacy access policy with
only Get under Secret permissions). No List, Set, or Delete access is needed.
AWS Secrets Manager
dotnet add package JD.Efcpt.Build.ConnectionStrings.AwsSecretsManager
<PropertyGroup>
<EfcptConnectionStringSource>aws-secrets</EfcptConnectionStringSource>
<EfcptAwsSecretId>my-app/connection-string</EfcptAwsSecretId>
<EfcptAwsRegion>us-east-1</EfcptAwsRegion>
<!-- Optional: the secret value is a JSON object - extract this field as the connection string -->
<EfcptAwsSecretJsonKey>connectionString</EfcptAwsSecretJsonKey>
</PropertyGroup>
Authentication uses the AWS SDK's default credential provider chain (environment variables, shared credentials file, an EC2/ECS/Lambda IAM role, etc.). No credentials are configured through JD.Efcpt.Build properties.
Least privilege: grant the build identity only secretsmanager:GetSecretValue and
secretsmanager:BatchGetSecretValue, scoped to the specific secret's ARN:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:BatchGetSecretValue"
],
"Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:my-app/connection-string-??????"
}
]
}
Note: this satellite retrieves the secret via the AWS
BatchGetSecretValueAPI (current AWS SDK releases no longer expose a single-secretGetSecretValueclient method), so thesecretsmanager:BatchGetSecretValueaction is required.secretsmanager:GetSecretValueis listed alongside it for forward compatibility.
Property reference
| Property | Applies to | Description |
|---|---|---|
EfcptConnectionStringSource |
All | Source key: env, azure-keyvault, or aws-secrets. Empty = disabled (default). |
EfcptConnectionStringEnvVar |
env |
Environment variable name. Defaults to EFCPT_CONNECTION_STRING. |
EfcptKeyVaultUri |
azure-keyvault |
Required. The vault's URI. |
EfcptKeyVaultSecretName |
azure-keyvault |
Required. The secret's name. |
EfcptKeyVaultSecretVersion |
azure-keyvault |
Optional. Pins a specific secret version. |
EfcptAwsSecretId |
aws-secrets |
Required. The secret's name or ARN. |
EfcptAwsRegion |
aws-secrets |
Required. The AWS region containing the secret. |
EfcptAwsSecretJsonKey |
aws-secrets |
Optional. Extracts one field from a JSON secret value. |
EfcptConnectionStringSourceSearchPath (item) |
azure-keyvault, aws-secrets |
Additional directories to search for a satellite source assembly; populated automatically when you dotnet add package the satellite. |
Fail-closed + offline matrix
| Outcome | Error code | Meaning |
|---|---|---|
| Secret/variable not found | JD0031 |
The store was reached (or, for env, the variable was checked) but no value was present. |
| Source resolution failed | JD0030 |
The source threw an unexpected exception (auth failure, timeout, transient error, etc.). |
| Offline blocked | JD0032 |
A network-backed source (azure-keyvault, aws-secrets) was blocked by offline mode before any request was made. |
| Satellite not installed | JD0033 |
EfcptConnectionStringSource names a satellite key but the matching package isn't installed. |
| Misconfigured | JD0034 |
Required settings are missing or invalid (vault URI, secret name, region, secret id). |
See Error Codes for full details and resolution steps for each code.
Security notes
- The resolved connection string is always excluded from build profiling output
(
[ProfileOutput(Exclude = true)]), regardless of source. - When
DumpResolvedInputs=truewritesresolved-inputs.jsonfor debugging, a connection string that came from a pluggable source is written as(redacted: sourced from <key>)instead of its raw value. - No source ever logs the resolved connection string value itself, only diagnostic context (secret name, vault URI, region) needed to troubleshoot a failure.