public bool ConfigureLocalNode(ClusterTopology topologyToDeploy)
        {
            try
            {
                TextLogger.LogInfo("Configuring local Service Fabric node based on bootstrap cluster manifest.");

                if (!this.InvokeFabricDeployer(topologyToDeploy, DeploymentType.Create, false))
                {
                    TextLogger.LogError("Failed to configure local Service Fabric node based on bootstrap cluster manifest.");

                    return(false);
                }

                Utilities.SetWindowsFabricNodeConfigurationCompleted(false);

                TextLogger.LogInfo("Successfully configured local Service Fabric node based on bootstrap cluster manifest.");

                return(true);
            }
            catch (Exception e)
            {
                TextLogger.LogError("Failed to configure local Service Fabric node based on bootstrap cluster manifest : {0}", e);

                return(false);
            }
        }
Ejemplo n.º 2
0
        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);
            }
        }
Ejemplo n.º 3
0
        /*
         * TODO: currently AP safe config deployment is not supported to update configurations.
         * The only way to update the configurations is via an application upgrade.
         */
        public static bool GetCurrentConfigurations()
        {
            IConfiguration configuration = APConfiguration.GetConfiguration();

            CertificateManagerRunIntervalSeconds = configuration.GetInt32Value(StringConstants.CertificateManagerConfigurationSectionName, "CertificateManagerRunIntervalSeconds", 3600);

            CertificateManagerRetryIntervalSeconds = configuration.GetInt32Value(StringConstants.CertificateManagerConfigurationSectionName, "CertificateManagerRetryIntervalSeconds", 300);

            EnableSecretStorePersistentCaching = configuration.GetBoolValue(StringConstants.CertificateManagerConfigurationSectionName, "EnableSecretStoreClientSidePersistentCaching", true);

            string logLevelString = configuration.GetStringValue(StringConstants.EnvironmentSyncConfigurationSectionName, "LogLevel", "Info");

            LogLevel logLevel;

            if (!Enum.TryParse <LogLevel>(logLevelString, out logLevel))
            {
                TextLogger.LogError("Log level is invalid : {0}.", logLevelString);

                return(false);
            }

            LogLevel = logLevel;

            return(true);
        }
        public bool InstallProduct()
        {
            TextLogger.LogInfo("Installing Service Fabric product.");

            try
            {
                string installedServiceFabricProductVersion = Utilities.GetCurrentWindowsFabricVersion();

                if (installedServiceFabricProductVersion == null)
                {
                    /*
                     * For Service Fabric on Autopilot, xcopyable deployment is the only supported mechanism for installing Service Fabric product.
                     * MSI is not supported.
                     */
                    string serviceFabricCabFile = this.GetServiceFabricCabFile();

                    if (File.Exists(serviceFabricCabFile))
                    {
                        TextLogger.LogInfo("Installing Service Fabric product with cab file {0}.", serviceFabricCabFile);

                        string localInstallationPath = Environment.ExpandEnvironmentVariables(Constants.FabricRootPath);
                        if (!Directory.Exists(localInstallationPath))
                        {
                            Directory.CreateDirectory(localInstallationPath);
                        }

                        Utilities.UnCabFile(serviceFabricCabFile, localInstallationPath);

                        Utilities.SetFabricRoot(localInstallationPath);

                        Utilities.SetFabricCodePath(Path.Combine(localInstallationPath, Constants.PathToFabricCode));

                        // TODO: registry key not available yet
                        installedServiceFabricProductVersion = Utilities.GetCurrentWindowsFabricVersion();

                        TextLogger.LogInfo("Successfully installed Service Fabric product version {0} to local path {1} and set Service Fabric registry keys.", installedServiceFabricProductVersion, localInstallationPath);
                    }
                    else
                    {
                        // TODO: [General] surface fatal errors outside the agent as AP health report.
                        TextLogger.LogError("Failed to install Service Fabric product : Service Fabric product cab file does not exist in agent application directory as {0}.", serviceFabricCabFile);

                        return(false);
                    }
                }
                else
                {
                    TextLogger.LogInfo("Service Fabric product version {0} is already installed locally. Skip product installation.", installedServiceFabricProductVersion);
                }

                return(true);
            }
            catch (Exception e)
            {
                TextLogger.LogError("Failed to install Service Fabric product : {0}", e);

                return(false);
            }
        }
