Pro / dkim-exchange

DKIM Signing Agent for Microsoft Exchange Server
Other
404 stars 140 forks source link

GUI for installation and configuration #23

Closed Pro closed 10 years ago

Pro commented 10 years ago

Create a simple GUI with following features:

AlexLaroche commented 10 years ago

I suggest you to use Inno Setup (http://www.jrsoftware.org) for the installation program. It's free to use. The current installation project support is InstallShield but it's very limited by default if you don't buy a professional license.

A new project like Windows Form or WPF application could be create for the configuration tool.

AlexLaroche commented 10 years ago

I begin to write a GUI for the application. (Check my two last commits in my fork.) A lot of the buttons are not yet implement. Can you help me with the configuration file (.csproject and .sln) of the project? What is the best way to generate the file in the bin folder?

Pro commented 10 years ago

Do we need to link against external .dll's like the one from Exchange? If not, you can simply create a normal csproject and set the target framework to 3.5. This binary should then also work on Windows Server 2012 (which uses .NET 4) because of its backward compatibility.

AlexLaroche commented 10 years ago

No, I don't need to link against external .dll's like Exchange.

I have created a normal project, but I need to reuse some class from the others projects DkimAlgorithmKind, DkimCanonicalizationKind, RSACryptoHelper, RSACryptoFormat. I also absolutely need to have the same App.config file.

I created the project in .NET 4.5.1. It's possible to install .NET 3.5 and .NET 4.5.1 on the same server.

.NET 4 don't have backward compatibility with 3.5 and previous. .NET 1, .NET2 and .NET3 are one framework. .NET4, .NET4.5, .NET4.5.1 are another one. If the both framework is needed the both have to be install one the server.

AlexLaroche commented 10 years ago

information dkim domain

AlexLaroche commented 10 years ago

It's possible to click on a domain entry and a recipient rule and sender rule. The upload and the download permit to define the private key.

I just don't know what is the best destination for the binary generate for the compilation...

Pro commented 10 years ago

.NET 3.5 Applications should run on .NET 4.0: http://stackoverflow.com/questions/13915498/fully-understanding-the-net-versions-and-backward-compatibility

Why do you need the same app.config? The GUI can be in a totally separate project and you simply reference the needed files.

We should avoid to force an admin to install .NET 4 on a Server running .NET 3.5 because most of the admins don't want to install any app/lib which isn't really necessary for production usage.

The best location for the binary is the default folder. When we release the app, we can add the binary separately on github.

the GUI looks nice so far!

AlexLaroche commented 10 years ago

I need to use .NET 4 because some functions are not available on .NET 3.5.

You can make compile .NET 3.5 in .NET 4.0 but isn't the same CLR. You will need to recompile your code if you want that your code run in .NET 4. You can't just install .NET4 if you want to run .NET 3.5 because the CLR in not the same.

Some Windows update required .NET 4 and .NET 4.5 for Windows Server 2008 R2. The sysadmin already have to install .NET 4.

Pro commented 10 years ago

Yes, you are right. We can use .NET 4. (I just checked my Server 2008 and there's 4.0 and 4.5 installed).

Pro commented 10 years ago

@AlexLaroche I've seen the new VERSION file within the repository. You want to use it for update detection? I think it's better to use the GitHub API to read all the available relases and then check if there's a new release. I.E curl -i https://api.github.com/repos/pro/dkim-exchange/releases Here you can also check if it is a prerelase (beta) or final release and show the release body (which will contain the changelog in future releases)

AlexLaroche commented 10 years ago

I already have some difficulties to implement the reading/editing the app.config file of another project and to use some class from one project in another one (namespace problem).

I also have some difficulties to implement powershell call from the GUI because System.Management.Automation isn't the same for powershell version.

I will keep the implementation of Github API to check new release as a improvement for the GUI.

AlexLaroche commented 10 years ago

I resolved my problem from loading app.config from another project. How can I link now this class from project to the other one (RSACryptoHelper, RSACryptoFormat, General, DomainSection, DomainElement, DomainCollection)? I don't want to duplicate the class and I looking for a logic manner to organize the both project code. What do you thing about that? I commit my work on my fork of your code if you want to see...

I haven't not solved my problem with Powershell libraries. I will probably have to link against external .dll's like the one from Exchange. I don't really like this idea... I continue to think about a solution. I can make direct call to the system but it's not a good idea too. A put a hold for the moment on that function.

AlexLaroche commented 10 years ago

Ok, I find a good way to resolv the problem. I created link file between the two projects. I remove dependencies to resources files for RSACryptoHelper and DomainElement. I changed the namespace of RSACryptoHelper and RSACryptoFormat. I changed DkimAlgorithmKind and DkimCanonicalizationKind namespace too.

AlexLaroche commented 10 years ago

The first release of the GUI is almost complete and the version 2.0 of Exchange DkimSigner!

Pro commented 10 years ago

Nice! Thanks for your contribution. I've added you to my repo so you can modify and push to it directly. Please create a pull request with your new version so we can add it to the main repo. I'll try to fix the powershell call problem in the next days/next weekend.

Pro commented 10 years ago

@AlexLaroche and since you now also can create new releases, don't create them on your own, please let's discuss them first. This counts also for big changes within the code or configuration structure. Thanks!

AlexLaroche commented 10 years ago

I didn't make a pull request because I need to fix the 32 bits registry reading support for the Exchange DkimSigner. Actually, it's only support 64 bits for the moment. It will be very easy to add.

I have also to fix the domain configuration because I only create the registry keys and no delete them...

I can make a pull request to your repository as we will work on the same code. I did major restructuring to the code. It will be a better idea if you want to make some change to the code now but the new implementation isn't 100% completed.

Pro commented 10 years ago

Yes, it would be better if we work in my repo. We have to test the new code anyway before the new release. Maybe i find some time to implement e.g. the git release api. Thus we can merge everything into my repo.

Pro commented 10 years ago

I managed to get C# and Powershell running with this script:

            string hostName = System.Net.Dns.GetHostEntry("").HostName;

            PSCredential psCredential = (PSCredential)null;
            WSManConnectionInfo connectionInfo = new WSManConnectionInfo(new Uri("http://" + hostName + "/Powershell"), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", psCredential);
            connectionInfo.OperationTimeout = 4 * 60 * 1000; // 4 minutes.
            connectionInfo.OpenTimeout = 1 * 60 * 1000; // 1 minute.

            using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
            {

                runspace.Open();
                using (PowerShell powershell = PowerShell.Create())
                {
                    powershell.Runspace = runspace;
                    //Create the command and add a parameter
                    powershell.AddCommand("Get-Mailbox");
                    powershell.AddParameter("RecipientTypeDetails", "UserMailbox");
                    //Invoke the command and store the results in a PSObject collection
                    Collection<PSObject> results = powershell.Invoke();
                    //Iterate through the results and write the DisplayName and PrimarySMTP
                    //address for each mailbox
                    foreach (PSObject result in results)
                   {
                       System.Windows.Forms.MessageBox.Show(
                            string.Format("Name: {0}, PrimarySmtpAddress: {1}",
                                result.Properties["DisplayName"].Value.ToString(),

                                result.Properties["PrimarySmtpAddress"].Value.ToString()
                                ));
                    }
                }
            }

At least it works on Exchange 2010 (Windows Server 2008) and Exchange 2013 (Server 2012). I'll implement the Transport Agent cmdlets in the next days. So the powershell problem should be fixed soon.

AlexLaroche commented 10 years ago

Your solution seen better than mine.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Text;
using System.Threading.Tasks;

namespace Configuration.DkimSigner
{
    public class PowershellHelper
    {
        public static string RunScript(string scriptText)
        {
            try
            {
                Runspace runspace = RunspaceFactory.CreateRunspace();
                runspace.Open();

                Pipeline pipeline = runspace.CreatePipeline();
                pipeline.Commands.AddScript(scriptText);
                pipeline.Commands.Add("Out-String");

                Collection<PSObject> results = pipeline.Invoke();

                runspace.Close();

                StringBuilder stringBuilder = new StringBuilder();
                foreach (PSObject obj in results)
                {
                    stringBuilder.AppendLine(obj.ToString());
                }

                return stringBuilder.ToString();
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }
    }
}
AlexLaroche commented 10 years ago

Do you have to use this to library System.Management.Automation and System.Management.Automation.Runspaces with your solution? The problem is this two libraries are not the same for .NET 3.5 and .NET 4.

Pro commented 10 years ago

Yes. I compiled the exe for.Net 4.0 and used the .dll from PowerShell SDK 2 (which is for .Net 2) but it seems to work anyway on .Net 4.

AlexLaroche commented 10 years ago

Sorry, I make a mistake when I wrote my message yesterday. The problem is with the powershell version 2 (DLL .NET 2) or 3 (DLL .NET 4) used. The problem isn't a the compilation but at the execution. If I was using the wrong Powershell SDK, I was not able to get the command execute. I test the class ExchangerHelper on Exchange 2007 SP3 and Exchange 2010 SP3 and it was not working as expected.

AlexLaroche commented 10 years ago

Maybe you will not like my idea but... :+1: I really think we should change the RecipientRule for complete regex as we make for the SenderRule.

RecipientRule and SenderRule are advanced configuration. It's not to us to decide if it's necessary to sign the email for all the domain and to don't permit just signing for a particular email address destination. I clearly understand that it's really particular situation but as I have previous mentioned is not to us to decide.

We should also add a another parameter in the domain registry to turn on/off domain/user regex if you want to support both mode...

Pro commented 10 years ago

The recipient Rule should already match the whole addres: https://github.com/Pro/dkim-exchange/commit/a7562bc4d9001c0750e7b7f1c8ba91c1684c3e0f Or did I miss something?

We should definetly give the user the option to use regex or not for each domain separately. Because not every Admin knows RegEx that well and you can make a lot of errors using RegEx.

Pro commented 10 years ago

I implemented now the Install and uninstall of the transport agent (using PowerShell) and tested it on a Windows Server 2008 with Exchange 2010 and Windows Server 2012 with Exchange 2013. In both cases it worked without any problems. Just press the "Update" button. It first tries to uninstall the Agent, then Install it again. I'll integrate these functions in the next days.

AlexLaroche commented 10 years ago

@Pro : I think we should avoid to create MessageBox in ExchangeHelper. We should return error code to MainWindows and create the MessageBox from it.

AlexLaroche commented 10 years ago

@Pro : To make the installation/update we should start a new independent process. We will never be able to update automatically the GUI if we don't do that. How to : http://stackoverflow.com/questions/1008886/how-to-create-a-process-that-outlives-its-parent

Pro commented 10 years ago

Yes, definetly. Best solution is to create a custom exception which will be thrown on error and then can be cought by the callee.

The optimal steps to update the app is:

  1. Download the new version to %temp% and extract
  2. Start the new downloaded .exe with parameter --upgrade and current install path, then close current
  3. The new .exe overwrites the old version by copying itself to the install path. The .dll can't yet be replaced because MSExchangeTransport still runs. Thus save the new corresponding .dll to e.g. ExchangeDkimSigner_new.dll
  4. Then start the copied .exe with --upgraded and temp path, then close
  5. The upgraded switch tells the new .exe to remove the temporary files, stop MSExchangeTransport, move (and overwrite) ExchangeDkimSigner_new.dll to ExchangeDkimSigner.dll and then start MSExchangeTransport

If we use these steps we can avoid creating an additional separate updater executable.

AlexLaroche commented 10 years ago

The optimal steps to update the app is (at my opinion):

  1. Download the new version to %temp% and extract
  2. Start the new downloaded .exe with parameter --upgrade and current install path, then close current
  3. Stop MSExchangeTransport and W3SVC
  4. The new .exe overwrites the old version by copying itself to the install path. The .dll can be replaced because MSExchangeTransport isn't still running.
  5. Then start MSExchangeTransport and W3SVC
  6. Then start the copied .exe as normally if desire.
Pro commented 10 years ago

There are two important points for the update:

Therefore I chose the approach where you prepare everything and at the end only need to replace the .dll.

Keeping these two points in mind it doesn't really matter how exactly the update is performed.

AlexLaroche commented 10 years ago

Sound better than calling two times the upgrade and upgraded

Pro commented 10 years ago

@AlexLaroche I implemented the updater functionality. How far are you with your configuration part? Can we release a beta version of the GUI ready for testing?

AlexLaroche commented 10 years ago

@Pro: I haven't worked on that since my last commit. I hadn't enough time to do it.

I will post a commit tonight for bug fix on SenderRule and recipientRule. If you want to continue to implement GUI configuration you can. I don't have the require time for now.

AlexLaroche commented 10 years ago

@Pro : I commit what I have done. I didn't test correctly the GUI specially the install/update/reinstall. If you are sure that most of bugs are correct you could done a beta release.

To get a better implementation of private key management, I should use openssl library. As wrapper for .NET on the Web are old, I will need to update them.

I saw that you use a new external DLL. You wasn't able to implement the function without using external dependencies? I preferred to don't use external dependencies.

AlexLaroche commented 10 years ago

@Pro : The new version of Dkim Signer Agent work as a charm. I don't get any catch exception in eventviewer. All emails are correctly signed.

Pro commented 10 years ago

Thanks for testing! I'll test the GUI next week and then release a beta for public testing.

AlexLaroche commented 10 years ago

I test it before commit, but I have also deployed the new version on my production servers.

AlexLaroche commented 10 years ago

untitled

I'm getting error when I try to install DkimSigner from the GUI. I let you fix that before test upgrade process. I also don't understand why when I try the install process it always ask to save configuration.

Suggest improvements before Beta release:

Pro commented 10 years ago

This error message occurs because on github there's currently only version 1.8.3 available which has not yet the executable for configuration. To test this further I've to release a beta version.

The dll to ionic.zip unzipping functionality can't be removed yet since .Net in Version 4.0 doesn't have a build in function for that (we currently depend on .Net 4 and not .Net 4.5).

Will try to implement the other two checks.

Pro commented 10 years ago

@AlexLaroche I finally managed to test and improve the GUI. There's now an alpha release ready for testing. I'll test it in the next days and hopefully will release a beta version soon. If you find any problems, please create a new issue for them. Thanks for your help!