Skip to content

Commit

Permalink
Merge pull request #123 from arambazamba:feature-flags
Browse files Browse the repository at this point in the history
Feature-flags
  • Loading branch information
alexander-kastil authored Feb 11, 2023
2 parents 51b2b70 + a11878f commit 8114e63
Show file tree
Hide file tree
Showing 19 changed files with 410 additions and 22 deletions.
5 changes: 5 additions & 0 deletions demos/07-secure-solutions/01-key-vault/readme.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Key Vault

Demonstrates how to use Azure Key Vault secrets. Execute `create-vault.azcli`.

## Readings


[Azure Key Vault](https://docs.microsoft.com/en-us/azure/key-vault/)

[az keyvault](https://docs.microsoft.com/en-us/cli/azure/keyvault?view=azure-cli-latest)
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# Using Managed Idenity
# Use System assigned Managed Identities to access Key Vault

Sample uses Managed Identity App from [GitHub](https://github.com/ARambazamba/ManagedIdentityApp)

- Explanin Microsoft.Azure.Services.AppAuthentication
- Explain .NET 5 support
- Show Deployment using GitHub Actions
- Execute `appservice-use-mi.azcli`. It deploys `food-api-mi`.
10 changes: 6 additions & 4 deletions demos/07-secure-solutions/02-managed-identity/demo-02/readme.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# Managed Identity in Virtual Machines
# Use User Assigned Managed Identities to in VM to access Key Vault

[Azure Instance Metadata Servicen for Virtual Machiness](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service)
## Demo

[Configure managed identities for Azure resources on an Azure VM using Azure CLI](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/qs-configure-cli-windows-vm)

Retriev Token:

```
curl -H Metadata:true "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://valut.azure.net&client_id=<clientid>"
```
## Readings

> Note: A more practical demo is part of the "AppConfig" module
[https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token](https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token)

[Configure managed identities for Azure resources on an Azure VM using Azure CLI](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/qs-configure-cli-windows-vm)
4 changes: 3 additions & 1 deletion demos/07-secure-solutions/02-managed-identity/readme.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Managed Identities

1. Use System addigned Managed Identities to access Key Vault
## Demos

1. Use System assigned Managed Identities to access Key Vault
2. Use User Assigned Managed Identities to in VM to access Key Vault
3. Use MI in Function App to access Key Vault (optional)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,6 @@ public ActionResult Get()
return Ok(config);
}

[HttpGet("GetPremiumFeatureEnabled")]
public ActionResult GetPremium()
{
//get string typed config
var config = cfg.Get<AppConfig>();
return Ok(config);
}

[HttpGet("GetSecretFromVault")]
public async Task<string> GetSecretFromVault()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

builder.Configuration.AddAzureAppConfiguration(options =>
{
options.Connect(cfg.Settings.AppConfigConnection)
options.Connect(new Uri(cfg.Settings.AppConfigEndpoint))
.ConfigureKeyVault(kv =>
{
kv.SetCredential(new DefaultAzureCredential());
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[defaults]
group = az204-m07-secure-solutions-dev
sku = FREE
appserviceplan = config-plan-dev
location = westeurope
web = config-api-dev

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/bin/Debug/net6.0/config-service-api.dll",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/config-service-api.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/config-service-api.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"--project",
"${workspaceFolder}/config-service-api.csproj"
],
"problemMatcher": "$msCompile"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
public class AppSettings
{
public string Title { get; set; }
public bool AuthEnabled { get; set; }
public string DBConnectionString { get; set; }
public string KeyVault { get; set; }
public string AppConfigEndpoint { get; set; }
public string AppConfigConnection { get; set; }
public string Sentinel { get; set; }
public string Environment { get; set; }
}

public class FeatureManagement
{
public bool PremiumFeature { get; set; }
}

public class Logging
{
public LogLevel LogLevel { get; set; }
}

public class LogLevel
{
public string Default { get; set; }
public string Microsoft { get; set; }
public string MicrosoftHostingLifetime { get; set; }
}

public class AppConfig
{
public Logging Logging { get; set; }
public string AllowedHosts { get; set; }
public AppSettings Settings { get; set; }
public FeatureManagement FeatureManagement { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Threading.Tasks;
using Azure.Security.KeyVault.Secrets;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.FeatureManagement;

namespace config_service_api.Controllers;

[ApiController]
[Route("[controller]")]
public class ConfigController : ControllerBase
{
IConfiguration cfg;
SecretClient sc;
IFeatureManager fm;

private readonly ILogger<ConfigController> logger;

public ConfigController(ILogger<ConfigController> ilogger, IConfiguration config, SecretClient secretClient, IFeatureManager featureManager)
{
cfg = config;
logger = ilogger;
sc = secretClient;
fm = featureManager;
}

[HttpGet(Name = "GetConfig")]
public ActionResult Get()
{
var config = cfg.Get<AppConfig>();
return Ok(config);
}

[HttpGet("GetPremiumFeatureEnabled")]
public async Task<ActionResult> GetPremium()
{
var premiumEnabled = await fm.IsEnabledAsync("PremiumFeature");
return Ok(premiumEnabled);
}

[HttpGet("GetSecretFromVault")]
public async Task<string> GetSecretFromVault()
{
var response = await sc.GetSecretAsync("conSQLite");
return response.Value.Value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using Microsoft.FeatureManagement;

var builder = WebApplication.CreateBuilder(args);

// Access Base Configuration
IConfiguration Configuration = builder.Configuration;
builder.Services.AddSingleton<IConfiguration>(Configuration);
AppConfig cfg = Configuration.Get<AppConfig>();

builder.Configuration.AddAzureAppConfiguration(options =>
{
options.Connect(cfg.Settings.AppConfigConnection)
.UseFeatureFlags()
.ConfigureKeyVault(kv =>
{
kv.SetCredential(new DefaultAzureCredential());
})
.Select("*", cfg.Settings.Environment)
.ConfigureRefresh(refreshOptions =>
refreshOptions.Register("Settings:Sentinel", refreshAll: true));
});

// Add services to the container.
// Key Vault Client
var client = new SecretClient(new Uri($"https://{cfg.Settings.KeyVault}"), new DefaultAzureCredential());
builder.Services.AddSingleton<SecretClient>(client);

// Feature Management
builder.Services.AddFeatureManagement();

builder.Services.AddControllers();

// Swagger
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "App-Config-Api", Version = "v1" });
});

// Cors
builder.Services.AddCors(o => o.AddPolicy("nocors", builder =>
{
builder
.SetIsOriginAllowed(host => true)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
}));

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

// Swagger
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "App-Config-Service-Api");
c.RoutePrefix = string.Empty;
});

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:33908",
"sslPort": 44365
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "",
"applicationUrl": "https://localhost:5001",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"Settings": {
"Title": "App Config From File",
"AuthEnabled": false,
"DBConnectionString": "Data Source=./food-local.db",
"KeyVault": "foodvault-dev.vault.azure.net",
"AppConfigEndpoint": "https://foodconfig-dev.azconfig.io",
"AppConfigConnection": "Endpoint=https://foodconfig-dev.azconfig.io;Id=fVrb-l9-s0:Kn9pxn7Ueh+XZ9viVGsR;Secret=hbr+jKb0SgK+RIrud2EXWXKZkschTJt23bCzN29xWRI=",
"Sentinel": 1,
"Environment": "production"
},
"FeatureManagement": {
"PremiumFeature": false
}
}
Loading

0 comments on commit 8114e63

Please sign in to comment.