Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setup AD based auth #40

Merged
merged 1 commit into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/content-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ jobs:
- name: Build and push content
run: |
cd GuildWarsPartySearch.FrontEnd
.\BuildAndUploadContent.ps1 -ConnectionString "${{ secrets.AZURE_TABLESTORAGE_CONNECTIONSTRING }}" -ContainerName "content" -SourceFolderPath Content
.\BuildAndUploadContent.ps1 -ContainerName content -SourceFolderPath Content -ClientId "${{ secrets.AZURE_CLIENT_ID }}" -ClientSecret "${{ secrets.AZURE_CLIENT_SECRET }}" -TenantId "${{ secrets.AZURE_TENANT_ID }}" -StorageAccountName "guildwarspartysearch"
shell: pwsh
6 changes: 4 additions & 2 deletions .github/workflows/docker-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ jobs:
cd GuildWarsPartySearch
$content = Get-Content Config.Release.json
$content = $content.Replace("[APIKEY]", "${{ secrets.APIKEY }}")
$content = $content.Replace("[AZURE_TABLESTORAGE_CONNECTIONSTRING]", "${{ secrets.AZURE_TABLESTORAGE_CONNECTIONSTRING }}")
$content = $content.Replace("[CERTIFICATE_BASE64]", "${{ secrets.CERTIFICATE_BASE64 }}")
$content = $content.Replace("[AZURE_INSIGHTS_INSTRUMENTATIONKEY]", "${{ secrets.AZURE_INSIGHTS_INSTRUMENTATIONKEY }}")
$content = $content.Replace("[AZURE_CLIENT_SECRET]", "${{ secrets.AZURE_CLIENT_SECRET }}")
$content = $content.Replace("[AZURE_CLIENT_ID]", "${{ secrets.AZURE_CLIENT_ID }}")
$content = $content.Replace("[AZURE_TENANT_ID]", "${{ secrets.AZURE_TENANT_ID }}")
Set-Content -Path Config.Release.json -Value $content
Write-Host "Placeholder replaced successfully in Config.Release.json"

Expand All @@ -55,7 +57,7 @@ jobs:
- name: Login to Azure
shell: pwsh
run: |
az login --service-principal -u "${{ secrets.AZURE_CLIENTID }}" -p "${{ secrets.AZURE_SECRET }}" --tenant "${{ secrets.AZURE_TENANT }}"
az login --service-principal -u "${{ secrets.AZURE_CLIENT_ID }}" -p "${{ secrets.AZURE_CLIENT_SECRET }}" --tenant "${{ secrets.AZURE_TENANT_ID }}"