Ejemplo n.º 5
0
        public static bool TryLoadFromFile(string encryptedPrivateKeyFile, string encryptedPasswordFile, out PrivateKeyCertificate privateKeyCertificate)
        {
            privateKeyCertificate = null;

            try
            {
                byte[] encryptedPrivateKeyBytes = File.ReadAllBytes(encryptedPrivateKeyFile);
                byte[] encryptedPasswordBytes   = File.ReadAllBytes(encryptedPasswordFile);

                byte[] decryptedPrivateKeyBlob;
                byte[] decryptedPasswordBlob;

                using (ApSecretProtection protect = new ApSecretProtection(ConfigurationManager.EnableSecretStorePersistentCaching))
                {
                    decryptedPrivateKeyBlob = protect.Decrypt(encryptedPrivateKeyBytes);
                    decryptedPasswordBlob   = protect.Decrypt(encryptedPasswordBytes);
                }

                string decryptedPassword;
                using (MemoryStream stream = new MemoryStream(decryptedPasswordBlob))
                    using (StreamReader reader = new StreamReader(stream))
                    {
                        decryptedPassword = reader.ReadToEnd().Trim();
                    }

                X509Certificate2 certificate = new X509Certificate2(decryptedPrivateKeyBlob, decryptedPassword, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet);

                if (!certificate.HasPrivateKey)
                {
                    TextLogger.LogError("Certificate from encrypted private key file {0} should present a private key.", encryptedPrivateKeyFile);

                    return(false);
                }

                if (!(certificate.PrivateKey is RSACryptoServiceProvider))
                {
                    TextLogger.LogError("Private key certificate from encrypted private key file {0} does not use a RSA based asymmetric algorithm implementation.", encryptedPrivateKeyFile);

                    return(false);
                }

                privateKeyCertificate = new PrivateKeyCertificate(certificate);

                return(true);
            }
            catch (Exception e)
            {
                TextLogger.LogError("Failed to load private key certificate from encrypted private key file {0} / encrypted password file {1} : {2}", encryptedPrivateKeyFile, encryptedPasswordFile, e);

                return(false);
            }
        }
