Sample code for loading secrets from the Akeyless Gateway at application startup and keeping resolved values in process memory only. You declare references (not plaintext secrets) using the akeyless:// URI scheme in configuration or environment variables; the library authenticates, calls the Gateway, and enriches configuration so application code can keep using one configuration surface.
- Discovery — At startup, the library finds every configuration value that looks like
akeyless:///path/to/item(plus optionalAKEYLESS_SECRET_NAMES). - Fetch — Either the local IIS Agent (
AKEYLESS_AGENT_URL, recommended for production) resolves paths over loopback HTTP, or each process calls the Gateway directly usingAKEYLESS_ACCESS_ID/AKEYLESS_ACCESS_KEY. - Enrich — Resolved values override the placeholders during startup. After that, application code uses configuration as usual (no branching on Akeyless vs file):
- .NET 8: an in-memory layer is added on top of
appsettings.json/ environment soIConfiguration,IOptions<T>, andbuilder.Configurationreturn the resolved string. - .NET Framework: resolved values are written onto
ConfigurationManagerwhere the platform allows (connection strings in-place; app settings via IISweb.configmetadata when available). Any key that cannot be patched in-place is still served through the same keys via a small in-memory overlay—useConfigurationManageror point your existing static helper atAppConfiguration(one delegation, no per-key Akeyless logic).
- .NET 8: an in-memory layer is added on top of
Logical keys for discovery match runtime lookup:
- appSettings key name (for example
MyApiKey), ConnectionStrings:{name}for connection strings,- environment variable name when the env value is an
akeyless://reference, - the secret path when using
AKEYLESS_SECRET_NAMESonly.
Paths are normalized with a leading / (for example akeyless:///prod/db/password → /prod/db/password).
The Akeyless.IIS.Agent project is a .NET 8 executable intended to run as a Windows Service on IIS servers. It:
- Listens only on loopback (default
http://127.0.0.1:17890; validated at startup). - Authenticates to the Akeyless Gateway and maintains an in-memory cache with TTL (
AkeylessAgent:CacheTtlSeconds). - Exposes
POST /api/v1/resolve(batch paths → values) andPOST /api/v1/discover-and-resolve(parse an allowlistedweb.configpath and resolve allakeyless://entries).
IIS application pools should set AKEYLESS_AGENT_URL to the agent base URL. They do not need AKEYLESS_ACCESS_ID / AKEYLESS_ACCESS_KEY when the agent is used.
Publish the agent, configure appsettings.json (or environment variables such as AkeylessAgent__AccessId), install as a service — see scripts/install-windows-service.example.md.
- With agent: IIS worker must reach loopback to the agent URL; the agent host must reach
AkeylessAgent:GatewayUrl. - Without agent: process must reach
AKEYLESS_GW_URLand exposeAKEYLESS_ACCESS_ID/AKEYLESS_ACCESS_KEY(for example on the app pool). - .NET Framework: 4.7.2 (or 4.6.1+) and NuGet package
akeyless2.20.1 (last line targetingnetstandard2.0for Framework). - .NET 8: current
akeylesspackage as referenced by the sample projects.
| Variable | Description |
|---|---|
AKEYLESS_AGENT_URL |
Recommended: base URL of the local agent (e.g. http://127.0.0.1:17890). When set, Gateway credentials are not required on the app pool. |
AKEYLESS_GW_URL |
Gateway base URL for direct mode (no agent). Default https://api.akeyless.io. |
AKEYLESS_ACCESS_ID |
Access ID (direct mode only, unless agent URL is unset). |
AKEYLESS_ACCESS_KEY |
Access Key (direct mode only). |
AKEYLESS_SECRET_NAMES |
Optional fallback: /path/one;/path/two when you are not using akeyless:// in config. Logical key equals the path. |
AKEYLESS_CACHE_TTL_SECONDS |
Optional (.NET Framework library only); if set to a positive number of seconds, periodically re-fetches secrets into the in-memory overlay (see AkeylessFrameworkBootstrapper). |
Reference the Akeyless.Bootstrap.Net472 project from your web application, or add the same package reference (akeyless 2.20.1) and copy the source files if you prefer a single project.
Store references, not secret values:
<configuration>
<appSettings>
<add key="MyApiKey" value="akeyless:///prod/myapp/api-key" />
</appSettings>
<connectionStrings>
<add name="DefaultConnection"
connectionString="akeyless:///prod/myapp/sql-connection-string"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>More patterns: examples/net472/web.config.snippet.xml.
In Global.asax.cs, enrich configuration once before the rest of your startup logic:
protected void Application_Start()
{
Akeyless.Bootstrap.AkeylessFrameworkBootstrapper.EnrichConfigurationAtStartup();
// Register routes, DI, etc.
}(LoadSecretsAtStartup() is an equivalent alias.)
See examples/net472/Global.asax.cs.example for a paste-friendly template.
After enrichment, use ConfigurationManager as you do today, or keep your existing static helper and delegate it to AppConfiguration (same method names; no Akeyless-specific branches in feature code):
// Typical — works for connection strings and many appSettings after enrichment:
string apiKey = ConfigurationManager.AppSettings["MyApiKey"];
string sql = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
// Or via AppConfiguration (recommended if you already centralize reads in a helper):
string apiKey2 = Akeyless.Bootstrap.AppConfiguration.GetAppSetting("MyApiKey");
string sql2 = Akeyless.Bootstrap.AppConfiguration.GetConnectionString("DefaultConnection");Point your static configuration helper at AppConfiguration.TryGet / Get once; callers stay unchanged.
After an IIS app pool recycle, Application_Start runs again and secrets are reloaded.
If you cannot put akeyless:// in XML, set AKEYLESS_SECRET_NAMES to a list of full paths. Keys in memory will match those paths (with a leading /).
Use akeyless:// in appsettings.json (or environment variables). Nested keys use : when reading:
{
"Secrets": {
"ApiKey": "akeyless:///prod/myapp/api-key"
},
"ConnectionStrings": {
"DefaultConnection": "akeyless:///prod/myapp/sql-connection-string"
}
}Example file: examples/net8/appsettings.akeyless.example.json.
Call AddAkeylessResolvedSecrets immediately after WebApplication.CreateBuilder. It reads the current configuration, resolves all akeyless:// values, and registers an in-memory configuration source last, so resolved values override placeholders for the rest of the host lifetime:
using Akeyless.WebApp.Net8;
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddAkeylessResolvedSecrets();
var app = builder.Build();Alternative (same enrichment, earlier in the pipeline):
builder.Host.ConfigureAppConfiguration((_, config) => config.AddAkeylessResolvedSecrets());Optional: pass an ILogger into the overload for structured diagnostics (counts only).
Use IConfiguration, IOptions<T>, or builder.Configuration as you already do—no injected secret service in application code:
app.MapGet("/example", (IConfiguration config) =>
{
var key = config["Secrets:ApiKey"];
return Results.Ok("ok"); // do not return the secret
});If there are no akeyless:// bindings, the Gateway is not called and startup continues unchanged.
TTL note: periodic refresh is implemented on the .NET Framework bootstrapper (AKEYLESS_CACHE_TTL_SECONDS). The .NET 8 enrichment path in this sample is one-shot at host build; add a hosted refresh if you need the same behavior on Core.
dotnet test Akeyless.DotNet.Samples.sln -c Releasetests/Akeyless.Integration.Tests (xUnit) covers:
- IIS Agent HTTP API (
/health,/api/v1/resolve,/api/v1/discover-and-resolve) usingWebApplicationFactorywith a fake gateway (no real Akeyless calls). Akeyless.Agent.ClientHTTP serialization against a stub handler.SecretReferenceParser,AllowedPathValidator,ConfigurationDiscoveryService(XML +configSource), ASP.NET CoreConfigurationSecretDiscovery, and FrameworkAppConfigurationread semantics (resolved vs placeholder).
GitHub Actions runs the same command on push and pull request (.github/workflows/dotnet.yml).
dotnet build Akeyless.DotNet.Samples.sln -c ReleaseRun the Core sample locally:
dotnet run --project src/Akeyless.WebApp.Net8/Akeyless.WebApp.Net8.csprojOpen /health for a trivial JSON response (no secret material).
src/Akeyless.IIS.Agent— Windows Service host: loopback REST, Gateway auth, cache, optional XML discovery.src/Akeyless.Agent.Client— netstandard2.0 HTTP client for the agent (referenced by Framework + Core samples).src/Akeyless.Bootstrap.Net472— .NET Framework library.src/Akeyless.WebApp.Net8— ASP.NET Core 8 sample.scripts/— example Windows service install notes.examples/—web.config,Global.asax, JSON, optional trace listener.tests/Akeyless.Integration.Tests— xUnit tests + CI scenarios for agent, client, and discovery helpers.
Do not log secret values, connection strings, or raw API error bodies in production.
Reference sample only; use and distribute according to your organization’s policies.