Server certificates and production D365fo

Server certificates and production D365fo


Many integrations require certificates to authenticate the identify of the caller, in this case D365fo.?Most documentation or code samples for these integrations?will instruct you to install the provided certificate(s) on your server.?That sample would then assume the certificate is installed and use the name or thumbprint guid to fetch it into the integration calls using app.config or similar approach.?The problem is remote desktop to the D365fo production server is disabled so one cannot install certificates to the server. After searching for alternatives and finding nothing, I figured I would share the solution I worked out for this problem.

Every integration is different, so you won't be able to copy paste everything into your specific problem, but this should get you most of the way there. Ultimately, the?certificates end up being passed in the http web request, and at that point, it doesn't matter if your certificate is installed on the server, as long as the certificate data is there in the web request.

Your first step will be to store the certificate in a parameter table.?Make a new container field, and an upload button.?To upload a file into this field use this code:

FileUploadResultBase upload = File::GetFileFromUser();

??????str filename = upload.getFileName();

??????System.IO.Stream stream = upload.openResult();

??????System.IO.MemoryStream ms = new System.IO.MemoryStream();

??????stream.CopyTo(ms);

??????Binary binary = Binary::constructFromMemoryStream(ms);

???????<your parameter table>.<certificate field> = binary.getContainer();

<your parameter table>.write();


Your certificate may also require a password.?If this is the case, see the base form "Email parameters" - field smtp password.?This code can be easily copied to store a password with encryption.??

Once you have uploaded your certificate to the container field, you can fetch to back into a byte array using this code:

Binary certBinary = Binary::constructFromContainer(<your parameter table>.<certificate field>);

??????System.IO.MemoryStream certMS = certBinary.getMemoryStream();

??????System.Byte[] certBytes = certMS.ToArray();

Now that you have your certificate in a byte array at runtime, you can create the certificate objects in C# (either with C# and dll reference, or in x++ with the C# objects).

Here are two samples, with and without a password.?You may need to use a different certificate object based on your integration

System.Security.Cryptography.X509Certificates.X509Certificate2 certPw = new System.Security.Cryptography.X509Certificates.X509Certificate2();

??????certPw.Import(<certBytes>, <yourpassword>, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.DefaultKeySet);

??????System.Security.Cryptography.X509Certificates.X509Certificate2 certNoPw = new System.Security.Cryptography.X509Certificates.X509Certificate2();

??????certNoPw.Import(<certBytes>);

Now that you have the certificate object, you will want to add it to the web request calls. This code will vary based on how you built your web requests.?

The HttpWebRequest object has a ClientCertifcates property you could assign there.?In our case, we were working with a System.ServiceModel.clientBase template, so our code looked like this:

System.ServiceModel.Security.X509CertificateInitiatorClientCredential client = clientBase.ClientCredentials.ClientCertificate;

??????client.Certificate = <certPw>/<certNoPw> from above;

System.ServiceModel.Security.X509CertificateRecipientClientCredential service = clientBase.ClientCredentials.ServiceCertificate;

??????service.DefaultCertificate = <certPw>/<certNoPw> from above;


If your integration provides you with sample code, the easiest way to figure this step out is to run their sample code in a dev environment where you can install the certificate. Debug and see which object and property is getting the certificate, then you know which property to set with your code.??

Edit: You could also store your certificates more securely with the new key vault feature. You would likely still need to download them to a byte array and assign as described in the second half of my article. More on key vault: https://jatomas.com/en/2020/06/02/azure-key-vault-msdyn365fo-setup-certificates-passwords/

Denis Trunin

Dynamics AX / Dynamics 365 FO Technical Consultant

3 年

Thanks for sharing, the post is great

回复
André Michel Vargas

Chief Data Officer @ Creative Artists Agency | Cand. Polit. MSc. Economics

3 年

Great job Gopi Balakrishnan and Michael Schiermeyer , and to the CAA team!

要查看或添加评论,请登录

Michael Schiermeyer的更多文章

  • AWS authentication in X++ for Vendor Central & others

    AWS authentication in X++ for Vendor Central & others

    The authentication step to AWS is rather complicated. A client had asked me to code the authentication step and they…

  • Default batch retry to 0

    Default batch retry to 0

    Microsoft introduced batch retry in 2021. This causes many unexpected results covered in many other articles.

    2 条评论
  • Refresh certificates on onebox dev machines

    Refresh certificates on onebox dev machines

    If you follow the onebox VHD setup, you have had to use the self signed certificate for a few years now during setup:…

    3 条评论
  • Force progress bar in X++

    Force progress bar in X++

    There are several standard, best practice approaches to showing your user a wait indicator. Such as…

  • D365 SSRS Checkboxes using wingdings

    D365 SSRS Checkboxes using wingdings

    This article is more of a reminder that this is an option when developing SSRS reports in d365. In my twelve years of…

    1 条评论
  • D365fo custom dimension defaulting in segmented entry controls

    D365fo custom dimension defaulting in segmented entry controls

    The below outlines how to code a custom dimension defaulting logic directly into the segmented entry controls such that…

  • D365fo join table as csv column in view/data entity

    D365fo join table as csv column in view/data entity

    Below is some sample code for joining a table to a view as a calculated field. Useful when you have data represented as…

社区洞察

其他会员也浏览了