Ejemplo n.º 6
0
        public static bool ReportMachineProperty(string machineName, MachinePropertyLevel propertyLevel, string property, string value)
        {
            if (useTestMode)
            {
                TextLogger.LogInfo("Test mode machine property report => machine : {0}, level : {1}, property : {2}, value : {3}.", machineName, propertyLevel, property, value);

                return(true);
            }
            else
            {
                try
                {
                    UpdateMachinePropertyRequest request = new UpdateMachinePropertyRequest
                    {
                        StatusFlag  = "always",
                        Environment = APRuntime.EnvironmentName,
                    };

                    request.PropertyList.Add(
                        new DMMachineProperty
                    {
                        MachineName = machineName,
                        Level       = propertyLevel,
                        Property    = property,
                        Value       = value
                    });

                    DMServerResponseCode responseCode = dmCommands.UpdateMachineProperty(request);
                    if (responseCode != DMServerResponseCode.Ok)
                    {
                        TextLogger.LogError("Failed to report {0} level machine property {1} against machine {2} with value {3}. Response code : {4}.", propertyLevel, property, machineName, value, responseCode);

                        return(false);
                    }

                    return(true);
                }
                catch (Exception e)
                {
                    TextLogger.LogError("Failed to report {0} level machine property {1} against machine {2} with value {3} : {4}.", propertyLevel, property, machineName, value, e);

                    return(false);
                }
            }
        }
        private bool ComputeNextStateFromManagingNetworkConfigurationState(out ServiceFabricAutopilotAgentState nextState)
        {
            nextState = ServiceFabricAutopilotAgentState.None;

            try
            {
                bool serviceFabricNodeConfigurationCompleted = Utilities.IsWindowsFabricNodeConfigurationCompleted(false);

                TextLogger.LogInfo("Service Fabric node configuration completed locally :  {0}.", serviceFabricNodeConfigurationCompleted);

                if (!serviceFabricNodeConfigurationCompleted)
                {
                    nextState = ServiceFabricAutopilotAgentState.InstallingProduct;
                }
                else
                {
                    ServiceController fabricHostService = this.localNodeManager.GetInstalledService(Constants.FabricHostServiceName);

                    if (fabricHostService == null)
                    {
                        // TODO: consider assert instead of an error message
                        TextLogger.LogError("Service Fabric node configuration has completed locally while Fabric host service does not exist.");

                        return(false);
                    }

                    if (fabricHostService.Status != ServiceControllerStatus.Running)
                    {
                        nextState = ServiceFabricAutopilotAgentState.StartingNode;
                    }
                    else
                    {
                        nextState = ServiceFabricAutopilotAgentState.NodeStarted;
                    }
                }

                return(true);
            }
            catch (Exception e)
            {
                TextLogger.LogError("Failed to compute next state from {0} state : {1}", ServiceFabricAutopilotAgentState.ManagingNetworkConfiguration, e);

                return(false);
            }
        }
        private bool GetLocalMachineSku(out string localMachineSku)
        {
            localMachineSku = null;

            if (this.useTestMode)
            {
                localMachineSku = "TestModeMachineSku";

                return(true);
            }

            // When server pool is enabled, logical machine name would be used. Otherwise, physical machine name would be used.
            // Note that in a server pool disabled environment, logical machine names would be the same as physical machine names.
            string machineInfoFile  = Path.Combine(APRuntime.DataDirectory, StringConstants.MachineInfoFileName);
            string localMachineName = APRuntime.MachineName;

            try
            {
                using (CsvReader reader = new CsvReader(machineInfoFile))
                {
                    while (reader.Read())
                    {
                        if (string.Compare(reader["MachineName"], localMachineName, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            localMachineSku = reader["SKU"];

                            TextLogger.LogInfo("Local machine {0} is using machine SKU {1}.", localMachineName, localMachineSku);

                            return(true);
                        }
                    }
                }

                TextLogger.LogError("Local machine {0} is not in machine info file {1}.", localMachineName, machineInfoFile);

                return(false);
            }
            catch (Exception e)
            {
                TextLogger.LogError("Failed to get machine SKU of local machine {0} from machine info file {1} : {2}", localMachineName, machineInfoFile, e);

                return(false);
            }
        }
        private bool ReadBootstrapClusterManifestFile(out ClusterManifestType bootstrapClusterManifest)
        {
            bootstrapClusterManifest = null;

            string bootstrapClusterManifestFile = this.GetBootstrapClusterManifestFile();

            try
            {
                if (!File.Exists(bootstrapClusterManifestFile))
                {
                    TextLogger.LogError("Bootstrap cluster manifest does not exist in application directory as {0}.", bootstrapClusterManifestFile);

                    return(false);
                }

                /*
                 * As part of application directory, the bootstrap cluster manifest would only be updated via application upgrades where the agent host would be stopped prior to the update.
                 */
                using (FileStream fileStream = File.Open(bootstrapClusterManifestFile, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    // TODO: validation against schema
                    XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
                    xmlReaderSettings.ValidationType = ValidationType.None;
                    xmlReaderSettings.XmlResolver    = null;

                    using (XmlReader xmlReader = XmlReader.Create(fileStream, xmlReaderSettings))
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(ClusterManifestType));

                        bootstrapClusterManifest = (ClusterManifestType)serializer.Deserialize(xmlReader);
                    }
                }

                return(true);
            }
            catch (Exception e)
            {
                TextLogger.LogError("Failed to read bootstrap cluster manifest file {0} : {1}", bootstrapClusterManifestFile, e);

                return(false);
            }
        }
        private bool SetDynamicPortRange(int startPort, int endPort)
        {
            int portCount = endPort - startPort + 1;

            TextLogger.LogInfo("Setting dynamic port range. Start port : {0}. Port count : {1}.", startPort, portCount);

            if (Socket.OSSupportsIPv4)
            {
                if (!SetDynamicPortRange(startPort, portCount, "ipv4", "tcp"))
                {
                    TextLogger.LogError("Failed to set dynamic port range for ipv4:tcp. Start port : {0}. Port count : {1}.", startPort, portCount);

                    return(false);
                }

                if (!SetDynamicPortRange(startPort, portCount, "ipv4", "udp"))
                {
                    TextLogger.LogError("Failed to set dynamic port range for ipv4:udp. Start port : {0}. Port count : {1}.", startPort, portCount);

                    return(false);
                }
            }

            if (Socket.OSSupportsIPv6)
            {
                if (!SetDynamicPortRange(startPort, portCount, "ipv6", "tcp"))
                {
                    TextLogger.LogError("Failed to set dynamic port range for ipv6:tcp. Start port : {0}. Port count : {1}.", startPort, portCount);

                    return(false);
                }

                if (!SetDynamicPortRange(startPort, portCount, "ipv6", "udp"))
                {
                    TextLogger.LogError("Failed to set dynamic port range for ipv6:udp. Start port : {0}. Port count : {1}.", startPort, portCount);

                    return(false);
                }
            }

            return(true);
        }
        private bool InvokeFabricDeployer(ClusterTopology topologyToDeploy, DeploymentType deploymentType, bool toUseCurrentClusterManifestForDeployment)
        {
            TextLogger.LogInfo("Invoking FabricDeployer with deployment type = {0} and toUseCurrentClusterManifestForDeployment = {1}.", deploymentType, toUseCurrentClusterManifestForDeployment);

            string clusterManifestFileToDeploy;

            if (toUseCurrentClusterManifestForDeployment)
            {
                string currentClusterManifestFile = this.GetCurrentClusterManifestFile(topologyToDeploy.CurrentNodeName);

                if (File.Exists(currentClusterManifestFile))
                {
                    TextLogger.LogInfo("Using current cluster manifest file {0} for deployment.", currentClusterManifestFile);

                    clusterManifestFileToDeploy = currentClusterManifestFile;
                }
                else
                {
                    TextLogger.LogError("Current cluster manifest file does not exist as {0} when toUseCurrentClusterManifestForDeployment = true.", currentClusterManifestFile);

                    return(false);
                }
            }
            else
            {
                clusterManifestFileToDeploy = this.GetBootstrapClusterManifestFile();
            }

            if (!this.FabricDeploy(deploymentType, clusterManifestFileToDeploy, this.DataRootDirectory, topologyToDeploy.ServiceFabricNodes, true))
            {
                TextLogger.LogError(
                    "Failed to invoke FabricDeployer with deployment type = {0}, cluster manifest file = {1}, data root directory = {2}.",
                    deploymentType,
                    clusterManifestFileToDeploy,
                    this.DataRootDirectory);

                return(false);
            }

            return(true);
        }
        public bool DiscoverTopology(out ClusterTopology expectedTopology)
        {
            expectedTopology = null;

            try
            {
                TextLogger.LogInfo("Discovering cluster topology from bootstrap cluster manifest file.");

                if (ConfigurationManager.BootstrapClusterManifestLocation == BootstrapClusterManifestLocationType.NotReady)
                {
                    TextLogger.LogWarning("Bootstrap cluster manifest is not ready. Cluster topology would not be discovered until bootstrap cluster manifest is ready.");

                    return(false);
                }

                ClusterManifestType bootstrapClusterManifest;
                if (!this.ReadBootstrapClusterManifestFile(out bootstrapClusterManifest))
                {
                    return(false);
                }

                TopologyProviderType topologyProviderType = TopologyProvider.GetTopologyProviderTypeFromClusterManifest(bootstrapClusterManifest);

                TextLogger.LogInfo("Topology provider type : {0}.", topologyProviderType);

                if (topologyProviderType != TopologyProviderType.StaticTopologyProvider)
                {
                    TextLogger.LogInfo("Topology provider type {0} is not supported to provide static topology.", topologyProviderType);

                    return(false);
                }
                else
                {
                    /*
                     * Static topology provider defines the authoritative cluster topology in the cluster manifest.
                     * If the local machine (physical or virtual) is not part of the cluster topology specified in static topology provider section, a Service Fabric node will not be started locally.
                     * During scale-up, bootstrap cluster manifest has to be upgraded to allow new Service Fabric nodes to be started on the new machines and join the ring.
                     * A scale-up is normally a two-phase process with allocation of new machines (and their IPs) and generation of a new bootstrap cluster manifest with updated topology.
                     */
                    ClusterManifestTypeInfrastructureWindowsAzureStaticTopology staticTopologyProviderElement = TopologyProvider.GetStaticTopologyProviderElementFromClusterManifest(bootstrapClusterManifest);

                    if (staticTopologyProviderElement.NodeList == null || staticTopologyProviderElement.NodeList.Length == 0)
                    {
                        TextLogger.LogError("Static topology provider section of bootstrap cluster manifest does not specify topology of the Service Fabric cluster.");

                        return(false);
                    }

                    LogClusterTopology(staticTopologyProviderElement);

                    ClusterTopology staticTopologyProviderClusterTopology = ClusterTopology.GetClusterTopology();

                    staticTopologyProviderClusterTopology.LogTopology();

                    expectedTopology = staticTopologyProviderClusterTopology;

                    TextLogger.LogInfo("Successfully discovered cluster topology.");

                    return(true);
                }
            }
            catch (Exception e)
            {
                TextLogger.LogError("Failed to discover cluster topology : {0}", e);

                return(false);
            }
        }
        private bool GetAndCreateDataRootDirectory(out string dataRootDirectory)
        {
            dataRootDirectory = null;

            try
            {
                // On AP machines, data root would depend on machine SKU (specifically the SKU's disk layout). For test mode testing, use C:\SFRoot.
                if (this.useTestMode)
                {
                    dataRootDirectory = Path.Combine(Path.GetPathRoot("C:\\"), StringConstants.ServiceFabricRootDirectoryName);

                    TextLogger.LogInfo("Using {0} as data root directory in test mode.", dataRootDirectory);
                }
                else
                {
                    string diskLayoutConfigurationFile = Path.Combine(this.agentApplicationDirectory, StringConstants.DiskLayoutConfigurationFileName);

                    TextLogger.LogInfo("Data root directory would be determined based on local machine SKU {0} and disk layout configuration file {1}.", this.LocalMachineSku, diskLayoutConfigurationFile);

                    string dataRootHint = null;
                    using (CsvReader reader = new CsvReader(diskLayoutConfigurationFile))
                    {
                        while (reader.Read())
                        {
                            if (Regex.IsMatch(this.LocalMachineSku, reader["SKU"], RegexOptions.IgnoreCase | RegexOptions.CultureInvariant))
                            {
                                dataRootHint = Path.GetFullPath(Environment.ExpandEnvironmentVariables(reader["DataRootHint"]));

                                TextLogger.LogInfo(
                                    "Local machine SKU {0} matched disk layout SKU rule '{1}' -> '{2}' which expands to data root '{3}'",
                                    this.LocalMachineSku,
                                    reader["SKU"],
                                    reader["DataRootHint"],
                                    dataRootHint);

                                break;
                            }
                        }
                    }

                    if (string.IsNullOrEmpty(dataRootHint))
                    {
                        TextLogger.LogError("Disk layout configuration file {0} does not contain a valid entry for local machine SKU {1}.", diskLayoutConfigurationFile, this.LocalMachineSku);

                        return(false);
                    }

                    dataRootDirectory = Path.Combine(Path.GetPathRoot(dataRootHint), StringConstants.ServiceFabricRootDirectoryName);

                    TextLogger.LogInfo("Using {0} as data root directory based on local machine SKU {1} and disk layout configuration file {2}.", dataRootDirectory, this.LocalMachineSku, diskLayoutConfigurationFile);
                }

                TextLogger.LogInfo("Creating data root directory {0}.", dataRootDirectory);

                Directory.CreateDirectory(dataRootDirectory);

                return(true);
            }
            catch (Exception e)
            {
                TextLogger.LogError("Failed to get and create data root directory : {0}", e);

                return(false);
            }
        }
        public bool StartLocalNode()
        {
            try
            {
                TextLogger.LogInfo("Starting local Service Fabric node.");

                // TODO: After current xcopyable issue is fixed, update the pattern here.

                // TODO: [General] disposal of ServiceController
                ServiceController fabricHostService = this.GetInstalledService(Constants.FabricHostServiceName);

                if (fabricHostService != null)
                {
                    if (fabricHostService.Status == ServiceControllerStatus.StartPending)
                    {
                        TextLogger.LogWarning("Fabric host service is starting.");

                        return(false);
                    }
                    else if (fabricHostService.Status == ServiceControllerStatus.Running)
                    {
                        TextLogger.LogInfo("Successfully started local Service Fabric node.");

                        return(true);
                    }
                    else if (!this.StartFabricHostService())
                    {
                        TextLogger.LogError("Failed to start local Service Fabric node ");

                        return(false);
                    }
                }
                else
                {
                    ServiceController fabricInstallerService = this.GetInstalledService(Constants.FabricInstallerServiceName);

                    // Install and configure Fabric installer service if not installed.
                    if (fabricInstallerService == null)
                    {
                        TextLogger.LogInfo("Installing and configuring Fabric installer service.");

                        if (!this.InstallAndConfigureFabricInstallerService(this.agentApplicationDirectory))
                        {
                            TextLogger.LogError("Failed to install and configure Fabric installer service");

                            return(false);
                        }

                        fabricInstallerService = this.GetInstalledService(Constants.FabricInstallerServiceName);
                    }

                    // If Fabric installer service is not in stopped state, stop it.
                    if (fabricInstallerService.Status != ServiceControllerStatus.Stopped)
                    {
                        TextLogger.LogInfo("Fabric installer service is in {0} state. Stopping it.", fabricInstallerService.Status);

                        if (!this.StopFabricInstallerService())
                        {
                            TextLogger.LogError("Failed to stop Fabric installer service.");

                            return(false);
                        }
                    }

                    // Start Fabric installer service to start Fabric host service.
                    TextLogger.LogInfo("Starting Fabric installer service to start Fabric host service.");
                    if (!this.StartFabricInstallerService())
                    {
                        TextLogger.LogError("Failed to start Fabric installer service.");

                        return(false);
                    }
                }

                TextLogger.LogInfo("Successfully started local Service Fabric node.");

                return(true);
            }
            catch (Exception e)
            {
                TextLogger.LogError("Failed to start local Service Fabric node : {0}", e);

                return(false);
            }
        }
