<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>BizTalk on Andrew Wilson's Blog</title><link>https://andrewilson.co.uk/tags/biztalk/</link><description>Recent content in BizTalk on Andrew Wilson's Blog</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Wed, 28 Jun 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://andrewilson.co.uk/tags/biztalk/index.xml" rel="self" type="application/rss+xml"/><item><title>BizTalk | Replacing Strong Name Keys</title><link>https://andrewilson.co.uk/post/2023/06/biztalk-replacing-strong-name-keys/</link><pubDate>Wed, 28 Jun 2023 00:00:00 +0000</pubDate><guid>https://andrewilson.co.uk/post/2023/06/biztalk-replacing-strong-name-keys/</guid><description>&lt;h2 id="background"&gt;Background&lt;/h2&gt;
&lt;p&gt;Strong Names provide .NET Framework assemblies with unique identities. When the .NET Framework loads a strong-named assembly for a referring assembly, it verifies the strong name signature. If the strong name signature of the assembly cannot be verified, the .NET Framework will not load the assembly.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;!Do not rely on strong names for security. They provide a unique identity only!&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Alternatively in our case, BizTalk assemblies are loaded into the Global Assembly Cache (GAC). In this case, instead of the .NET Framework verifying the assembly identity each time it requires loading, the assembly identity is verified once when installed into the GAC.&lt;/p&gt;</description><content:encoded><![CDATA[<h2 id="background">Background</h2>
<p>Strong Names provide .NET Framework assemblies with unique identities. When the .NET Framework loads a strong-named assembly for a referring assembly, it verifies the strong name signature. If the strong name signature of the assembly cannot be verified, the .NET Framework will not load the assembly.</p>
<blockquote>
<p><code>!Do not rely on strong names for security. They provide a unique identity only!</code></p>
</blockquote>
<p>Alternatively in our case, BizTalk assemblies are loaded into the Global Assembly Cache (GAC). In this case, instead of the .NET Framework verifying the assembly identity each time it requires loading, the assembly identity is verified once when installed into the GAC.</p>
<p>Why do we need to strong-name our BizTalk assemblies:</p>
<ol>
<li>Strong-naming is required if we want to store our assembly in the GAC.</li>
<li>The assembly can be loaded side by side with other versions of the assembly.</li>
<li>The assembly can be referenced and used by other strong-named assemblies.</li>
<li>Strong-naming can prevent assembly conflicts.</li>
<li>Strong-naming prevents spoofing of your code (<em>malicious user can modify your code but cannot re-sign it as you</em>)
<blockquote>
<p><code>! Only as long as you keep the private key secure !</code></p>
</blockquote>
</li>
</ol>
<h2 id="problem-space">Problem Space</h2>
<p>One of the big <code>NO NO's</code> when it comes to strong-naming assemblies is, do not add, remove, or change the strong naming key that is used to sign the assembly. Reasoning behind is that by modifying the assembly&rsquo;s strong-name key you have effectively changed the assembly&rsquo;s identity. This means any application that uses the assembly will be requiring the assembly with the previous signed public key, thereby .NET Framework will fail verification and or the assembly with that identity wont be found in the GAC.</p>
<p>However, what if you find yourself in the position where:</p>
<ol>
<li>You have lost the Signing Key that was used to strong-name your assembly.</li>
<li>You have previously password protected your Signing Key but have now forgotten/lost the password.</li>
<li>Your Signing Key has been compromised and you believe a malicious user might wish to modify and re-sign.</li>
</ol>
<p>In this situation, we need to find a way to regenerate a signing key, and update our BizTalk Applications referencing points so that it knows to look for our assembly with the new identity.</p>
<h2 id="solution">Solution</h2>
<p>Every strong-named assembly has a public key that it is identified by, in this case referenced by your BizTalk Application. Each BizTalk Application will reference its dependant assemblies(<em>schemas, maps, orchestrations etc.</em>) through its Bindings of which will also contain the public key for the relevant assemblies. It is this public key that will need to change to the new public key in order to retain the correct assembly identity reference. As part of this verification process, you will also need to make sure the you are referencing the correct version of the assembly.</p>
<blockquote>
<p>For Example: Orchestration</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span> <span style="color:#ff79c6">&lt;ModuleRef</span> <span style="color:#50fa7b">Name=</span><span style="color:#f1fa8c">&#34;Application.Orchestrations&#34;</span> <span style="color:#50fa7b">Version=</span><span style="color:#f1fa8c">&#34;1.0.0.0&#34;</span> <span style="color:#50fa7b">Culture=</span><span style="color:#f1fa8c">&#34;neutral&#34;</span> <span style="color:#50fa7b">PublicKeyToken=</span><span style="color:#f1fa8c">&#34;PublicTokenToBeReplaced&#34;</span> <span style="color:#50fa7b">FullName=</span><span style="color:#f1fa8c">&#34;Application.Orchestrations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=PublicTokenToBeReplaced&#34;</span><span style="color:#ff79c6">&gt;</span>
</span></span></code></pre></div><blockquote>
<p>For Example: Pipeline</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#ff79c6">&lt;ReceivePipeline</span> <span style="color:#50fa7b">Name=</span><span style="color:#f1fa8c">&#34;Application.Pipelines.FlatFileReceivePipeline&#34;</span> <span style="color:#50fa7b">FullyQualifiedName=</span><span style="color:#f1fa8c">&#34;Application.Pipelines.FlatFileReceivePipeline, Application.Pipelines, Version=1.0.0.0, Culture=neutral, PublicKeyToken=PublicTokenToBeReplaced&#34;</span> <span style="color:#50fa7b">Type=</span><span style="color:#f1fa8c">&#34;1&#34;</span> <span style="color:#50fa7b">TrackingOption=</span><span style="color:#f1fa8c">&#34;ServiceStartEnd MessageSendReceive PipelineEvents&#34;</span> <span style="color:#50fa7b">Description=</span><span style="color:#f1fa8c">&#34;&#34;</span> <span style="color:#ff79c6">/&gt;</span>
</span></span></code></pre></div><p>If you are like me, all my BizTalk Applications are deployed using the BizTalk Deployment Framework allowing me to conduct repeatable deployments without manual configuration and setup between environments. In this case you will need to update your PortBindingsMaster.xml file to replace the public key tokens as shown above.</p>
<p>If deployed manually from scratch, by setting up your ports, orchestrations etc. you will be setting up the new public key link by default. If deploying over the solution, then you will see in your Applications resources two of the same assembly but different PublicKeyToken. You will need to restart host instances (reloads assemblies) and then either update the references to point to the new version of the assembly or you may need to extract the bindings for the application, replace the Public Token, and then import the bindings. Be aware that any secrets held in your bindings will not be extracted and therefore you may need to re-enter these after you import. Once the references to the new assembly are complete, you can remove the old reference.</p>
<h3 id="retrieving-new-and-old-public-key-from-strong-name-key">Retrieving New and Old Public Key from Strong Name Key</h3>
<h4 id="biztalk-server-admin-console">BizTalk Server Admin Console</h4>
<p>The simplest method of retrieving the current (old) public key is to have a look in the BizTalk Server Admin Console.</p>
<ol>
<li>Navigate to your Application in BizTalk.</li>
<li>Navigate to Resources.</li>
<li>Find your assembly in the list of resources you are updating.</li>
<li>The Name of the assembly contains the PublicKeyToken.</li>
</ol>
<p>This method is useful if you have lost the current Strong Name Key, or have forgotten the password.</p>
<h4 id="strong-name-tool-snexe">Strong Name Tool Sn.exe</h4>
<p>This method relies on the fact that you still have the current (old) strong name key (if password protected, the password) and have already created the new key.</p>
<ol>
<li>
<p>Load Visual Studio Developer Command Line.</p>
</li>
<li>
<p>CD to the path that holds your Strong Name Keys</p>
</li>
<li>
<p>Enter the following command</p>
<p><code>sn -p NameOfKey.snk(can also be .pfx) token.snk</code></p>
<blockquote>
<p>This command extracts the public key from the key pair in the provided strong name and stores it in the new file token.snk</p>
</blockquote>
</li>
<li>
<p>(<strong>Password Protected</strong>) If you provided a .pfx file, you will be prompted with a password, enter the password that protects the key.</p>
</li>
<li>
<p>Enter the following command</p>
<p><code>sn -t token.snk</code></p>
<blockquote>
<p>This command displays the public key stored in the new file token.snk</p>
</blockquote>
</li>
</ol>
<p>These steps can be followed for both the old key to be replaced and the new key.</p>
<hr>
<blockquote>
<p><strong>Sources</strong></p>
<ol>
<li>
<p>Using Strong Name Signatures | <a href="https://learn.microsoft.com/en-us/archive/msdn-magazine/2006/july/clr-inside-out-using-strong-name-signatures">https://learn.microsoft.com/en-us/archive/msdn-magazine/2006/july/clr-inside-out-using-strong-name-signatures</a></p>
</li>
<li>
<p>Strong-named assemblies | <a href="https://learn.microsoft.com/en-us/dotnet/standard/assembly/strong-named">https://learn.microsoft.com/en-us/dotnet/standard/assembly/strong-named</a></p>
</li>
<li>
<p>Global Assembly Cache | <a href="https://learn.microsoft.com/en-us/dotnet/framework/app-domains/gac">https://learn.microsoft.com/en-us/dotnet/framework/app-domains/gac</a></p>
</li>
<li>
<p>Creating a Strong-Named BizTalk Assembly | <a href="https://learn.microsoft.com/en-us/biztalk/adapters-and-accelerators/accelerator-swift/lesson-2-creating-a-strong-named-biztalk-assembly-for-the-swiftschemas-project">https://learn.microsoft.com/en-us/biztalk/adapters-and-accelerators/accelerator-swift/lesson-2-creating-a-strong-named-biztalk-assembly-for-the-swiftschemas-project</a></p>
</li>
<li>
<p>Sn.exe (Strong Name Tool) | <a href="https://learn.microsoft.com/en-us/dotnet/framework/tools/sn-exe-strong-name-tool">https://learn.microsoft.com/en-us/dotnet/framework/tools/sn-exe-strong-name-tool</a></p>
</li>
<li>
<p>Deployment Framework for BizTalk Server V5.5 | <a href="http://www.tfabraham.com/BTDFDocs/V5_5/">http://www.tfabraham.com/BTDFDocs/V5_5/</a></p>
</li>
<li>
<p>Strong Naming | <a href="https://learn.microsoft.com/en-us/dotnet/standard/library-guidance/strong-naming">https://learn.microsoft.com/en-us/dotnet/standard/library-guidance/strong-naming</a></p>
</li>
</ol>
</blockquote>
]]></content:encoded></item><item><title>BizTalk | Deploying and Reading Secure SSO Settings</title><link>https://andrewilson.co.uk/post/2023/04/biztalk-secure-sso-settings/</link><pubDate>Wed, 26 Apr 2023 00:00:00 +0000</pubDate><guid>https://andrewilson.co.uk/post/2023/04/biztalk-secure-sso-settings/</guid><description>&lt;h2 id="background"&gt;Background&lt;/h2&gt;
&lt;p&gt;One of the fundamental parts to BizTalk for both configuration and integration applications is &lt;a href="https://learn.microsoft.com/en-us/biztalk/core/enterprise-single-sign-on-sso"&gt;&lt;code&gt;Enterprise Single Sign On&lt;/code&gt;&lt;/a&gt;, or as we will continue to reference as &lt;code&gt;SSO&lt;/code&gt; from now on.&lt;/p&gt;
&lt;p&gt;SSO outside the bounds of BizTalk is an available service that is used to store and transmit encrypted user credentials. However, due to the nature of the service it is fairly generic, this has meant that many middleware applications and custom adapters have been designed to leverage SSO to securely store and transmit secure &lt;code&gt;settings&lt;/code&gt;.&lt;/p&gt;</description><content:encoded><![CDATA[<h2 id="background">Background</h2>
<p>One of the fundamental parts to BizTalk for both configuration and integration applications is  <a href="https://learn.microsoft.com/en-us/biztalk/core/enterprise-single-sign-on-sso"><code>Enterprise Single Sign On</code></a>, or as we will continue to reference as <code>SSO</code> from now on.</p>
<p>SSO outside the bounds of BizTalk is an available service that is used to store and transmit encrypted user credentials. However, due to the nature of the service it is fairly generic, this has meant that many middleware applications and custom adapters have been designed to  leverage SSO to securely store and transmit secure <code>settings</code>.</p>
<p>The SSO System holds any secure values in logical entities called <code>Affiliate Applications</code>. Affiliate Applications represent a system or sub-system, back-end system, or line of business application.</p>
<p>Looking back at BizTalk, each deployed application (<code>Line of business application</code>) is setup in SSO as an Affiliate Application. BizTalk uses the Affiliate Application to store internal configurations such as secure adapter data and configuration.</p>
<blockquote>
<p>This post is written in mind for a BizTalk project that makes use of the <a href="https://github.com/BTDF/DeploymentFramework"><code>BizTalk Deployment Framework (BTDF)</code></a>. I would highly recommend making use of BTDF as it will assist you in conducting repeatable deployments without manual configuration and setup between environments.</p>
</blockquote>
<p>BTDF when added to your BizTalk project will include a <code>SettingsFileGenerator.xml</code>. This file will enable you to configure environment settings that are used to tokenise your PortBindings configuration and more. Another key aspect to this file, is that you can include settings that are utilised by your integrations at run-time such as database connection strings. When you deploy your application(s) to BizTalk, the selected environment settings are deployed to the Affiliate Application in SSO. These settings are encrypted at rest, and are available from anywhere within the BizTalk group.</p>
<h2 id="problem-space">Problem Space</h2>
<p>SSO is brilliant for securely storing my settings, but how would I <code>securely</code> get those settings there?</p>
<p>One of the big problems with the BizTalk Deployment Framework <code>SettingsFileGenerator.xml</code> is that it stores your integration environment setting values in plain text, to add to the issue, this file is usually checked into source control.</p>
<p>Now you might think that you would be able to tokenise the settings values and then replace them at a CI/CD level. Agreed this is one step further into secure storage and removal of these values in source control. However, this file will still then contain your secure setting values in plain text as part of a CI/CD artefact, and this file will exist on the BizTalk App box that the deployment has occurred on. So you are still no further secured.</p>
<h2 id="solution--secure-deployment">Solution | Secure Deployment</h2>
<p>When your BizTalk Application msi is extracted as part of a deployment (extracted onto the App Box <em>Programs x86</em>), the msi will have included some framework deployment tools. One of these tools is the <code>SSOSettingsEditor.exe</code>. This editor will allow you to specify the Affiliate Application name, of which it will then display all the currently deployed settings and values in SSO for that application. This editor will also allow you to edit such values.</p>
<p>Handily, this editor is backed by a DLL that has also been made available in the same folder <code>SSOSettingsFileReader.dll</code>. This means we can use this DLL as part of our CI/CD pipeline as a post deployment step to update values in SSO. So how do we do this?</p>
<p>Firstly, we will require our handy <code>SettingsFileGenerator.xml</code>, we still want our setting being loaded into SSO for us to update later, but don&rsquo;t require the value to be the real one. It can be a dummy value, and so we don&rsquo;t mind it being in plain text.</p>
<p>Secondly, we can use PowerShell and the <code>SSOSettingsFileReader.dll</code> as a Post Deployment Step. The DLL contains a set of static classes and methods of which we can make effective use of. For this use case, we will require <code>[SSOSettingsFileManager.SSOSettingsManager]::WriteSetting</code>. The WriteSetting method takes three parameters:</p>
<ol>
<li><strong>The Affiliate Application Name</strong> | this will be the name of your project as seen in your <code>.btdfproj</code></li>
<li><strong>The Setting Name</strong> | this is the name of the setting that you wish to replace it&rsquo;s value.</li>
<li><strong>The New Setting Value</strong> | this is the value you wish to replace the default with.</li>
</ol>
<p>After you have run this command, you can verify the changes have been made with the <code>SSOSettingsEditor.exe</code> as mentioned above.</p>
<h2 id="solution--reading-from-sso-in-your-integration">Solution | Reading from SSO in your Integration</h2>
<p>Let&rsquo;s assume that you have an integration that will require a setting value from SSO such as a database connection string. To access this setting we can make use of the same DLL as mentioned above. There is another static class and method that will read a value from SSO:</p>
<ul>
<li><code>[SSOSettingsFileManager.SSOSettingsFileReader]::ReadString</code></li>
</ul>
<p>This method takes two parameters:</p>
<ol>
<li><strong>The Affiliate Application Name</strong> | this will be the name of your project as seen in your <code>.btdfproj</code></li>
<li><strong>The Setting Name</strong> | this is the name of the setting that you wish to retrieve.</li>
</ol>
<p>To make such as call, you will need to:</p>
<ol>
<li>Add the DLL as a reference to you BizTalk Project.</li>
<li>Include the DLL as a component, this is done in your <code>.btdfproj</code></li>
<li>Add the call to your integration as either:
<ol>
<li>A variable in your orchestration.</li>
<li>A Scripting Functoid calling the external assembly in a Map.</li>
</ol>
</li>
</ol>
<h2 id="conclusion">Conclusion</h2>
<p>Provided both solutions, you can now specify your own secure integration settings values where these values are only stored as secure variables in your CI/CD and passed into SSO, and then read these values into your integrations straight from SSO. These secret values no longer need to live in plain text.</p>
]]></content:encoded></item></channel></rss>