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 int GetChangedThumbprintCount(CertificateDescription currentCerts, CertificateDescription targetCerts)
        {
            List <string> currentThumbprints = CertificateClusterUpgradeFlow.GetThumbprints(currentCerts);
            List <string> targetThumbprints  = CertificateClusterUpgradeFlow.GetThumbprints(targetCerts);

            return(CertificateClusterUpgradeFlow.GetChangedCertCount(currentThumbprints, targetThumbprints, isThumbprint: true));
        }
        internal static int GetChangedCnCount(ServerCertificateCommonNames currentCerts, ServerCertificateCommonNames targetCerts)
        {
            List <string> currentCns = CertificateClusterUpgradeFlow.GetCns(currentCerts).Keys.ToList();
            List <string> targetCns  = CertificateClusterUpgradeFlow.GetCns(targetCerts).Keys.ToList();

            return(CertificateClusterUpgradeFlow.GetChangedCertCount(currentCns, targetCns, isThumbprint: false));
        }
        public ClusterManifestType[] UpdateCertificateInClusterManifest(
            ClusterManifestType existingClusterManifest,
            Security currentSecurity,
            FabricSettingsMetadata currentFabricSettingsMetadata)
        {
            List <NodeDescription> existingSeedNodes = this.OnGetExistingSeedNodes(existingClusterManifest);

            List <CertificateClusterUpgradeStep> upgradeSteps = CertificateClusterUpgradeFlow.GetUpgradeFlow(
                currentSecurity.CertificateInformation,
                this.TargetCsmConfig.Security.CertificateInformation);

            ClusterManifestType[] result = new ClusterManifestType[upgradeSteps.Count];
            for (int i = 0; i < upgradeSteps.Count; i++)
            {
                result[i] = this.UpdateClusterManifest(
                    i == 0 ? existingClusterManifest : result[i - 1],
                    currentFabricSettingsMetadata,
                    this.VersionGenerator.GetNextClusterManifestVersion(),
                    upgradeSteps[i],
                    existingSeedNodes);
            }

            return(result);
        }
        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);
        }