Ejemplo n.º 15
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);
            }
        }
Ejemplo n.º 16
0
        public static int ExecuteCommand(string command, string arguments, string workingDirectory, TimeSpan timeout)
        {
            TextLogger.LogInfo("Executing command {0} with arguments = {1}, working directory = {2}, timeout = {3} seconds.", command, arguments, workingDirectory, timeout == TimeSpan.MaxValue ? "infinite" : timeout.TotalSeconds.ToString());

            using (Process process = new Process())
            {
                process.StartInfo.FileName               = command;
                process.StartInfo.Arguments              = arguments;
                process.StartInfo.UseShellExecute        = false;
                process.StartInfo.CreateNoWindow         = true;
                process.StartInfo.WorkingDirectory       = workingDirectory;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError  = true;

                ProcessStandardOutputHandler processStandardOutputHandler = new ProcessStandardOutputHandler();
                process.OutputDataReceived += new DataReceivedEventHandler(processStandardOutputHandler.StandardOutputHandler);
                process.ErrorDataReceived  += new DataReceivedEventHandler(processStandardOutputHandler.StandardErrorHandler);

                process.Start();

                process.BeginOutputReadLine();

                process.BeginErrorReadLine();

                int exitCode;
                if (timeout == TimeSpan.MaxValue)
                {
                    process.WaitForExit();

                    TextLogger.LogInfo("Commond execution completed with exit code {0}.", process.ExitCode);

                    exitCode = process.ExitCode;
                }
                else
                {
                    if (!process.WaitForExit((int)timeout.TotalMilliseconds))
                    {
                        process.Kill();

                        TextLogger.LogError("Execution of command {0} with arguments {1} timed out after {2} seconds. The process is terminated.", command, arguments, timeout.TotalSeconds);

                        exitCode = -1;
                    }
                    else
                    {
                        TextLogger.LogInfo("Commond execution completed with exit code {0}.", process.ExitCode);

                        exitCode = process.ExitCode;
                    }
                }

                if (!string.IsNullOrEmpty(processStandardOutputHandler.StandardOutput))
                {
                    TextLogger.LogInfo("Standard output : {0}", processStandardOutputHandler.StandardOutput);
                }

                if (!string.IsNullOrEmpty(processStandardOutputHandler.StandardError))
                {
                    TextLogger.LogInfo("Standard error : {0}", processStandardOutputHandler.StandardError);
                }

                return(exitCode);
            }
        }
