示例#1
0
        public void Load()
        {
            var path1 = Path.GetTempFileName();
            var path2 = Path.GetTempFileName();

            try
            {
                // Separate files with CRLF line endings.

                File.WriteAllText(path1, TestCertPart);
                File.WriteAllText(path2, TestKeyPart);

                var cert = TlsCertificate.Load(path1, path2);

                Assert.Equal(TlsCertificate.NormalizePem(TestCertPart), cert.CertPem);
                Assert.Equal(TlsCertificate.NormalizePem(TestKeyPart), cert.KeyPem);

                // Separate files with LF line endings.

                File.WriteAllText(path1, TlsCertificate.NormalizePem(TestCertPart));
                File.WriteAllText(path2, TlsCertificate.NormalizePem(TestKeyPart));

                cert = TlsCertificate.Load(path1, path2);

                Assert.Equal(TlsCertificate.NormalizePem(TestCertPart), cert.CertPem);
                Assert.Equal(TlsCertificate.NormalizePem(TestKeyPart), cert.KeyPem);

                // Combined file with CRLF line endings.

                File.WriteAllText(path1, TestCertPart + TestKeyPart);

                cert = TlsCertificate.Load(path1);

                File.WriteAllText(path1, TlsCertificate.NormalizePem(TestCertPart));
                File.WriteAllText(path2, TlsCertificate.NormalizePem(TestKeyPart));

                // Combined file with LF line endings.

                File.WriteAllText(path1, TlsCertificate.NormalizePem(TestCertPart) + TlsCertificate.NormalizePem(TestKeyPart));

                cert = TlsCertificate.Load(path1);

                File.WriteAllText(path1, TlsCertificate.NormalizePem(TestCertPart));
                File.WriteAllText(path2, TlsCertificate.NormalizePem(TestKeyPart));
            }
            finally
            {
                File.Delete(path1);
                File.Delete(path2);
            }
        }
示例#2
0
        /// <summary>
        /// Loads the certificate files (if any).
        /// </summary>
        /// <returns>
        /// Returns a <see cref="TlsCertificate"/> instance with the loaded public certificate
        /// and private key or <c>null</c> if no certificate is defined.
        /// </returns>
        public TlsCertificate Load()
        {
            if (IsSecured)
            {
                var certificate = TlsCertificate.Load(Path);

                certificate.Parse();

                return(certificate);
            }
            else
            {
                return(null);
            }
        }
示例#3
0
        public void Load()
        {
            using (var tempFolder = new TempFolder())
            {
                var path1 = Path.Combine(tempFolder.Path, "test1");
                var path2 = Path.Combine(tempFolder.Path, "test2");

                // Separate files with CRLF line endings.

                File.WriteAllText(path1, TestCertPart);
                File.WriteAllText(path2, TestKeyPart);

                var cert = TlsCertificate.Load(path1, path2);

                Assert.Equal(TlsCertificate.NormalizePem(TestCertPart), cert.CertPem);
                Assert.Equal(TlsCertificate.NormalizePem(TestKeyPart), cert.KeyPem);

                // Separate files with LF line endings.

                File.WriteAllText(path1, TlsCertificate.NormalizePem(TestCertPart));
                File.WriteAllText(path2, TlsCertificate.NormalizePem(TestKeyPart));

                cert = TlsCertificate.Load(path1, path2);

                Assert.Equal(TlsCertificate.NormalizePem(TestCertPart), cert.CertPem);
                Assert.Equal(TlsCertificate.NormalizePem(TestKeyPart), cert.KeyPem);

                // Combined file with CRLF line endings.

                File.WriteAllText(path1, TestCertPart + TestKeyPart);

                cert = TlsCertificate.Load(path1);

                File.WriteAllText(path1, TlsCertificate.NormalizePem(TestCertPart));
                File.WriteAllText(path2, TlsCertificate.NormalizePem(TestKeyPart));

                // Combined file with LF line endings.

                File.WriteAllText(path1, TlsCertificate.NormalizePem(TestCertPart) + TlsCertificate.NormalizePem(TestKeyPart));

                cert = TlsCertificate.Load(path1);

                File.WriteAllText(path1, TlsCertificate.NormalizePem(TestCertPart));
                File.WriteAllText(path2, TlsCertificate.NormalizePem(TestKeyPart));
            }
        }
