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)}
}
};
}