Ejemplo n.º 17
0
        public bool EnsureEnvironmentCertificatesPresence()
        {
            foreach (var storeEnvironmentCertificates in this.environmentCertificates)
            {
                StoreName storeName = storeEnvironmentCertificates.Key;

                TextLogger.LogInfo("Ensuring all environment certificates for certificate store {0}\\{1} are present in local environment.", StoreLocation.LocalMachine, storeName);

                int       installedEnvironmentCertificates = 0;
                X509Store store = null;
                try
                {
                    store = new X509Store(storeName, StoreLocation.LocalMachine);

                    store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);

                    foreach (var environmentCertificateEntry in storeEnvironmentCertificates.Value)
                    {
                        bool             environmentCertificateInstalled = false;
                        X509Certificate2 environmentCertificate          = environmentCertificateEntry.Value.Certificate;
                        if (store.Certificates != null)
                        {
                            X509Certificate2Collection certificateCollection = store.Certificates.Find(X509FindType.FindByThumbprint, environmentCertificate.Thumbprint, false);

                            environmentCertificateInstalled = certificateCollection.Count > 0;
                        }

                        if (!environmentCertificateInstalled)
                        {
                            TextLogger.LogInfo(
                                "{0} certificate with thumbprint {1}, subject {2} is being installed in certificate store {3}\\{4}.",
                                environmentCertificate.HasPrivateKey ? "Private key" : "Public key",
                                environmentCertificate.Thumbprint,
                                environmentCertificate.Subject,
                                StoreLocation.LocalMachine,
                                storeName);

                            store.Add(environmentCertificate);

                            if (environmentCertificate.HasPrivateKey)
                            {
                                TextLogger.LogInfo(
                                    "Private key certificate with thumbprint {0}, subject {1} is being ACLed.",
                                    environmentCertificate.Thumbprint,
                                    environmentCertificate.Subject);

                                // ACL private key part of a private key certificate to network service.
                                RSACryptoServiceProvider cryptoServiceProvider = environmentCertificate.PrivateKey as RSACryptoServiceProvider;

                                CspParameters cspParameters = new CspParameters(cryptoServiceProvider.CspKeyContainerInfo.ProviderType, cryptoServiceProvider.CspKeyContainerInfo.ProviderName, cryptoServiceProvider.CspKeyContainerInfo.KeyContainerName)
                                {
                                    Flags = CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore,

                                    CryptoKeySecurity = cryptoServiceProvider.CspKeyContainerInfo.CryptoKeySecurity
                                };

                                cspParameters.CryptoKeySecurity.AddAccessRule(new CryptoKeyAccessRule(new SecurityIdentifier(WellKnownSidType.NetworkServiceSid, null), CryptoKeyRights.FullControl | CryptoKeyRights.GenericRead, AccessControlType.Allow));

                                using (RSACryptoServiceProvider updatedCryptoServiceProvider = new RSACryptoServiceProvider(cspParameters))
                                {
                                    // Create a new RSACryptoServiceProvider with updated ACL rules to apply ACL changes.
                                }
                            }

                            installedEnvironmentCertificates++;
                        }
                    }
                }
                catch (Exception e)
                {
                    TextLogger.LogError("Failed to ensure all environment certificates for certificate store {0}\\{1} are present in local environment : {2}", StoreLocation.LocalMachine, storeName, e);

                    return(false);
                }
                finally
                {
                    if (store != null)
                    {
                        store.Close();
                    }
                }

                TextLogger.LogInfo("Certificate store {0}\\{1} : Successfully installed {2} environment certificates. All {3} environment certificates referred to in current configurations for the certificate store have been installed.", StoreLocation.LocalMachine, storeName, installedEnvironmentCertificates, storeEnvironmentCertificates.Value.Count);
            }

            return(true);
        }