- name: Check and Delete Existing Container Instance
shell: pwsh
Expand Down
17 changes: 13 additions & 4 deletions GuildWarsPartySearch.FrontEnd/BuildAndUploadContent.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
param(
[Parameter(Mandatory=$true)]
[string]$ConnectionString,
[string]$ClientId,

[Parameter(Mandatory=$true)]
[string]$ClientSecret,

[Parameter(Mandatory=$true)]
[string]$TenantId,

[Parameter(Mandatory=$true)]
[string]$StorageAccountName,

[Parameter(Mandatory=$true)]
[string]$ContainerName,
Expand All @@ -9,6 +18,6 @@ param(
[string]$SourceFolderPath
)


az storage blob delete-batch --source $ContainerName --connection-string $ConnectionString --pattern '*'
az storage blob upload-batch --destination $ContainerName --source $SourceFolderPath --connection-string $ConnectionString
az login --service-principal -u $ClientId -p $ClientSecret --tenant $TenantId
az storage blob delete-batch --source $ContainerName --pattern '*' --account-name $StorageAccountName
az storage blob upload-batch --destination $ContainerName --source $SourceFolderPath --account-name $StorageAccountName
7 changes: 6 additions & 1 deletion GuildWarsPartySearch/Config.Debug.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"HeartbeatFrequency": "0:0:1"
},
"StorageAccountOptions": {
"ConnectionString": "[AZURE_TABLESTORAGE_CONNECTIONSTRING]"
"Name": "guildwarspartysearch"
},
"PartySearchTableOptions": {
"TableName": "searches"
Expand All @@ -62,5 +62,10 @@
404,
429
]
},
"AzureCredentialsOptions": {
"ClientSecret": "[AZURE_CLIENT_SECRET]",
"ClientId": "[AZURE_CLIENT_ID]",
"TenantId": "[AZURE_TENANT_ID]"
}
}
7 changes: 6 additions & 1 deletion GuildWarsPartySearch/Config.Release.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"HeartbeatFrequency": "0:0:1"
},
"StorageAccountOptions": {
"ConnectionString": "[AZURE_TABLESTORAGE_CONNECTIONSTRING]"
"Name": "guildwarspartysearch"
},
"PartySearchTableOptions": {
"TableName": "searches"
Expand All @@ -62,5 +62,10 @@
404,
429
]
},
"AzureCredentialsOptions": {
"ClientSecret": "[AZURE_CLIENT_SECRET]",
"ClientId": "[AZURE_CLIENT_ID]",
"TenantId": "[AZURE_TENANT_ID]"
}
}
16 changes: 11 additions & 5 deletions GuildWarsPartySearch/Extensions/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using GuildWarsPartySearch.Server.Options;
using Azure.Core;
using GuildWarsPartySearch.Server.Options;
using GuildWarsPartySearch.Server.Options.Azure;
using GuildWarsPartySearch.Server.Services.Azure;
using Microsoft.Extensions.Options;
using System.Core.Extensions;
Expand All @@ -13,10 +15,11 @@ public static IServiceCollection AddSingletonTableClient<TOptions>(this IService
services.ThrowIfNull()
.AddSingleton(sp =>
{
var tokenCredential = sp.GetRequiredService<TokenCredential>();
var storageOptions = sp.GetRequiredService<IOptions<StorageAccountOptions>>();
var clientOptions = sp.GetRequiredService<IOptions<TOptions>>();
var logger = sp.GetRequiredService<ILogger<NamedTableClient<TOptions>>>();
return new NamedTableClient<TOptions>(logger, storageOptions.Value.ConnectionString!, clientOptions.Value.TableName);
return new NamedTableClient<TOptions>(logger, new Uri($"https://{storageOptions.Value.Name}.table.core.windows.net"), clientOptions.Value.TableName, tokenCredential, default);
});

return services;
Expand All @@ -28,10 +31,11 @@ public static IServiceCollection AddScopedTableClient<TOptions>(this IServiceCol
services.ThrowIfNull()
.AddScoped(sp =>
{
var tokenCredential = sp.GetRequiredService<TokenCredential>();
var storageOptions = sp.GetRequiredService<IOptions<StorageAccountOptions>>();
var clientOptions = sp.GetRequiredService<IOptions<TOptions>>();
var logger = sp.GetRequiredService<ILogger<NamedTableClient<TOptions>>>();
return new NamedTableClient<TOptions>(logger, storageOptions.Value.ConnectionString!, clientOptions.Value.TableName);
return new NamedTableClient<TOptions>(logger, new Uri($"https://{storageOptions.Value.Name}.table.core.windows.net"), clientOptions.Value.TableName, tokenCredential, default);
});

return services;
Expand All @@ -43,9 +47,10 @@ public static IServiceCollection AddSingletonBlobContainerClient<TOptions>(this
services.ThrowIfNull()
.AddSingleton(sp =>
{
var tokenCredential = sp.GetRequiredService<TokenCredential>();
var storageOptions = sp.GetRequiredService<IOptions<StorageAccountOptions>>();
var clientOptions = sp.GetRequiredService<IOptions<TOptions>>();
return new NamedBlobContainerClient<TOptions>(storageOptions.Value.ConnectionString!, clientOptions.Value.ContainerName);
return new NamedBlobContainerClient<TOptions>(new Uri($"https://{storageOptions.Value.Name}.blob.core.windows.net/{clientOptions.Value.ContainerName}"), tokenCredential, default);
});

return services;
Expand All @@ -57,9 +62,10 @@ public static IServiceCollection AddScopedBlobContainerClient<TOptions>(this ISe
services.ThrowIfNull()
.AddScoped(sp =>
{
var tokenCredential = sp.GetRequiredService<TokenCredential>();
var storageOptions = sp.GetRequiredService<IOptions<StorageAccountOptions>>();
var clientOptions = sp.GetRequiredService<IOptions<TOptions>>();
return new NamedBlobContainerClient<TOptions>(storageOptions.Value.ConnectionString!, clientOptions.Value.ContainerName);
return new NamedBlobContainerClient<TOptions>(new Uri($"https://{storageOptions.Value.Name}.blob.core.windows.net/{clientOptions.Value.ContainerName}"), tokenCredential, default);
});

return services;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
using GuildWarsPartySearch.Server.Attributes;
using Azure.Core;
using Azure.Identity;
using GuildWarsPartySearch.Server.Attributes;
using GuildWarsPartySearch.Server.Options.Azure;
using Microsoft.Extensions.Options;
using System.Core.Extensions;
using System.Extensions;

namespace GuildWarsPartySearch.Server.Extensions;

public static class WebApplicationBuilderExtensions
{
public static WebApplicationBuilder ConfigureAzureClientSecretCredentials<TOptions>(this WebApplicationBuilder builder)
where TOptions : class, IAzureClientSecretCredentialOptions, new()
{
builder.ThrowIfNull()
.ConfigureExtended<TOptions>()
.Services.AddSingleton<TokenCredential>(sp =>
{
var options = sp.GetRequiredService<IOptions<TOptions>>().Value;
return new ClientSecretCredential(options.TenantId, options.ClientId, options.ClientSecret);
});

return builder;
}

public static WebApplicationBuilder ConfigureExtended<TOptions>(this WebApplicationBuilder builder)
where TOptions : class, new()
{
Expand Down
1 change: 1 addition & 0 deletions GuildWarsPartySearch/GuildWarsPartySearch.Server.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<ItemGroup>
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="Azure.Data.Tables" Version="12.8.2" />
<PackageReference Include="Azure.Identity" Version="1.10.4" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.19.1" />
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.21.0" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.21.0" />
Expand Down
4 changes: 1 addition & 3 deletions GuildWarsPartySearch/Launch/ServerConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using AspNetCoreRateLimit;
using Azure.Data.Tables;
using GuildWarsPartySearch.Common.Converters;
using GuildWarsPartySearch.Server.Endpoints;
using GuildWarsPartySearch.Server.Extensions;
Expand All @@ -13,8 +12,6 @@
using GuildWarsPartySearch.Server.Services.PartySearch;
using GuildWarsPartySearch.Server.Telemetry;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Extensions.Azure;
using Microsoft.Extensions.Options;
using System.Core.Extensions;
using System.Extensions;
using System.Text.Json.Serialization;
Expand Down Expand Up @@ -65,6 +62,7 @@ public static ILoggingBuilder SetupLogging(this ILoggingBuilder builder)
public static WebApplicationBuilder SetupOptions(this WebApplicationBuilder builder)
{
return builder.ThrowIfNull()
.ConfigureAzureClientSecretCredentials<AzureCredentialsOptions>()
.ConfigureExtended<EnvironmentOptions>()
.ConfigureExtended<ContentOptions>()
.ConfigureExtended<PartySearchTableOptions>()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace GuildWarsPartySearch.Server.Options;
namespace GuildWarsPartySearch.Server.Options.Azure;

public interface IAzureBlobStorageOptions
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace GuildWarsPartySearch.Server.Options.Azure;

public interface IAzureClientSecretCredentialOptions : IAzureCredentialOptions
{
string ClientSecret { get; set; }
}
8 changes: 8 additions & 0 deletions GuildWarsPartySearch/Options/Azure/IAzureCredentialOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace GuildWarsPartySearch.Server.Options.Azure;

public interface IAzureCredentialOptions
{
string ClientId { get; set; }

string TenantId { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace GuildWarsPartySearch.Server.Options;
namespace GuildWarsPartySearch.Server.Options.Azure;

public interface IAzureTableStorageOptions
{
Expand Down
16 changes: 16 additions & 0 deletions GuildWarsPartySearch/Options/AzureCredentialsOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using GuildWarsPartySearch.Server.Options.Azure;
using System.Text.Json.Serialization;

namespace GuildWarsPartySearch.Server.Options;

public sealed class AzureCredentialsOptions : IAzureClientSecretCredentialOptions
{
[JsonPropertyName(nameof(ClientSecret))]
public string ClientSecret { get; set; } = default!;

[JsonPropertyName(nameof(ClientId))]
public string ClientId { get; set; } = default!;

[JsonPropertyName(nameof(TenantId))]
public string TenantId { get; set; } = default!;
}
1 change: 1 addition & 0 deletions GuildWarsPartySearch/Options/ContentOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
using GuildWarsPartySearch.Server.Options.Azure;

namespace GuildWarsPartySearch.Server.Options;

Expand Down
3 changes: 1 addition & 2 deletions GuildWarsPartySearch/Options/PartySearchTableOptions.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using System.Text.Json.Serialization;
using GuildWarsPartySearch.Server.Options.Azure;

namespace GuildWarsPartySearch.Server.Options;

public class PartySearchTableOptions : IAzureTableStorageOptions
{
[JsonPropertyName(nameof(TableName))]
public string TableName { get; set; } = default!;
}
10 changes: 2 additions & 8 deletions GuildWarsPartySearch/Options/StorageAccountOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@ namespace GuildWarsPartySearch.Server.Options;

public sealed class StorageAccountOptions
{
[JsonPropertyName(nameof(TableName))]
public string? TableName { get; set; }

[JsonPropertyName(nameof(ConnectionString))]
public string? ConnectionString { get; set; }

[JsonPropertyName(nameof(ContainerName))]
public string? ContainerName { get; set; }
[JsonPropertyName(nameof(Name))]
public string? Name { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Azure.Storage;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using GuildWarsPartySearch.Server.Options;
using GuildWarsPartySearch.Server.Options.Azure;

namespace GuildWarsPartySearch.Server.Services.Azure;

Expand Down
Loading