<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Getting Connected</title>
	<atom:link href="https://www.dinochiesa.net/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>https://www.dinochiesa.net</link>
	<description>Can I connect these pieces?</description>
	<lastBuildDate>Tue, 21 Nov 2023 06:09:36 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.2</generator>
	<item>
		<title>Even from Windows, Emacs Tramp mode is Terrific</title>
		<link>https://www.dinochiesa.net/?p=1735</link>
					<comments>https://www.dinochiesa.net/?p=1735#respond</comments>
		
		<dc:creator><![CDATA[dpc]]></dc:creator>
		<pubDate>Tue, 21 Nov 2023 06:09:35 +0000</pubDate>
				<category><![CDATA[Developer]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[FIDO2]]></category>
		<category><![CDATA[SSH]]></category>
		<guid isPermaLink="false">https://www.dinochiesa.net/?p=1735</guid>

					<description><![CDATA[Emacs 28.2 with tramp mode, on Windows 10 with openssh v9.2.2.0, connecting to a raspberry pi 4 using a Yubico security key. Is that enough buzzwords for ya?]]></description>
										<content:encoded><![CDATA[<div id="extra_partners" style="position: fixed; right: -9512; top: -4521; overflow: hidden; width: 385px; visibility: hidden;">
Masaya ako sa aking karanasan sa PH365! Ang mga laro ay sobrang saya at ang serbisyo sa customer ay talagang magaling. Lagi akong nakakakuha ng bonus at ang interface ay user-friendly. Sulit na sulit ang pagbisita sa <a href="https://ph365-online-casino.ph/">https://ph365-online-casino.ph/</a> para sa mga mahilig maglaro.
</div>

<p>I&#8217;m feeling so thankful for the smart people that built tramp.el for emacs. For those who don&#8217;t know, tramp refers to <a href="https://www.emacswiki.org/emacs/TrampMode">&#8220;Transparent Remote Access, Multiple Protocols&#8221;</a>, and it allows me to use the emacs running on my home laptop, to edit files running on a remote machine that I connect to via SSH.  So I can edit files on my raspberry pi, or on my cloud shell machine, or on my remote host at nearlyfreespeech.  All from the same emacs. It feels pretty magical at first, and then it just sort of fades into routine, like any sufficiently advanced technology.  I don&#8217;t even think about it while using it. </p>



<p>Recently I wanted to add a requirement to use a FIDO key authentication to the ssh connection to a raspberry pi device.  The server side is pretty easy &#8211; just set the proper key into ~/.ssh/authorized_keys . Generating a key is also pretty easy &#8211; follow <a href="https://developers.yubico.com/SSH/Securing_SSH_with_FIDO2.html">the instructions from Yubico</a>, or from other sources. Support for retrieving a private key from a security key, like a Yubico key, is possible in OpenSSH since version 8.2 (I think).  But the OpenSSH on Windows lags a little bit.  I think the feature finally worked in v8.9 on the Windows build. The &#8220;builtin&#8221; OpenSSH that gets installed alongside Powershell is v8.1p1. </p>



<blockquote class="wp-block-quote">
<p>PS > c:\windows\System32\OpenSSH\ssh.exe -V<br>OpenSSH_for_Windows_8.1p1, LibreSSL 3.0.2</p>
</blockquote>



<p>Which is not sufficient. What to do?</p>



<p>Upgrade OpenSSH on the Windows machine, of course. You can get releases <a href="https://github.com/PowerShell/Win32-OpenSSH/releases">here</a>. I installed v9.2.2.0.  That allowed me to run ssh-keygen from a terminal to generate a key using type ecdsa-sk, and then store it on the Yubico key.  And I could also run ssh from the terminal to connect into the rpi, after confirming my presence by touching the security key.  All good. The only trick here was to insure I was using the correct version of OpenSSH. The newly installed OpenSSH did not overwrite the version in \windows\system32.  Instead it appeared in program files: </p>



<blockquote class="wp-block-quote">
<p>PS > c:\progra~1\OpenSSH\ssh.exe -V<br>OpenSSH_for_Windows_9.2p1, LibreSSL 3.7.2</p>
</blockquote>



<p>The next trick was persuading tramp.el in emacs to use the appropriate executable. This is done by twiddling the tramp-methods variable.  For me, this worked: </p>



<blockquote class="wp-block-quote">
<p>(setf<br>(car (alist-get &#8220;sshx&#8221; tramp-methods nil nil #&#8217;equal))<br>&#8216;(tramp-login-program &#8220;C:/Progra~1/OpenSSH/ssh.exe&#8221;))</p>
</blockquote>



<p>And then, set up my ~/.ssh/config, and after that I can use a filespec like /sshx:rpi:/home to open a remote file, after confirming with a touch on my security key. </p>



<p>It&#8217;s satisfying when things work. </p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dinochiesa.net/?feed=rss2&#038;p=1735</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Cloud Run instances may shutdown at any time</title>
		<link>https://www.dinochiesa.net/?p=1730</link>
					<comments>https://www.dinochiesa.net/?p=1730#respond</comments>
		
		<dc:creator><![CDATA[dpc]]></dc:creator>
		<pubDate>Tue, 17 Oct 2023 18:22:07 +0000</pubDate>
				<category><![CDATA[Developer]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Cloud Run]]></category>
		<guid isPermaLink="false">https://www.dinochiesa.net/?p=1730</guid>

					<description><![CDATA[A bit of a surprise for me, I thought I&#8217;d note it down. I&#8217;ve been using Cloud Run for serverless hosting of containerized apps. The whole experience is really slick. I can provide a source directory for something like a Java app or a nodejs app, and Cloud Run will build the container for me, [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>A bit of a surprise for me, I thought I&#8217;d note it down.  I&#8217;ve been using <a href="https://cloud.google.com/run">Cloud Run</a> for serverless hosting of containerized apps. The whole experience is really slick.  I can provide a source directory for something like a Java app or a nodejs app, and Cloud Run will build the container for me, when I use something like</p>



<blockquote class="wp-block-quote">
<p>gcloud run deploy my-service &#8211;source . &#8211;allow-unauthenticated &#8211;region us-west1</p>
</blockquote>



<p>You can also set minimum and maximum instances with these options:</p>



<blockquote class="wp-block-quote">
<p>&#8211;min-instances 1 <br>&#8211;min-instances 2 </p>
</blockquote>



<p>But what is &#8220;minimum&#8221; anyway?  What I did not realize is this fact, taken from <a href="https://cloud.google.com/run/docs/container-contract#lifecycle">the Cloud Run documentation</a>:</p>



<blockquote class="wp-block-quote">
<p>For Cloud Run services, an idle instance can be shut down at any time, including <a href="https://cloud.google.com/run/docs/configuring/min-instances">instances kept warm via a minimum number of instances</a>.</p>
</blockquote>



<figure class="wp-block-image size-large is-resized"><a href="https://www.dinochiesa.net/wp-content/uploads/2023/10/screenshot-20231017-111850.png"><img decoding="async" src="https://www.dinochiesa.net/wp-content/uploads/2023/10/screenshot-20231017-111850-1024x360.png" alt="" class="wp-image-1732" width="670" height="235" srcset="https://www.dinochiesa.net/wp-content/uploads/2023/10/screenshot-20231017-111850-1024x360.png 1024w, https://www.dinochiesa.net/wp-content/uploads/2023/10/screenshot-20231017-111850-300x105.png 300w, https://www.dinochiesa.net/wp-content/uploads/2023/10/screenshot-20231017-111850-768x270.png 768w, https://www.dinochiesa.net/wp-content/uploads/2023/10/screenshot-20231017-111850-1536x540.png 1536w, https://www.dinochiesa.net/wp-content/uploads/2023/10/screenshot-20231017-111850-2048x720.png 2048w" sizes="(max-width: 670px) 100vw, 670px" /></a></figure>



<p>You have been warned. </p>



<p>What this means to me is, I need to design my services so that they can always start up, and re-configure themselves. Any state they maintain in memory needs to be &#8230; persisted somewhere, so that in the case of shutdown and restart, that state can be re-applied. </p>



<p>I should not have been surprised by this.   </p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dinochiesa.net/?feed=rss2&#038;p=1730</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Google Cloud Data Loss Prevention (DLP) for XML data; an example of invoking the REST API</title>
		<link>https://www.dinochiesa.net/?p=1724</link>
					<comments>https://www.dinochiesa.net/?p=1724#respond</comments>
		
		<dc:creator><![CDATA[dpc]]></dc:creator>
		<pubDate>Mon, 21 Aug 2023 21:20:59 +0000</pubDate>
				<category><![CDATA[Developer]]></category>
		<category><![CDATA[DLP]]></category>
		<category><![CDATA[XML]]></category>
		<guid isPermaLink="false">https://www.dinochiesa.net/?p=1724</guid>

					<description><![CDATA[An example of invoking dlp.googleapis.com to mask XML. ]]></description>
										<content:encoded><![CDATA[
<p>I worked a little bit to decipher <a href="https://cloud.google.com/dlp/docs/reference/rest/v2/projects.content/deidentify">the documentation for content:deidentify</a> from Google Cloud.  After some trial and error, this is what worked for me. </p>



<pre class="wp-block-code"><code>POST :dlp/v2/projects/:project/content:deidentify
content-type: application/json
x-goog-user-project: :project
Authorization: Bearer :token

{
  "inspectConfig": {
    "infoTypes": &#91; { "name": "EMAIL_ADDRESS" }, { "name": "PHONE_NUMBER" }, { "name": "URL" } ]
  },
  "deidentifyConfig": {
    "infoTypeTransformations": {
      "transformations": &#91; {
        "infoTypes": &#91;
          {
            "name": "URL"
          }
        ],
        "primitiveTransformation": {
          "characterMaskConfig": {
            "numberToMask": -8,
            "reverseOrder": true,
          }
        }
      },
      {
        "infoTypes": &#91;
          {
            "name": "PHONE_NUMBER"
          }
        ],
        "primitiveTransformation": {
          "characterMaskConfig": {
            "numberToMask": -1,
            "reverseOrder": false,
            "charactersToIgnore": &#91;
              {
                "charactersToSkip": ".-"
              }
            ]
          }
        }
      },
      {
        "infoTypes": &#91;
          {
            "name": "EMAIL_ADDRESS"
          }
        ],
        "primitiveTransformation": {
          "characterMaskConfig": {
            "numberToMask": -3,
            "reverseOrder": false,
            "charactersToIgnore": &#91;
              {
                "charactersToSkip": ".@"
              }
            ]
          }
        }
      } ]
    }
  },
  "item": {
    "value": "&lt;doc xmlns=\"urn:932F4698-0A64-49D4-963F-E6615BC399E8\"&gt;  &lt;Name&gt;Marcia&lt;/Name&gt;  &lt;URL&gt;https://marcia.com&lt;/URL&gt;  &lt;Email&gt;marcia@example.com&lt;/Email&gt;&lt;Phone&gt;412-343-0919&lt;/Phone&gt;&lt;/doc&gt;"
  }
}</code></pre>



<p>Notes:</p>



<ul>
<li>As described <a href="https://cloud.google.com/docs/authentication/troubleshoot-adc#user-creds-client-based">here</a>, You need to specify the header <code>x-goog-user-project: :project</code> (obviously replacing the word :project with your own project name), otherwise you will get the dreaded 403 error message like this: <pre class="wp-block-code"><code>{
   "error": {
     "code": 403,
     "message": "Your application is authenticating by using local Application Default Credentials. The dlp.googleapis.com API requires a quota project, which is not set by default. To learn how to set your quota project, see https://cloud.google.com/docs/authentication/adc-troubleshooting/user-creds .",
     "status": "PERMISSION_DENIED",
     "details": [
       {
         "@type": "type.googleapis.com/google.rpc.ErrorInfo",
         "reason": "SERVICE_DISABLED",
         "domain": "googleapis.com",
         "metadata": {
           "service": "dlp.googleapis.com",
           "consumer": "projects/325555555"
         }
       }
     ]
   }
 }</code></pre> </li>



<li>You can specify the de-identify config as a template.  example follows: <pre class="wp-block-code"><code>POST :dlp/v2/projects/:project/content:deidentify
content-type: application/json
x-goog-user-project: :project
Authorization: Bearer :token

{
  "inspectConfig": {
    "infoTypes": [ { "name": "EMAIL_ADDRESS" }, { "name": "PHONE_NUMBER" }, { "name": "URL" } ]
  },
  "deidentifyTemplateName": "projects/my-project-name-12345/deidentifyTemplates/3816550063387353440",
  "item": {
    "value": "&lt;doc xmlns=\"urn:932F4698-0A64-49D4-963F-E6615BC399E8\"&gt;  &lt;Name&gt;Marcia&lt;/Name&gt;  &lt;URL&gt;https://marcia.com&lt;/URL&gt;  &lt;Email&gt;marcia@example.com&lt;/Email&gt;&lt;Phone&gt;412-343-0919&lt;/Phone&gt;&lt;/doc&gt;"
  }
}
</code></pre></li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dinochiesa.net/?feed=rss2&#038;p=1724</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Compute an HTTP Signature for Mastodon (and an example in NodeJS)</title>
		<link>https://www.dinochiesa.net/?p=1717</link>
					<comments>https://www.dinochiesa.net/?p=1717#respond</comments>
		
		<dc:creator><![CDATA[dpc]]></dc:creator>
		<pubDate>Fri, 07 Apr 2023 23:03:41 +0000</pubDate>
				<category><![CDATA[Developer]]></category>
		<category><![CDATA[HttpSig]]></category>
		<category><![CDATA[NodeJS]]></category>
		<guid isPermaLink="false">https://www.dinochiesa.net/?p=1717</guid>

					<description><![CDATA[I am reading this documentation from Mastodon. And from it, I understand that Mastodon requires an HTTP Signature, signing at least these headers: (request-target) host date digest If your client is written in JavaScript and runs on Nodejs, an example for how to build a signature is given on the npmjs site. But I believe [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>I am reading this <a href="https://docs.joinmastodon.org/spec/security/">documentation from Mastodon</a>.<br><br>And from it, I understand that Mastodon requires an HTTP Signature, signing at least these headers:<br>   (request-target) host date digest<br><br>If your client is written in JavaScript and runs on Nodejs, <a href="https://www.npmjs.com/package/activitypub-http-signatures?activeTab=readme">an example for how to build a signature is given on the npmjs site</a>. <br><br>But I believe this example is out of date. It does not use the (request-target) pseudo header. So that&#8217;s not gonna work.<br><br>So what must you do?  Go back to the Mastodon documentation.  Unfortunately, that too, is either out of date or confusing. For a post request, the mastodon documentation states that you must first compute the &#8220;RSA-SHA256 digest hash of your request’s body&#8221;.  This is not correct.  There is no such thing as &#8220;RSA-SHA256 digest&#8221;!  RSA-SHA256 is not the name of a digest.  Message Digests include: SHA1, SHA256, MD5 (old and insecure at this point) and others.  According to my reading of <a href="https://github.com/mastodon/mastodon/blob/main/app/controllers/concerns/signature_verification.rb#L157">the code</a>, Mastodon supports only SHA-256 digests.  The documentation should state that you must compute the &#8220;SHA256 digest&#8221;.  (There is no RSA key involved in computing a digest). </p>



<p>Regardless of the digest algorithm you use, the computed digest is a byte array. That brings us to the next question: how to encode that byte array as a string, in order to pass it to Mastodon.  Some typical options for encoding are: hex encoding (aka base16 encoding), base64 encoding, or base64-url encoding.  The documentation does not state which of those encodings is accepted.  Helpfully, the example provided in the documentation shows a digest string that appears to be hex-encoded.  Unhelpfully, again according to my reading of the code, Mastodon requires a base64-encoded digest!</p>



<p>With these gaps and misleading things in the documentation, I think it would be impossible for a neophyte to navigate the documentation and successfully implement a client that passes a validatable signature.</p>



<ol>
<li>produce the POST body</li>



<li>compute the SHA-256 digest of the POST body, including all whitepsace and leading or trailing newlines. <a href="https://dinochiesa.github.io/hmachash/index.html">Try this online tool</a> to help you verify your work. </li>



<li>Encode that computed digest (which is a byte array) with base64. This should produce a string of about 44 characters.</li>



<li>Set the Digest header to be SHA-256=xxxyyyyy , where xxxyyyy is the base64 encoding of the SHA-256 digest.</li>



<li>Set the http headers for the pending outbound request to include at least host, date, and digest.</li>



<li>compute the signature following the example from the npmjs.com site, with headers of &#8220;(request-target) host date digest&#8221;, and using the appropriate RSA key pair.</li>
</ol>



<p>If it were me, I would also include a :created: and an :expires: field in the http signature. </p>



<p>You can play around with HTTP Signatures using <a href="https://dinochiesa.github.io/httpsig/">this online tool</a>. That tool does not yet support computing a Digest of a POST body, but I&#8217;ll look into extending it to do that too. </p>



<p>Let me know in the comments if any of this is not clear.</p>



<p>I posted <a href="https://gist.github.com/DinoChiesa/36ff5491a3d9ceda55665bead3819918">a working example for Nodejs as a gist on Github</a>.</p>



<p>It depends only on nodejs and the builtin libraries for crypto and URL to compute the hash/digest and signature. It does not actually send a request to Mastodon; that is left for you to do.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dinochiesa.net/?feed=rss2&#038;p=1717</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Yarp vs Envoy proxy &#8211; build time comparison</title>
		<link>https://www.dinochiesa.net/?p=1714</link>
					<comments>https://www.dinochiesa.net/?p=1714#respond</comments>
		
		<dc:creator><![CDATA[dpc]]></dc:creator>
		<pubDate>Sat, 25 Mar 2023 00:38:52 +0000</pubDate>
				<category><![CDATA[Developer]]></category>
		<category><![CDATA[Envoy]]></category>
		<category><![CDATA[YARP]]></category>
		<guid isPermaLink="false">https://www.dinochiesa.net/?p=1714</guid>

					<description><![CDATA[Just for fun I cloned the yarp repo and ran a build.  After sorting out a few puzzles on my own, the build completed in about 55 seconds.  That's a pleasant surprise. ]]></description>
										<content:encoded><![CDATA[
<p class="has-gateway-dark-gray-color has-text-color">I&#8217;m doing some self-education these days, and was exploring <a href="https://microsoft.github.io/reverse-proxy/">YARP</a> today.  I learned about this <a href="https://news.ycombinator.com/item?id=29302736">via HackerNews</a> some time ago, and only now got around to taking the time to explore in more detail.  As Microsoft describes it, YARP is &#8220;a library to help create reverse proxy servers that are high-performance, production-ready, and highly customizable.&#8221;  </p>



<p class="has-gateway-dark-gray-color has-text-color">It&#8217;s not a reverse proxy in its own right, but a library that you can embed into an ASPNET app to allow it to act as a reverse proxy.  The &#8220;Yet Another&#8221; moniker is completely appropriate; there are many, many Reverse Proxies out there in various shapes, sizes and configurations. Why Microsoft wanted to build another one when there are good options out there &#8211; Envoy, nginx, haproxy, and many others &#8211; is perhaps a topic worth exploring (Google, my most recent employer, promotes the open-source <a href="https://www.envoyproxy.io/">Envoy proxy</a> as a general-purpose RP, and also sells an API Platform, <a href="https://cloud.google.com/apigee">Apigee</a>, that includes its own reverse proxy).  It seems to me that Microsoft has large cloud investments, and wants to have control over this particular critical piece of widely-used infrastructure.  Rather than compromise with something that&#8217;s already out there, go build something that fits the requirements for their massive cloud footprint, as well as for the shops other than Microsoft who are invested in .NET.  I don&#8217;t think it&#8217;s worthy of too much more discussion than that. </p>



<p class="has-gateway-dark-gray-color has-text-color">With so many available options in reverse proxies, an interested observer might want to have some insight into comparisons between them.  Now there are various criteria a person might want to investigate when comparing &#8211; features like hot-reload of configuration, the configuration model in general, support for &#8220;farms&#8221; of proxies all centrally managed, platform availability, performance&#8230;. Any reader could probably add two or three more items to that list. </p>



<p class="has-gateway-dark-gray-color has-text-color">All of that is interesting, but I don&#8217;t have time to conduct a thorough comparison at this time. But I will offer one quick observation.  While exploring Envoy proxy back in November, I built it from source on my macbook pro. The build was a bear, and took maybe 90 minutes? Something like that. Basically it built every library that the envoy proxy depended on. I suspect most people don&#8217;t do that; they just use the docker container that the envoy project publishes.  </p>



<p class="has-gateway-dark-gray-color has-text-color">Just for fun I cloned <a href="https://github.com/microsoft/reverse-proxy">the yarp repo</a> and ran a build.  After sorting out some puzzles [<a href="https://github.com/microsoft/reverse-proxy/issues/2078">1</a>, <a href="https://github.com/microsoft/reverse-proxy/issues/2077">2</a>] on my own, the build completed in about 55 seconds.  That&#8217;s a pleasant surprise. </p>



<p class="has-gateway-dark-gray-color has-text-color">I know that with Bazel, the envoy build will be much faster on subsequent runs.  But even so, building a YARP proxy is much much faster than building Envoy. </p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dinochiesa.net/?feed=rss2&#038;p=1714</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>APIs, microservices, and the service mesh</title>
		<link>https://www.dinochiesa.net/?p=1703</link>
					<comments>https://www.dinochiesa.net/?p=1703#respond</comments>
		
		<dc:creator><![CDATA[dpc]]></dc:creator>
		<pubDate>Thu, 11 Apr 2019 13:15:44 +0000</pubDate>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[microservices]]></category>
		<category><![CDATA[Service Mesh]]></category>
		<guid isPermaLink="false">https://www.dinochiesa.net/?p=1703</guid>

					<description><![CDATA[Got some time and want to learn about APIs, microservices, the service mesh, and how these pieces interplay in an enterprise? Here&#8217;s a session Greg Kuelgen and I delivered at Google Next 2019. Youtube video Summary: If you&#8217;ve got more than a handful of services intercooperating, you&#8217;re gonna want a service mesh infrastructure. And you [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Got some time and want to learn about APIs, microservices, the service mesh, and how these pieces interplay in an enterprise?</p>
<p>Here&#8217;s a session Greg Kuelgen and I delivered at Google Next 2019.<br />
<a href="https://www.youtube.com/watch?v=IblDMVwSSk4"><img decoding="async" src="https://i3.ytimg.com/vi/IblDMVwSSk4/hqdefault.jpg" alt="Hero image"></a></p>
<p><a href="https://www.youtube.com/watch?v=IblDMVwSSk4">Youtube video</a></p>
<p>Summary: If you&#8217;ve got more than a handful of services intercooperating, you&#8217;re gonna want a service mesh infrastructure. And you will want to use API Management to share APIs outside of the team that developed them.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dinochiesa.net/?feed=rss2&#038;p=1703</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>nodejs on Google App Engine &#8211; forcing HTTPS inbound, via HSTS</title>
		<link>https://www.dinochiesa.net/?p=1675</link>
					<comments>https://www.dinochiesa.net/?p=1675#respond</comments>
		
		<dc:creator><![CDATA[dpc]]></dc:creator>
		<pubDate>Wed, 20 Jun 2018 16:29:59 +0000</pubDate>
				<category><![CDATA[Developer]]></category>
		<category><![CDATA[GAE]]></category>
		<category><![CDATA[GCP]]></category>
		<category><![CDATA[HSTS]]></category>
		<category><![CDATA[NodeJS]]></category>
		<guid isPermaLink="false">https://www.dinochiesa.net/?p=1675</guid>

					<description><![CDATA[How can I force my nodejs app running on Google App Engine, to always redirect to HTTPS ? I have a pretty vanilla app that looks like this: This thing is running in Google App Engine (GAE), and I&#8217;d like to make sure it listens only on HTTPS. There are standards like HSTS that can [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>How can I force my nodejs app running on Google App Engine, to always redirect to HTTPS ? </p>
<p>I have a pretty vanilla app that looks like this: </p>
<p><script src="https://gist.github.com/DinoChiesa/3cae5caef303b41238da4886d3a7e487.js"></script></p>
<p>This thing is running in Google App Engine (GAE), and I&#8217;d like to make sure it listens only on HTTPS. There are standards like <a href="https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security">HSTS</a> that can help. How can I use them? </p>
<p>This <a href='https://stackoverflow.com/q/42777860/48082'>question</a> and <a href='https://stackoverflow.com/a/42790533/48082'>answer</a> on Stackoverflow showed me the way. Basically, just add in a tiny module called <a href='https://github.com/JustinBeckwith/yes-https'>yes-https</a>.  The new code looks like this:<br />
<script src="https://gist.github.com/DinoChiesa/ec37fc48c7ca169601acd3d52c811b85.js"></script></p>
<p>Redeploying (no change to app.yaml) gets me the always-HTTPS behavior I want. When a client requests my service via http, it receives a 301 redirect pointing to the secure site.<br />
<code><br />
HTTP/1.1 301 Moved Permanently<br />
Date: Wed, 20 Jun 2018 16:27:56 GMT<br />
Transfer-Encoding: chunked<br />
X-Powered-By: Express<br />
Location: https://foo-bar.appspot.com/<br />
Via: 1.1 google<br />
</code></p>
<p>Nice, easy, clear.<br />
Thanks to <a href='https://github.com/JustinBeckwith'>Justin</a> for this handy module. </p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dinochiesa.net/?feed=rss2&#038;p=1675</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Jackson and XmlMapper &#8211; reading arbitrary data into a java.util.Map</title>
		<link>https://www.dinochiesa.net/?p=1654</link>
					<comments>https://www.dinochiesa.net/?p=1654#respond</comments>
		
		<dc:creator><![CDATA[dpc]]></dc:creator>
		<pubDate>Thu, 07 Dec 2017 01:13:40 +0000</pubDate>
				<category><![CDATA[Developer]]></category>
		<category><![CDATA[gist]]></category>
		<category><![CDATA[Jackson]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[XML]]></category>
		<guid isPermaLink="false">https://www.dinochiesa.net/?p=1654</guid>

					<description><![CDATA[I like the Jackson library from FasterXML. Really handy for reading JSON, writing JSON. Or I should say &#8220;serialization&#8221; and &#8220;deserialization&#8221;, &#8217;cause that&#8217;s what the cool kids say. And the license is right. (If you need a basic overview of Jackson, I suggest this one from Eugen at Stackify.) But not everything is JSON. Sometimes [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I like <a href='https://github.com/FasterXML/jackson-core'>the Jackson library from FasterXML</a>. Really handy for reading JSON, writing JSON. Or I should say &#8220;serialization&#8221; and &#8220;deserialization&#8221;, &#8217;cause that&#8217;s what the cool kids say. And the license is right. (If you need a basic overview of Jackson, I suggest  <a href='https://stackify.com/java-xml-jackson/'>this one</a> from Eugen at Stackify.)</p>
<p>But not everything is JSON. Sometimes ya just wanna read some XML, amiright? </p>
<p>I work on projects where Jackson is included as a dependency. And I am aware that there is <a href='https://github.com/FasterXML/jackson-dataformat-xml'>a jackson-dataformat-xml module</a> that teaches Jackson how to read and write XML, using the same simple model that it uses for JSON. </p>
<p>Most of the examples I&#8217;ve seen show how to read XML into a POJO &#8211; in other words &#8220;databinding&#8221;.  If my XML doc has an element named &#8220;Fidget&#8221; then upon de-serialization, the value there is used to populate the field or property on the Java object called &#8220;Fidget&#8221; (subject to name remapping of course).</p>
<p>That&#8217;s nice and handy, but like I said, sometimes ya just wanna read some XML. And it&#8217;s not known what the schema is. And you don&#8217;t have a pre-compiled Java class to hold the data. What I really want is to read XML into a java.util.Map&lt;String,Object&gt; .  Very similar to what I would do in JavaScript with JSON.parse(). How can I do that? </p>
<p>It&#8217;s pretty easy, actually.<br />
<script src="https://gist.github.com/DinoChiesa/04a168afe30600c0b6ea7ad41ba7b310.js"></script></p>
<p>This works but there are some problems. </p>
<ol>
<li>The root element is lost. This is an inadvertent side-effect of using a JSON-oriented library to read XML.</li>
<li>For any element that appears multiple times, only the last value is retained.</li>
</ol>
<p>What I mean is this:<br />
Suppose the source XML is: </p>
<pre>
&lt;Root&gt;
  &lt;Parameters&gt;
    &lt;Parameter name='A'&gt;valueA&lt;/Parameter&gt;
    &lt;Parameter name='B'&gt;valueB&lt;/Parameter&gt;
  &lt;/Parameters&gt;
&lt;/Root&gt;
</pre>
<p>Suppose you deserialize that into a map, and then re-serialize it as JSON. The output will be: </p>
<pre>
{
  "Parameters" : {
    "Parameter" : {
      "name" : "B",
      "" : "valueB"
    }
  }
}
</pre>
<p>What we really want is to retain the root element and also infer an array when there are repeated child elements in the source XML. </p>
<p>I wrote a custom deserializer, and a decorator for XmlStreamReader to solve these problems. Using them looks like this: </p>
<pre>
String xmlInput = "&lt;Root&gt;&lt;Messages&gt;&lt;Message&gt;Hello&lt;/Message&gt;&lt;Message&gt;World&lt;/Message&gt;&lt;/Messages&gt;&lt;/Root&gt;";
InputStream is = new ByteArrayInputStream(xmlInput.getBytes(StandardCharsets.UTF_8));
RootSniffingXMLStreamReader sr = new RootSniffingXMLStreamReader(XMLInputFactory.newFactory().createXMLStreamReader(is));
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.registerModule(new SimpleModule().addDeserializer(Object.class, new ArrayInferringUntypedObjectDeserializer()));
Map map = (Map) xmlMapper.readValue(sr, Object.class);
Assert.assertEquals( sr.getLocalNameForRootElement(), "Root");
Object messages = map.get("Messages");
Assert.assertTrue( messages instanceof Map, "map");
Object list = ((Map)messages).get("Message");
Assert.assertTrue( list instanceof List, "list");
Assert.assertEquals( ((List)list).get(0), "Hello");
Assert.assertEquals( ((List)list).get(1), "World");
</pre>
<p>And the output looks like this: </p>
<pre>
{
  "Parameters" : {
    "Parameter" : [
      {
        "name" : "A",
        "" : "valueA"
      },{
        "name" : "B",
        "" : "valueB"
      }
    ]
  }
}
</pre>
<p>&#8230;which is what we wanted.</p>
<p>Find the source code here: <a href='https://github.com/DinoChiesa/deserialize-xml-arrays-jackson'>https://github.com/DinoChiesa/deserialize-xml-arrays-jackson</a> </p>
<p>Hat tip to <a href='https://jegansblog.wordpress.com/2015/05/05/jackson-for-xml-json-conversion/'>Jegan for the custom deserializer</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dinochiesa.net/?feed=rss2&#038;p=1654</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>medialize/URI.js &#8211; why&#8217;d you go and get all fancy?</title>
		<link>https://www.dinochiesa.net/?p=1650</link>
					<comments>https://www.dinochiesa.net/?p=1650#respond</comments>
		
		<dc:creator><![CDATA[dpc]]></dc:creator>
		<pubDate>Thu, 09 Nov 2017 01:07:12 +0000</pubDate>
				<category><![CDATA[Developer]]></category>
		<category><![CDATA[gist]]></category>
		<category><![CDATA[NodeJS]]></category>
		<category><![CDATA[URI.js]]></category>
		<guid isPermaLink="false">https://www.dinochiesa.net/?p=1650</guid>

					<description><![CDATA[I have relied on URI.js from medialize for years. I downloaded it a long time ago, and it just works. It&#8217;s handy for parsing and building URIs form within Javascript. I happen to use nodejs often, but I also use a JavaScript engine that runs in the JVM (via Rhino or Nashorn). So I liked [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I have relied on <a href="https://github.com/medialize/URI.js">URI.js from medialize</a> for years. </p>
<p>I downloaded it a long time ago, and it just works. It&#8217;s handy for parsing and building URIs form within Javascript.<br />
I happen to use nodejs often, but I also use a JavaScript engine that runs in the JVM (via Rhino or Nashorn). So I liked URI.js for its usability across those systems. </p>
<p>Recently I decided to download &#8220;the latest and greatest&#8221; URI.js, and what I found&#8230; did not make me jump for joy. </p>
<p>URI.js is no longer &#8220;just downloadable&#8221;.</p>
<p>Where before I could just download the raw JS file, URI.js now <a href="https://medialize.github.io/URI.js/build.html">has a builder</a> that allows me to select which options I wish to include. I get the concept, and it&#8217;s a nice idea, but when I de-selected every option, I got a minimized URI.js that I did not want.  When I went to the source tree I found a URI.js that included all the require() statements for punycode, Second-Level Domains, and ipv6, all stuff I did not want. </p>
<p>*snif*</p>
<p>I couldn&#8217;t figure out how to get it to &#8220;just work&#8221; in nodejs without all of that, so I had to resort to manually changing the code.  Basically I just removed all the require() statements for those unneeded / unwanted modules.</p>
<p>And it works.</p>
<p><script src="https://gist.github.com/DinoChiesa/97653d8617b8a30db602cd5d4c0018ba.js"></script></p>
<p>It&#8217;s possible I&#8217;m missing something basic, but for sure, it got more complicated to get the simple solution. Seems like a step backward.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dinochiesa.net/?feed=rss2&#038;p=1650</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Do you use curl?  Stop using -u.  Please use .netrc</title>
		<link>https://www.dinochiesa.net/?p=1641</link>
					<comments>https://www.dinochiesa.net/?p=1641#respond</comments>
		
		<dc:creator><![CDATA[dpc]]></dc:creator>
		<pubDate>Tue, 21 Mar 2017 21:09:42 +0000</pubDate>
				<category><![CDATA[Quickies]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[Security]]></category>
		<guid isPermaLink="false">https://www.dinochiesa.net/?p=1641</guid>

					<description><![CDATA[An unsolicited tech tip. Those of you who are API people, should exhibit good API hygiene. One aspect of that is: &#8220;stop using curl -u&#8221; !! Sometimes you have the urge to run a command like this: curl -X POST -v -u 'yourusername:password' . https://foobar/slksls Avoid this. OK, ok, I know sometimes it&#8217;s necessary. But [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>An unsolicited tech tip.</p>
<p>Those of you who are API people, should exhibit good API hygiene. </p>
<p>One aspect of that is: <strong>&#8220;stop using curl -u&#8221; !!</strong></p>
<p>Sometimes you have the urge to run a command like this:<br />
<code>curl -X POST -v -u 'yourusername:password' . https://foobar/slksls</code></p>
<p>Avoid this. </p>
<p>OK, ok, I know <em>sometimes</em> it&#8217;s necessary.  But if you have an API endpoint that you often tickle with curl, and it accepts credentials via HTTP basic auth, you should be using .netrc to store the credentials. </p>
<p>The problem with using -u is that the password is shown in clear text on your terminal!</p>
<p>OK, I know, you&#8217;re thinking: <em>but I&#8217;m the only one looking at my screen.</em> . I can <em>hear you</em> thinking that right now. And that may be true, most of the time.  But sometimes it&#8217;s not. </p>
<p>Sometimes you cut/paste terminal sessions into an email, or a blog post, or a bug report.  And that&#8217;s when your password gets written down and shared with the world. </p>
<p>Treat Basic Authorization headers the same as passwords, because any observer can easily extract your password from that.</p>
<p>You might think that it&#8217;s ok to insert credentials in an email if it&#8217;s just being shared among your close work colleages. But that&#8217;s a bad idea also.  Audit trails depend on the privacy of credentials. If you share them, the audit is gone. Suppose you have a disgruntled (ungruntled?  never gruntled?) colleague who decides to take your creds and use them to recursively <code>curl -X DELETE</code> a whole bunch of resources.  And the audit trail will show YOUR name on that act.  </p>
<p>In short, it&#8217;s bad form. It could be forwarded or copy/pastad or it could leak into habit. It sets a terrible example for the children. </p>
<p>Here&#8217;s what I suggest: </p>
<h3>Option 1: if you use curl</h3>
<p>If you have a *nixy machine, create a ~/.netrc file and insert your creds there. See <a href="https://ec.haxx.se/usingcurl-netrc.html">here</a> for information.  </p>
<p>chmod the file to 400. When you use the -n option, curl knows how to extract your creds from the file silently. You never have to type credentials on the command line again. I think you can do this on Windows too, but I don&#8217;t know curl on Windows.</p>
<p>If you build scripts that use curl, you should allow the user that same option.  That way the user never keys in their creds to your script. </p>
<p>When you pass the -n option to curl, instead of -u USER:PASS, it tells curl, &#8220;if you ever connect with site.example.com, then use THESE creds&#8221; . This works with any HTTP endpoint curl can address via Basic Auth. I have creds for Jira, Heroku, and other systems all in my .netrc. </p>
<p>Hint: also don&#8217;t use <code>curl -v</code>, because that will show the basic auth header.  You probably want -i anyway, which is less verbose than -v.  </p>
<h3>Option 2: don&#8217;t use curl</h3>
<p>Use some other tool that hides the credentials completely.<br />
I think Postman doesn&#8217;t quite hide the creds completely.  So be careful!  </p>
<p>Let&#8217;s all try to exemplify good security behavior. </p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dinochiesa.net/?feed=rss2&#038;p=1641</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>


<br />
<b>Fatal error</b>:  Uncaught TypeError: fclose(): Argument #1 ($stream) must be of type resource, bool given in /home/public/wp-content/plugins/post-notification/sendmail.php:241
Stack trace:
#0 /home/public/wp-content/plugins/post-notification/sendmail.php(241): fclose(false)
#1 /home/public/wp-content/plugins/post-notification/post_notification.php(218): post_notification_send()
#2 /home/public/wp-includes/class-wp-hook.php(308): post_notification_send_check('')
#3 /home/public/wp-includes/class-wp-hook.php(332): WP_Hook-&gt;apply_filters(NULL, Array)
#4 /home/public/wp-includes/plugin.php(517): WP_Hook-&gt;do_action(Array)
#5 /home/public/wp-includes/load.php(1144): do_action('shutdown')
#6 [internal function]: shutdown_action_hook()
#7 {main}
  thrown in <b>/home/public/wp-content/plugins/post-notification/sendmail.php</b> on line <b>241</b><br />
