Skip to content

Commit 89fda16

Browse files
committed
Updated tests
1 parent c3dbd6f commit 89fda16

104 files changed

Lines changed: 6170 additions & 3 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Tests/AwsSecretsManager/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Intent Architect
2+
3+
**/.intent/*
4+
!*.application.output.log
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
7+
<NoWarn>$(NoWarn);1591</NoWarn>
8+
<Nullable>enable</Nullable>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<ProjectReference Include="..\AwsSecretsManager.Application\AwsSecretsManager.Application.csproj" />
13+
<ProjectReference Include="..\AwsSecretsManager.Infrastructure\AwsSecretsManager.Infrastructure.csproj" />
14+
<ProjectReference Include="..\AwsSecretsManager.Domain\AwsSecretsManager.Domain.csproj" />
15+
</ItemGroup>
16+
17+
<ItemGroup>
18+
<PackageReference Include="Asp.Versioning.Mvc" Version="8.1.0" />
19+
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
20+
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="9.0.0" />
21+
<PackageReference Include="AWSSDK.SecretsManager" Version="4.0.1.8" />
22+
<PackageReference Include="Duende.IdentityModel" Version="7.0.0" />
23+
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.20" />
24+
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
25+
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.6" />
26+
</ItemGroup>
27+
</Project>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using Asp.Versioning;
2+
using Asp.Versioning.ApiExplorer;
3+
using Intent.RoslynWeaver.Attributes;
4+
using Microsoft.Extensions.Options;
5+
using Microsoft.OpenApi.Models;
6+
using Swashbuckle.AspNetCore.SwaggerGen;
7+
8+
[assembly: DefaultIntentManaged(Mode.Fully)]
9+
[assembly: IntentTemplate("Intent.AspNetCore.Versioning.ApiVersionSwaggerGenOptions", Version = "1.0")]
10+
11+
namespace AwsSecretsManager.Api.Configuration
12+
{
13+
public class ApiVersionSwaggerGenOptions : IConfigureOptions<SwaggerGenOptions>
14+
{
15+
private readonly IApiVersionDescriptionProvider _provider;
16+
17+
public ApiVersionSwaggerGenOptions(IApiVersionDescriptionProvider provider)
18+
{
19+
_provider = provider;
20+
}
21+
22+
public void Configure(SwaggerGenOptions options)
23+
{
24+
foreach (var description in _provider.ApiVersionDescriptions.OrderByDescending(o => o.ApiVersion))
25+
{
26+
options.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description));
27+
}
28+
}
29+
30+
private static OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description)
31+
{
32+
var info = new OpenApiInfo()
33+
{
34+
Title = "AwsSecretsManager API",
35+
Version = description.ApiVersion.ToString()
36+
};
37+
38+
if (description.IsDeprecated)
39+
{
40+
info.Description = "This API version has been deprecated.";
41+
}
42+
43+
return info;
44+
}
45+
}
46+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using Asp.Versioning;
2+
using Asp.Versioning.ApiExplorer;
3+
using Intent.RoslynWeaver.Attributes;
4+
5+
[assembly: DefaultIntentManaged(Mode.Fully)]
6+
[assembly: IntentTemplate("Intent.AspNetCore.Versioning.ApiVersioningConfiguration", Version = "1.0")]
7+
8+
namespace AwsSecretsManager.Api.Configuration
9+
{
10+
public static class ApiVersioningConfiguration
11+
{
12+
public static IServiceCollection ConfigureApiVersioning(this IServiceCollection services)
13+
{
14+
services.AddApiVersioning(options =>
15+
{
16+
options.AssumeDefaultVersionWhenUnspecified = true;
17+
options.ReportApiVersions = true;
18+
options.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader());
19+
})
20+
.AddMvc()
21+
.AddApiExplorer(options =>
22+
{
23+
options.GroupNameFormat = "'v'VVV";
24+
options.SubstituteApiVersionInUrl = true;
25+
});
26+
return services;
27+
}
28+
}
29+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System.IdentityModel.Tokens.Jwt;
2+
using AwsSecretsManager.Api.Services;
3+
using AwsSecretsManager.Application.Common.Interfaces;
4+
using Intent.RoslynWeaver.Attributes;
5+
using Microsoft.AspNetCore.Authentication.JwtBearer;
6+
using Microsoft.AspNetCore.Authorization;
7+
using Microsoft.IdentityModel.Tokens;
8+
9+
[assembly: DefaultIntentManaged(Mode.Fully)]
10+
[assembly: IntentTemplate("Intent.Application.Identity.ApplicationSecurityConfiguration", Version = "1.0")]
11+
12+
namespace AwsSecretsManager.Api.Configuration
13+
{
14+
public static class ApplicationSecurityConfiguration
15+
{
16+
public static IServiceCollection ConfigureApplicationSecurity(
17+
this IServiceCollection services,
18+
IConfiguration configuration)
19+
{
20+
services.AddSingleton<ICurrentUserService, CurrentUserService>();
21+
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
22+
services.AddHttpContextAccessor();
23+
24+
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
25+
.AddJwtBearer(
26+
JwtBearerDefaults.AuthenticationScheme,
27+
options =>
28+
{
29+
options.Authority = configuration.GetSection("Security.Bearer:Authority").Get<string>();
30+
options.Audience = configuration.GetSection("Security.Bearer:Audience").Get<string>();
31+
32+
options.TokenValidationParameters.RoleClaimType = "role";
33+
options.SaveToken = true;
34+
});
35+
36+
services.AddAuthorization(ConfigureAuthorization);
37+
38+
return services;
39+
}
40+
41+
[IntentManaged(Mode.Ignore)]
42+
private static void ConfigureAuthorization(AuthorizationOptions options)
43+
{
44+
// Configure policies and other authorization options here. For example:
45+
// options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("role", "employee"));
46+
// options.AddPolicy("AdminOnly", policy => policy.RequireClaim("role", "admin"));
47+
}
48+
}
49+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using Intent.RoslynWeaver.Attributes;
2+
3+
[assembly: DefaultIntentManaged(Mode.Fully)]
4+
[assembly: IntentTemplate("Intent.Aws.SecretsManager.AwsSecretsManagerConfiguration", Version = "1.0")]
5+
6+
namespace AwsSecretsManager.Api.Configuration
7+
{
8+
public static class AwsSecretsManagerConfiguration
9+
{
10+
public static void ConfigureAwsSecretsManager(this IConfigurationBuilder builder, IConfiguration configuration)
11+
{
12+
var options = new AwsSecretsManagerOptions();
13+
configuration.GetSection("SecretsManager").Bind(options);
14+
15+
foreach (var secret in options.Secrets)
16+
{
17+
builder.Add(new AwsSecretsManagerConfigurationSource(secret.Region, secret.SecretName));
18+
}
19+
}
20+
}
21+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using System.Text;
2+
using Amazon;
3+
using Amazon.SecretsManager;
4+
using Amazon.SecretsManager.Model;
5+
using Intent.RoslynWeaver.Attributes;
6+
7+
[assembly: DefaultIntentManaged(Mode.Fully)]
8+
[assembly: IntentTemplate("Intent.Aws.SecretsManager.AwsSecretsManagerConfigurationSource", Version = "1.0")]
9+
10+
namespace AwsSecretsManager.Api.Configuration
11+
{
12+
public class AwsSecretsManagerConfigurationProvider(string region, string secretName) : ConfigurationProvider
13+
{
14+
private const string SecretVersionStage = "AWSCURRENT";
15+
16+
public override void Load()
17+
{
18+
var secretJson = GetSecret();
19+
20+
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(secretJson)))
21+
{
22+
var tempConfig = new ConfigurationBuilder()
23+
.AddJsonStream(ms)
24+
.Build();
25+
Data = tempConfig.AsEnumerable(makePathsRelative: false)
26+
.Where(kv => kv.Value is not null)
27+
.ToDictionary(kv => kv.Key, kv => kv.Value, StringComparer.OrdinalIgnoreCase);
28+
}
29+
}
30+
31+
private string GetSecret()
32+
{
33+
var request = new GetSecretValueRequest
34+
{
35+
SecretId = secretName,
36+
VersionStage = SecretVersionStage
37+
};
38+
39+
using (var client = new AmazonSecretsManagerClient(RegionEndpoint.GetBySystemName(region)))
40+
{
41+
var response = client.GetSecretValueAsync(request).GetAwaiter().GetResult();
42+
43+
if (!string.IsNullOrEmpty(response.SecretString))
44+
{
45+
return response.SecretString;
46+
}
47+
48+
using (var reader = new StreamReader(response.SecretBinary))
49+
{
50+
var base64 = reader.ReadToEnd();
51+
var bytes = Convert.FromBase64String(base64);
52+
return Encoding.UTF8.GetString(bytes);
53+
}
54+
}
55+
}
56+
}
57+
58+
public class AwsSecretsManagerConfigurationSource(string region, string secretName) : IConfigurationSource
59+
{
60+
public IConfigurationProvider Build(IConfigurationBuilder builder)
61+
{
62+
return new AwsSecretsManagerConfigurationProvider(region, secretName);
63+
}
64+
}
65+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Intent.RoslynWeaver.Attributes;
2+
3+
[assembly: DefaultIntentManaged(Mode.Fully)]
4+
[assembly: IntentTemplate("Intent.Aws.SecretsManager.AwsSecretsManagerOptions", Version = "1.0")]
5+
6+
namespace AwsSecretsManager.Api.Configuration
7+
{
8+
public class AwsSecretsManagerOptions
9+
{
10+
public bool Enabled { get; set; }
11+
public List<AwsSecretsManagerSecret> Secrets { get; set; } = new List<AwsSecretsManagerSecret>();
12+
}
13+
14+
public class AwsSecretsManagerSecret
15+
{
16+
public string Region { get; set; }
17+
public string SecretName { get; set; }
18+
}
19+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using HealthChecks.UI.Client;
2+
using Intent.RoslynWeaver.Attributes;
3+
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
4+
5+
[assembly: DefaultIntentManaged(Mode.Fully)]
6+
[assembly: IntentTemplate("Intent.AspNetCore.HealthChecks.HealthChecksConfiguration", Version = "1.0")]
7+
8+
namespace AwsSecretsManager.Api.Configuration
9+
{
10+
public static class HealthChecksConfiguration
11+
{
12+
public static IServiceCollection ConfigureHealthChecks(
13+
this IServiceCollection services,
14+
IConfiguration configuration)
15+
{
16+
var hcBuilder = services.AddHealthChecks();
17+
18+
return services;
19+
}
20+
21+
public static IEndpointRouteBuilder MapDefaultHealthChecks(this IEndpointRouteBuilder endpoints)
22+
{
23+
endpoints.MapHealthChecks("/hc", new HealthCheckOptions
24+
{
25+
Predicate = _ => true,
26+
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
27+
});
28+
return endpoints;
29+
}
30+
}
31+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System.Diagnostics;
2+
using Intent.RoslynWeaver.Attributes;
3+
using Microsoft.AspNetCore.Diagnostics;
4+
5+
[assembly: DefaultIntentManaged(Mode.Fully)]
6+
[assembly: IntentTemplate("Intent.AspNetCore.ProblemDetailsConfiguration", Version = "1.0")]
7+
8+
namespace AwsSecretsManager.Api.Configuration
9+
{
10+
public static class ProblemDetailsConfiguration
11+
{
12+
public static IServiceCollection ConfigureProblemDetails(this IServiceCollection services)
13+
{
14+
services.AddProblemDetails(conf => conf.CustomizeProblemDetails = context =>
15+
{
16+
context.ProblemDetails.Type = $"https://httpstatuses.io/{context.ProblemDetails.Status}";
17+
18+
if (context.ProblemDetails.Status != 500) return;
19+
context.ProblemDetails.Title = "Internal Server Error";
20+
context.ProblemDetails.Extensions.TryAdd("traceId", Activity.Current?.Id ?? context.HttpContext.TraceIdentifier);
21+
22+
var env = context.HttpContext.RequestServices.GetService<IWebHostEnvironment>()!;
23+
if (!env.IsDevelopment()) return;
24+
25+
var exceptionFeature = context.HttpContext.Features.Get<IExceptionHandlerFeature>();
26+
if (exceptionFeature is null) return;
27+
context.ProblemDetails.Detail = exceptionFeature.Error.ToString();
28+
});
29+
return services;
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)