Ejemplo n.º 18
0
        /*
         * TODO: currently AP safe config deployment is not supported to update configurations.
         * The only way to update the configurations is via an application upgrade.
         * This is OK since none of the configurations are critical.
         * To update all things critical in Service Fabric Autopilot Agent, an AP application upgrade is needed.
         */
        public static bool GetCurrentConfigurations(bool useTestMode = false)
        {
            if (useTestMode)
            {
                GetTestConfigurations();
            }
            else
            {
                IConfiguration configuration = APConfiguration.GetConfiguration();

                BackgroundStateMachineRunIntervalSeconds = configuration.GetInt32Value(StringConstants.AgentConfigurationSectionName, "BackgroundStateMachineRunIntervalSeconds", 10);

                DeploymentRetryIntervalSeconds = configuration.GetInt32Value(StringConstants.AgentConfigurationSectionName, "DeploymentRetryIntervalSeconds", 120);

                string bootstrapClusterManifestLocationString = configuration.GetStringValue(StringConstants.AgentConfigurationSectionName, "BootstrapClusterManifestLocation", string.Empty);

                BootstrapClusterManifestLocationType bootstrapClusterManifestLocation;
                if (!Enum.TryParse <BootstrapClusterManifestLocationType>(bootstrapClusterManifestLocationString, out bootstrapClusterManifestLocation))
                {
                    TextLogger.LogError("Bootstrap cluster manifest location is invalid or not specified : {0}.", bootstrapClusterManifestLocationString);

                    return(false);
                }

                BootstrapClusterManifestLocation = bootstrapClusterManifestLocation;

                DynamicPortRangeStart = configuration.GetInt32Value(StringConstants.AgentConfigurationSectionName, "DynamicPortRangeStart", -1);

                DynamicPortRangeEnd = configuration.GetInt32Value(StringConstants.AgentConfigurationSectionName, "DynamicPortRangeEnd", -1);

                // please refer to http://support.microsoft.com/kb/929851 for valid dynamic port range in Windows.
                if (DynamicPortRangeStart < 1025 || DynamicPortRangeEnd > 65535 || DynamicPortRangeEnd - DynamicPortRangeStart + 1 < 255)
                {
                    TextLogger.LogError("Dynamic port range is invalid or not specified : [{0}, {1}].", DynamicPortRangeStart, DynamicPortRangeEnd);

                    return(false);
                }

                DynamicTopologyUpdateMode = (DynamicTopologyUpdateMode)configuration.GetInt32Value(StringConstants.AgentConfigurationSectionName, "DynamicTopologyUpdateMode", 0);

                string logLevelString = configuration.GetStringValue(StringConstants.AgentConfigurationSectionName, "LogLevel", "Info");

                LogLevel logLevel;
                if (!Enum.TryParse <LogLevel>(logLevelString, out logLevel))
                {
                    TextLogger.LogError("Log level is invalid : {0}.", logLevelString);

                    return(false);
                }

                LogLevel = logLevel;

                PortFowardingRules = new List <PortFowardingRule>();
                if (configuration.SectionExists(StringConstants.PortForwardingConfigurationSectionName))
                {
                    string[] portFowardingRuleNames = configuration.GetSectionKeys(StringConstants.PortForwardingConfigurationSectionName);

                    if (portFowardingRuleNames != null)
                    {
                        foreach (string portFowardingRuleName in portFowardingRuleNames)
                        {
                            string[] portFowardingRuleComponents = configuration.GetStringValueAndSplit(StringConstants.PortForwardingConfigurationSectionName, portFowardingRuleName, ",");

                            if (portFowardingRuleComponents == null || portFowardingRuleComponents.Length != 3)
                            {
                                TextLogger.LogError("Port forwarding rule {0} is invalid. Valid rule format : RuleName=ListenPort,ConnectPort,MachineFunction", portFowardingRuleName);

                                return(false);
                            }

                            int listenPort;
                            if (!int.TryParse(portFowardingRuleComponents[0], out listenPort) || listenPort <= 0 || listenPort > 65535)
                            {
                                TextLogger.LogError("Port forwarding rule {0} is invalid with invalid listen port {1}. Valid rule format : RuleName=ListenPort,ConnectPort,MachineFunction", portFowardingRuleName, portFowardingRuleComponents[0]);

                                return(false);
                            }

                            int connectPort;
                            if (!int.TryParse(portFowardingRuleComponents[1], out connectPort) || connectPort <= 0 || connectPort > 65535)
                            {
                                TextLogger.LogError("Port forwarding rule {0} is invalid with invalid connect port {1}. Valid rule format : RuleName=ListenPort,ConnectPort,MachineFunction", portFowardingRuleName, portFowardingRuleComponents[1]);

                                return(false);
                            }

                            PortFowardingRules.Add(new PortFowardingRule {
                                RuleName = portFowardingRuleName, ListenPort = listenPort, ConnectPort = connectPort, MachineFunction = portFowardingRuleComponents[2]
                            });
                        }
                    }
                }
            }

            return(true);
        }