internal static bool TryGetStepOne(
            X509 currentCerts,
            X509 targetCerts,
            CertificateClusterUpgradeStep previousStep,
            out CertificateClusterUpgradeStep step)
        {
            // step 1 adds all newly added certs and issuers (if any) to the white list
            step = null;
            List <string> currentThumbprints               = CertificateClusterUpgradeFlow.GetThumbprints(currentCerts.ClusterCertificate);
            List <string> addedThumbprints                 = CertificateClusterUpgradeFlow.GetAddedThumbprints(currentCerts.ClusterCertificate, targetCerts.ClusterCertificate);
            Dictionary <string, string> currentCns         = CertificateClusterUpgradeFlow.GetCns(currentCerts.ClusterCertificateCommonNames);
            Dictionary <string, string> addedCnsAndIssuers = CertificateClusterUpgradeFlow.GetAddedCnsAndIssuers(currentCerts.ClusterCertificateCommonNames, targetCerts.ClusterCertificateCommonNames);

            if (addedThumbprints.Any() || addedCnsAndIssuers.Any())
            {
                step = new CertificateClusterUpgradeStep(
                    thumbprintWhiteList: currentThumbprints.Concat(addedThumbprints).ToList(),
                    thumbprintLoadList: currentCerts.ClusterCertificate,
                    thumbprintFileStoreSvcList: currentCerts.ClusterCertificate,
                    commonNameWhiteList: CertificateClusterUpgradeFlow.MergeCnsAndIssuers(currentCns, addedCnsAndIssuers),
                    commonNameLoadList: currentCerts.ClusterCertificateCommonNames,
                    commonNameFileStoreSvcList: currentCerts.ClusterCertificateCommonNames);
            }

            return(true);
        }
        internal static bool TryGetStepThree(
            X509 currentCerts,
            X509 targetCerts,
            CertificateClusterUpgradeStep previousStep,
            out CertificateClusterUpgradeStep step)
        {
            Dictionary <string, string> commonNameWhiteList = targetCerts.ClusterCertificateCommonNames == null || !targetCerts.ClusterCertificateCommonNames.Any() ?
                                                              null : targetCerts.ClusterCertificateCommonNames.CommonNames.ToDictionary(p => p.CertificateCommonName, p => p.CertificateIssuerThumbprint);

            step = new CertificateClusterUpgradeStep(
                thumbprintWhiteList: targetCerts.ClusterCertificate == null ? null : targetCerts.ClusterCertificate.ToThumbprintList(),
                thumbprintLoadList: targetCerts.ClusterCertificate,
                thumbprintFileStoreSvcList: targetCerts.ClusterCertificate,
                commonNameWhiteList: commonNameWhiteList,
                commonNameLoadList: targetCerts.ClusterCertificateCommonNames,
                commonNameFileStoreSvcList: targetCerts.ClusterCertificateCommonNames);

            return(true);
        }
        public static List <CertificateClusterUpgradeStep> GetUpgradeFlow(X509 currentCerts, X509 targetCerts)
        {
            List <CertificateClusterUpgradeStep> result       = new List <CertificateClusterUpgradeStep>();
            CertificateClusterUpgradeStep        previousStep = null;
            bool shouldContinue = true;

            for (int i = 0; i < CertificateClusterUpgradeFlow.upgradeStepDelegateTable.Length && shouldContinue; i++)
            {
                CertificateClusterUpgradeStep step;
                shouldContinue = CertificateClusterUpgradeFlow.upgradeStepDelegateTable[i](currentCerts, targetCerts, previousStep, out step);
                previousStep   = step;
                if (step != null)
                {
                    result.Add(step);
                }
            }

            return(result);
        }
        private ClusterManifestType UpdateClusterManifest(
            ClusterManifestType existingClusterManifest,
            FabricSettingsMetadata currentFabricSettingsMetadata,
            string clusterManifestVersion,
            CertificateClusterUpgradeStep step,
            List <NodeDescription> existingSeedNodes)
        {
            Security nodeTypeSecurity = this.TargetCsmConfig.Security.Clone();

            nodeTypeSecurity.CertificateInformation.ClusterCertificate            = step.ThumbprintLoadList;
            nodeTypeSecurity.CertificateInformation.ClusterCertificateCommonNames = step.CommonNameLoadList;

            return(this.UpdateClusterManifest(
                       this.TargetCsmConfig.Security,
                       existingClusterManifest,
                       this.GetNodeTypes(this.TargetCsmConfig.NodeTypes, nodeTypeSecurity),
                       currentFabricSettingsMetadata,
                       clusterManifestVersion,
                       step.ThumbprintFileStoreSvcList,
                       step.ThumbprintWhiteList,
                       step.CommonNameFileStoreSvcList,
                       step.CommonNameWhiteList,
                       existingSeedNodes));
        }
        internal static bool TryGetStepTwo(
            X509 currentCerts,
            X509 targetCerts,
            CertificateClusterUpgradeStep previousStep,
            out CertificateClusterUpgradeStep step)
        {
            // step 2:
            // white list: inherit from the previous step
            // load list: replace all current certs with target certs
            // fss list: change if necessary
            int changedThumbprintCount = CertificateClusterUpgradeFlow.GetChangedThumbprintCount(currentCerts.ClusterCertificate, targetCerts.ClusterCertificate);
            int changedCnCount         = CertificateClusterUpgradeFlow.GetChangedCnCount(currentCerts.ClusterCertificateCommonNames, targetCerts.ClusterCertificateCommonNames);

            List <string> removedThumbprints = CertificateClusterUpgradeFlow.GetAddedThumbprints(targetCerts.ClusterCertificate, currentCerts.ClusterCertificate);
            List <string> removedCns         = CertificateClusterUpgradeFlow.GetAddedCns(targetCerts.ClusterCertificateCommonNames, currentCerts.ClusterCertificateCommonNames);

            CertificateDescription       thumbprintFileStoreSvcCerts = null;
            ServerCertificateCommonNames commonNameFileStoreSvcCerts = null;
            bool shouldContinue = true;

            switch (changedThumbprintCount + changedCnCount)
            {
            case 1:
            {
                if (removedThumbprints.Any() || removedCns.Any())
                {
                    // cert removal
                    thumbprintFileStoreSvcCerts = currentCerts.ClusterCertificate;
                    commonNameFileStoreSvcCerts = currentCerts.ClusterCertificateCommonNames;
                }
                else
                {
                    // cert add
                    thumbprintFileStoreSvcCerts = targetCerts.ClusterCertificate;
                    commonNameFileStoreSvcCerts = targetCerts.ClusterCertificateCommonNames;
                    shouldContinue = false;
                }

                break;
            }

            case 2:
            {
                if (CertificateClusterUpgradeFlow.IsSwap(currentCerts.ClusterCertificate, targetCerts.ClusterCertificate))
                {
                    thumbprintFileStoreSvcCerts = new CertificateDescription()
                    {
                        Thumbprint          = currentCerts.ClusterCertificate.Thumbprint,
                        ThumbprintSecondary = currentCerts.ClusterCertificate.Thumbprint,
                        X509StoreName       = currentCerts.ClusterCertificate.X509StoreName,
                    };
                }
                else
                {
                    if (changedThumbprintCount == 2)
                    {
                        // thumbprint replace
                        thumbprintFileStoreSvcCerts = new CertificateDescription()
                        {
                            Thumbprint          = currentCerts.ClusterCertificate.Thumbprint,
                            ThumbprintSecondary = targetCerts.ClusterCertificate.Thumbprint,
                            X509StoreName       = currentCerts.ClusterCertificate.X509StoreName,
                        };
                    }
                    else if (changedCnCount == 2)
                    {
                        // cn replace
                        commonNameFileStoreSvcCerts = new ServerCertificateCommonNames()
                        {
                            CommonNames = new List <CertificateCommonNameBase>()
                            {
                                currentCerts.ClusterCertificateCommonNames.CommonNames[0],
                                targetCerts.ClusterCertificateCommonNames.CommonNames[0]
                            },
                            X509StoreName = currentCerts.ClusterCertificateCommonNames.X509StoreName
                        };
                    }
                    else
                    {
                        // 1 thumbprint <-> 1 cn
                        CertificateClusterUpgradeFlow.GetFileStoreSvcListForCertTypeChange(
                            currentCerts,
                            targetCerts,
                            out thumbprintFileStoreSvcCerts,
                            out commonNameFileStoreSvcCerts);
                    }
                }

                break;
            }

            case 3:
            case 4:
            {
                // 1 thumbprints <-> 2 cns, or 2 thumbprints <-> 1 cns, or 2 thumbprints <-> 2 cns
                CertificateClusterUpgradeFlow.GetFileStoreSvcListForCertTypeChange(
                    currentCerts,
                    targetCerts,
                    out thumbprintFileStoreSvcCerts,
                    out commonNameFileStoreSvcCerts);
                break;
            }

            default:
                throw new NotSupportedException(string.Format("It's not supported that {0} certificate thumbprints and {1} certificate common names have changed", changedThumbprintCount, changedCnCount));
            }

            step = new CertificateClusterUpgradeStep(
                thumbprintWhiteList: previousStep != null ? previousStep.ThumbprintWhiteList : CertificateClusterUpgradeFlow.GetThumbprints(currentCerts.ClusterCertificate),
                thumbprintLoadList: targetCerts.ClusterCertificate,
                thumbprintFileStoreSvcList: thumbprintFileStoreSvcCerts,
                commonNameWhiteList: previousStep != null ? previousStep.CommonNameWhiteList : CertificateClusterUpgradeFlow.GetCns(currentCerts.ClusterCertificateCommonNames),
                commonNameLoadList: targetCerts.ClusterCertificateCommonNames,
                commonNameFileStoreSvcList: commonNameFileStoreSvcCerts);

            return(shouldContinue);
        }