public async Task RecoverNetwork()

in src/ccf/ccf-provider-client/Controllers/NetworksController.cs [324:482]


    public async Task<IActionResult> RecoverNetwork(
        [FromRoute] string networkName,
        [FromBody] RecoverNetworkInput content)
    {
        var error = ValidateRecoverInput();
        if (error != null)
        {
            return error;
        }

        CcfNetworkProvider ccfNetworkProvider = this.GetNetworkProvider(content.InfraType);
        CcfNetwork network;
        if (content.OperatorRecovery != null)
        {
            using RSA rsaEncKey =
                !string.IsNullOrEmpty(content.OperatorRecovery.EncryptionPrivateKey) ?
                Utils.ToRSAKey(content.OperatorRecovery.EncryptionPrivateKey) :
                await Utils.ToRSAKey(new Uri(content.OperatorRecovery.EncryptionKeyId!));
            network = await ccfNetworkProvider.RecoverNetwork(
                networkName,
                content.NodeCount ?? 1,
                content.NodeLogLevel,
                SecurityPolicyConfigInput.Convert(content.SecurityPolicy),
                content.PreviousServiceCertificate,
                rsaEncKey,
                content.ProviderConfig);
        }
        else
        {
            var svcName = content.ConfidentialRecovery!.RecoveryServiceName;
            var svcProvider = this.GetRecoveryServiceProvider(content.InfraType);
            var recoveryService = await svcProvider.GetService(
                svcName,
                content.ProviderConfig);
            if (recoveryService == null)
            {
                return this.NotFound(new ODataError(
                    code: "ServiceNotFound",
                    message: $"No endpoint for service {svcName} was found."));
            }

            network = await ccfNetworkProvider.RecoverNetwork(
                networkName,
                content.NodeCount ?? 1,
                content.NodeLogLevel,
                SecurityPolicyConfigInput.Convert(content.SecurityPolicy),
                content.PreviousServiceCertificate,
                this.GetRecoveryAgentProvider(content.InfraType),
                content.ConfidentialRecovery!.MemberName,
                recoveryService,
                content.ProviderConfig);
        }

        return this.Ok(network);

        IActionResult? ValidateRecoverInput()
        {
            if (!string.IsNullOrEmpty(content.NodeLogLevel))
            {
                List<string> allowedValues =
                [
                    "Trace", "Debug", "Info", "Fail", "Fatal"
                ];

                if (!allowedValues.Contains(content.NodeLogLevel))
                {
                    return this.BadRequest(new ODataError(
                        code: "InvalidNodeLogLevel",
                        message: $"Value should be one of: {string.Join(",", allowedValues)}"));
                }
            }

            if (content.OperatorRecovery != null && content.ConfidentialRecovery != null)
            {
                return this.BadRequest(new ODataError(
                    code: "ConflictingInput",
                    message: "Both operatorRecovery and confidentialRecovery cannot be specified" +
                    " together."));
            }

            if (content.OperatorRecovery == null && content.ConfidentialRecovery == null)
            {
                return this.BadRequest(new ODataError(
                    code: "InputMissing",
                    message: "Either operatorRecovery or confidentialRecovery must be specified."));
            }

            try
            {
                using var c = X509Certificate2.CreateFromPem(content.PreviousServiceCertificate);
            }
            catch (Exception e)
            {
                return this.BadRequest(new ODataError(
                    code: "InvalidCertificate",
                    message: e.Message));
            }

            if (content.OperatorRecovery != null)
            {
                var opRec = content.OperatorRecovery;
                if (string.IsNullOrEmpty(opRec.EncryptionPrivateKey) &&
                    string.IsNullOrEmpty(opRec.EncryptionKeyId))
                {
                    return this.BadRequest(new ODataError(
                        code: "InvalidEncryptionKey",
                        message: "Either encryptionPrivateKey or encryptionKeyId must be specified."));
                }

                if (!string.IsNullOrEmpty(opRec.EncryptionPrivateKey) &&
                    !string.IsNullOrEmpty(opRec.EncryptionKeyId))
                {
                    return this.BadRequest(new ODataError(
                        code: "InvalidEncryptionKey",
                        message: "Only one of encryptionPrivateKey or encryptionKeyId must be specified."));
                }

                if (!string.IsNullOrEmpty(opRec.EncryptionPrivateKey))
                {
                    try
                    {
                        using var rsa = RSA.Create();
                        rsa.ImportFromPem(opRec.EncryptionPrivateKey);
                    }
                    catch (Exception e)
                    {
                        return this.BadRequest(new ODataError(
                            code: "InvalidEncryptionPrivateKey",
                            message: e.Message));
                    }
                }
                else
                {
                    try
                    {
                        new Uri(opRec.EncryptionKeyId!);
                    }
                    catch (Exception e)
                    {
                        return this.BadRequest(new ODataError(
                            code: "InvalidEncryptionKeyId",
                            message: e.Message));
                    }
                }
            }

            if (content.ConfidentialRecovery != null)
            {
                if (string.IsNullOrEmpty(content.ConfidentialRecovery.MemberName))
                {
                    return this.BadRequest(new ODataError(
                        code: "InputMissing",
                        message: "confidentialRecovery.memberName must be specified."));
                }
            }

            return null;
        }
    }