Friday, February 25, 2022

Debugging Network Communications - For the Rest of the World


In one of my very early forays into IHE standards implementation, I had to implement TLS version 1.0 shortly after it became an IETF RFC, in Java, using Tomcat.  Thus began the ATNA FAQ.  Thiat document is now 15 years old, and is still being used (at least by me).  I started writing these kinds of things down so I don't forget them, which eventually resulted in this blog.

I'm still debugging TLS connections, and I have to admit that it's become a particular art form, but not so much as in finding out what when wrong, and figuring out the solution, but rather in explaining it to someone who is NOT versed in the ingredients of TLS connection sausages so that can a) find the right person to fix it, and b) communicate what needs to be fixed without c) further intervention from me.  That's high art.

I have a highly evolved tool set including:

  • DNS, Ping and TraceRt
  • WireShark
  • OpenSsl
  • JVM debugging arguments
Here's the problems these tools help me identify.  Each requires appropriate communication..
  1. My computer cannot get a good TCP/IP address for the supplied hostname.
    1. Either DNS is down somewhere, or the new DNS record is still propagating, or it simply does not exist.
  2. My computer cannot connect to the TCP/IP address that DNS gave it.
    1. The DNS change for your server may still be propagating
    2. That IP address is not connected to the Internet, is not within my reachable networks
      1. The sending computer sends a SYN, but no ACK is ever returned.
        1. Ping returns no response to that IP (may be blocked by a firewall).
    3. The firewall doesn't like the computer it is coming from.
      1. Same symptoms as above.  Firewalls and application gateways (Firewalls on steroids) and other interfacing technologies (e.g., AWS Lambdas or Azure Functions, gateways that have been weaned from Steroids) can mimic just about anything, but most often, they just hide your computer from mine.
    4. The computer is actively NOT listening to connections from that address.
      1. SYN goes out, but a RST comes back.  In other words, I'm listening to communications, just not to THAT port.
  3. The computers can connect (three way TCP SYN, ACK, SYN-ACK completed), but we cannot make a TLS connection.
    1. My client sent your computer a TLS version it didn't like. You server needs to enable support for TLS Version (1.2 or higher).
    2. My client sent your computer a set of encryption protocols it really doesn't care for.  Your server needs to enable the following encryption protocols ...  (RSA or DCHE Galois Cipher Mode[GCM]).  Cyclic block cyphers (CBC) are no longer considered to be secure.
    3. Your server sent my system a certificate it didn't like, it was:
      1. Expired, please renew it
      2. Revoked,  please replace it with a new certificate
      3. Not secure enough ... please use a certificate supporting at cipher strength of at least (2048 bits).
      4. Not signed by an entity trusted on my end
        1. Our system doesn't accept self-signed certificates, please get your certificate signed by (a commonly trusted CA, or a CA of my choosing)
      5. Prepared using an algorithm my server doesn't support.  Please use an certificate signed using (the RSA algorithm).
      6. For a server going by a different name (this one is rare.  Hostname matching is important in many circumstances, but in cases where the server that is supplying the certificate is three layers deep behind other network infrastructure, it has no clue, and so is often disabled.
    4. Your server required a client certificate from my system that it doesn't have.
      1. Here's our certificate chain, please trust someone in this chain - OR -
      2. Please supply me with the necessary client certificate and the instructions for the obtaining one (the administrative hoops that I have to jump through to get them).
The problem with this are:
  1. The tools are complicated and require either good training or documentation for folks who haven't needed to learn to use them.
  2. You actually have to understand how the Internet standards work to determine what tool to use and when.
  3. I don't scale.  We need me in a box (or more specifically, in a service).
So, I've resolved to work on a tool to do this sort of testing for me, with the details about what is wrong written in very user friendly language about what it finds about the problem.  It's an interesting bit of interface engineering.



Monday, February 21, 2022

Automating FHIR IG Generation from Non-FHIR Sources by cloning myself

An awesome lot of my FHIR IG development involves taking data in one structure and converting it to other structured formats required by the FHIR IG Development process.

That includes creating .fsh and .md files from structured data.

I do most of my FHIR IG development in Eclipse (because if it involves code or transforms, that's where my XML Editors plug in, or my Java transform code for other formats).  I've narrowed down my processes so that I can run Sushi, the FHIR Build or my "custom build script" from within eclipse with one of three external tool configuration scripts:

Here's my normal "Build" script, which just launches build.bat in the project root folder:

<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
    <stringAttribute key="org.eclipse.debug.ui.ATTR_CONSOLE_ENCODING" value="UTF-8"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LAUNCH_CONFIGURATION_BUILD_SCOPE" value="${project}"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="C:\Windows\System32\cmd.exe"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="/c build.bat"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc}"/></launchConfiguration>

Sometimes I just want to rebuild the IG, for that I can just call the IG Publisher:

<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
    <stringAttribute key="org.eclipse.debug.ui.ATTR_CONSOLE_ENCODING" value="UTF-8"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LAUNCH_CONFIGURATION_BUILD_SCOPE" value="${project}"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="C:\jdk-11.0.2\bin\java.exe"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-Xmx2G -jar ../publisher.jar -ig ig.ini -tx n/a"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc}"/>
</launchConfiguration>

And sometimes I just want to rerun Sushi alone, without running FHIR:

<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
    <stringAttribute key="org.eclipse.debug.ui.ATTR_CONSOLE_ENCODING" value="UTF-8"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="C:\Program Files\nodejs\node.exe"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="C:\Users\kboone\AppData\Roaming\npm\node_modules\fsh-sushi\dist\app.js fsh -o ."/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc}"/>
</launchConfiguration>

Save any of these snipped to a file named your-file-name.launch and you should be able to import it as an external tool configuration.

I've even gone so far (finally) as to make this build process an automated part of my check-ins to the FHIR Repository (that way I don't need to be present to run the scripts when source material changes).  What I usually do is take the command line (Windows) script and convert it to Unix and run it in GitHub CI/CD.  For V2-to-FHIR, I just recently created a CI/CD workflow that updates the Sushi from CSV files downloaded from Google Sheets.  This is all for publication purposes.  For SANER, I had other tools to create the SANER IG from an XML file I've been using for IG creation for IHE profiles.  Effectively what I'm doing is cloning myself using GitHub CICD.  I'm not even the first person in the community to do this.  It's basically how build.fhir.org runs, essentially as Grahame in-a-box, but it scales and neither I nor Grahame do.

We were running that up until a few weeks before final publication, after which we did all edits to the files created by the automated process, and removed all the code that supported that process.  That's because the FSH and FHIR IG content in GitHub are the official sources for the IG, not the process inputs used to generate them, and I don't want to be on the hook for maintenance for life for my own tooling that I'm using MOSTLY to make my life easier.

I've build now about 5 different guides using automated FHIR IG (and FSH generation tools).  It's the only way to fly when you have to turn dozens of structured inputs into FHIR IG outputs.