Skip to content

Commit

Permalink
Add ability to do cert based authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
crcobb committed Sep 5, 2024
1 parent 0ebfb2f commit c401782
Showing 1 changed file with 75 additions and 0 deletions.
75 changes: 75 additions & 0 deletions src/Svrooij.WinTuner.CmdLets/Commands/ConnectWtWinTuner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Kiota.Abstractions;
using System.Security.Cryptography.X509Certificates;

namespace Svrooij.WinTuner.CmdLets.Commands;
/// <summary>
Expand Down Expand Up @@ -59,6 +60,7 @@ public class ConnectWtWinTuner : DependencyCmdlet<Startup>
private const string DefaultClientCredentialScope = "https://graph.microsoft.com/.default";
private const string ParamSetInteractive = "Interactive";
private const string ParamSetClientCredentials = "ClientCredentials";
private const string ParamSetClientCertificateCredentials = "ClientCertificateCredentials";

/// <summary>
/// Used default scopes
Expand Down Expand Up @@ -144,6 +146,13 @@ public class ConnectWtWinTuner : DependencyCmdlet<Startup>
ValueFromPipeline = false,
ValueFromPipelineByPropertyName = false,
HelpMessage = "Specify the tenant ID. Loaded from `AZURE_TENANT_ID`")]
[Parameter(
Mandatory = true,
Position = 2,
ParameterSetName = ParamSetClientCertificateCredentials,
ValueFromPipeline = false,
ValueFromPipelineByPropertyName = false,
HelpMessage = "Specify the tenant ID. Loaded from `AZURE_TENANT_ID`")]
public string? TenantId { get; set; } = Environment.GetEnvironmentVariable("AZURE_TENANT_ID");

/// <summary>
Expand All @@ -156,6 +165,13 @@ public class ConnectWtWinTuner : DependencyCmdlet<Startup>
ValueFromPipeline = false,
ValueFromPipelineByPropertyName = false,
HelpMessage = "Specify the client ID, mandatory for Client Credentials flow. Loaded from `AZURE_CLIENT_ID`")]
[Parameter(
Mandatory = true,
Position = 0,
ParameterSetName = ParamSetClientCertificateCredentials,
ValueFromPipeline = false,
ValueFromPipelineByPropertyName = false,
HelpMessage = "Specify the client ID, mandatory for Client Certificate flow. Loaded from `AZURE_CLIENT_ID`")]
[Parameter(
Mandatory = false,
Position = 3,
Expand All @@ -178,6 +194,17 @@ public class ConnectWtWinTuner : DependencyCmdlet<Startup>
HelpMessage = "Specify the client secret. Loaded from `AZURE_CLIENT_SECRET`")]
public string? ClientSecret { get; set; } = Environment.GetEnvironmentVariable("AZURE_CLIENT_SECRET");

/// <summary>
/// Certificate Thumbprint for client authentication
/// </summary>
[Parameter(
Mandatory = true,
Position = 1,
ParameterSetName = ParamSetClientCertificateCredentials,
ValueFromPipeline = false,
HelpMessage = "Specify the thumbprint of the certificate.")]
public string? ClientCertificateThumbprint { get; set; }

/// <summary>
/// Specify scopes to use
/// </summary>
Expand All @@ -202,6 +229,13 @@ public class ConnectWtWinTuner : DependencyCmdlet<Startup>
ValueFromPipeline = false,
ValueFromPipelineByPropertyName = false,
HelpMessage = "Specify the scopes to request, default is `https://graph.microsoft.com/.default`")]
[Parameter(
Mandatory = false,
Position = 10,
ParameterSetName = ParamSetClientCertificateCredentials,
ValueFromPipeline = false,
ValueFromPipelineByPropertyName = false,
HelpMessage = "Specify the scopes to request, default is `https://graph.microsoft.com/.default`")]
[Parameter(
Mandatory = false,
Position = 10,
Expand Down Expand Up @@ -278,6 +312,47 @@ private IAuthenticationProvider CreateAuthenticationProvider(CancellationToken c
}
}

if (ParameterSetName == ParamSetClientCertificateCredentials)
{
if( !string.IsNullOrEmpty(ClientId) && !string.IsNullOrEmpty(TenantId) &&
!string.IsNullOrEmpty(ClientCertificateThumbprint))
{
using var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var certificate = store.Certificates.Cast<X509Certificate2>().FirstOrDefault(cert => cert.Thumbprint == ClientCertificateThumbprint);
store.Close();
if (certificate == null)
{
using var storeLocal = new X509Store(StoreName.My, StoreLocation.LocalMachine);
storeLocal.Open(OpenFlags.ReadOnly);
certificate = storeLocal.Certificates.Cast<X509Certificate2>().FirstOrDefault(cert => cert.Thumbprint == ClientCertificateThumbprint);
storeLocal.Close();
}
if( certificate == null)
{
throw new ArgumentException( "Cannot find cert thumbprint in User or Machine store");
}

return new Microsoft.Graph.Authentication.AzureIdentityAuthenticationProvider(
new Azure.Identity.ClientCertificateCredential (TenantId, ClientId, certificate,
new Azure.Identity.ClientCertificateCredentialOptions
{
TokenCachePersistenceOptions = new Azure.Identity.TokenCachePersistenceOptions
{
Name = "WinTuner-PowerShell-CC",
UnsafeAllowUnencryptedStorage = true,
}
}
), isCaeEnabled: false, scopes: DefaultClientCredentialScope);

}
else
{
throw new ArgumentException("Not all parameters for client certificate are specified",
nameof(ClientId));
}

}
if (ParameterSetName == ParamSetInteractive)
{
if (NoBroker || RuntimeInformation.IsOSPlatform(OSPlatform.Windows) == false)
Expand Down

0 comments on commit c401782

Please sign in to comment.