示例#4
0
        /// <inheritdoc/>
        public override void Run(CommandLine commandLine)
        {
            if (commandLine.Arguments.Length == 0 || commandLine.HasHelpOption)
            {
                Help();
                Program.Exit(0);
            }

            Program.ConnectHive();

            var hive = HiveHelper.Hive;

            // Parse the arguments.

            var command = commandLine.Arguments.ElementAtOrDefault(0);

            if (string.IsNullOrEmpty(command))
            {
                Console.Error.WriteLine($"*** ERROR: COMMAND expected.");
                Program.Exit(1);
            }

            var registry = string.Empty;
            var username = string.Empty;
            var password = string.Empty;
            var certPath = string.Empty;
            var secret   = string.Empty;

            switch (command)
            {
            case "login":

                // Read the arguments.

                registry = commandLine.Arguments.ElementAtOrDefault(1);

                if (!string.IsNullOrEmpty(registry))
                {
                    if (!HiveDefinition.NameRegex.IsMatch(registry))
                    {
                        Console.Error.WriteLine($"*** ERROR: [{registry}] is not a valid hostname.");
                        Program.Exit(1);
                    }

                    username = commandLine.Arguments.ElementAtOrDefault(1);

                    if (!string.IsNullOrEmpty(username))
                    {
                        password = commandLine.Arguments.ElementAtOrDefault(2);

                        if (password == "-")
                        {
                            password = NeonHelper.ReadStandardInputText().Trim();

                            if (string.IsNullOrEmpty(password))
                            {
                                Console.Error.WriteLine("*** ERROR: No password was read from STDIN.");
                                Program.Exit(1);
                            }
                        }
                    }
                }

                // Execute the command.

                hive.Registry.Login(registry, username, password);
                break;

            case "logout":

                // Read the arguments.

                registry = commandLine.Arguments.ElementAtOrDefault(1);

                if (!string.IsNullOrEmpty(registry) && !HiveDefinition.NameRegex.IsMatch(registry))
                {
                    Console.Error.WriteLine($"*** ERROR: [{registry}] is not a valid hostname.");
                    Program.Exit(1);
                }

                // Execute the command.

                hive.Registry.Logout(registry);
                break;

            case "service":

                var serviceCommand = commandLine.Arguments.ElementAtOrDefault(1);

                if (string.IsNullOrEmpty(serviceCommand))
                {
                    Console.Error.WriteLine($"*** ERROR: service COMMAND expected.");
                    Program.Exit(1);
                }

                switch (serviceCommand)
                {
                case "create":

                    registry = commandLine.Arguments.ElementAtOrDefault(2);

                    if (string.IsNullOrEmpty(registry))
                    {
                        Console.Error.WriteLine($"*** ERROR: Expected HOSTNAME.");
                        Program.Exit(1);
                    }

                    if (!HiveDefinition.NameRegex.IsMatch(registry))
                    {
                        Console.Error.WriteLine($"*** ERROR: [{registry}] is not a valid hostname.");
                        Program.Exit(1);
                    }

                    certPath = commandLine.Arguments.ElementAtOrDefault(3);

                    if (string.IsNullOrEmpty(certPath))
                    {
                        Console.Error.WriteLine($"*** ERROR: Expected CERT-PATH.");
                        Program.Exit(1);
                    }

                    if (!File.Exists(certPath))
                    {
                        Console.Error.WriteLine($"*** ERROR: Cannot load certificate from [{certPath}].");
                        Program.Exit(1);
                    }

                    var certificate = TlsCertificate.Load(certPath);

                    certificate.Parse();

                    if (!certificate.IsValidDate())
                    {
                        Console.Error.WriteLine($"*** ERROR: The certificate expired on [{certificate.ValidUntil}].");
                        Program.Exit(1);
                    }

                    if (!certificate.IsValidHost(registry))
                    {
                        Console.Error.WriteLine($"*** ERROR: The certificate does not cover [{registry}].");
                        Program.Exit(1);
                    }

                    secret = commandLine.Arguments.ElementAtOrDefault(4);

                    if (string.IsNullOrEmpty(secret))
                    {
                        Console.Error.WriteLine($"*** ERROR: Expected SECRET.");
                        Program.Exit(1);
                    }

                    username = commandLine.Arguments.ElementAtOrDefault(5);

                    if (!string.IsNullOrEmpty(username))
                    {
                        password = commandLine.Arguments.ElementAtOrDefault(6);

                        if (password == "-")
                        {
                            password = NeonHelper.ReadStandardInputText().Trim();

                            if (string.IsNullOrEmpty(password))
                            {
                                Console.Error.WriteLine("*** ERROR: No password was read from STDIN.");
                                Program.Exit(1);
                            }
                        }
                    }

                    // Execute the command.

                    Console.WriteLine();
                    hive.Registry.CreateLocalRegistry(registry, username, password, secret, certificate,
                                                      progress:  message => Console.WriteLine(message));

                    break;

                case "prune":

                    if (!hive.Registry.HasLocalRegistry)
                    {
                        Console.Error.WriteLine($"*** ERROR: The [{hive.Name}] hive does not have a local registry deployed.");
                        Program.Exit(1);
                    }

                    Console.WriteLine();
                    hive.Registry.PruneLocalRegistry(progress: message => Console.WriteLine(message));
                    break;

                case "remove":
                case "rm":

                    if (!hive.Registry.HasLocalRegistry)
                    {
                        Console.Error.WriteLine($"*** ERROR: The [{hive.Name}] hive does not have a local registry deployed.");
                        Program.Exit(1);
                    }

                    Console.WriteLine();
                    hive.Registry.RemoveLocalRegistry(progress: message => Console.WriteLine(message));
                    break;

                case "status":

                    Console.WriteLine();

                    if (hive.Registry.HasLocalRegistry)
                    {
                        Console.WriteLine($"Local Docker registry is deployed on [{hive.Name}].");
                        Program.Exit(0);
                    }
                    else
                    {
                        Console.WriteLine($"No local Docker registry is deployed on [{hive.Name}].");
                        Program.Exit(1);
                    }
                    break;

                default:

                    Console.Error.WriteLine($"*** ERROR: Unexpected [{serviceCommand}] command.");
                    Program.Exit(1);
                    break;
                }
                break;

            default:

                Console.Error.WriteLine($"*** ERROR: Unexpected [{command}] command.");
                Program.Exit(1);
                break;
            }
        }
