private void VerifyExpectedClusterSize()

in src/prod/src/managed/Api/src/System/Fabric/Management/fabricvalidator/FabricSettingsValidator.cs [1204:1956]


        private void VerifyExpectedClusterSize()
        {
            int intExpectedClusterSize = 0;
            try
            {
                intExpectedClusterSize = Convert.ToInt32(this.windowsFabricSettings.GetParameter(FabricValidatorConstants.SectionNames.FailoverManager, FabricValidatorConstants.ParameterNames.ExpectedClusterSize).Value);
            }
            catch (FormatException e)
            {
                WriteError(String.Format(StringResources.Warning_ExceptedClusterSizeIsNotDigits, e));
            }
            if (intExpectedClusterSize < 0)
            {
                WriteError(StringResources.Warning_ExpectedClusterSizeMustBeGreaterThanZero);
            }
            int nodeCount = 0;
#if DotNetCoreClrLinux
            if (this.clusterManifest.Infrastructure.Item is ClusterManifestTypeInfrastructureLinux)
            {
                var serverInfra = this.clusterManifest.Infrastructure.Item as ClusterManifestTypeInfrastructureLinux;
#else
            if (this.clusterManifest.Infrastructure.Item is ClusterManifestTypeInfrastructureWindowsServer)
            {
                var serverInfra = this.clusterManifest.Infrastructure.Item as ClusterManifestTypeInfrastructureWindowsServer;
#endif
                foreach (FabricNodeType node in serverInfra.NodeList)
                {
                    nodeCount++;
                }
            }
            else if (clusterManifest.Infrastructure.Item is ClusterManifestTypeInfrastructureWindowsAzureStaticTopology)
            {
                ClusterManifestTypeInfrastructureWindowsAzureStaticTopology windowsAzureStaticTopologyServerInfra = this.clusterManifest.Infrastructure.Item as ClusterManifestTypeInfrastructureWindowsAzureStaticTopology;
                foreach (FabricNodeType node in windowsAzureStaticTopologyServerInfra.NodeList)
                {
                    nodeCount++;
                }
            }
            if (this.clusterManifest.Infrastructure.Item is ClusterManifestTypeInfrastructurePaaS)
            {
                ClusterManifestTypeInfrastructurePaaS paasInfra = this.clusterManifest.Infrastructure.Item as ClusterManifestTypeInfrastructurePaaS;
                foreach (var role in paasInfra.Roles)
                {
                    nodeCount += role.RoleNodeCount;
                }
            }
            else if (this.clusterManifest.Infrastructure.Item is ClusterManifestTypeInfrastructureWindowsAzure && this.infrastructureInformation != null)
            {
                foreach (InfrastructureNodeType infra in this.infrastructureInformation)
                {
                    nodeCount++;
                }
            }
            else if (this.clusterManifest.Infrastructure.Item is ClusterManifestTypeInfrastructureWindowsAzure && this.infrastructureInformation == null)
            {
                return;
            }

            if (intExpectedClusterSize > nodeCount)
            {
                WriteError(String.Format(StringResources.Warning_ExpectedClusterSizeSmallerThanNodeCount, intExpectedClusterSize, nodeCount));
            }
        }

        private void VerifyRunAsSettings(string runAsSectionName)
        {
            if (!this.windowsFabricSettings.GetParameter(runAsSectionName, FabricValidatorConstants.ParameterNames.RunAsAccountType).IsFromClusterManifest)
            {
                return;
            }
            var runAsSection = this.windowsFabricSettings.GetSection(runAsSectionName);

            if (!runAsSection[FabricValidatorConstants.ParameterNames.RunAsAccountType].IsFromClusterManifest)
            {
                WriteError("Invalid RunAs section: parameter account type is missing");
            }

            string accountTypeString = runAsSection[FabricValidatorConstants.ParameterNames.RunAsAccountType].Value;
            if (!TryParseRunAsAccountType(accountTypeString, out fabricAccountType))
            {
                WriteError("Invalid RunAs section: parameter account type {0} is invalid", accountTypeString);
            }

            if (fabricAccountType == SecurityPrincipalsTypeUserAccountType.DomainUser)
            {
                if (!runAsSection[FabricValidatorConstants.ParameterNames.RunAsPassword].IsFromClusterManifest)
                {
                    WriteError("Invalid RunAs section: parameter password is missing for domain user");
                }
            }
            else
            {
                if (runAsSection[FabricValidatorConstants.ParameterNames.RunAsPassword].IsFromClusterManifest)
                {
                    WriteError("Invalid RunAs section: parameter password is present for non domain user");
                }
            }

            if (fabricAccountType == SecurityPrincipalsTypeUserAccountType.DomainUser || fabricAccountType == SecurityPrincipalsTypeUserAccountType.ManagedServiceAccount)
            {
                if (!runAsSection[FabricValidatorConstants.ParameterNames.RunAsAccountName].IsFromClusterManifest)
                {
                    WriteError("Invalid RunAs section: parameter account name is missing");
                }

                string accountNameString = runAsSection[FabricValidatorConstants.ParameterNames.RunAsAccountName].Value;

                if (!ImageBuilderUtility.IsValidAccountName(accountNameString))
                {
                    WriteError("Invalid RunAs section: parameter account name {0} is invalid", accountNameString);
                }
            }
        }

        private void VerifyClusterHealthPolicy()
        {
            var policySection = this.windowsFabricSettings.SettingsMap[FabricValidatorConstants.SectionNames.HealthManager_ClusterHealthPolicy];

            foreach (var entry in policySection)
            {
                if (entry.Key == FabricValidatorConstants.ParameterNames.MaxPercentUnhealthyNodes ||
                    entry.Key == FabricValidatorConstants.ParameterNames.MaxPercentUnhealthyApplications)
                {
                    ValidatePercentage(entry.Key, entry.Value.Value);
                }
                else if (entry.Key.StartsWith(FabricValidatorConstants.ParameterNames.ApplicationTypeMaxPercentUnhealthyApplicationsPrefix))
                {
                    // Entries in the application type map
                    if (entry.Key.Length <= FabricValidatorConstants.ParameterNames.ApplicationTypeMaxPercentUnhealthyApplicationsPrefix.Length)
                    {
                        WriteError("Invalid application type name for entry {0}. Expected pattern: {1}<ApplicationTypeName>", entry.Key, FabricValidatorConstants.ParameterNames.ApplicationTypeMaxPercentUnhealthyApplicationsPrefix);
                    }

                    ValidatePercentage(entry.Key, entry.Value.Value);
                }
                else
                {
                    try
                    {
                        WindowsFabricSettings.ValidateConfigurationTypes(FabricValidatorConstants.SectionNames.HealthManager_ClusterHealthPolicy, entry.Key, entry.Value.Type, entry.Value.Value);
                    }
                    catch (Exception)
                    {
                        WriteError("Section {0}, entry {1}: value {2} is invalid. Error: {3}", FabricValidatorConstants.SectionNames.HealthManager_ClusterHealthPolicy, entry.Key, entry.Value.Value);
                    }
                }
            }
        }

        private void ValidatePercentage(string key, string value)
        {
            int percent;
            if (!int.TryParse(value, out percent) || percent < 0 || percent > 100)
            {
                WriteError("{0} must be in the range [0, 100]: {1}", key, value);
            }
        }

        private void VerifyClientRoleSettings(CredentialType serverCredentialType)
        {
            if (serverCredentialType == CredentialType.None)
            {
                return;
            }

            var securitySection = this.windowsFabricSettings.SettingsMap[FabricValidatorConstants.SectionNames.Security];
            if (!securitySection.ContainsKey(FabricValidatorConstants.ParameterNames.ClientRoleEnabled))
            {
                return;
            }

            string clientRoleEnabledValue = securitySection[FabricValidatorConstants.ParameterNames.ClientRoleEnabled].Value;
            bool clientRoleEnabled;
            if (!bool.TryParse(clientRoleEnabledValue, out clientRoleEnabled))
            {
                WriteError("ClientRoleEnabled can only be true/false: Value found - {0}", clientRoleEnabledValue);
            }

            if (serverCredentialType == CredentialType.X509)
            {
                if (clientRoleEnabled)
                {
                    bool zeroAdminClientCommonNames =
                        !securitySection.ContainsKey(FabricValidatorConstants.ParameterNames.AdminClientCommonNames) ||
                        securitySection[FabricValidatorConstants.ParameterNames.AdminClientCommonNames].Value.Trim() == string.Empty;
                    bool zeroAdminClientCertThumbprints =
                        !securitySection.ContainsKey(FabricValidatorConstants.ParameterNames.AdminClientCertThumbprints) ||
                        securitySection[FabricValidatorConstants.ParameterNames.AdminClientCertThumbprints].Value.Trim() == string.Empty;
                    bool zeroAdminClientX509Names = true;
                    if (windowsFabricSettings.SettingsMap.ContainsKey(FabricValidatorConstants.SectionNames.AdminClientX509Names))
                    {
                        zeroAdminClientX509Names = windowsFabricSettings.SettingsMap[FabricValidatorConstants.SectionNames.AdminClientX509Names].Count == 0;
                    }

                    if (zeroAdminClientCommonNames && zeroAdminClientCertThumbprints && zeroAdminClientX509Names)
                    {
                        WriteWarning("Default client certificate is not in admin role, future releases will fail on this, you must add it to {0} or {1}", FabricValidatorConstants.ParameterNames.AdminClientCertThumbprints, FabricValidatorConstants.SectionNames.AdminClientX509Names);
                    }
                }
                else
                {
                    bool zeroClientAuthAllowedCommonNames =
                        !securitySection.ContainsKey(FabricValidatorConstants.ParameterNames.ClientAuthAllowedCommonNames) ||
                        securitySection[FabricValidatorConstants.ParameterNames.ClientAuthAllowedCommonNames].Value.Trim() == string.Empty;
                    bool zeroClientCertThumbprints =
                        !securitySection.ContainsKey(FabricValidatorConstants.ParameterNames.ClientCertThumbprints) ||
                        securitySection[FabricValidatorConstants.ParameterNames.ClientCertThumbprints].Value.Trim() == string.Empty;
                    bool zeroClientX509Names = true;
                    if (windowsFabricSettings.SettingsMap.ContainsKey(FabricValidatorConstants.SectionNames.ClientX509Names))
                    {
                        zeroClientX509Names = windowsFabricSettings.SettingsMap[FabricValidatorConstants.SectionNames.ClientX509Names].Count == 0;
                    }

                    if (zeroClientAuthAllowedCommonNames && zeroClientCertThumbprints && zeroClientX509Names)
                    {
                        WriteWarning("Default client certificate is not in allow list, future releases will fail on this, you must add it to {0} or {1}", FabricValidatorConstants.ParameterNames.ClientCertThumbprints, FabricValidatorConstants.SectionNames.ClientX509Names);
                    }
                }

                return;
            }

            if (serverCredentialType == CredentialType.Windows)
            {
                if (clientRoleEnabled)
                {
                    if (!securitySection.ContainsKey(FabricValidatorConstants.ParameterNames.AdminClientIdentities) ||
                        (securitySection[FabricValidatorConstants.ParameterNames.AdminClientIdentities].Value.Trim() == string.Empty))
                    {
                        WriteWarning("AdminClientIdentities is empty, thus only fabric gateway account is allowed to do admin operations");
                    }
                }
            }
        }

#if !DotNetCoreClr // Disable compiling on windows for now. Need to correct when porting fabricvalidator for windows.
        private void VerifyClusterSpn(Dictionary<string, WindowsFabricSettings.SettingsValue> securitySection)
        {
            string clusterSpn = string.Empty;
            if (securitySection.ContainsKey(FabricValidatorConstants.ParameterNames.ClusterSpn))
            {
                clusterSpn = securitySection[FabricValidatorConstants.ParameterNames.ClusterSpn].Value;
            }

            clusterSpn = clusterSpn.Trim();
            if (clusterSpn == string.Empty)
            {
                if (!this.FabricRunAsMachineAccount())
                {
                    WriteError("ClusterSpn cannot be empty when fabric runs as {0}", this.fabricAccountType);
                }

                WriteInfo("ClusterSpn is left empty for running fabric as {0}", this.fabricAccountType);
                this.ShouldRegisterSpnForMachineAccount = true;
                return;
            }

            WriteInfo("ClusterSpn is set to {0} for running fabric as {1}", clusterSpn, this.fabricAccountType);

            using (Domain thisDomain = Domain.GetCurrentDomain())
            {
                WriteInfo("Searching ClusterSpn {0} in domain {1} ...", clusterSpn, thisDomain.Name);

                using (DirectorySearcher search = new DirectorySearcher(thisDomain.GetDirectoryEntry()))
                {
                    search.Filter = string.Format(CultureInfo.InvariantCulture, "(ServicePrincipalName={0})", clusterSpn);
                    search.SearchScope = SearchScope.Subtree;

                    try
                    {
                        var matches = search.FindAll();
                        if (matches.Count < 1)
                        {
                            WriteError("ClusterSpn {0} is not found in domain {1}", clusterSpn, thisDomain.Name);
                        }

                        if (matches.Count == 1)
                        {
                            WriteInfo(
                                "ClusterSpn {0} is registered to {1} {2} in domain {2}",
                                clusterSpn,
                                matches[0].GetDirectoryEntry().Name,
                                matches[0].GetDirectoryEntry().Guid,
                                thisDomain.Name);

                            return;
                        }

                        // matches.Count > 1
                        WriteError(
                            "ClusterSpn {0} is registered to more than one objects in domain {1}",
                            clusterSpn, thisDomain.Name);

                        foreach (SearchResult match in matches)
                        {
                            WriteError(
                                "ClusterSpn {0} is registered to {1} {2}",
                                clusterSpn,
                                match.GetDirectoryEntry().Name,
                                match.GetDirectoryEntry().Guid);
                        }
                    }
                    catch (Exception e)
                    {
                        WriteError("Failed to search ClusterSpn {0}: {1}", clusterSpn, e);
                    }
                }
            }
        }
#endif
        private bool TryParseCredentialType(string stringValue, out CredentialType credentialType)
        {
            if (string.Compare(stringValue, FabricValidatorConstants.CredentialTypeNone, StringComparison.OrdinalIgnoreCase) == 0)
            {
                credentialType = CredentialType.None;
                return true;
            }

            if (string.Compare(stringValue, FabricValidatorConstants.CredentialTypeX509, StringComparison.OrdinalIgnoreCase) == 0)
            {
                credentialType = CredentialType.X509;
                return true;
            }

            if (string.Compare(stringValue, FabricValidatorConstants.CredentialTypeWindows, StringComparison.OrdinalIgnoreCase) == 0)
            {
                credentialType = CredentialType.Windows;
                return true;
            }

            credentialType = CredentialType.None;
            return false;
        }

        private bool TryParseRunAsAccountType(string stringValue, out SecurityPrincipalsTypeUserAccountType runAsAccountType)
        {
            if (string.Compare(stringValue, FabricValidatorConstants.RunAsAccountTypeDomainUser, StringComparison.OrdinalIgnoreCase) == 0)
            {
                runAsAccountType = SecurityPrincipalsTypeUserAccountType.DomainUser;
                return true;
            }

            if (string.Compare(stringValue, FabricValidatorConstants.RunAsAccountTypeLocalService, StringComparison.OrdinalIgnoreCase) == 0)
            {
                runAsAccountType = SecurityPrincipalsTypeUserAccountType.LocalService;
                return true;
            }

            if (string.Compare(stringValue, FabricValidatorConstants.RunAsAccountTypeManagedService, StringComparison.OrdinalIgnoreCase) == 0)
            {
                runAsAccountType = SecurityPrincipalsTypeUserAccountType.ManagedServiceAccount;
                return true;
            }

            if (string.Compare(stringValue, FabricValidatorConstants.RunAsAccountTypeNetworkService, StringComparison.OrdinalIgnoreCase) == 0)
            {
                runAsAccountType = SecurityPrincipalsTypeUserAccountType.NetworkService;
                return true;
            }

            if (string.Compare(stringValue, FabricValidatorConstants.RunAsAccountTypeLocalSystem, StringComparison.OrdinalIgnoreCase) == 0)
            {
                runAsAccountType = SecurityPrincipalsTypeUserAccountType.LocalSystem;
                return true;
            }

            runAsAccountType = SecurityPrincipalsTypeUserAccountType.LocalUser;
            return false;
        }

        private void VerifyRequiredParameters()
        {
            foreach (var sectionName in FabricSettingsValidator.RequiredParameters.Keys)
            {
                var settingsSection = this.windowsFabricSettings.GetSection(sectionName);
                foreach (var parameterName in FabricSettingsValidator.RequiredParameters[sectionName])
                {
                    if (!settingsSection[parameterName].IsFromClusterManifest)
                    {
                        WriteError("Parameter {0} in section {1} is required.", parameterName, sectionName);
                    }
                }
            }
        }

        private void VerifyNoLeadingTrailingSpaces()
        {
            foreach (var section in this.windowsFabricSettings.SettingsMap)
            {
                foreach (var parameterKey in section.Value)
                {
                    if (parameterKey.Key.StartsWith(" ") || parameterKey.Key.EndsWith(" "))
                    {
                        WriteWarning(StringResources.Warning_ParameterContainsLeadingTrailingSpace, parameterKey.Key, section.Key);
                        DeployerTrace.WriteWarning(StringResources.Warning_ParameterContainsLeadingTrailingSpace, parameterKey.Key, section.Key);
                    }
                }
            }
        }

        private void VerifyVoteConfiguration()
        {
            NonSeedNodeVoteCount = 0;
            foreach (var parameter in this.windowsFabricSettings.GetSection(FabricValidatorConstants.SectionNames.Votes).Values)
            {
                string[] voteInfo = parameter.Value.Split(',');
                if (voteInfo[0] != FabricValidatorConstants.SQLVoteType)
                {
                    WriteError("Invalid vote type {0}. Only SQL vote type is allowed here.", voteInfo[0]);
                }
                else
                {
                    NonSeedNodeVoteCount++;
                }
            }
        }

        private void VerifyEncryptionFlag()
        {
            foreach (var section in this.windowsFabricSettings.SettingsMap.Where(s => !this.windowsFabricSettings.IsDCASetting(s.Key)))
            {
                foreach (var parameter in section.Value)
                {
                    if (parameter.Value.IsEncrypted)
                    {
                        if (FabricSettingsValidator.AllowedSecureConfigurations.ContainsKey(section.Key))
                        {
                            if (!FabricSettingsValidator.AllowedSecureConfigurations[section.Key].Contains(parameter.Key))
                            {
                                WriteError("Section '{0}', parameter '{1}' cannot be encrypted.", section.Key, parameter.Key);
                            }
                            else if (string.IsNullOrEmpty(parameter.Value.Value))
                            {
                                WriteError("Section '{0}', parameter '{1}' is encrypted and hence cannot be empty.", section.Key, parameter.Key);
                            }
                        }
                        else
                        {
                            WriteError("Section '{0}' cannot contain encrypted parameters.", section.Key, parameter.Key);
                        }
                    }
                }
            }
        }

        private void VerifyDependencies()
        {
            foreach (var dependency in FabricSettingsValidator.Dependencies)
            {
                string[] source = dependency.Key.Split('|');
                foreach (string dest in dependency.Value)
                {
                    string[] destination = dest.Split('|');
                    if ((this.windowsFabricSettings.SettingsMap.ContainsKey(source[0]) && this.windowsFabricSettings.SettingsMap[source[0]].ContainsKey(source[1])))
                    {
                        bool valueComparisonResult = source[2].StartsWith("!", StringComparison.Ordinal) ?
                            this.windowsFabricSettings.SettingsMap[source[0]][source[1]].Value != source[2].Substring(1) :
                            source[2].StartsWith("~", StringComparison.Ordinal) ?
                            this.windowsFabricSettings.SettingsMap[source[0]][source[1]].Value.Equals(source[2].Substring(1), StringComparison.OrdinalIgnoreCase) :
                            this.windowsFabricSettings.SettingsMap[source[0]][source[1]].Value == source[2];
                        if (valueComparisonResult)
                        {
                            if (destination[0] != FabricValidatorConstants.NodeType)
                            {
                                if (!(this.windowsFabricSettings.SettingsMap.ContainsKey(destination[0]) && this.windowsFabricSettings.SettingsMap[destination[0]].ContainsKey(destination[1]) && this.windowsFabricSettings.SettingsMap[destination[0]][destination[1]].IsFromClusterManifest))
                                {
                                    WriteError(
                                        "Section {0} parameter {1} is required if section {2} parameter {3} is {4} set to {5}",
                                        destination[0],
                                        destination[1],
                                        source[0],
                                        source[1],
                                        source[2].StartsWith("!", StringComparison.Ordinal) ? "not" : "",
                                        source[2]);
                                }
                            }
                            else
                            {
                                foreach (var nodeType in nodeTypes)
                                {
                                    if (destination[1] == FabricValidatorConstants.Certificates)
                                    {
                                        VerifyCertificates(source, destination, nodeType);
                                    }
                                    else if (destination[1] == FabricValidatorConstants.Endpoints)
                                    {
                                        VerifyEndpoints(source, destination, nodeType);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        private void VerifyEndpoints(string[] source, string[] destination, ClusterManifestTypeNodeType nodeType)
        {
            if (destination[2] == FabricValidatorConstants.ApplicationEndpoints)
            {
                if (nodeType.Endpoints != null && nodeType.Endpoints.ApplicationEndpoints == null)
                {
                    WriteError(
                    "NodeType.{0}.{1} is required if section {2} parameter {3} is {4} set to {5}",
                    FabricValidatorConstants.Endpoints,
                    FabricValidatorConstants.ApplicationEndpoints,
                    source[0],
                    source[1],
                    source[2].StartsWith("!", StringComparison.Ordinal) ? "not" : "",
                    source[2]);
                }
            }
        }

        private void VerifyCertificates(string[] source, string[] destination, ClusterManifestTypeNodeType nodeType)
        {

            if (nodeType.Certificates == null)
            {
                WriteError(
                    "NodeType.Certificates is required if section {0} parameter {1} is {2} set to {3}",
                    source[0],
                    source[1],
                    source[2].StartsWith("!", StringComparison.Ordinal) ? "not" : "",
                    source[2]);
            }
            else if (destination[2] == FabricValidatorConstants.ClientCertificate)
            {
                if (nodeType.Certificates.ClientCertificate == null)
                {
                    WriteError(
                    "NodeType.Certificates.ClientCertificate is required if section {0} parameter {1} is {2} set to {3}",
                    source[0],
                    source[1],
                    source[2].StartsWith("!", StringComparison.Ordinal) ? "not" : "",
                    source[2]);
                }
                else
                {
                    ValidateCertificateSetting(nodeType.Certificates.ClientCertificate);
                }
            }
            else if (destination[2] == FabricValidatorConstants.ServerCertificate)
            {
                if (nodeType.Certificates.ServerCertificate == null)
                {
                    WriteError(
                    "NodeType.Certificates.ServerCertificate is required if section {0} parameter {1} is {2} set to {3}",
                    source[0],
                    source[1],
                    source[2].StartsWith("!", StringComparison.Ordinal) ? "not" : "",
                    source[2]);
                }
                else
                {
                    ValidateCertificateSetting(nodeType.Certificates.ServerCertificate);
                }
            }
            else if (destination[2] == FabricValidatorConstants.ClusterCertificate)
            {
                if (nodeType.Certificates.ClusterCertificate == null)
                {
                    WriteError(
                    "NodeType.Certificates.ClusterCertificate is required if section {0} parameter {1} is {2} set to {3}",
                    source[0],
                    source[1],
                    source[2].StartsWith("!", StringComparison.Ordinal) ? "not" : "",
                    source[2]);
                }
                else
                {
                    ValidateCertificateSetting(nodeType.Certificates.ClusterCertificate);
                }
            }
        }

        void ValidateCertificateSetting(FabricCertificateType fabricCertificateType)
        {
            if (fabricCertificateType.X509FindType != FabricCertificateTypeX509FindType.FindByThumbprint)
            {
                return;
            }

            for (int i = 0; i < fabricCertificateType.X509FindValue.Length; ++i)
            {
                if (!IsHexDigit(fabricCertificateType.X509FindValue[i]) &&
                    !char.IsWhiteSpace(fabricCertificateType.X509FindValue[i]))
                {
                    WriteError(
                        "{0}: thumbprint string {1} contains invalid HEX digit, [{2}] = 0x{3:x}",
                        fabricCertificateType.Name,
                        fabricCertificateType.X509FindValue,
                        i,
                        (int)(fabricCertificateType.X509FindValue[i]));
                }
            }
        }

        private static bool IsHexDigit(char character)
        {
            return ((character >= '0') && (character <= '9'))
                || ((character >= 'A') && (character <= 'F'))
                || ((character >= 'a') && (character <= 'f'));
        }

        private Dictionary<string, Dictionary<string, WindowsFabricSettings.SettingsValue>> GetAllTVSSettings()
        {
            var allTVSSettings = new Dictionary<string, Dictionary<string, WindowsFabricSettings.SettingsValue>>();
            foreach (string sectionName in windowsFabricSettings.SettingsMap.Keys)
            {
                if (sectionName.StartsWith(FabricValidatorConstants.SectionNames.TokenValidationService, StringComparison.OrdinalIgnoreCase) ||
                    sectionName.StartsWith(FabricValidatorConstants.SectionNames.DSTSTokenValidationService, StringComparison.OrdinalIgnoreCase))
                {
                    foreach (string paramName in windowsFabricSettings.SettingsMap[sectionName].Keys)
                    {
                        var param = windowsFabricSettings.SettingsMap[sectionName][paramName];
                        if (param.IsFromClusterManifest)
                        {
                            if (!allTVSSettings.ContainsKey(sectionName))
                            {
                                allTVSSettings.Add(sectionName, new Dictionary<string, WindowsFabricSettings.SettingsValue>());
                            }
                            allTVSSettings[sectionName].Add(paramName, param);
                        }
                    }
                }
            }
            return allTVSSettings;
        }

        private static bool IsSingleChangeAllowed(WindowsFabricSettings.SettingsValue oldSettings, WindowsFabricSettings.SettingsValue newSettings)
        {
            if (((oldSettings.Value == null) != (newSettings.Value == null)) /* Value is newly added/removed to/from Configurations.csv */  ||
                (oldSettings.Value != null
                && newSettings.Value != null
                && (!oldSettings.IsFromClusterManifest && newSettings.IsFromClusterManifest) || (oldSettings.IsFromClusterManifest && !newSettings.IsFromClusterManifest)))
                /* Value is changed from default -> some value or some value -> default*/ 
            {
                return true;
            }

            return false;
        }

        private static void WriteWarning(string format, params object[] args)
        {
            FabricValidator.TraceSource.WriteWarning(FabricValidatorUtility.TraceTag, format, args);
        }


        private static void WriteError(string format, params object[] args)
        {
            throw new ArgumentException(string.Format(format, args));
        }

        private static void WriteInfo(string format, params object[] args)
        {
            FabricValidator.TraceSource.WriteInfo(FabricValidatorUtility.TraceTag, format, args);
        }

        private string storeName;
        private WindowsFabricSettings windowsFabricSettings;
        private ClusterManifestTypeNodeType[] nodeTypes;
        private DCASettingsValidator dcaSettingsValidator;
        private HttpGatewaySettingsValidator httpGatewaySettingsValidator;
        private HttpAppGatewaySettingsValidator httpAppGatewaySettingsValidator;
        private TokenValidationServiceSettingsValidator tokenValidationServiceValidator;

        // Types to be used for type checking.
        private const string IntType = "int";
        private const string UIntType = "uint";
        private const string TimeSpanType = "TimeSpan";
        private const string CommonTimeSpanType = "Common::TimeSpan";
        private const string BoolType = "bool";
        private const string DoubleType = "double";

        /// <summary>
        /// This is a hashset of required parameters. We ensure that all these parameters are present in a deployment.
        /// In order to add new required parameters,
        ///     If the required parameters are part of sections already listed here, add the required parameters to these sections.
        ///     Else create new section (SectionName, HashSet and add the parameters there
        /// Either case follow the format of adding only constants here and actual value in the constants file.
        /// </summary>
        private static readonly Dictionary<string, HashSet<string>> RequiredParameters =
            new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase) {
                { FabricValidatorConstants.SectionNames.FailoverManager, new HashSet<string>(StringComparer.OrdinalIgnoreCase) {FabricValidatorConstants.ParameterNames.ExpectedClusterSize}},
                { FabricValidatorConstants.SectionNames.Security, new HashSet<string>(StringComparer.OrdinalIgnoreCase) {FabricValidatorConstants.ParameterNames.ClusterCredentialType, FabricValidatorConstants.ParameterNames.ServerAuthCredentialType }}};

        /// <summary>
        /// This is a set of paremeters that can be secured by a security certificate.
        /// Read instructions for RequiredParameters on how to add new securable configurations.
        /// </summary>
        private static readonly Dictionary<string, HashSet<string>> AllowedSecureConfigurations =
            new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase) {
                { FabricValidatorConstants.SectionNames.Management, new HashSet<string>(StringComparer.OrdinalIgnoreCase) { FabricValidatorConstants.ParameterNames.ImageStoreConnectionString }},
                { FabricValidatorConstants.SectionNames.DiagnosticFileStore, new HashSet<string>(StringComparer.OrdinalIgnoreCase) { FabricValidatorConstants.ParameterNames.StoreConnectionString }},
                { FabricValidatorConstants.SectionNames.DiagnosticTableStore, new HashSet<string>(StringComparer.OrdinalIgnoreCase) { FabricValidatorConstants.ParameterNames.StoreConnectionString }},
                { FabricValidatorConstants.SectionNames.Hosting, new HashSet<string>(StringComparer.OrdinalIgnoreCase) { FabricValidatorConstants.ParameterNames.NTLMAuthenticationPasswordSecret }},
                { FabricValidatorConstants.SectionNames.RunAs, new HashSet<string>(StringComparer.OrdinalIgnoreCase) { FabricValidatorConstants.ParameterNames.RunAsPassword }},
                { FabricValidatorConstants.SectionNames.RunAs_Fabric, new HashSet<string>(StringComparer.OrdinalIgnoreCase) { FabricValidatorConstants.ParameterNames.RunAsPassword }},
                { FabricValidatorConstants.SectionNames.RunAs_DCA, new HashSet<string>(StringComparer.OrdinalIgnoreCase) { FabricValidatorConstants.ParameterNames.RunAsPassword }},
                { FabricValidatorConstants.SectionNames.RunAs_HttpGateway, new HashSet<string>(StringComparer.OrdinalIgnoreCase) { FabricValidatorConstants.ParameterNames.RunAsPassword }},
                { FabricValidatorConstants.SectionNames.FileStoreService,
                    new HashSet<string>(StringComparer.OrdinalIgnoreCase)
                    {
                        FabricValidatorConstants.ParameterNames.FileStoreService.PrimaryAccountNTLMPasswordSecret,
                        FabricValidatorConstants.ParameterNames.FileStoreService.PrimaryAccountUserPassword,
                        FabricValidatorConstants.ParameterNames.FileStoreService.SecondaryAccountNTLMPasswordSecret,
                        FabricValidatorConstants.ParameterNames.FileStoreService.SecondaryAccountUserPassword
                    }
                }};

        /// <summary>
        /// This is a set of dependencies.
        /// The key of the hash table describes configurations which have dependencies on other other configurations.
        /// The format of the key "SectionName|ParameterName|[!]Value.
        /// This means the if the parameter in the section provided has a particular value the dependency condition holds.
        /// The optional ! sign indicates negation of value check. The option ~ sign shows case independent comparison.
        /// The HashSet describes the list of configurations that must be present based on the dependency.
        /// The format for elements in the hashset can be one of
        ///     "SectionName|ParameterName" - Indicates particular parameter in section should be present.
        ///     "NodeType|Endpoints|EndpointType" - Indicates particular endpoint type should be present in all node types.
        ///     "NodeType|Certificates|CertificateType" - Indicates particular certificate type should be present in all node types.
        /// </summary>
        private static readonly Dictionary<string, HashSet<string>> Dependencies =
            new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase){
                {
                    string.Format(CultureInfo.InvariantCulture, "{0}|{1}|~{2}", FabricValidatorConstants.SectionNames.Hosting, FabricValidatorConstants.ParameterNames.NTLMAuthenticationEnabled, "true"),
                    new HashSet<string>(StringComparer.OrdinalIgnoreCase) {string.Format(CultureInfo.InvariantCulture, "{0}|{1}", FabricValidatorConstants.SectionNames.Hosting, FabricValidatorConstants.ParameterNames.NTLMAuthenticationPasswordSecret)}
                },
                {
                    string.Format(CultureInfo.InvariantCulture, "{0}|{1}|{2}", FabricValidatorConstants.SectionNames.Security, FabricValidatorConstants.ParameterNames.ServerAuthCredentialType, FabricValidatorConstants.CredentialTypeX509),
                    new HashSet<string>(StringComparer.OrdinalIgnoreCase) { string.Format(CultureInfo.InvariantCulture, "{0}|{1}|{2}", FabricValidatorConstants.NodeType, FabricValidatorConstants.Certificates, FabricValidatorConstants.ClientCertificate),
                        string.Format(CultureInfo.InvariantCulture, "{0}|{1}|{2}", FabricValidatorConstants.NodeType, FabricValidatorConstants.Certificates, FabricValidatorConstants.ServerCertificate)}
                },
                {
                    string.Format(CultureInfo.InvariantCulture, "{0}|{1}|{2}", FabricValidatorConstants.SectionNames.Security, FabricValidatorConstants.ParameterNames.ClusterCredentialType, FabricValidatorConstants.CredentialTypeX509),
                    new HashSet<string>(StringComparer.OrdinalIgnoreCase) {string.Format(CultureInfo.InvariantCulture, "{0}|{1}|{2}", FabricValidatorConstants.NodeType, FabricValidatorConstants.Certificates, FabricValidatorConstants.ClusterCertificate)}
                },
                {
                    string.Format(CultureInfo.InvariantCulture, "{0}|{1}|~{2}", FabricValidatorConstants.SectionNames.DiagnosticFileStore, FabricValidatorConstants.ParameterNames.IsEnabled, "true"),
                    new HashSet<string>(StringComparer.OrdinalIgnoreCase) {string.Format(CultureInfo.InvariantCulture, "{0}|{1}", FabricValidatorConstants.SectionNames.DiagnosticFileStore, FabricValidatorConstants.ParameterNames.StoreConnectionString)}
                },
                {
                    string.Format(CultureInfo.InvariantCulture, "{0}|{1}|~{2}", FabricValidatorConstants.SectionNames.DiagnosticFileStore, FabricValidatorConstants.ParameterNames.IsAppLogCollectionEnabled, "true"),
                    new HashSet<string>(StringComparer.OrdinalIgnoreCase) {string.Format(CultureInfo.InvariantCulture, "{0}|{1}", FabricValidatorConstants.SectionNames.DiagnosticFileStore, FabricValidatorConstants.ParameterNames.StoreConnectionString)}
                },
                {
                    string.Format(CultureInfo.InvariantCulture, "{0}|{1}|~{2}", FabricValidatorConstants.SectionNames.DiagnosticTableStore, FabricValidatorConstants.ParameterNames.IsEnabled, "true"),
                    new HashSet<string>(StringComparer.OrdinalIgnoreCase) {string.Format(CultureInfo.InvariantCulture, "{0}|{1}", FabricValidatorConstants.SectionNames.DiagnosticTableStore, FabricValidatorConstants.ParameterNames.StoreConnectionString)}
                }
            };
    }