Skip to content

Commit

Permalink
Merge pull request #1849 from fowl2/OutputTypeAttribute-AzureCertificate
Browse files Browse the repository at this point in the history
AzureCertificate: unify output production, add OutputType Attribute
  • Loading branch information
KoenZomers authored May 23, 2022
2 parents ea10625 + 8bf606d commit bbc09f9
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 52 deletions.
69 changes: 49 additions & 20 deletions src/Commands/Base/GetAzureCertificate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
namespace PnP.PowerShell.Commands.Base
{
[Cmdlet(VerbsCommon.Get, "PnPAzureCertificate", DefaultParameterSetName = "SELF")]
[OutputType(typeof(Model.AzureCertificate))]
public class GetPnPAdalCertificate : PSCmdlet
{
[Parameter(Mandatory = true)]
Expand All @@ -26,13 +27,23 @@ protected override void ProcessRecord()
if (System.IO.File.Exists(Path))
{
var certificate = new X509Certificate2(Path, Password, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
var rawCert = certificate.GetRawCertData();
var base64Cert = Convert.ToBase64String(rawCert);
var rawCertHash = certificate.GetCertHash();
var base64CertHash = Convert.ToBase64String(rawCertHash);
var keyId = Guid.NewGuid();
WriteAzureCertificateOutput(this, certificate, Password);
}
else
{
throw new PSArgumentException("Certificate file does not exist");
}
}

static string GetManifestEntry(X509Certificate2 certificate)
{
var rawCert = certificate.GetRawCertData();
var base64Cert = Convert.ToBase64String(rawCert);
var rawCertHash = certificate.GetCertHash();
var base64CertHash = Convert.ToBase64String(rawCertHash);
var keyId = Guid.NewGuid();

var template = @"
var template = @"
{{
""customKeyIdentifier"": ""{0}"",
""keyId"": ""{1}"",
Expand All @@ -41,24 +52,42 @@ protected override void ProcessRecord()
""value"": ""{2}""
}}
";
var manifestEntry = string.Format(template, base64CertHash, keyId, base64Cert);

var record = new PSObject();
record.Properties.Add(new PSVariableProperty(new PSVariable("Subject", certificate.Subject)));
record.Properties.Add(new PSVariableProperty(new PSVariable("ValidFrom", certificate.NotBefore)));
record.Properties.Add(new PSVariableProperty(new PSVariable("ValidTo", certificate.NotAfter)));
record.Properties.Add(new PSVariableProperty(new PSVariable("Thumbprint", certificate.Thumbprint)));

record.Properties.Add(new PSVariableProperty(new PSVariable("KeyCredentials", manifestEntry)));
record.Properties.Add(new PSVariableProperty(new PSVariable("Certificate", CertificateHelper.CertificateToBase64(certificate))));
record.Properties.Add(new PSVariableProperty(new PSVariable("PrivateKey", CertificateHelper.PrivateKeyToBase64(certificate))));
var manifestEntry = string.Format(template, base64CertHash, keyId, base64Cert);
return manifestEntry;
}

WriteObject(record);
static string/*?*/ GetPfxBase64OrWarn(Cmdlet cmdlet, X509Certificate2 certificate, SecureString password)
{
try
{
var pfxBytes = certificate.Export(X509ContentType.Pfx, password);
var base64string = Convert.ToBase64String(pfxBytes);
return base64string;
}
else
catch (Exception ex)
{
throw new PSArgumentException("Certificate file does not exist");
cmdlet.WriteWarning(ex.Message);
return null;
}
}

internal static void WriteAzureCertificateOutput(PSCmdlet cmdlet, X509Certificate2 certificate, SecureString password)
{
string manifestEntry = GetManifestEntry(certificate);
var pfxBase64 = GetPfxBase64OrWarn(cmdlet, certificate, password);

var record = new Model.AzureCertificate(
subject: certificate.Subject,
notBefore: certificate.NotBefore,
notAfter: certificate.NotAfter,
thumbprint: certificate.Thumbprint,
pfxBase64: pfxBase64,
keyCredentials: manifestEntry,
certificate: CertificateHelper.CertificateToBase64(certificate),
privateKey: CertificateHelper.PrivateKeyToBase64(certificate)
);

cmdlet.WriteObject(record);
}
}
}
36 changes: 4 additions & 32 deletions src/Commands/Base/NewAzureCertificate.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
using System.Management.Automation;
using PnP.PowerShell.Commands.Utilities;