示例#5
0
        /// <summary>
        /// Verifies a local certificate file.
        /// </summary>
        /// <param name="commandLine">The command line.</param>
        private void VerifyLocalCertificate(CommandLine commandLine)
        {
            // $todo(jeff.lill):
            //
            // Consider using the new [TlsCertificate.Validate()] method.  The only
            // disadvantage of this method is that it doesn't output the error
            // messages from the certificate tool.
            //
            // On the other hand, this code might become moot when we upgrade
            // to use the built-in .NET X.509 classes.

            if (commandLine.Arguments.Length != 1)
            {
                Console.Error.WriteLine("*** ERROR: Expected argument: PATH");
                Program.Exit(1);
            }

            var certificate = TlsCertificate.Load(commandLine.Arguments[0]);

            // We're going to split the certificate into two files, the issued
            // certificate and the certificate authority's certificate chain
            // (AKA the CA bundle).

            var tempCertPath = Path.GetTempFileName();
            var tempCaPath   = Path.GetTempFileName();
            var tool         = "openssl";

            if (NeonHelper.IsLinux && HiveHelper.InToolContainer)
            {
                // Choose nicer looking temporary file names when we're running the
                // tool container and don't need to worry about conflicting files.

                tempCertPath = Path.GetFileNameWithoutExtension(commandLine.Arguments[0]);
                tempCaPath   = tempCertPath + ".ca";
            }

            try
            {
                var pos = certificate.CertPem.IndexOf("-----END CERTIFICATE-----");

                if (pos == -1)
                {
                    throw new ArgumentNullException("The certificate is not formatted properly.");
                }

                pos = certificate.CertPem.IndexOf("-----BEGIN CERTIFICATE-----", pos);

                var issuedCert = certificate.CertPem.Substring(0, pos);
                var caBundle   = certificate.CertPem.Substring(pos);

                File.WriteAllText(tempCertPath, issuedCert);
                File.WriteAllText(tempCaPath, caBundle);

                var sbArgs = new StringBuilder();

                // We're going to use [certutil] for Windows and [OpenSSL]
                // for everything else.

                if (NeonHelper.IsWindows)
                {
                    tool = "certutil";

                    sbArgs.Append("-verify ");
                    sbArgs.Append($"\"{tempCertPath}\" ");
                    sbArgs.Append($"\"{tempCaPath}\"");

                    var result = NeonHelper.ExecuteCapture("certutil", sbArgs.ToString());

                    Console.WriteLine(result.OutputText);
                    Console.Error.WriteLine(result.ErrorText);

                    Program.Exit(result.ExitCode);
                }
                else
                {
                    sbArgs.Append("verify ");
                    sbArgs.Append("-purpose sslserver ");
                    sbArgs.Append($"-CAfile \"{tempCaPath}\" ");
                    sbArgs.Append($"\"{tempCertPath}\"");

                    var result = NeonHelper.ExecuteCapture("openssl", sbArgs.ToString());

                    Console.WriteLine(result.OutputText);
                    Console.Error.WriteLine(result.ErrorText);

                    Program.Exit(result.ExitCode);
                }
            }
            catch (Win32Exception)
            {
                Console.Error.WriteLine($"*** ERROR: Cannot find the [{tool}] SSL certificate utility on the PATH.");
                Program.Exit(1);
            }
            finally
            {
                File.Delete(tempCertPath);
                File.Delete(tempCaPath);
            }
        }
