Skip to content

Commit

Permalink
Initial port of KubeClient.Extensions.DataProtection implementation
Browse files Browse the repository at this point in the history
This code has been ported from https://github.com/rriverak/KubeClient.Extensions.DataProtection (thanks, @rriverak!).
Note that, at this, stage, it is a work in progress (we need to decide on strategies for thread-safety and handling of common error conditions (such as the underlying Secret being deleted).

Relates to #94.
  • Loading branch information
tintoy committed Sep 15, 2019
1 parent 444e7dd commit f36d103
Show file tree
Hide file tree
Showing 6 changed files with 441 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,8 @@ csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true

# Spacing
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
15 changes: 15 additions & 0 deletions KubeClient.sln
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeploymentWithRollback", "s
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchEvents", "samples\WatchEvents\WatchEvents.csproj", "{EA1B1086-1813-478A-96B8-D54ABAEA77BE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeClient.Extensions.DataProtection", "src\KubeClient.Extensions.DataProtection\KubeClient.Extensions.DataProtection.csproj", "{4B6C7D05-0B7D-42A8-97CD-B6D2E3219F8E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -232,6 +234,18 @@ Global
{EA1B1086-1813-478A-96B8-D54ABAEA77BE}.Release|x64.Build.0 = Release|Any CPU
{EA1B1086-1813-478A-96B8-D54ABAEA77BE}.Release|x86.ActiveCfg = Release|Any CPU
{EA1B1086-1813-478A-96B8-D54ABAEA77BE}.Release|x86.Build.0 = Release|Any CPU
{4B6C7D05-0B7D-42A8-97CD-B6D2E3219F8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4B6C7D05-0B7D-42A8-97CD-B6D2E3219F8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4B6C7D05-0B7D-42A8-97CD-B6D2E3219F8E}.Debug|x64.ActiveCfg = Debug|Any CPU
{4B6C7D05-0B7D-42A8-97CD-B6D2E3219F8E}.Debug|x64.Build.0 = Debug|Any CPU
{4B6C7D05-0B7D-42A8-97CD-B6D2E3219F8E}.Debug|x86.ActiveCfg = Debug|Any CPU
{4B6C7D05-0B7D-42A8-97CD-B6D2E3219F8E}.Debug|x86.Build.0 = Debug|Any CPU
{4B6C7D05-0B7D-42A8-97CD-B6D2E3219F8E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4B6C7D05-0B7D-42A8-97CD-B6D2E3219F8E}.Release|Any CPU.Build.0 = Release|Any CPU
{4B6C7D05-0B7D-42A8-97CD-B6D2E3219F8E}.Release|x64.ActiveCfg = Release|Any CPU
{4B6C7D05-0B7D-42A8-97CD-B6D2E3219F8E}.Release|x64.Build.0 = Release|Any CPU
{4B6C7D05-0B7D-42A8-97CD-B6D2E3219F8E}.Release|x86.ActiveCfg = Release|Any CPU
{4B6C7D05-0B7D-42A8-97CD-B6D2E3219F8E}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -252,6 +266,7 @@ Global
{4DCB98B3-4B9D-4A80-A819-60281A1B0739} = {619D7194-2A3C-4C5C-A5A3-EBAD28C1D65F}
{2DEC9BCC-AA1C-4A1A-B0EA-FC5930297568} = {619D7194-2A3C-4C5C-A5A3-EBAD28C1D65F}
{EA1B1086-1813-478A-96B8-D54ABAEA77BE} = {619D7194-2A3C-4C5C-A5A3-EBAD28C1D65F}
{4B6C7D05-0B7D-42A8-97CD-B6D2E3219F8E} = {1F77AA9A-2C82-4CC5-A896-EE6E0DDB7DB3}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {191B89E7-F944-4315-9E98-F6F736D27296}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ public static class KubeClientConfigurationExtensions
/// <param name="reloadOnChange">
/// Reload the configuration if the ConfigMap changes?
/// </param>
/// <param name="throwOnNotFound">
/// Throw an exception if the ConfigMap cannot be found?
/// </param>
/// <returns>
/// The configured <see cref="IConfigurationBuilder"/>.
/// </returns>
Expand Down
114 changes: 114 additions & 0 deletions src/KubeClient.Extensions.DataProtection/DataProtectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.Extensions.DependencyInjection;
using System;

namespace KubeClient
{
using Extensions.DataProtection;

/// <summary>
/// <see cref="IDataProtectionBuilder"/> extension methods to persist Keys in a Kubernetes Secret.
/// </summary>
public static class DataProtectionExtensions
{
/// <summary>
/// Add or Create a Kubernetes Secret as a Repository.
/// </summary>
/// <param name="builder">
/// The <see cref="IDataProtectionBuilder"/> to Configure.
/// </param>
/// <param name="clientOptions">
/// <see cref="KubeClientOptions"/> for the <see cref="KubeApiClient"/> used to communicate with the Kubernetes API.
/// </param>
/// <param name="secretName">
/// The name of the target Secret.
/// </param>
/// <param name="kubeNamespace">
/// The namespace of the target Secret.
/// </param>
/// <returns>
/// The configured <see cref="IDataProtectionBuilder"/>.
/// </returns>
public static IDataProtectionBuilder PersistKeysToKubeSecret(this IDataProtectionBuilder builder, KubeClientOptions clientOptions, string secretName, string kubeNamespace = null)
{
if (builder == null)
throw new ArgumentNullException(nameof(builder));

if (clientOptions == null)
throw new ArgumentNullException(nameof(clientOptions));

if (String.IsNullOrWhiteSpace(secretName))
throw new ArgumentException($"Argument cannot be null, empty, or entirely composed of whitespace: {nameof(secretName)}.", nameof(secretName));

KubeApiClient client = KubeApiClient.Create(clientOptions);

return builder.PersistKeysToKubeSecret(client, secretName, kubeNamespace);
}

/// <summary>
/// Add or Create a Kubernetes Secret as a Repository.
/// </summary>
/// <param name="builder">
/// The <see cref="IDataProtectionBuilder"/> to Configure.
/// </param>
/// <param name="client">
/// The <see cref="IKubeApiClient"/> used to communicate with the Kubernetes API.
/// </param>
/// <param name="secretName">
/// The name of the target Secret.
/// </param>
/// <param name="kubeNamespace">
/// The namespace of the target Secret.
/// </param>
/// <returns>
/// The configured <see cref="IDataProtectionBuilder"/>.
/// </returns>
public static IDataProtectionBuilder PersistKeysToKubeSecret(this IDataProtectionBuilder builder, IKubeApiClient client, string secretName, string kubeNamespace = null)
{
if (builder == null)
throw new ArgumentNullException(nameof(builder));

if (client == null)
throw new ArgumentNullException(nameof(client));

if (String.IsNullOrWhiteSpace(secretName))
throw new ArgumentException($"Argument cannot be null, empty, or entirely composed of whitespace: {nameof(secretName)}.", nameof(secretName));

builder.Services.Configure<KeyManagementOptions>(options =>
{
// Add KubeClientXmlRepository as KeyStore
options.XmlRepository = new KubeSecretXmlRepository(client, secretName, kubeNamespace ?? client.DefaultNamespace);
});

return builder;
}

/// <summary>
/// Internal Implementation
/// </summary>
/// <param name="builder">
/// The <see cref="IDataProtectionBuilder"/> to Configure.
/// </param>
/// <param name="client">
/// <see cref="KubeApiClient"/> used to communicate with the Kubernetes API.
/// </param>
/// <param name="secretName">
/// The name of the target Secret.
/// </param>
/// <param name="kubeNamespace">
/// The namespace of the target Secret.
/// </param>
/// <returns>The <see cref="IDataProtectionBuilder"/> (enables method-chaining).</returns>
private static IDataProtectionBuilder PersistKeysToKubeSecretInternal(IDataProtectionBuilder builder, IKubeApiClient client, string secretName, string kubeNamespace = null)
{
builder.Services.Configure<KeyManagementOptions>(options =>
{
// Add KubeClientXmlRepository as KeyStore
options.XmlRepository = new KubeSecretXmlRepository(client, secretName, kubeNamespace);
});

return builder;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>

<Description>KubeClient extensions for ASP.NET Core data-protection</Description>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\KubeClient\KubeClient.csproj" />
<ProjectReference Include="..\KubeClient.Extensions.Configuration\KubeClient.Extensions.Configuration.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.DataProtection" Version="2.2.0" />
</ItemGroup>

<Import Project="..\Common.props" />
</Project>
Loading

0 comments on commit f36d103

Please sign in to comment.