public static bool TryLoadFromFile(string publicKeyFile, out PublicKeyCertificate publicKeyCertificate)
        {
            publicKeyCertificate = null;

            try
            {
                X509Certificate2 certificate = new X509Certificate2(publicKeyFile);

                if (certificate.HasPrivateKey)
                {
                    TextLogger.LogError("Certificate from public key file {0} should not present a private key.", publicKeyFile);

                    return(false);
                }

                publicKeyCertificate = new PublicKeyCertificate(certificate);

                return(true);
            }
            catch (Exception e)
            {
                TextLogger.LogError("Failed to load public key certificate from public key file {0} : {1}", publicKeyFile, e);

                return(false);
            }
        }
Exemplo n.º 2
0
        /*
         * Private key certificate files (each private key certificate has an encrypted private key file (.pfx.encr) and an encrypted password file (.pfx.password.encr) ) as well as public key certificate files (i.e. cer files) are part of ServiceFabricEnvironmentSync application packages.
         *
         * All certificates to be installed by ServiceFabricEnvironmentSync need to be listed in the form of "CertificateFriendlyName=CertificateDataDirectory" in certificate section of ServiceFabricEnvironmentSync configuration file.
         *      1) CertificateDataDirectory refers to a relative path from application package root directory.
         *      2) For a public key certificate, CertificateFriendlyName.cer should be present in CertificateDataDirectory.
         *      3) For a private key certificate, CertificateFriendlyName.pfx.encr + CertificateFriendlyName.password.encr should be present in CertificateDataDirectory.
         *
         * All certificates listed would be installed in LocalMachine\My or LocalMachine\CA certificate store.
         *
         * Sample certificate configuration sections
         * [ServiceFabricEnvironmentSync.Certificate.LocalMachine.My]
         *  certA=data\certificates
         *  certB=data\certificates
         *
         * [ServiceFabricEnvironmentSync.Certificate.LocalMachine.CertificateAuthority]
         *  certC=data\certificates
         *  certD=data\certificates
         */
        public bool GetEnvironmentCertificatesFromCurrentConfigurations(StoreName storeName)
        {
            try
            {
                if (storeName != StoreName.My && storeName != StoreName.CertificateAuthority)
                {
                    TextLogger.LogError("Certificate store name {0} is not supported. Supported store names : {1}, {2}.", storeName, StoreName.My, StoreName.CertificateAuthority);

                    return(false);
                }

                string certificateListConfigurationSectionName = string.Format(CultureInfo.InvariantCulture, StringConstants.CertificateListConfigurationSectionNameTemplate, storeName);

                IConfiguration configuration = APConfiguration.GetConfiguration();

                if (configuration != null && configuration.SectionExists(certificateListConfigurationSectionName))
                {
                    string[] certificateFriendlyNames = configuration.GetSectionKeys(certificateListConfigurationSectionName);

                    if (certificateFriendlyNames != null)
                    {
                        foreach (string certificateFriendlyName in certificateFriendlyNames)
                        {
                            string certificateDataDirectoryName = configuration.GetStringValue(certificateListConfigurationSectionName, certificateFriendlyName);

                            string certificateDataDirectory = Path.Combine(this.applicationDirectory, certificateDataDirectoryName);

                            string encryptedPrivateKeyFile = Path.Combine(
                                certificateDataDirectory,
                                string.Format(
                                    CultureInfo.InvariantCulture,
                                    StringConstants.EncryptedPrivateKeyFileNameTemplate,
                                    certificateFriendlyName));

                            bool encryptedPrivateKeyFileExists = File.Exists(encryptedPrivateKeyFile);

                            string encryptedPasswordFile = Path.Combine(
                                certificateDataDirectory,
                                string.Format(
                                    CultureInfo.InvariantCulture,
                                    StringConstants.EncryptedPasswordFileNameTemplate,
                                    certificateFriendlyName));

                            bool encryptedPasswordFileExists = File.Exists(encryptedPasswordFile);

                            string publicKeyFile = Path.Combine(
                                certificateDataDirectory,
                                string.Format(
                                    CultureInfo.InvariantCulture,
                                    StringConstants.PublicKeyFileNameTemplate,
                                    certificateFriendlyName));

                            bool publicKeyFileExists = File.Exists(publicKeyFile);

                            // TODO: report health
                            if (!encryptedPrivateKeyFileExists && !encryptedPasswordFileExists && !publicKeyFileExists)
                            {
                                TextLogger.LogError("Neither encrypted private key & encrypted password files nor public key file exist for certificate {0} in certificate data directory {1}. A certificate to be installed needs to be either a public key certificate or a private key certificate.", certificateFriendlyName, certificateDataDirectory);

                                return(false);
                            }

                            if ((encryptedPrivateKeyFileExists || encryptedPasswordFileExists) && publicKeyFileExists)
                            {
                                TextLogger.LogError("Both encrypted private key & encrypted password files and public key file exist for certificate {0} in certificate data directory {1}. A certificate to be installed needs to be either a public key certificate or a private key certificate but not both.", certificateFriendlyName, certificateDataDirectory);

                                return(false);
                            }

                            if (encryptedPrivateKeyFileExists ^ encryptedPasswordFileExists)
                            {
                                TextLogger.LogError("Only one of encrypted private key file and encrypted password file exist for certificate {0} in certificate data directory {1}. Both are required to install a private key certificate.", certificateFriendlyName, certificateDataDirectory);

                                return(false);
                            }

                            if (publicKeyFileExists)
                            {
                                PublicKeyCertificate publicKeyCertificate;
                                if (!PublicKeyCertificate.TryLoadFromFile(publicKeyFile, out publicKeyCertificate))
                                {
                                    return(false);
                                }

                                if (this.environmentCertificates[storeName].ContainsKey(publicKeyCertificate.Thumbprint) && this.environmentCertificates[storeName][publicKeyCertificate.Thumbprint].HasPrivateKey)
                                {
                                    TextLogger.LogError("Certificate with thumbprint {0}, subject {1} are requested to be installed as both public key certificate and private key certificate in configuration under different entries.", publicKeyCertificate.Thumbprint, publicKeyCertificate.Certificate.Subject);

                                    return(false);
                                }

                                this.environmentCertificates[storeName][publicKeyCertificate.Thumbprint] = publicKeyCertificate;

                                TextLogger.LogInfo("Public key certificate with thumbprint {0}, subject {1} needs to be present in certificate store {2}\\{3} in local environment based on current configurations.", publicKeyCertificate.Thumbprint, publicKeyCertificate.Certificate.Subject, StoreLocation.LocalMachine, storeName);
                            }
                            else
                            {
                                if (storeName == StoreName.CertificateAuthority)
                                {
                                    TextLogger.LogError("Private key certificate {0} cannot be installed in certificate store with name {1}.", certificateFriendlyName, storeName);

                                    return(false);
                                }

                                PrivateKeyCertificate privateKeyCertificate;
                                if (!PrivateKeyCertificate.TryLoadFromFile(encryptedPrivateKeyFile, encryptedPasswordFile, out privateKeyCertificate))
                                {
                                    return(false);
                                }

                                if (this.environmentCertificates[storeName].ContainsKey(privateKeyCertificate.Thumbprint) && !this.environmentCertificates[storeName][privateKeyCertificate.Thumbprint].HasPrivateKey)
                                {
                                    TextLogger.LogError("Certificate with thumbprint {0}, subject {1} are requested to be installed as both public key certificate and private key certificate in configuration under different entries.", privateKeyCertificate.Thumbprint, privateKeyCertificate.Certificate.Subject);

                                    return(false);
                                }

                                this.environmentCertificates[storeName][privateKeyCertificate.Thumbprint] = privateKeyCertificate;

                                TextLogger.LogInfo("Private key certificate with thumbprint {0}, subject {1} needs to be present in certificate store {2}\\{3} in local environment based on current configurations.", privateKeyCertificate.Thumbprint, privateKeyCertificate.Certificate.Subject, StoreLocation.LocalMachine, storeName);
                            }
                        }
                    }
                }

                return(true);
            }
            catch (Exception e)
            {
                TextLogger.LogError("Failed to get environment certificates based on current configurations : {0}", e);

                return(false);
            }
        }