示例#6
0
        /// <inheritdoc/>
        public override void Run(CommandLine commandLine)
        {
            if (commandLine.HasHelpOption)
            {
                Console.WriteLine(usage);
                Program.Exit(0);
            }

            // Process the command arguments.

            TlsCertificate certificate;
            string         certName;

            var command = commandLine.Arguments.FirstOrDefault();

            if (command == null)
            {
                Console.WriteLine(usage);
                Program.Exit(1);
            }

            commandLine = commandLine.Shift(1);

            switch (command)
            {
            case "get":

                Program.ConnectHive();

                certName = commandLine.Arguments.FirstOrDefault();

                if (string.IsNullOrEmpty(certName))
                {
                    Console.Error.WriteLine("*** ERROR: Expected arguments: NAME");
                    Program.Exit(1);
                }

                if (!HiveDefinition.IsValidName(certName))
                {
                    Console.Error.WriteLine($"*** ERROR: [{certName}] is not a valid certificate name.");
                    Program.Exit(1);
                }

                certificate = HiveHelper.Hive.Certificate.Get(certName);

                if (certificate == null)
                {
                    Console.Error.WriteLine($"*** ERROR: Certificate [{certName}] does not exist.");
                    Program.Exit(1);
                }

                Console.WriteLine(certificate.CombinedPem);
                break;

            case "join":

                if (commandLine.Arguments.Length != 3)
                {
                    Console.Error.WriteLine("*** ERROR: Expected arguments: PATH-CERT PATH-KEY PATH-OUTPUT");
                    Program.Exit(1);
                }

                certificate = TlsCertificate.Load(commandLine.Arguments[0], commandLine.Arguments[1]);

                File.WriteAllText(commandLine.Arguments[2], certificate.CombinedPem);
                break;

            case "list":
            case "ls":

                Program.ConnectHive();

                var certList = new List <CertInfo>();

                DateTime?checkDate = null;
                bool     expired   = false;

                if (commandLine.GetOption("--expired") != null)
                {
                    checkDate = DateTime.UtcNow;
                    expired   = true;
                }
                else if (commandLine.GetOption("--expiring") != null)
                {
                    checkDate = DateTime.UtcNow + TimeSpan.FromDays(30);
                }

                // List the certificate key/names and then fetch each one
                // to capture details like the expiration date and covered
                // hostnames.

                foreach (var name in HiveHelper.Hive.Certificate.List())
                {
                    certificate = HiveHelper.Hive.Certificate.Get(name);

                    if (checkDate.HasValue && certificate.IsValidDate(checkDate))
                    {
                        continue;
                    }

                    certList.Add(new CertInfo(name, certificate));
                }

                if (checkDate.HasValue && certList.Count == 0)
                {
                    Console.WriteLine(expired ? "* No certificates have expired." : "* No certificates are expiring within 30 days.");
                    Program.Exit(0);
                }

                if (certList.Count > 0)
                {
                    var nameHeader       = "Name";
                    var validUntilHeader = "Valid Until";
                    var hostsHeader      = "Hosts";
                    var nameColumnWidth  = Math.Max(nameHeader.Length, certList.Max(ci => ci.Name.Length));
                    var dateColumnWidth  = Math.Max(validUntilHeader.Length, certList.Max(ci => ci.ValidUntil.Length));
                    var hostColumnWidth  = Math.Max(hostsHeader.Length, certList.Max(ci => ci.Hosts.Length));

                    Console.WriteLine($"{nameHeader}{new string(' ', nameColumnWidth - "Name".Length)}   {validUntilHeader}{new string(' ', dateColumnWidth - validUntilHeader.Length)}   {hostsHeader}");
                    Console.WriteLine($"{new string('-', nameColumnWidth)}   {new string('-', dateColumnWidth)}   {new string('-', hostColumnWidth)}");

                    foreach (var certInfo in certList.OrderBy(ci => ci.Name.ToLowerInvariant()))
                    {
                        Console.WriteLine($"{certInfo.Name}{new string(' ', nameColumnWidth - certInfo.Name.Length)}   {certInfo.ValidUntil}{new string(' ', dateColumnWidth - certInfo.ValidUntil.Length)}   {certInfo.Hosts}");
                    }

                    if (checkDate.HasValue)
                    {
                        Program.Exit(1);
                    }
                }
                else
                {
                    Console.WriteLine("* No certificates");
                }
                break;

            case "remove":
            case "rm":

                Program.ConnectHive();

                certName = commandLine.Arguments.FirstOrDefault();

                if (string.IsNullOrEmpty(certName))
                {
                    Console.Error.WriteLine("*** ERROR: Expected arguments: NAME");
                    Program.Exit(1);
                }

                if (!HiveDefinition.IsValidName(certName))
                {
                    Console.Error.WriteLine($"*** ERROR: [{certName}] is not a valid certificate name.");
                    Program.Exit(1);
                }

                if (HiveHelper.Hive.Certificate.Get(certName) != null)
                {
                    HiveHelper.Hive.Certificate.Remove(certName);
                    Console.WriteLine($"Certificate [{certName}] was removed.");
                }
                else
                {
                    Console.Error.WriteLine($"*** ERROR: [{certName}] does not exist.");
                    Program.Exit(1);
                }
                break;

            case "set":

                Program.ConnectHive();

                using (var vault = HiveHelper.OpenVault(Program.HiveLogin.VaultCredentials.RootToken))
                {
                    if (commandLine.Arguments.Length != 2)
                    {
                        Console.Error.WriteLine("*** ERROR: Expected arguments: NAME PATH");
                        Program.Exit(1);
                    }

                    certName = commandLine.Arguments.FirstOrDefault();

                    if (string.IsNullOrEmpty(certName))
                    {
                        Console.Error.WriteLine("*** ERROR: Expected arguments: NAME");
                        Program.Exit(1);
                    }

                    if (!HiveDefinition.IsValidName(certName))
                    {
                        Console.Error.WriteLine($"*** ERROR: [{certName}] is not a valid certificate name.");
                        Program.Exit(1);
                    }

                    certificate = TlsCertificate.Load(commandLine.Arguments.ElementAtOrDefault(1));

                    certificate.Parse();

                    if (HiveHelper.Hive.Certificate.Get(certName) == null)
                    {
                        HiveHelper.Hive.Certificate.Set(certName, certificate);
                        Console.WriteLine($"Certificate [{certName}] was added.");
                    }
                    else
                    {
                        HiveHelper.Hive.Certificate.Set(certName, certificate);
                        Console.WriteLine($"Certificate [{certName}] was updated.");
                    }
                }
                break;

            case "split":

                if (commandLine.Arguments.Length != 3)
                {
                    Console.Error.WriteLine("*** ERROR: Expected arguments: PATH PATH-CERT PATH-KEY");
                    Program.Exit(1);
                }

                certificate = TlsCertificate.Load(commandLine.Arguments[0]);

                File.WriteAllText(commandLine.Arguments[1], certificate.CertPem);
                File.WriteAllText(commandLine.Arguments[2], certificate.KeyPem);
                break;

            case "verify":

                VerifyLocalCertificate(commandLine);
                break;

            default:

                Console.Error.WriteLine($"*** ERROR: Unknown command: [{command}]");
                Program.Exit(1);
                break;
            }
        }