diff --git a/src/MembershipServices.Cli/Program.cs b/src/MembershipServices.Cli/Program.cs index e922c8edf19..6ed5774d357 100644 --- a/src/MembershipServices.Cli/Program.cs +++ b/src/MembershipServices.Cli/Program.cs @@ -90,6 +90,25 @@ class ExtendOptions public string Type { get; set; } } + [Verb("sync", HelpText = "Synchronize local MSD with the specified CA.")] + class SyncOptions + { + [Option("datadir", Required = true, HelpText = "The location of the underlying node's root folder.")] + public string DataDir { get; set; } + + [Option("caurl", Required = false, Default = "https://localhost:5001", HelpText = "The URL of the certificate authority to synchronize with.")] + public string CaUrl { get; set; } + + [Option("caaccountid", Required = true, HelpText = "The account ID of the CA user.")] + public string CaAccountId { get; set; } + + [Option("capassword", Required = true, HelpText = "The account password of the CA user.")] + public string CaPassword { get; set; } + + [Option("password", Required = true, HelpText = "The password for the node's keystore.")] + public string Password { get; set; } + } + static int RunHelp(HelpOptions options) { return 0; @@ -164,7 +183,6 @@ static int RunGenerate(GenerateOptions options) File.WriteAllBytes(Path.Combine(nodeSettings.DataFolder.RootPath, CertificatesManager.ClientCertificateName), CaCertificatesManager.CreatePfx(clientCert, privateKey, keyStoreSettings.Password)); return 0; - } static int RunShowTemplate(ShowTemplateOptions options) @@ -224,16 +242,41 @@ static int RunExtend(ExtendOptions options) return 0; } + static int RunSync(SyncOptions options) + { + // TODO: Move this logic into a reusable method + var network = new TokenlessNetwork(); + var nodeSettings = new NodeSettings(network, args: new[] { $"-datadir={options.DataDir}", $"-password={options.Password}", $"-caaccountid={options.CaAccountId}", $"-capassword={options.CaPassword}" }); + + var membershipServices = new MembershipServicesDirectory(nodeSettings); + membershipServices.Initialize(); + + var caClient = new CaClient(new Uri(options.CaUrl), new HttpClient(), int.Parse(options.CaAccountId), options.CaPassword); + + foreach (var cert in caClient.GetAllCertificates()) + { + membershipServices.AddLocalMember(cert.ToCertificate(), MemberType.NetworkPeer); + } + + foreach (string thumbprint in caClient.GetRevokedCertificates()) + { + membershipServices.RevokeCertificate(thumbprint); + } + + return 0; + } + public static void Main(string[] args) { // https://hyperledger-fabric.readthedocs.io/en/release-2.0/commands/cryptogen.html - Parser.Default.ParseArguments(args) + Parser.Default.ParseArguments(args) .MapResult( (HelpOptions opts) => RunHelp(opts), (GenerateOptions opts) => RunGenerate(opts), (ShowTemplateOptions opts) => RunShowTemplate(opts), (VersionOptions opts) => RunVersion(opts), (ExtendOptions opts) => RunExtend(opts), + (SyncOptions opts) => RunSync(opts), errs => 1); } } diff --git a/src/MembershipServices/IMembershipServicesDirectory.cs b/src/MembershipServices/IMembershipServicesDirectory.cs index 0de2c8de1cc..f4e6ee26432 100644 --- a/src/MembershipServices/IMembershipServicesDirectory.cs +++ b/src/MembershipServices/IMembershipServicesDirectory.cs @@ -13,6 +13,8 @@ public interface IMembershipServicesDirectory X509Certificate GetCertificateForTransactionSigningPubKeyHash(byte[] transactionSigningPubKeyHash); + void RevokeCertificate(string thumbprint); + bool IsCertificateRevoked(string thumbprint); /// diff --git a/src/MembershipServices/LocalMembershipServicesConfiguration.cs b/src/MembershipServices/LocalMembershipServicesConfiguration.cs index cffaade34bc..a1fa6bfb2a4 100644 --- a/src/MembershipServices/LocalMembershipServicesConfiguration.cs +++ b/src/MembershipServices/LocalMembershipServicesConfiguration.cs @@ -175,7 +175,8 @@ public void RevokeCertificate(string thumbprint) file.Flush(); file.Dispose(); - // TODO: Delete from the local MSD folders and mappings too? + // TODO: Delete from the other mappings & the local MSD folder(s) + this.mapThumbprints.TryRemove(thumbprint, out _); } public bool IsCertificateRevoked(string thumbprint) diff --git a/src/MembershipServices/MembershipServicesDirectory.cs b/src/MembershipServices/MembershipServicesDirectory.cs index 3f8d7025340..ec3343cdfd5 100644 --- a/src/MembershipServices/MembershipServicesDirectory.cs +++ b/src/MembershipServices/MembershipServicesDirectory.cs @@ -2,7 +2,6 @@ using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Runtime.CompilerServices; using System.Security.Cryptography.X509Certificates; using System.Text; using CertificateAuthority; @@ -124,6 +123,11 @@ public X509Certificate GetCertificateForTransactionSigningPubKeyHash(byte[] tran return this.localMembershipServices.GetCertificateByTransactionSigningPubKeyHash(transactionSigningPubKeyHash); } + public void RevokeCertificate(string thumbprint) + { + this.localMembershipServices.RevokeCertificate(thumbprint); + } + // TODO: Perhaps move revocation checking into a sub-component of the MSD to keep the top level cleaner. public bool IsCertificateRevoked(string thumbprint) {