using System;
using System.Collections.Generic;
using System.IO;
using System.Management.Automation;
using System.Security;
using System.Security.Cryptography.X509Certificates;
using PnP.PowerShell.Commands.Utilities;

namespace PnP.PowerShell.Commands.Base
{
[Cmdlet(VerbsCommon.New, "PnPAzureCertificate")]
[OutputType(typeof(Model.AzureCertificate))]
public class NewPnPAdalCertificate : PSCmdlet
{
[Parameter(Mandatory = false, Position = 0)]
Expand Down Expand Up @@ -108,36 +109,7 @@ protected override void ProcessRecord()
Host.UI.WriteLine(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, "Certificate added to store");
}

var rawCert = certificate.GetRawCertData();
var base64Cert = Convert.ToBase64String(rawCert);
var rawCertHash = certificate.GetCertHash();
var base64CertHash = Convert.ToBase64String(rawCertHash);
var keyId = Guid.NewGuid();

var template = @"
{{
""customKeyIdentifier"": ""{0}"",
""keyId"": ""{1}"",
""type"": ""AsymmetricX509Cert"",
""usage"": ""Verify"",
""value"": ""{2}""
}}
";
var manifestEntry = string.Format(template, base64CertHash, keyId, base64Cert);

var record = new PSObject();
record.Properties.Add(new PSVariableProperty(new PSVariable("Subject", certificate.Subject)));
record.Properties.Add(new PSVariableProperty(new PSVariable("ValidFrom", certificate.NotBefore)));
record.Properties.Add(new PSVariableProperty(new PSVariable("ValidTo", certificate.NotAfter)));
record.Properties.Add(new PSVariableProperty(new PSVariable("Thumbprint", certificate.Thumbprint)));
var pfxBytes = certificate.Export(X509ContentType.Pfx, CertificatePassword);
var base64string = Convert.ToBase64String(pfxBytes);
record.Properties.Add(new PSVariableProperty(new PSVariable("PfxBase64", base64string)));
record.Properties.Add(new PSVariableProperty(new PSVariable("KeyCredentials", manifestEntry)));
record.Properties.Add(new PSVariableProperty(new PSVariable("Certificate", CertificateHelper.CertificateToBase64(certificate))));
record.Properties.Add(new PSVariableProperty(new PSVariable("PrivateKey", CertificateHelper.PrivateKeyToBase64(certificate))));

WriteObject(record);
GetPnPAdalCertificate.WriteAzureCertificateOutput(this, certificate, CertificatePassword);
}
}
}
34 changes: 34 additions & 0 deletions src/Commands/Model/AzureCertificate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using PnP.PowerShell.Commands.Utilities;

using System;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace PnP.PowerShell.Commands.Model
{
public sealed class AzureCertificate
{
internal AzureCertificate(string subject, DateTime notBefore, DateTime notAfter, string thumbprint, string/*?*/ pfxBase64, string keyCredentials, string certificate, string privateKey)
{
Subject = subject ?? throw new ArgumentNullException(nameof(subject));
NotBefore = notBefore;
NotAfter = notAfter;
Thumbprint = thumbprint ?? throw new ArgumentNullException(nameof(thumbprint));
PfxBase64 = pfxBase64;
KeyCredentials = keyCredentials ?? throw new ArgumentNullException(nameof(keyCredentials));
Certificate = certificate ?? throw new ArgumentNullException(nameof(certificate));
PrivateKey = privateKey ?? throw new ArgumentNullException(nameof(privateKey));
}

public string Subject { get; }
public DateTime NotBefore { get; }
public DateTime NotAfter { get; }
public string Thumbprint { get; }
public string/*?*/ PfxBase64 { get; }
public string KeyCredentials { get; }
public string Certificate { get; }
public string PrivateKey { get; }

}
}

0 comments on commit bbc09f9

Please sign in to comment.