<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Ramblings of a Unix Geek</title>
    <link>https://www.sweharris.org/</link>
    <description>Recent content on Ramblings of a Unix Geek</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <copyright>&lt;a href=http://creativecommons.org/licenses/by-nc-nd/4.0/&gt;&lt;img alt=&#39;Creative Commons License&#39; style=&#39;border-width:0&#39; src=&#39;https://www.sweharris.org/images/cc-by-nc-nd-88x31.png&#39; /&gt;&lt;/a&gt;</copyright>
    <lastBuildDate>Sun, 07 Jun 2026 11:37:57 -0400</lastBuildDate>
    
        <atom:link href="https://www.sweharris.org/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Post Quantum Cryptography Apache TLS settings</title>
      <link>https://www.sweharris.org/post/2026-06-07-pqc-compliant/</link>
      <pubDate>Sun, 07 Jun 2026 11:37:57 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2026-06-07-pqc-compliant/</guid>
      <description>

&lt;p&gt;In December I documented &lt;a href=&#34;https://www.sweharris.org/post/2025-12-02-ssl-redux/&#34;&gt;TLS settings for Debian 13&lt;/a&gt;.
These settings gave us TLS1.3, the ability to use ECDSA, backwards compatibility
with some older software, and an A+ rating in &lt;a href=&#34;https://www.ssllabs.com/ssltest&#34;&gt;SSL Labs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Last week I re-ran the tests and noticed an additional flag had been added; &amp;ldquo;This server supports PQC (Post-Quantum Cryptography) key exchange.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;So I thought I&amp;rsquo;d summarize all the previous posts into a single one and
describe my setup.  There&amp;rsquo;s not really any new information here, but it
means you don&amp;rsquo;t have to go back through 4 or 5 other posts to get the same
stuff!&lt;/p&gt;

&lt;h2 id=&#34;my-setup&#34;&gt;My Setup&lt;/h2&gt;

&lt;p&gt;For various complicated reasons I don&amp;rsquo;t use &lt;code&gt;certbot&lt;/code&gt; to get my certificates
from &lt;a href=&#34;https://www.letsencrypt.org&#34;&gt;LetsEncrypt&lt;/a&gt;.  Instead I use a shell
script called &lt;a href=&#34;https://github.com/dehydrated-io/dehydrated&#34;&gt;Dehydrated&lt;/a&gt;.
This can do &lt;code&gt;http-01&lt;/code&gt; or &lt;code&gt;dns-01&lt;/code&gt; challenges (in my case I use dns) and
retrieve the certificates to a local file.  From there I use &lt;code&gt;ansible&lt;/code&gt; to
deploy them (web servers, SMTP, IMAP, NNTP, MQTT,&amp;hellip;  lots of places across
multiple machines!)&lt;/p&gt;

&lt;h2 id=&#34;getting-rsa-and-ecdsa-certs-from-letsencrypt&#34;&gt;Getting RSA &lt;em&gt;and&lt;/em&gt; ECDSA certs from LetsEncrypt&lt;/h2&gt;

&lt;p&gt;I want to use both RSA and ECDSA certificates on this site but Dehydrated
can only handle one type at a time.  Fortunately it has a work around;
you can create a second certificate directory and have that override
the cert type.&lt;/p&gt;

&lt;p&gt;So in my case I configured the app to default to &lt;code&gt;rsa&lt;/code&gt; and then created
an override.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;   % cat domains.txt
   *.sweharris.org sweharris.org &amp;gt; sweharris
   *.sweharris.org sweharris.org &amp;gt; sweharris_ecdsa

   % grep KEY_ALGO config
   KEY_ALGO=rsa

   % cat certs/sweharris_ecdsa/config
   KEY_ALGO=&amp;quot;secp384r1&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yes, I use a wildcard cert; it&amp;rsquo;s easier than managing a SAN entry of a
dozen entries and then have to regenerate a new cert each time I add a
new machine!&lt;/p&gt;

&lt;p&gt;With this setup when I run the &amp;ldquo;refresh&amp;rdquo; command (&lt;code&gt;dehydrated -c&lt;/code&gt;) it
will place the RSA cert in the &lt;code&gt;sweharris&lt;/code&gt; directory and ECDSA cert in
the &lt;code&gt;sweharris_ecdsa&lt;/code&gt; directory:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;   % openssl x509 -noout -text -in certs/sweharris/cert.pem | grep Public.Key.Algo
               Public Key Algorithm: rsaEncryption

   % openssl x509 -noout -text -in certs/sweharris_ecdsa/cert.pem | grep Public.Key.Algo
               Public Key Algorithm: id-ecPublicKey
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Inside the &lt;code&gt;certs&lt;/code&gt; directory we will find four files of interest.  These
are always symbolic links to the latest version, so that provides a
consistent name for us to use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cert.pem&lt;br&gt;
This is the public key for the server certificate&lt;/li&gt;
&lt;li&gt;privkey.pem&lt;br&gt;
This is the private key for the server.&lt;/li&gt;
&lt;li&gt;chain.pem&lt;br&gt;
This file contains the &amp;ldquo;chaining&amp;rdquo; certificates needed to generate a chain
of trust to the root.&lt;/li&gt;
&lt;li&gt;fullchain.pem&lt;br&gt;
This file contains the chaining certificates &lt;em&gt;and&lt;/em&gt; the server public key.
Sometimes this can be easier to use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will use the &lt;code&gt;fullchain&lt;/code&gt; and &lt;code&gt;privkey&lt;/code&gt; files with Apache.&lt;/p&gt;

&lt;h2 id=&#34;configuring-apache&#34;&gt;Configuring apache&lt;/h2&gt;

&lt;p&gt;Debian 13 comes with Apache/2.4.67 and OpenSSL 3.5.6.  This supports TLS1.3.&lt;/p&gt;

&lt;p&gt;I enabled the &lt;code&gt;default-ssl&lt;/code&gt; site but commented out the
&lt;code&gt;SSLCertificateFile&lt;/code&gt; and &lt;code&gt;SSLCertificateKeyFile&lt;/code&gt; lines.  This is probably
not necessary but it works :-)&lt;/p&gt;

&lt;h3 id=&#34;tls-settings&#34;&gt;TLS settings&lt;/h3&gt;

&lt;p&gt;I put the TLS settings in a &lt;code&gt;conf-enabled&lt;/code&gt; file, at the top level, not
restricted to a virtual host.  In this way every vhost gets the same
certificates and same ciphers.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;SSLCertificateFile /etc/apache2/SSL/sweharris/fullchain.pem
SSLCertificateKeyFile /etc/apache2/SSL/sweharris/privkey.pem

SSLCertificateFile /etc/apache2/SSL/sweharris_ecdsa/fullchain.pem
SSLCertificateKeyFile /etc/apache2/SSL/sweharris_ecdsa/privkey.pem

SSLCipherSuite TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;why-those-ciphers&#34;&gt;Why those ciphers?&lt;/h3&gt;

&lt;p&gt;I go into more details in my previous posts (&lt;a href=&#34;https://www.sweharris.org/post/2025-12-02-ssl-redux/&#34;&gt;here&lt;/a&gt; and &lt;a href=&#34;https://www.sweharris.org/post/2020-09-23-update-ssl/&#34;&gt;here&lt;/a&gt;) but to summarize:&lt;/p&gt;

&lt;p&gt;These four are the only &amp;ldquo;fully&amp;rdquo; safe ones to use with TLS1.2 with RSA:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;  TLS_AES_128_GCM_SHA256
  TLS_AES_256_GCM_SHA384
  TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And a couple to enable ECDSA:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;  TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Unfortunately this will stop a few machines from connecting, so we add
a couple of theoretically weak CBC ciphers:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;  TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then we get a couple of nice new ones:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;  TLS_CHACHA20_POLY1305_SHA256
  TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;virtual-host-settings&#34;&gt;Virtual host settings&lt;/h3&gt;

&lt;p&gt;The virtual host setting is pretty generic; it&amp;rsquo;s pretty much the same
as you&amp;rsquo;d set up for any virtual host.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;VirtualHost _default_:443&amp;gt;
  SSLEngine On
  ServerName mytesthost.sweharris.org
  ServerAlias mytesthost.sweharris.org

  DocumentRoot /var/www/ssl-docs
  &amp;lt;Location /&amp;gt;
    Options +Indexes
  &amp;lt;/Location&amp;gt;

  &amp;lt;Directory &amp;quot;/var/www/ssl-docs&amp;quot;&amp;gt;
    Options Indexes
    Require all granted
  &amp;lt;/Directory&amp;gt;

  ErrorLog ${APACHE_LOG_DIR}/ssl_error_log
  CustomLog ${APACHE_LOG_DIR}/ssl_access_log combined
  LogLevel warn
  CustomLog ${APACHE_LOG_DIR}/ssl_request_log \
          &amp;quot;%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \&amp;quot;%r\&amp;quot; %b&amp;quot;

&amp;lt;/VirtualHost&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can define multiple virtual hosts the same way.  If you want the
vhosts to have different TLS settings then move the relevant lines
inside the &lt;code&gt;VirtualHost&lt;/code&gt; setting.  This may require replication of
configuration, but you get more flexibility that way.&lt;/p&gt;

&lt;h3 id=&#34;other-settings&#34;&gt;Other settings&lt;/h3&gt;

&lt;p&gt;Since we&amp;rsquo;re building a good configuration we can also (in the &lt;code&gt;conf-enabled&lt;/code&gt;
file) add a few more useful settings:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ServerSignature off
ServerTokens Prod

Header set Strict-Transport-Security &amp;quot;max-age=31536000; includeSubDomains&amp;quot;
Header set X-Content-Type-Options &amp;quot;nosniff&amp;quot;
Header set X-XSS-Protection &amp;quot;1; mode=block&amp;quot;
Header set X-Frame-Options &amp;quot;SAMEORIGIN&amp;quot;
Header set Referrer-Policy &amp;quot;no-referrer&amp;quot;
Header set Permissions-Policy: interest-cohort=()
Header set Content-Security-Policy: &amp;quot;script-src &#39;self&#39;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Some of these may definitely be VirtualHost specific in a larger environment,
especially the Content-Security-Policy header!&lt;/p&gt;

&lt;h2 id=&#34;results&#34;&gt;Results.&lt;/h2&gt;

&lt;h3 id=&#34;an-a-rating&#34;&gt;An A+ rating&lt;/h3&gt;

&lt;p&gt;The first result is we get an A+ rating and supports PQC:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/tls-results-2026.png&#34; alt=&#34;TLS results&#34;&gt;
&lt;/div&gt;


&lt;h3 id=&#34;the-ciphers&#34;&gt;The Ciphers&lt;/h3&gt;

&lt;p&gt;The ciphers all support forward secrecy:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/tls-ciphers-2026.png&#34; alt=&#34;TLS ciphers&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Notice the TLS1.3 ciphers have &lt;code&gt;X25519MLKEM768&lt;/code&gt; against them; these are
our post-quantum ciphers and are the hybrid of X25519 and ML-KEM-768
(aka Kyber-768).  Now this is new; 6 months previously this configuration
only showed &amp;ldquo;ECDH x25519&amp;rdquo; as the cipher, so either openssl has improved
and I got those improvements as a Debian patch, or SSL Labs has improved
their detection (or both; could always be both!).&lt;/p&gt;

&lt;h3 id=&#34;weak-cbc&#34;&gt;Weak CBC&lt;/h3&gt;

&lt;p&gt;We can see the two CBC ciphers have been marked as &amp;ldquo;Weak&amp;rdquo;.  Now this is
debatable.  CBC isn’t necessarily weak, but it’s historically had
a lot of bad implementations, leading to variations of POODLE attacks
(amongst others).  It’s was kinda expected that there will be yet another
variation of POODLE on CBC, so SSLlabs flag these ciphers as weak,
as an encouragement to move people off and onto stronger ciphers.&lt;/p&gt;

&lt;p&gt;Without those two ciphers the following clients can&amp;rsquo;t negotiate nor talk
to the server, and it&amp;rsquo;s been years since the last known attack on these
ciphers, so I&amp;rsquo;m not concerned, and it doesn&amp;rsquo;t reduce the score and lets
you support older clients (how many Java 8 apps are still out there?
probably too many!)&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    IE 11 / Win 7
    IE 11 / Win 8.1
    IE 11 / Win Phone 8.1
    IE 11 / Win Phone 8.1 Update
    Java 8u161 
    Safari 6 / iOS 6.0.1 
    Safari 7 / iOS 7.1
    Safari 7 / OS X 10.9
    Safari 8 / iOS 8.4
    Safari 8 / OS X 10.10
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;security-headers&#34;&gt;Security Headers&lt;/h3&gt;

&lt;p&gt;And, finally, the security headers score:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/security-headers-2026.png&#34; alt=&#34;security headers&#34;&gt;
&lt;/div&gt;


&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;In theory I&amp;rsquo;m not really concerned about post-quantum.
Definitely not for this site (I use TLS mostly for &lt;a href=&#34;https://www.sweharris.org/post/2016-05-31-secure-webserver/&#34;&gt;data
integrity&lt;/a&gt;) but also in the wider
cryptographic sense; IMHO practical useful quantum compute is still 20
years away, and has been for the past 20 years.  I don&amp;rsquo;t see 2048 bit
RSA from being broken in my lifetime.&lt;/p&gt;

&lt;p&gt;BUT, and this is a big &amp;ldquo;but&amp;rdquo;, your &lt;em&gt;customers&lt;/em&gt; might.  So we need to
understand how to do this properly.&lt;/p&gt;

&lt;p&gt;Fortunately we kind of get this &amp;ldquo;for free&amp;rdquo; with a well configured server.
I didn&amp;rsquo;t need to make any changes to my configuration in order to get this
result.&lt;/p&gt;

&lt;p&gt;The challenges, now, are client-side.  According to the SSL Labs
simulation the only clients currently supporting PQC are Chrome 131+,
Firefox 135+, Edge 131+, and Opera 117+.  It looks like we need the new
&lt;a href=&#34;https://openjdk.org/jeps/527&#34;&gt;Java 27&lt;/a&gt;, which is not yet on general
release, to have support this cipher!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What Linux distribution should I use?</title>
      <link>https://www.sweharris.org/post/2026-04-22-what-distribution/</link>
      <pubDate>Wed, 22 Apr 2026 14:20:58 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2026-04-22-what-distribution/</guid>
      <description>

&lt;p&gt;I got asked a question&amp;hellip; this gives me a chance to write an opinion.  I have
lots of them!&lt;/p&gt;

&lt;h2 id=&#34;what-linux-distribution-should-i-use&#34;&gt;What Linux distribution should I use?&lt;/h2&gt;

&lt;p&gt;Oh boy, this is a biggie and could almost be a religious one!&lt;/p&gt;

&lt;p&gt;In the past we had the Unix wars and then the Linux distro wars.  But with
Microsoft making Windows worse and people trying out (and liking!) Linux
is becoming a viable desktop operating system.  Heck, even gamers have
started to use Linux, with the March 2026
&lt;a href=&#34;https://www.phoronix.com/news/Steam-On-Linux-Tops-5p&#34;&gt;steam survey&lt;/a&gt;
showing that 5% of steam users are using Linux.  5% sounds low, but this
is just for gaming; even I (a Linux user for 30+ years) have a Windows
machine to play games.&lt;/p&gt;

&lt;p&gt;So if this is going to be the year of Linux on the desktop then what&amp;rsquo;s the
right choice?&lt;/p&gt;

&lt;p&gt;And it depends.&lt;/p&gt;

&lt;h2 id=&#34;are-you-learning-linux-because-you-want-it-for-job&#34;&gt;Are you learning Linux because you want it for job?&lt;/h2&gt;

&lt;p&gt;If you&amp;rsquo;re in North America then RedHat Linux is probably the number one
OS you&amp;rsquo;ll find in the commercial space.  Definitely in finance, which is
where I&amp;rsquo;ve been.  So if your goal is to learn skills that will help you
find a job (or get promoted) then a RedHat or derivative is a good starting
point.  It&amp;rsquo;s not the best desktop, but it makes a really good server OS.
You can also run KVM based virtualization and have virtual machines and
networking which will let you experiment; want to try something out? Build
a VM, play in it, destroy it when you&amp;rsquo;re finished.&lt;/p&gt;

&lt;p&gt;The three main options, here, are Rocky Linux, Alma Linux or even a free
RedHat developer trial.  The RedHat solution is something you have to renew
every year but it gives you real licenses for real RedHat and gives you access
to their knowledge base.&lt;/p&gt;

&lt;p&gt;These are Long Term Support (LTS) operating systems; if you install a 10.x
release today it will still be supported until &lt;a href=&#34;https://wiki.rockylinux.org/rocky/version/&#34;&gt;end May 2035&lt;/a&gt;.  Upgrades between major versions has historically
been a bit of pain, but once every 10 years?  Not &lt;em&gt;too&lt;/em&gt; bad!&lt;/p&gt;

&lt;p&gt;The one big downside to RedHat is that they&amp;rsquo;ve become a little more
hostile to the free derivatives in recent years; they can&amp;rsquo;t &lt;em&gt;stop&lt;/em&gt; them
from existing but they can make it harder.  It&amp;rsquo;s for this reason that
I have been migrating my own servers away from Rocky and onto Debian.&lt;/p&gt;

&lt;h2 id=&#34;for-home-lab&#34;&gt;For home lab&lt;/h2&gt;

&lt;p&gt;If you don&amp;rsquo;t need to learn the RedHat way then you might want to look at
Debian Linux instead.  This is what I&amp;rsquo;m mostly using, these days.&lt;/p&gt;

&lt;p&gt;Debian has many of the same advantages of RedHat except it&amp;rsquo;s not what
large corporate entities tend to be using.  It&amp;rsquo;s also a really good server
OS, and can do the same KVM virtualization as RedHat.  You could have both
worlds, potentially; have a primary Debian OS and run some RedHat VMs to
learn the corporate tools.&lt;/p&gt;

&lt;p&gt;Debian&amp;rsquo;s &lt;a href=&#34;https://www.debian.org/releases/&#34;&gt;lifecycle&lt;/a&gt; is a new release
every 2 years, with each release supported for 3 years, and LTS support
up to 5 years.  That seems short compared to RedHat, but Debian has a smoother
upgrade path between major versions; I have a machine that was originally
installed with Debian 11, then upgraded to 12, and is now running 13.  It
was mostly smooth with only minor issues.&lt;/p&gt;

&lt;p&gt;There are forks and derivatives of Debian, most notably Ubuntu, but I don&amp;rsquo;t
see any reason to run these for a home server setup.  There are some
corporates using Ubuntu, but it&amp;rsquo;s not something I&amp;rsquo;d recommend.&lt;/p&gt;

&lt;h2 id=&#34;and-containers&#34;&gt;And containers?&lt;/h2&gt;

&lt;p&gt;This kinda almost doesn&amp;rsquo;t matter.  Generally you shouldn&amp;rsquo;t treat the container
base as an OS to be used, but merely as a base layer.&lt;/p&gt;

&lt;p&gt;The idea behind a container is that you layer your software on top of a base image and you &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; admin the OS layer.  If you need to make a change (e.g. there&amp;rsquo;s patches needed) then you rebuild and redeploy.  So you typically don&amp;rsquo;t need to understand the underlying OS beyond knowing &lt;code&gt;dnf&lt;/code&gt; or &lt;code&gt;apt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Commonly you&amp;rsquo;ll find Debian or Alpine being used; historically I also
saw a fair bit of Ubuntu but that seems to have dropped (at least from
what I&amp;rsquo;ve seen).  RedHat tried to get into the game but I&amp;rsquo;ve not seen
anyone use it!&lt;/p&gt;

&lt;h2 id=&#34;for-desktops-or-gaming&#34;&gt;For desktops or gaming?&lt;/h2&gt;

&lt;p&gt;Now we&amp;rsquo;re getting into a large messy area.  I, personally, use Debian
with LXDE as my desktop environment.  This is stable and means all the
tools I use on my server can also be used on my desktop.  However Debian,
being a &lt;em&gt;stable&lt;/em&gt; release, doesn&amp;rsquo;t always have the latest and greatest
libraries and so some software may not work or some new hardware will
have issues (back in 2022 I bought a &amp;ldquo;stick computer&amp;rdquo; which had an Intel
Celeron J4125 CPU in it; Debian just didn&amp;rsquo;t work with the sound chip;
Ubuntu did; might be interesting to see how things work today!)&lt;/p&gt;

&lt;p&gt;Outside of that there&amp;rsquo;s really the two main families; those in the RedHat
side of things and those from the Debian side of things.&lt;/p&gt;

&lt;p&gt;Fedora and its remixes are probably the main RedHat based desktops.
It has a very fast release cycle (roughly every 6 months) which means
you might spend a fair bit of time upgrading.  Fedora &lt;em&gt;can&lt;/em&gt; be upgraded
between major versions and even allows you to skip a version, but you&amp;rsquo;ll
still be forced to upgrade once a year.  The plus side is you&amp;rsquo;ll always
have more recent libraries and newer versions of software compared
to Debian.&lt;/p&gt;

&lt;p&gt;The biggest Debian descendent used to be Ubuntu.  It&amp;rsquo;s still popular.
Note that it sometimes does stuff differently and pushing agendas
(e.g. Wayland instead of X11; heavy use of snap; LXD containers) and it
sometimes feels bloated.  I haven&amp;rsquo;t used this for a few years because
I really didn&amp;rsquo;t like how it felt.  But that&amp;rsquo;s a personal preference.&lt;/p&gt;

&lt;p&gt;In the past I&amp;rsquo;ve also used Linux Mint (Debian Edition), especially on
low under-powered laptops.  As I understand it, Mint is generally built
on Ubuntu but LMDE is built on Debian.  You&amp;rsquo;re meant to get the same
experience on both; I just picked LMDE because it was closer to Debian.&lt;/p&gt;

&lt;p&gt;And then we get into the weeds.  If we look at
&lt;a href=&#34;https://distrowatch.com/dwres.php?resource=popularity&#34;&gt;DistroWatch&lt;/a&gt; then
we&amp;rsquo;ll also find distros that have been optimized for gaming, such as
CachyOS or Pop!OS.  And more.  I really can&amp;rsquo;t talk to this because I don&amp;rsquo;t
really use Linux for gaming.  I can only suggest testing them out and
seeing what you like the most, or what works best on your hardware
(different kernels, different libraries; you may get different performance).&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://repo.steampowered.com/steam/&#34;&gt;Steam for Linux&lt;/a&gt; appears to be mostly
focused on Ubuntu, but a many of these distros have it packaged in their
app store (e.g. &lt;a href=&#34;https://wiki.cachyos.org/configuration/gaming/&#34;&gt;CachyOS&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id=&#34;what-about-arch-or-gentoo&#34;&gt;What about Arch or Gentoo?&lt;/h2&gt;

&lt;p&gt;I consider these distros as doing Linux on &amp;ldquo;hard mode&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;I started with PCs in 1987 and learned how the machine booted all the way
from power on through the BIOS to the hard disk boot loaders (primary,
secondary) and so on.  This meant that when Linux had its own bootloader
(LILO) I understood what it was doing.   Similarly I&amp;rsquo;ve spent more than
enough time doing things like &lt;code&gt;./configure &amp;amp;&amp;amp; make &amp;amp;&amp;amp; make test &amp;amp;&amp;amp; make install&lt;/code&gt;
in the past (and even built my own distro in 1993 for
&lt;a href=&#34;https://www.linuxjournal.com/article/1111&#34;&gt;deployment at sea&lt;/a&gt;).  I don&amp;rsquo;t
need to have my OS installer do this for me.&lt;/p&gt;

&lt;p&gt;So, yes, it can be instructive to use these distros.  You can get a lot
closer to the guts of the OS and it may be worth testing them out in a
VM to see what you can learn.  But I wouldn&amp;rsquo;t use them daily.&lt;/p&gt;

&lt;p&gt;On the plus side, the &lt;a href=&#34;https://wiki.archlinux.org/title/Main_page&#34;&gt;Arch wiki&lt;/a&gt;
has some of the best documentation around!&lt;/p&gt;

&lt;h2 id=&#34;what-about-other-unix-systems&#34;&gt;What about other Unix systems?&lt;/h2&gt;

&lt;p&gt;Mostly, these days, this means a BSD variant.  Yes Solaris 11 is still out
there&amp;hellip;&lt;/p&gt;

&lt;p&gt;But if you&amp;rsquo;re asking me a question about what distro to use then you&amp;rsquo;re
probably not the right audience for these alternatives.  They&amp;rsquo;re &lt;em&gt;good&lt;/em&gt;
operating systems and have some real use cases that they&amp;rsquo;re possibly
the best for.  But for a general purpose server or desktop with the most
support and compatibility?  I&amp;rsquo;d stick with a Linux distro.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Yeah, this is a messy area.  And it&amp;rsquo;s got messier.  Everyone has their own
opinion and can argue it with religious fervor.  Every distro has pros
and cons, and there&amp;rsquo;s no one size fits all.&lt;/p&gt;

&lt;p&gt;For a conservative desktop or server, I&amp;rsquo;d recommend Debian.  For learning
marketable skills then Rocky Linux.  For more cutting edge desktops or
gaming&amp;hellip; I dunno.&lt;/p&gt;

&lt;p&gt;And then there&amp;rsquo;s SteamOS&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Should I homelab or outsource</title>
      <link>https://www.sweharris.org/post/2026-04-01-should-i-homelab/</link>
      <pubDate>Wed, 01 Apr 2026 12:22:01 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2026-04-01-should-i-homelab/</guid>
      <description>&lt;p&gt;Over on Reddit someone commented that self-hosting solutions (eg email,
calendars, file sync) was too much like hard work.  Needing to update
TLS certificates, keeping code up to date, acting like IT support
(especially if what you&amp;rsquo;re doing is used by friends and family) was
becoming too much like a job.&lt;/p&gt;

&lt;p&gt;And you know what, they could be right.  Other people starting out on
their homelab and self-hosted path need to be aware of this.&lt;/p&gt;

&lt;p&gt;Firstly, it&amp;rsquo;s very important to recognise that this isn&amp;rsquo;t for everyone.
If you don&amp;rsquo;t get a sense of fun or enjoyment out of doing something then
why do it?  &amp;ldquo;Because Google Bad&amp;rdquo; and owning your own data isn&amp;rsquo;t really
enough to make someone do stuff they don&amp;rsquo;t enjoy.&lt;/p&gt;

&lt;p&gt;Now I&amp;rsquo;m about to say something that might sound nasty, but I really don&amp;rsquo;t
mean it that way.  The problem could be a skills issue.  The good news
is that these skills can be gained, and it&amp;rsquo;s not that hard.  You just
have to persevere.&lt;/p&gt;

&lt;p&gt;Let me explain.&lt;/p&gt;

&lt;p&gt;As the original poster noticed, running a homelab is harder
than just running a gaming PC and off loading everything else to
Google/Microsoft/Apple.  It requires &amp;ldquo;a particular set of skills&amp;rdquo;
(to quote a famous movie).&lt;/p&gt;

&lt;p&gt;I guess I started homelab type stuff in the early 90s.  The tools we
have today didn&amp;rsquo;t exist back then so I would create my own scripts and
automations.  It really helped that I found this fun and interesting;
&amp;ldquo;ooh, I learned something!  This is cool!&amp;rdquo;&lt;/p&gt;

&lt;p&gt;The homelab I have today is far superior (and more complicated) than
what I had then (we didn&amp;rsquo;t even have virtual servers so my spare bedroom
had half a dozen machines, including two Sun SPARCs, all running and
doing stuff!).  Today &amp;ldquo;maintenance&amp;rdquo; of my homelab is maybe 5 minutes
each morning to check for any errors and 10 minutes every 80 days to
renew certs (that &amp;ldquo;complicated&amp;rdquo; bit means I haven&amp;rsquo;t 100% automated TLS
cert renewal; instead I have to run one command and check the output;
I really should fix that).&lt;/p&gt;

&lt;p&gt;But this didn&amp;rsquo;t happen in 1 day; it&amp;rsquo;s taken years to get to this point.
Heck, just last month I reworked by backup reporting system.  I have 17
OS instances running permanently (some physical, some virtual, some cloud
hosted) and they all backup and send me reports.  I was getting annoyed
with checking 17 reports daily.  So I wrote some code and now I get 1
report that basically says &amp;ldquo;17 servers have backup reports (17 good,
0 bad)&amp;rdquo; (or alerts if something isn&amp;rsquo;t good).  It&amp;rsquo;s only saved a couple
of minutes per day, but it&amp;rsquo;s a lot less annoyance :-)&lt;/p&gt;

&lt;p&gt;And this can be part of the problem, when starting out; you&amp;rsquo;re seeing
enthusiasts like me who have been doing this for years and find it easy;
we can do it in our sleep.  You&amp;rsquo;re comparing what you&amp;rsquo;re going through
and learning to something that&amp;rsquo;s been tweaked and optimised over a period
of time.&lt;/p&gt;

&lt;p&gt;And I&amp;rsquo;ll let you into a little secret; I may run my own mail server, web
server, DNS, DHCP, home assistant, firewall&amp;hellip;  I have written automations
to extend Alexa, to report and alert on stuff.  I&amp;rsquo;ve automated server
builds so I can create a new VM (with my preferred customisations) in
a few minutes just with a single command.  And despite all that I still
use Microsoft OneDrive as a way to sync photos from my phone to my PC.
Because it&amp;rsquo;s easier.&lt;/p&gt;

&lt;p&gt;Homelabs are first and foremost a hobby.  If you&amp;rsquo;re not enjoying it and
don&amp;rsquo;t think you ever will enjoy it then don&amp;rsquo;t do it!  But if you think
it&amp;rsquo;ll be fun and you&amp;rsquo;re just frustrated now &amp;lsquo;cos it&amp;rsquo;s hard then maybe
stick with it; you&amp;rsquo;ll learn the skills and it will get easier.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Why I&#39;m not a fan of AI everywhere</title>
      <link>https://www.sweharris.org/post/2026-01-24-no-ai/</link>
      <pubDate>Sat, 24 Jan 2026 21:09:14 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2026-01-24-no-ai/</guid>
      <description>

&lt;p&gt;These days it seems that AI is everywhere.  It&amp;rsquo;s being pushed in your face,
every application has an AI component.  Even your OS is going to be
&lt;a href=&#34;https://www.theregister.com/2025/11/17/windows_agentic_os_feedback/&#34;&gt;agentic&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In many cases I&amp;rsquo;m not a fan.  But I can see some benefits under some
circumstances.&lt;/p&gt;

&lt;p&gt;Because of how many areas AI is getting into, this has become something of
a long post (I&amp;rsquo;ve been putting it off for a while &amp;lsquo;cos I expected this!).
And I&amp;rsquo;ve only covered a fraction of the potential use cases.&lt;/p&gt;

&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;

&lt;p&gt;When I&amp;rsquo;m talking about &amp;ldquo;AI&amp;rdquo; in this post then I&amp;rsquo;m mostly talking about the
modern &amp;ldquo;Large Language Model&amp;rdquo; style of systems.  These are, inherently,
prediction systems.  Based on input and training models and constraints
on the output the system will generate responses that are statistically
likely to be relevant.&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/John_Scalzi&#34;&gt;John Scalzi&lt;/a&gt;, a pretty
successful SciFi author, has written how xAI&amp;rsquo;s grokipedia
&lt;a href=&#34;https://whatever.scalzi.com/2025/10/30/a-review-of-grokipedia-using-myself-as-test-subject/&#34;&gt;makes shit up&lt;/a&gt;
using himself as the subject of a query.  He&amp;rsquo;s done this with other AIs and
got similarly wrong results.&lt;/p&gt;

&lt;p&gt;This, for example, is why AI&amp;rsquo;s have trouble with basic maths
or why they
&lt;a href=&#34;https://www.technologyreview.com/2024/06/18/1093440/what-causes-ai-hallucinate-chatbots/&#34;&gt;&amp;ldquo;hallucinate&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Despite these failures, somehow these AIs can
&lt;a href=&#34;https://law.stanford.edu/2023/04/19/gpt-4-passes-the-bar-exam-what-that-means-for-artificial-intelligence-tools-in-the-legal-industry/&#34;&gt;pass bar association exams&lt;/a&gt;
or do well in maths tests.  Yet they fail to be accurate in the
real world, famously
&lt;a href=&#34;https://www.reuters.com/technology/artificial-intelligence/ai-hallucinations-court-papers-spell-trouble-lawyers-2025-02-18/&#34;&gt;inventing cases&lt;/a&gt;.
I suspect this is because exam questions and answers are more generally
known, and so show up in training data.&lt;/p&gt;

&lt;p&gt;With this background I&amp;rsquo;m going to look at a few use cases and give my opinion
on the suitability (or not) of AI.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not going to discuss whether the current generation of AI is &lt;em&gt;true&lt;/em&gt; AI
(&lt;a href=&#34;https://en.wikipedia.org/wiki/Artificial_general_intelligence&#34;&gt;AGI&lt;/a&gt;), or
whether the current path is going to lead to it.  I&amp;rsquo;m not going to discuss
how marketing has caused a terminology shift.  I&amp;rsquo;m not going to discuss
the potential AI economic bubble, nor the energy and water used.  Nor the
data and intellectual property stolen to create the current models.&lt;/p&gt;

&lt;p&gt;What I&amp;rsquo;m going to talk about is the &lt;em&gt;use&lt;/em&gt; of this AI.&lt;/p&gt;

&lt;h2 id=&#34;agentic-os&#34;&gt;Agentic OS&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ll start here since I mentioned it earlier.  And I really really don&amp;rsquo;t want
this.&lt;/p&gt;

&lt;p&gt;The problem, in my mind, is one of determinism.  We have spent decades
making computers do exactly what we tell them.  We&amp;rsquo;ve invented specialized
languages to try and be as precise as possible in making these statements.&lt;/p&gt;

&lt;p&gt;Natural language is inherently imprecise.  We see this, all the time, in
online conversations.  Emoticons (and later emojis) appeared in online
text communities (eg Usenet) to try and avoid the problems caused by
language ambiguities and through the lack of secondary information
channels (tone of voice, facial expressions, body language); I might
call my friend an arsehole or wanker as a mild humourous jab, but then
use the same words to denigrate a stranger.  An outsider, reading just
the text, can&amp;rsquo;t tell.&lt;/p&gt;

&lt;p&gt;So if two humans can&amp;rsquo;t understand each other perfectly (even worse if
one is English and the other is American), can we expect some AI to
understand my intent?  I really don&amp;rsquo;t want my computer to do unexpected
things because it interpreted my natural language commands differently
to what I intended.&lt;/p&gt;

&lt;p&gt;A common counter to this would be a &amp;ldquo;Human In The Loop&amp;rdquo; (HITL) process,
but this really won&amp;rsquo;t work.  Imagine this scenario&amp;hellip;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Computer, open the last document I was working on&lt;/li&gt;
&lt;li&gt;Do you want to open pornographic_document.jpg?&lt;/li&gt;
&lt;li&gt;Dammit, no!  That&amp;rsquo;s not what I meant!  Go away, I&amp;rsquo;ll do it using keyboard and mouse&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It would get even worse as your PC starts to control more of your life;
for example if you have a smart house you won&amp;rsquo;t want to be prompted
every time you ask it to turn a light on&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Computer, turn on the light&lt;/li&gt;
&lt;li&gt;Do you want me to turn on the light?&lt;/li&gt;
&lt;li&gt;Oh STFU, and just do it without asking me in the future.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As an Alexa user since 2016 I would have smashed the thing with a hammer
if it had kept asking me for verification.&lt;/p&gt;

&lt;p&gt;We will tune the algorithm (some things don&amp;rsquo;t need HITL,  others will) but
there will always be edge cases.&lt;/p&gt;

&lt;p&gt;So, no; I don&amp;rsquo;t want my computer guessing my intent.  I don&amp;rsquo;t want an agentic
OS.  I want my interactions with my OS to be deterministic, not probabilistic.&lt;/p&gt;

&lt;h2 id=&#34;speech-recognition&#34;&gt;Speech recognition&lt;/h2&gt;

&lt;p&gt;But since I mentioned Alexa, something AI should be good at is speech
recognition.  Because it&amp;rsquo;s predictive it should be able to better
recognise speech and perform a more accurate speech-to-text conversion.
Words it doesn&amp;rsquo;t clearly recognise can be statistically determined
based on what it did recognise.  And, similarly, to help detect false positive
activations.&lt;/p&gt;

&lt;p&gt;This can definitely assist in dictation scenarios, or even
when talking to &amp;ldquo;smart devices&amp;rdquo;.  It should also help with
&lt;a href=&#34;https://en.wikipedia.org/wiki/Interactive_voice_response&#34;&gt;IVR&lt;/a&gt; systems.&lt;/p&gt;

&lt;p&gt;I distinguish this from the &amp;ldquo;agentic&amp;rdquo;, above, because we&amp;rsquo;re not trying
to determine the &lt;em&gt;intent&lt;/em&gt; of the speech, just recognise the speech itself.&lt;/p&gt;

&lt;h2 id=&#34;vibe-coding&#34;&gt;Vibe coding&lt;/h2&gt;

&lt;p&gt;Agh, OMG, no.  I hate this.  This is the worst of everything I don&amp;rsquo;t want
about an agentic OS, made 10x worse.&lt;/p&gt;

&lt;p&gt;Programming languages exist as a means of being explicit to the computer about
what we want.  Yes, it&amp;rsquo;s a skill; not just one of &lt;em&gt;learning&lt;/em&gt; the language
but also of one around how to think in a logical manner, of breaking problems
down.  The coding aspect of programming is, really, easy when compared to the
brain power of understanding the problem and decomposing it.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s this latter aspect that vibe coding is replacing, and why I feel it&amp;rsquo;s
ultimately a bad idea.&lt;/p&gt;

&lt;p&gt;With vibe coding you describe the end state and, magically, the AI
produces code for you.  Except it doesn&amp;rsquo;t quite work so you refine the
description and it changes the code.  And you iterate on this dozens of
times and eventually you get something you think does what you intended.
Success, right?  You haven&amp;rsquo;t had to learn a programming language, you haven&amp;rsquo;t
had to break the problem down.  You just used natural language to do stuff.&lt;/p&gt;

&lt;p&gt;Well, it depends.&lt;/p&gt;

&lt;p&gt;If this is for a home personal project and you&amp;rsquo;re not concerned about security
or efficiency or even 100% accuracy then this is fine.  Linus Torvalds
has famously &lt;a href=&#34;https://github.com/torvalds/AudioNoise&#34;&gt;vibe coded&lt;/a&gt; and people
point to this and say &amp;ldquo;Hey, if the inventor of Linux does it then it must be
OK&amp;rdquo;.  But this was for a personal project.&lt;/p&gt;

&lt;p&gt;Linus has also said
&lt;a href=&#34;https://www.zdnet.com/article/linus-torvalds-im-not-a-programmer-anymore/&#34;&gt;&amp;ldquo;I&amp;rsquo;m not a programmer anymore&amp;rdquo;&lt;/a&gt;.
Indeed, if you read that article he &amp;ldquo;vibe codes&amp;rdquo; in real life; writes
an email stating intent (pseudo code).  There&amp;rsquo;s a HITL process; the
person at the other end of the email, and the maintainers who control
the merge process.&lt;/p&gt;

&lt;p&gt;My &lt;a href=&#34;https://www.sweharris.org/post/2025-06-10-chatgpt-oauth/&#34;&gt;small attempt&lt;/a&gt; at vibe coding resulted
in working code&amp;hellip; but not good code.  There were architectural issues, even
in the small program I wanted to write.&lt;/p&gt;

&lt;p&gt;And there&amp;rsquo;s a big difference between &amp;ldquo;personal use&amp;rdquo; and &amp;ldquo;enterprise
use&amp;rdquo;.  Code you write today will be modified tomorrow (for some value of
&amp;ldquo;tomorrow&amp;rdquo;).  Your vibed code in your repo isn&amp;rsquo;t going to have any state.
Someone, or &lt;em&gt;something&lt;/em&gt;, is going to have to understand what was written,
why it does what it does, how it works.  That person might be you (I
joke &amp;ldquo;I try to write good code and document it because the next person
to maintain it could just easily be me&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s a big difference between &amp;ldquo;working code&amp;rdquo; and &amp;ldquo;maintainable code&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve seen some people just say &amp;ldquo;Eh, the AI of tomorrow will be good enough
to understand the code and build the context&amp;rdquo;, but that&amp;rsquo;s just magical
thinking.&lt;/p&gt;

&lt;p&gt;The other thing I&amp;rsquo;ve seen is &amp;ldquo;this is what code reviews are
for&amp;rdquo;; this is the HITL part of the process.  But this is,
essentially, just moving the coding cost from the original coder
to the reviewer.  If a review now takes twice as long because
the supplied code is harder to understand then we&amp;rsquo;re not actually
winning.  The original developer may code faster (although this may be a
&lt;a href=&#34;https://www.theregister.com/2025/07/11/ai_code_tools_slow_down/&#34;&gt;misperception&lt;/a&gt;)
but the whole workflow could be slower.&lt;/p&gt;

&lt;p&gt;In the past we&amp;rsquo;ve complained about &amp;ldquo;Stack Overflow programmers&amp;rdquo; who just
blindly cut&amp;rsquo;n&amp;rsquo;paste code.  I suspect we&amp;rsquo;ll also start seeing the same about
vibe programmers.&lt;/p&gt;

&lt;p&gt;Especially since the AI was trained on Stack Overflow (and has probably
killed it, based on the traffic the site is now getting) and so has all of
the bugs and security issues that will come as a  result.&lt;/p&gt;

&lt;p&gt;So, sure, vibe code for personal projects.  But don&amp;rsquo;t take it anywhere near
the enterprise.  It will cost you in the long term.&lt;/p&gt;

&lt;h2 id=&#34;coding-assistance&#34;&gt;Coding assistance&lt;/h2&gt;

&lt;p&gt;Now here I&amp;rsquo;m distinguishing coding assistance from actual coding itself.
Indeed, almost the &lt;em&gt;opposite&lt;/em&gt;; instead of telling the developer what to do
we tell them what &lt;em&gt;not&lt;/em&gt; to do.&lt;/p&gt;

&lt;p&gt;We could have an agent sitting in the IDE that&amp;rsquo;s predicting &lt;em&gt;mistakes&lt;/em&gt;
and highlighting them.  There are already systems that deal with this, but
I could see an LLM based AI being better at detecting bad coding patterns.&lt;/p&gt;

&lt;p&gt;Today an LLM takes too many resources to be efficient locally (umm,
unless we give every developer a beefy GPU in their laptop?) so this
may be better as part of a SaaS scan, but smaller models may be more
efficient in the future.&lt;/p&gt;

&lt;p&gt;Having a model that can predict errors and warn the developer while they&amp;rsquo;re
coding can cut down the detect/fix cycle time, improve developer efficiency
and reduce overall development time.  The HITL process is immediate.&lt;/p&gt;

&lt;h2 id=&#34;meeting-summaries&#34;&gt;Meeting summaries&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve worked with people who said &amp;ldquo;wow, this is great; it&amp;rsquo;s saved me so much
time&amp;rdquo;.  But whenever I&amp;rsquo;ve tried to use it I&amp;rsquo;ve found it&amp;hellip; lacking.  The
problem, for me, is that it loses nuance and can easily overlook an essential
statement.  When you try to summarise an hour long contentious meeting
getting a summary of &amp;ldquo;we discussed foo; bar was mention; baz was suggested as
a solution&amp;rdquo; is just not good enough (although AI will expand that out to 5
or 6 paragraphs &amp;lsquo;cos it loves to be verbose).  I&amp;rsquo;ve not seen it be &lt;em&gt;wrong&lt;/em&gt;
but I&amp;rsquo;ve seen it miss important stuff.&lt;/p&gt;

&lt;p&gt;Definitely a scenario with HITL is essential.  Don&amp;rsquo;t rely on AI, here.&lt;/p&gt;

&lt;h2 id=&#34;document-website-whatever-generation&#34;&gt;Document/website/whatever generation&lt;/h2&gt;

&lt;p&gt;I hate this.  I mentioned, in the intro, how AI has caused lawyers issues
because the produced document referenced non-existent cases.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve seen marketing websites and &amp;ldquo;apps&amp;rdquo; (whatever was meant by that)
that are AI generated, and came away wondering &amp;ldquo;just WTH did any of that mean&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve seen proposals that are so generic and meaningless that I&amp;rsquo;ve laughed
at them and told the vendor to go away (to be fair, I&amp;rsquo;ve also told vendors
with lazy sales people to do the same thing).&lt;/p&gt;

&lt;p&gt;But the thing that gets me about a lot of AI generated content is the banality
of a lot of it.  Now maybe I&amp;rsquo;m just being exposed to the worst of the worst
(eg on LinkedIn) but there seems to be a lack of &lt;em&gt;tone&lt;/em&gt; to the document.  It&amp;rsquo;s
just bland and lacking anything to keep me reading.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve been told by people I know personally that when they read this blog
they hear my voice in their head; I write this as I would speak it.  AI
generated content seems to lack this.  And that leads to a form of
&lt;a href=&#34;https://en.wikipedia.org/wiki/Uncanny_valley&#34;&gt;uncanny valley&lt;/a&gt;.  I get a gut
aversion to the content.&lt;/p&gt;

&lt;p&gt;Can I tell AI content from human content all the time?  Heck, no.  I probably
get it wrong more often than not.  But that just means other content is just
as bad :-)&lt;/p&gt;

&lt;p&gt;Using an AI to create bad content is not excused because humans also create
bad content.&lt;/p&gt;

&lt;p&gt;(And, hush; no calling this blog &amp;ldquo;bad content&amp;rdquo;!).&lt;/p&gt;

&lt;h2 id=&#34;marketing-emails&#34;&gt;Marketing emails&lt;/h2&gt;

&lt;p&gt;Just &lt;a href=&#34;https://www.urbandictionary.com/define.php?term=foad&#34;&gt;FOAD&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hate marketing spam at the best of times; sending AI generated slop is
a quick way of getting me to hate you and your company and to tell everyone
to avoid you.&lt;/p&gt;

&lt;p&gt;In my career I&amp;rsquo;ve had people cold-email me; I&amp;rsquo;ve had these cold-emails &lt;em&gt;lie&lt;/em&gt;
to me (&amp;ldquo;I&amp;rsquo;ve tried to contact you&amp;hellip;&amp;rdquo;; no you haven&amp;rsquo;t, I&amp;rsquo;d have blocked your
company if you had!).  I really don&amp;rsquo;t want AI spam in my inbox.&lt;/p&gt;

&lt;p&gt;Fortunately I&amp;rsquo;ve retired, but this still triggers me :-)&lt;/p&gt;

&lt;p&gt;As a joke (which I formulated over a decade ago), I&amp;rsquo;ve wondered if spam
is going to be the path to &lt;em&gt;true&lt;/em&gt; AI.  See, the spammers use better
and better systems to generate email that looks like it&amp;rsquo;s from a human.
Which means we need better and better solutions.  And this is what is
ultimately going to lead to a true AI&amp;hellip; who might just destroy the world
because of all the content it learned from!&lt;/p&gt;

&lt;h2 id=&#34;image-generation&#34;&gt;Image generation&lt;/h2&gt;

&lt;p&gt;Y&amp;rsquo;know; I&amp;rsquo;m of two minds on this one.  For an idiot like me I can see the
use of image generation to help get messages across.  You might notice
a distinct lack of pictures on this blog; I&amp;rsquo;m not a visual person and
my attempts at drawing might be considered &amp;ldquo;scribbles&amp;rdquo; on a good day.  So
a &amp;ldquo;vibe coded&amp;rdquo; image might be beneficial?  Maybe?&lt;/p&gt;

&lt;p&gt;This is kinda like vibe coding in general; for personal use I could see
a benefit, but be very aware of using it in an enterprise or commercial
situation.  And doubly so if using it for marketing; you don&amp;rsquo;t want a
potential customer to laugh at you because your images are so obviously
bad.&lt;/p&gt;

&lt;p&gt;And here&amp;rsquo;s another minefield.  I said I wasn&amp;rsquo;t going to get into stuff
like IP theft and the like.  But this is an area that is rife for abuse.
I can&amp;rsquo;t stay silent with things like Grok can create &lt;a href=&#34;https://www.bbc.com/news/articles/cvg1mzlryxeo&#34;&gt;Child Sexual Abuse
Imagery&lt;/a&gt;(CSAM).&lt;/p&gt;

&lt;p&gt;Now it&amp;rsquo;s not just Grok that can do this, but its the one with the worst guard
rails.&lt;/p&gt;

&lt;h2 id=&#34;guard-rails&#34;&gt;Guard rails&lt;/h2&gt;

&lt;p&gt;And this kinda takes me all the way back to the beginning; when we&amp;rsquo;re
parsing the intent of human language how can we &lt;em&gt;prevent&lt;/em&gt; abuse.  Humans
are already bad at this.  Con men are adept at bypassing guard rails.
Business Email Compromise is based on the precept that people can be
convinced to bypass guard rails.&lt;/p&gt;

&lt;p&gt;We call it &amp;ldquo;prompt injection&amp;rdquo; but it&amp;rsquo;s really the same thing; we convince
the AI to do things it&amp;rsquo;s not meant to do.  Whether it is creating porn
images of celebrities, or CSAM, or revenge porn, or&amp;hellip;&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;re already seeing use of this in &lt;a href=&#34;https://www.malwarebytes.com/blog/news/2025/07/car-crash-victim-calls-mother-for-help-and-15k-bail-money-but-its-an-ai-voice-scammer&#34;&gt;scam calls&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the future we&amp;rsquo;re going to see a LOT of fake images during election season.
Previously Trump used them to generate fake images promoting himself; eg
hanging out with people of colour.  In the future we&amp;rsquo;re going to see fake
videos of political opponents doing/saying things they never did.&lt;/p&gt;

&lt;p&gt;How can we build the necessary guard rails, especially since this stuff
is open source and can be run locally?  Fact checkers won&amp;rsquo;t help because
we already have people believing &amp;ldquo;alternate facts&amp;rdquo;.  Consensus reality
appears to be a thing of the past, and everyone lives in their own private
reality.&lt;/p&gt;

&lt;p&gt;(This is depressing.  Sorry!  And it&amp;rsquo;s not really an AI problem, but it&amp;rsquo;s
something AI will make worse).&lt;/p&gt;

&lt;p&gt;I think we&amp;rsquo;ve entered a future where you can&amp;rsquo;t believe anything you don&amp;rsquo;t
see or here, in person, with your own eyes and ears.  And, as noted, even
that&amp;rsquo;s not infallible!&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;m not, in general, a fan of AI.  I don&amp;rsquo;t want it on my machine, I don&amp;rsquo;t
want it writing my code.  I definitely don&amp;rsquo;t want it writing code for
my employer (if I still had one).  I&amp;rsquo;ve modified my web browser configs
so that my search excludes AI results, because they&amp;rsquo;re frequently wrong.&lt;/p&gt;

&lt;p&gt;But I can see areas where, &lt;em&gt;as a consumer of services&lt;/em&gt; it can make my
life better (eg IVR systems).&lt;/p&gt;

&lt;p&gt;Wherever this form of AI is used, it&amp;rsquo;s essential that HITL is present.
And you need to evaluate the &lt;em&gt;cost&lt;/em&gt; of that; it might turn out that you&amp;rsquo;ve
shifted cost from stage 1 over to stage 3 of a process (in programming
terms you&amp;rsquo;ve shifted right!) and potentially increased overall costs as
a result.&lt;/p&gt;

&lt;p&gt;I suspect this whole post will be controversial simply because of the areas
I&amp;rsquo;m covering.  Everyone has their own opinions.  But that&amp;rsquo;s what this blog
is here for; for me to opine on things!&lt;/p&gt;

&lt;p&gt;If you have an AI area you want to hear me ramble on about, let me know :-)&lt;/p&gt;

&lt;p&gt;And this post was written without the help of any AI; indeed I wrote it using
&lt;code&gt;vi&lt;/code&gt; in an &lt;code&gt;ssh&lt;/code&gt; window.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>TLS Settings in 2025</title>
      <link>https://www.sweharris.org/post/2025-12-02-ssl-redux/</link>
      <pubDate>Tue, 02 Dec 2025 13:10:49 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2025-12-02-ssl-redux/</guid>
      <description>

&lt;p&gt;Back in &lt;a href=&#34;https://www.sweharris.org/post/2016-10-16-ssl-score&#34;&gt;2016&lt;/a&gt; and then in &lt;a href=&#34;https://www.sweharris.org/post/2020-09-23-update-ssl&#34;&gt;2020&lt;/a&gt; I described how to get an A+ score with your TLS config.&lt;/p&gt;

&lt;p&gt;That was 5 years ago.  Since then OpenSSL and Apache have both
advanced and there&amp;rsquo;s even more options than before.  Nicely OpenSSL
can now also use the official TLS names for ciphers, so we don&amp;rsquo;t
need to keep switching between entries reported by &lt;a href=&#34;https://www.ssllabs.com/ssltest&#34;&gt;Qualys SSL
Labs&lt;/a&gt; and the OpenSSL internal names.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m also migrating to Debian, which has some differences.&lt;/p&gt;

&lt;p&gt;Since we&amp;rsquo;re at it, we can also set security headers and make sure we have
a proper CAA DNS entry set.&lt;/p&gt;

&lt;h2 id=&#34;support-rsa-and-ecdsa-certificates&#34;&gt;Support RSA and ECDSA certificates&lt;/h2&gt;

&lt;p&gt;In &lt;a href=&#34;https://www.sweharris.org/post/2021-05-08-ecdsa-certs&#34;&gt;2021&lt;/a&gt; I described how to configure
apache to support modern certificates based on elliptical curves, as
well as traditional RSA certificates.  That blog entry also describes how
I use &lt;a href=&#34;https://github.com/dehydrated-io/dehydrated&#34;&gt;Dehydrated&lt;/a&gt; to get
these certs from &lt;a href=&#34;https://letsencrypt.org/&#34;&gt;LetsEncrypt&lt;/a&gt;.  With newer
versions of Apache (eg RedHat 8 onwards, or Debian) we can specify this
pretty easily; e.g.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;	SSLCertificateFile /etc/apache2/SSL/sweharris/fullchain.pem
	SSLCertificateKeyFile /etc/apache2/SSL/sweharris/privkey.pem

	SSLCertificateFile /etc/apache2/SSL/sweharris_ecdsa/fullchain.pem
	SSLCertificateKeyFile /etc/apache2/SSL/sweharris_ecdsa/privkey.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;debian-ciphers-out-of-the-box&#34;&gt;Debian Ciphers Out Of The Box&lt;/h2&gt;

&lt;p&gt;The default configuration for Debian is &lt;code&gt;SSLCipherSuite HIGH:!aNULL&lt;/code&gt;.  You
might think that&amp;rsquo;s good.  Unfortunately it&amp;rsquo;s not.   Reading the &lt;code&gt;openssl-ciphers(1)&lt;/code&gt; manual page we see&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;HIGH - &amp;ldquo;High&amp;rdquo; encryption cipher suites. This currently means those
with key lengths larger than 128 bits, and some cipher  suites  with
128-bit keys.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;This setting results in a B grade by SSL Labs because a number of those
ciphers do not include &amp;ldquo;forward secrecy&amp;rdquo;.  Forward secrecy (FS) is very much
a nice thing to have; it means that if your private key ever leaks then
it can not be used to decrypt &lt;em&gt;old&lt;/em&gt; saved traffic logs (which is what
&amp;ldquo;harvest now, decrypt later&amp;rdquo; type attacks try to do; save your data now,
decrypt it in the future).  After all, key management is one of the hardest
parts of encryption!&lt;/p&gt;

&lt;p&gt;So what OpenSSL means by &amp;ldquo;HIGH&amp;rdquo; is simply the bit strength.&lt;/p&gt;

&lt;p&gt;Debian also defaults to a complicated protocol list; &lt;code&gt;SSLProtocol all
-SSLv2 -SSLv3 -TLSv1 -TLSv1.1&lt;/code&gt;.  The practical result of this is versions
1.2 and 1.3 are supported.  I&amp;rsquo;m guessing it&amp;rsquo;s written this way so that if
a mythical 1.4 was ever supported then this line wouldn&amp;rsquo;t need changing.&lt;/p&gt;

&lt;h2 id=&#34;remove-all-the-non-fs-ciphers&#34;&gt;Remove all the non-FS ciphers&lt;/h2&gt;

&lt;p&gt;Fortunately the SSL Labs results page can be used to get a list of all the
ciphers that were supported by the default configuration and it flags those
that provide FS.  A bit of cut&amp;rsquo;n&amp;rsquo;paste and editing resulted in this list:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;	TLS_AES_128_GCM_SHA256
	TLS_AES_256_GCM_SHA384
	TLS_CHACHA20_POLY1305_SHA256
	TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
	TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
	TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
	TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256
	TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256
	TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256
	TLS_DHE_RSA_WITH_AES_128_CCM
	TLS_ECDHE_ECDSA_WITH_AES_128_CCM
	TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
	TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
	TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
	TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384
	TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384
	TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384
	TLS_DHE_RSA_WITH_AES_256_CCM
	TLS_ECDHE_ECDSA_WITH_AES_256_CCM
	TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
	TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
	TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Unfortunately it doesn&amp;rsquo;t seem as if OpenSSL has a short-cut for these
&amp;ldquo;FS&amp;rdquo; ciphers, so we have to list each one separately on the &lt;code&gt;SSLCipherSuite&lt;/code&gt;
line.&lt;/p&gt;

&lt;h2 id=&#34;we-need-cbc-as-well&#34;&gt;We need CBC as well&lt;/h2&gt;

&lt;p&gt;As in 2020, this still results in some older software being unable to
negotiate a cipher, even though they support TLS1.2.  SSL Labs still
flags CBC ciphers as weak, but it doesn&amp;rsquo;t reduce the score.  So let&amp;rsquo;s
add these two in:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;	TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
	TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;is-this-too-much&#34;&gt;Is this too much?&lt;/h2&gt;

&lt;p&gt;What I noticed in the results was that although we offer every cipher,
all the simulations provided by the SSL Labs tester ended up only using
a subset of them!  So we could provide a small list of ciphers&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;	TLS_AES_128_GCM_SHA256
	TLS_AES_256_GCM_SHA384
	TLS_CHACHA20_POLY1305_SHA256
	TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
	TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
	TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
	TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
	TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
	TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
	TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is shorter and so may (especially on TLS1.2) result in smaller packets.
The downside is that an odd client may need one of the other ones.&lt;/p&gt;

&lt;p&gt;But with this configuration, we get the following results:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;	SSLCipherSuite TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
&lt;/code&gt;&lt;/pre&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/tls-ciphers-2025.png&#34; alt=&#34;TLS ciphers&#34;&gt;
&lt;/div&gt;


&lt;h2 id=&#34;hsts-and-other-headers&#34;&gt;HSTS and other headers&lt;/h2&gt;

&lt;p&gt;To round this off we need to specify strict transport security headers.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;	Header set Strict-Transport-Security &amp;quot;max-age=31536000; includeSubDomains&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;While we are here we can also add some other good and useful
&lt;a href=&#34;https://securityheaders.com/&#34;&gt;security headers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I consider these to be a good default, but you might have different needs.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;	ServerSignature off
	ServerTokens Prod

	Header set X-Content-Type-Options &amp;quot;nosniff&amp;quot;
	Header set X-XSS-Protection &amp;quot;1; mode=block&amp;quot;
	Header set X-Frame-Options &amp;quot;SAMEORIGIN&amp;quot;
	Header set Referrer-Policy &amp;quot;no-referrer&amp;quot;
	Header set Permissions-Policy: interest-cohort=()
	Header set Content-Security-Policy: script-src &#39;self&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Content-Security-Policy entry is very likely to need to be customised
for your site; e.g. if you include fonts from Google you&amp;rsquo;d need to include
those here.  Check out Scott Helme&amp;rsquo;s &lt;a href=&#34;https://scotthelme.co.uk/content-security-policy-an-introduction/&#34;&gt;description&lt;/a&gt; for an introduction to CSP.&lt;/p&gt;

&lt;p&gt;And a Security Headers scan nicely returns an &amp;ldquo;A&amp;rdquo; score with that setup.&lt;/p&gt;

&lt;h2 id=&#34;restricting-what-cas-can-be-used&#34;&gt;Restricting what CAs can be used&lt;/h2&gt;

&lt;p&gt;A well behaved Certificate Authority will check to see if the requested
domain has a Certificate Authority Authorization (CAA) policy defined and,
if one is found, will only issue certificates if permitted.  This is set
in DNS.  Since I use LetsEncrypt I have a simple policy:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;	@       IN      CAA     0       issue   &amp;quot;letsencrypt.org&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;http-2-support&#34;&gt;HTTP/2 support&lt;/h2&gt;

&lt;p&gt;This isn&amp;rsquo;t really needed but it might be useful to set up.  It can
speed up traffic and reduce overhead with TLS1.2.  With Debian it&amp;rsquo;s as
simple as doing a &lt;code&gt;a2enmod http2&lt;/code&gt;.  On RedHat systems you may need to
&lt;code&gt;dnf install mod_http2&lt;/code&gt; first.&lt;/p&gt;

&lt;h2 id=&#34;the-result&#34;&gt;The result&lt;/h2&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/tls-results-2025.png&#34; alt=&#34;TLS results&#34;&gt;
&lt;/div&gt;


&lt;p&gt;And all the clients that support TLS1.2 or TLS1.3 and are simulated by
SSL Labs connect cleanly.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A personal growth moment</title>
      <link>https://www.sweharris.org/post/2025-10-26-its-dns/</link>
      <pubDate>Sun, 26 Oct 2025 20:39:25 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2025-10-26-its-dns/</guid>
      <description>

&lt;p&gt;The recent AWS outage led to a slew of &lt;a href=&#34;https://www.cyberciti.biz/humour/a-haiku-about-dns/&#34;&gt;It was DNS&lt;/a&gt; jokes.&lt;/p&gt;

&lt;p&gt;It reminded me of a time maybe 12 or 13 years back.  I was part of the
architecture/engineering team for the company&amp;rsquo;s Unix authentication
product.  Basically every login, su, privilege escalation call went
through our code.&lt;/p&gt;

&lt;p&gt;So when things went wrong we got the blame.&lt;/p&gt;

&lt;p&gt;One day a call got escalated to me.  It went something like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Caller (C): It&amp;rsquo;s taking a long time to login&lt;/li&gt;
&lt;li&gt;Me (M): How long?&lt;/li&gt;
&lt;li&gt;C: About 10 seconds&lt;/li&gt;
&lt;li&gt;M: (thinking &amp;ldquo;hmm, that sounds like a DNS timeout&amp;rdquo;).  Does it happen
if you login again?&lt;/li&gt;
&lt;li&gt;C: No, just on first login&lt;/li&gt;
&lt;li&gt;M: It&amp;rsquo;s DNS&lt;/li&gt;
&lt;li&gt;C: It can&amp;rsquo;t be, otherwise we&amp;rsquo;d have got an alert&lt;/li&gt;
&lt;li&gt;M: OK, so what happens is that the SSH daemon is trying to do a reverse
DNS lookup on the IP address connecting to it.  If DNS isn&amp;rsquo;t working
properly then this can take some time.  But the &lt;code&gt;nscd&lt;/code&gt; process caches
this for a while, which is why the second login is fast.&lt;/li&gt;
&lt;li&gt;C: What can we do about it?&lt;/li&gt;
&lt;li&gt;M: Well, we can change the &lt;code&gt;sshd_config&lt;/code&gt; file to disable those lookups but it might not always work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then we went through the process of checking their DNS configs were
correct, being able to demonstrate an issue using &lt;code&gt;nslookup&lt;/code&gt;, and then
configuring SSH to disabling the lookup.  The caller went away happy;
their logins worked fast again.  I told my team of a potential DNS issue.&lt;/p&gt;

&lt;p&gt;2 hours later a global email announcement of DNS issues was made.&lt;/p&gt;

&lt;p&gt;Yeah, it was DNS.&lt;/p&gt;

&lt;h2 id=&#34;how-i-ve-grown&#34;&gt;How I&amp;rsquo;ve grown&lt;/h2&gt;

&lt;p&gt;But going through this again in my mind, I realised where I didn&amp;rsquo;t go
far enough.&lt;/p&gt;

&lt;p&gt;Yes, I solved the caller&amp;rsquo;s problem.  People were happy that my team
was responsive.  The business kept running.  I did my job :-)&lt;/p&gt;

&lt;p&gt;But what I didn&amp;rsquo;t do was to take this to the next step.  Was it worth
disabling this configuration globally?  It would be any easy change
to make and to deploy a new &lt;code&gt;rpm&lt;/code&gt; which we could push out and it would
deploy as part of the patching process.&lt;/p&gt;

&lt;p&gt;What I &lt;em&gt;should&lt;/em&gt; have done was to discuss this with the Linux and Unix
engineering teams to come up with a consensus of whether to leave the
default values as-is, or to disable this lookup.  I think it would have
made an interesting discussion, especially considering the potential
impact.  It likely would have had the Linux/Unix teams trying to evaluate
the likelihood of that impact (perhaps collecting the config files from
the 60,000+ endpoints).&lt;/p&gt;

&lt;p&gt;Clearly somewhere in the past decade I learned to look further than just
&amp;ldquo;incident response&amp;rdquo; and into a &amp;ldquo;what could be done to prevent this from
happening again&amp;rdquo; mindset.&lt;/p&gt;

&lt;p&gt;Because it&amp;rsquo;s always DNS.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Don&#39;t ask &#39;manpage&#39; questions in interviews</title>
      <link>https://www.sweharris.org/post/2025-10-23-options-to-ls/</link>
      <pubDate>Thu, 23 Oct 2025 12:06:39 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2025-10-23-options-to-ls/</guid>
      <description>

&lt;p&gt;One of the things you might see a lot on sites like LinkedIn is the
recommendation to not ask interview questions for stuff that is easy
and trivial to look up.  For example, asking about command line options
to a program.  To an extent I agree with this.  I always need to look up
the &amp;ldquo;key field&amp;rdquo; options to the &lt;code&gt;sort&lt;/code&gt; command (especially since they changed
from when I learned the command!).&lt;/p&gt;

&lt;p&gt;Indeed, when I interviewed for a job in 1999 one of the questions was
&amp;ldquo;How would you count the number of times each shell was used in a NIS
password map?&amp;ldquo;.  Off the top of my head I said&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ypcat passwd | cut -d: -f7 | sort | uniq -c | sort -nr
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, what I really said was &amp;ldquo;ypcat password filtered through cut minus
d 7 (umm, I think it&amp;rsquo;s field 7; I&amp;rsquo;d need to check the manpage) filtered
through sort filtered through uniq minus c (shrugged shoulders) filtered
through sort minus nr (to get them ordered by use)&amp;ldquo;.&lt;/p&gt;

&lt;p&gt;And that&amp;rsquo;s the thing; I knew the commands and how to put them together; but
a trivial detail like the right field of the password file is easy to look
up (&lt;code&gt;man 7 passwd&lt;/code&gt;) that it&amp;rsquo;s not really important.&lt;/p&gt;

&lt;h2 id=&#34;when-a-joke-taught-me-something&#34;&gt;When a joke taught me something&lt;/h2&gt;

&lt;p&gt;Back in the long distant past I remember a joke going around Usenet that
the &lt;code&gt;ls&lt;/code&gt; command had so many options to it that it was harder to find a
letter that &lt;em&gt;wasn&amp;rsquo;t&lt;/em&gt; an option.  So I added a joke question to the list of
questions I asked people interviewing for a senior security engineer role.
This was for someone who was going to build code that would run on 60,000+
different machines across multiple different operating systems (primarily
RedHat, Solaris).  I&amp;rsquo;d already dug deep into their knowledge of &lt;code&gt;PAM&lt;/code&gt;
and &lt;code&gt;NSS&lt;/code&gt; and &lt;code&gt;SSH&lt;/code&gt;, so I thought to lighten things with an easy joke question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This question is a bit of a joke; there&amp;rsquo;s so many options to the &lt;code&gt;ls&lt;/code&gt;
command, can you list 10 of them and what they mean?  I don&amp;rsquo;t expect you to
get 10 and don&amp;rsquo;t worry if you can&amp;rsquo;t; it&amp;rsquo;s just a joke question.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now this breaks the &amp;ldquo;don&amp;rsquo;t ask manpage questions&amp;rdquo; guidance.&lt;/p&gt;

&lt;p&gt;I thought it would be easy.   After all I use 4 options (&lt;code&gt;-lart&lt;/code&gt;)
daily; easy to remember for anyone who had spent time in the
&lt;a href=&#34;http://www.catb.org/jargon/html/S/scary-devil-monastery.html&#34;&gt;Scary Devil Monastery&lt;/a&gt;
(SDM) on Usenet.  And since the early &amp;lsquo;90s I had &lt;code&gt;alias
ls=&#39;/bin/ls -F&#39;&lt;/code&gt; in my profile.  So coming up with 5 more would be easy.&lt;/p&gt;

&lt;p&gt;I just went about it logically.&lt;/p&gt;

&lt;p&gt;We start with&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-l&lt;/code&gt; - long listing&lt;/li&gt;
&lt;li&gt;which leads to &lt;code&gt;-g&lt;/code&gt; for group information (bonus points for mentioning the
historical difference between BSD and SysV implementations of &lt;code&gt;-g&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;also leads to &lt;code&gt;-L&lt;/code&gt; for following symlinks&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-a&lt;/code&gt; - all files&lt;/li&gt;
&lt;li&gt;which leads to &lt;code&gt;-A&lt;/code&gt; for all files except &lt;code&gt;.&lt;/code&gt; and &lt;code&gt;..&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-r&lt;/code&gt; - reverse sort&lt;/li&gt;
&lt;li&gt;Which leads to &lt;code&gt;-R&lt;/code&gt; for recursive lists&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-t&lt;/code&gt; - to sort by modified time&lt;/li&gt;
&lt;li&gt;which leads to &lt;code&gt;-c&lt;/code&gt; for metadata change time&lt;/li&gt;
&lt;li&gt;and to &lt;code&gt;-u&lt;/code&gt; for access time&lt;/li&gt;
&lt;li&gt;and the &lt;code&gt;-c&lt;/code&gt; takes us to &lt;code&gt;-C&lt;/code&gt; for forcing column based output (e.g. in pipelines)&lt;/li&gt;
&lt;li&gt;which takes us to &lt;code&gt;-1&lt;/code&gt; for single column output&lt;/li&gt;
&lt;li&gt;Inhabitants of SDM might also have heard of &lt;code&gt;LARTd&lt;/code&gt; (the &lt;a href=&#34;https://en.wiktionary.org/wiki/LART&#34;&gt;LART&lt;/a&gt; daemon) so we have &lt;code&gt;-d&lt;/code&gt; to show the directory and not the contents of the directory&lt;/li&gt;
&lt;li&gt;And I use &lt;code&gt;-F&lt;/code&gt; to add a filetype marker (e.g. &lt;code&gt;*&lt;/code&gt; for executable, &lt;code&gt;@&lt;/code&gt; for symlink) to the output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, yeah, I could get 14 without really thinking, just by following a chain
through a starting point.  There are other options I&amp;rsquo;ve used in the past,
but that&amp;rsquo;d take some thinking and, yes, checking the manpage to remember
them :-)&lt;/p&gt;

&lt;p&gt;So, sure, I thought 10 would be an achievable goal.&lt;/p&gt;

&lt;h2 id=&#34;what-i-learned&#34;&gt;What I learned&lt;/h2&gt;

&lt;p&gt;Only 1 person was able to get 10.  That surprised me.&lt;/p&gt;

&lt;p&gt;One person mentioned an option I didn&amp;rsquo;t know (from GNU ls).  Another used
GNU long options (which was fair; I hadn&amp;rsquo;t specified traditional options).&lt;/p&gt;

&lt;p&gt;What surprised me most was that some people didn&amp;rsquo;t understand that &lt;code&gt;-al&lt;/code&gt;
wasn&amp;rsquo;t an option, but was two options (&lt;code&gt;-a&lt;/code&gt; and &lt;code&gt;-l&lt;/code&gt; combined).  That&amp;rsquo;s
almost a basic convention of Unix; how can you go for a &lt;em&gt;senior&lt;/em&gt; role without
knowing that basic knowledge?&lt;/p&gt;

&lt;p&gt;And what disappointed me was that no one took a logical approach; they
just tried to remember stuff they&amp;rsquo;d used in the past.  Where I took a
&amp;ldquo;l leads to L; t leads to c leads to C leads to 1&amp;rdquo; approach, they just
struggled.&lt;/p&gt;

&lt;p&gt;When I mentioned some options to people (e.g. &lt;code&gt;-A&lt;/code&gt;) and asked them what
it did they didn&amp;rsquo;t know.  Which, to me, feels like they didn&amp;rsquo;t know the
functionality of the command and what it could do.  This could have led to
inefficient code or poor scripts where they had to work around problems
that didn&amp;rsquo;t have to have existed.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;It turned out that my joke question caused interviewees some stress, even
when I emphasized the joke nature of it.  But I did learn a lot from it!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Hands off Rocky/Debian installs</title>
      <link>https://www.sweharris.org/post/2025-08-13-hands-off-linux-install/</link>
      <pubDate>Wed, 13 Aug 2025 18:35:34 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2025-08-13-hands-off-linux-install/</guid>
      <description>

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;This is a long long post because I&amp;rsquo;m providing a &lt;em&gt;lot&lt;/em&gt; of
configuration files and explanation.  I could have split this into
multiple posts, but I felt it made sense to put it all in one entry&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;In my homelab I use &lt;code&gt;virsh&lt;/code&gt; to manage QEMU/KVM virtual machines.  I might
want to spin up a test VM (oh, say Debian 12) to do some playing around
and then destroy it again.  And, naturally, I don&amp;rsquo;t want to do an interactive
install each time; I just want to run a script and 5 minutes later have a
shiny new VM to play with.   And I don&amp;rsquo;t want a GUI; these are &amp;ldquo;server&amp;rdquo;
builds, and so should have a serial console.&lt;/p&gt;

&lt;p&gt;Fortunately both Rocky Linux (via RedHat kickstart) and Debian Linux (via
preseed) has the ability to perform hands-off installations.&lt;/p&gt;

&lt;h2 id=&#34;pre-requisites&#34;&gt;Pre-requisites.&lt;/h2&gt;

&lt;p&gt;Pretty much all you need is a local webserver that can server out the
kickstart/preseed file, and any other file you want.&lt;/p&gt;

&lt;p&gt;For historical reasons (I started doing this with RedHat, then later CentOS)
the base of my tree is at &lt;code&gt;http://10.0.0.137/CentOS/kickstart&lt;/code&gt;.  I still use this
base for my Debian builds, even though it isn&amp;rsquo;t needed.&lt;/p&gt;

&lt;p&gt;A fast internet connection is useful.  You &lt;em&gt;could&lt;/em&gt;
mirror upstream installer trees (&lt;a href=&#34;https://github.com/sweharris/centos8-local&#34;&gt;I used to do this&lt;/a&gt;),
and then install locally, but now I have gigabit internet access the
speed of the download isn&amp;rsquo;t so much the limiting factor.  As part of
my migration to Debian, I installed &lt;code&gt;apt-cacher-ng&lt;/code&gt; on a machine so
repeated installs won&amp;rsquo;t hit the upstream infrastructure so much (packages
are served locally instead) and this ended up only saving 4 or 5 seconds.
(Enterprise&amp;rsquo;s probably have a local mirror already because you shouldn&amp;rsquo;t
be allowing direct access to external sites!)&lt;/p&gt;

&lt;h2 id=&#34;scripting&#34;&gt;Scripting&lt;/h2&gt;

&lt;p&gt;Now I&amp;rsquo;ve scripted everything I&amp;rsquo;m going to describe below so I don&amp;rsquo;t actually
run any of these commands.  But I&amp;rsquo;m going to explain the low level commands
so you can see what to do and can write your own wrappers.  My scripts aren&amp;rsquo;t
that useful because they are very dependent on other parts of my highly unique
setup (e.g. it looks at the inventory file, if it sees the hostname I want to
build in there then it extracts the MAC address and allocates this to the VM;
in that way the VM will get a consistent value from DHCP &amp;lsquo;cos the DHCP server
config is also built from the same file!)&lt;/p&gt;

&lt;h2 id=&#34;allocating-disk-space&#34;&gt;Allocating disk space&lt;/h2&gt;

&lt;p&gt;KVM can use files on the filesystem or volumes.  For example, to create
a 10G logical volume I could run&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   sudo lvcreate --wipesignatures n -L 10G -n vm.debian13 SSD
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will create &lt;code&gt;/dev/SSD/vm.debian13&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;(I have a naming scheme; all VM logical volumes are called &lt;code&gt;vm.&lt;/code&gt; followed
by the name of the VM.  That way I can do an &lt;code&gt;lvs&lt;/code&gt; and know exactly what
each volume is for).&lt;/p&gt;

&lt;p&gt;Now when running &lt;code&gt;virt-install&lt;/code&gt; to create the VM you would pass this paramter&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   --disk path=/dev/SSD/vm.debian13`
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Alternatively if you want to use a QCOW image on the filesystem would would
specify the path to the image and the size you want; the paramter then becomes
something like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   --disk path=/var/lib/libvirt/images/debian13.img,size=10G
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;networking&#34;&gt;Networking&lt;/h2&gt;

&lt;p&gt;I have 3 &lt;a href=&#34;https://www.sweharris.org/post/2024-07-18-home-router-redux/&#34;&gt;VLANs&lt;/a&gt; that are visible on
the host as &lt;code&gt;br-lan&lt;/code&gt;, &lt;code&gt;br-guest&lt;/code&gt;, and &lt;code&gt;br-iot&lt;/code&gt;. Normally I build my VMs on
the main LAN, but I &lt;em&gt;could&lt;/em&gt; build on any of the VLANs.&lt;/p&gt;

&lt;p&gt;This is specified with the &lt;code&gt;virt-install&lt;/code&gt; network paramter;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   --network=bridge=br-lan,target=v-debian13
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can also specify a MAC address here if we wanted to:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   --network=bridge=br-lan,target=v-debian13,mac=01:02:03:04:05:06
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;target&lt;/code&gt; value will &lt;em&gt;name&lt;/em&gt; the virtual interface so, once again, I can
quickly see what running VMs are on what bridges:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   % brctl show
   bridge name     bridge id               STP enabled     interfaces
   br-guest        8000.b0416f0e52ab       no              enp1s0.11
                                                           v-pinky9-guest
   br-lan          8000.b0416f0e52ab       no              enp1s0.10
                                                           v-debian13
                                                           v-pinky9
                                                           v-test-debian
   br-iot          8000.b0416f0e52ab       no              enp1s0.12
                                                           v-pinky9-iot
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or by looking at the &lt;code&gt;ip a&lt;/code&gt; output we can also see it; eg&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   19: v-debian13: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue master br-lan state UNKNOWN group default qlen 1000
       link/ether fe:54:00:92:38:7f brd ff:ff:ff:ff:ff:ff
       inet6 fe80::fc54:ff:fe92:387f/64 scope link
          valid_lft forever preferred_lft forever
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;other-common-parameters&#34;&gt;Other common parameters&lt;/h2&gt;

&lt;p&gt;To name the VM, &lt;code&gt;-n debian13&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To prevent &lt;code&gt;virt-install&lt;/code&gt; from allocating a graphics console we specify `&lt;code&gt;--nographics&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To allocate RAM, we specify &lt;code&gt;--ram 1024&lt;/code&gt; (although the amount allocated may
vary across the different OS releases; we&amp;rsquo;ll get to that, below).&lt;/p&gt;

&lt;p&gt;To specify the number of virtual CPUs, &lt;code&gt;--vcpus=1&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&#34;installing-different-oses&#34;&gt;Installing different OSes&lt;/h2&gt;

&lt;p&gt;Now we&amp;rsquo;ve got the basics out of the way we can start to look at the differences
between different OS builds.  For ease of reading when it comes to the
network and disk allocations, I&amp;rsquo;ll just &lt;code&gt;...&lt;/code&gt; the value since I&amp;rsquo;ve described
them in detail above.&lt;/p&gt;

&lt;h2 id=&#34;rocky-linux&#34;&gt;Rocky Linux&lt;/h2&gt;

&lt;p&gt;I have configurations for Rocky 8 and Rocky 9.  Most of the parameters
to &lt;code&gt;virt-install&lt;/code&gt; are the same.  The differences are:&lt;/p&gt;

&lt;h3 id=&#34;rocky-8-variables&#34;&gt;Rocky 8 variables&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;   ks=rocky8
   repo=https://dl.rockylinux.org/pub/rocky/8/BaseOS/x86_64/kickstart/ 
   ram=3073 
   os=rocky8
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;rocky-9-variables&#34;&gt;Rocky 9 variables&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;   ks=rocky9 
   repo=https://dl.rockylinux.org/pub/rocky/9/BaseOS/x86_64/kickstart/ 
   ram=4096 
   os=rocky9
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;kicking-off-the-rocky-install&#34;&gt;Kicking off the Rocky install&lt;/h3&gt;

&lt;p&gt;We can then run the install process&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   virt-install \
       --noreboot \
       --vcpus=1 \
       --nographics \
       --machine pc-i440fx-rhel7.6.0 \
       --accelerate \
       -v \
       -n $name \
       --os-variant=$os \
       -r $ram \
       --network=... \
       --disk ... \
       -l $repo \
       -x &amp;quot;inst.ks=http://10.0.0.137/CentOS/kickstart/$ks.cfg
       ksdevice=ens2 ip=dhcp console=ttyS0,9600&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(that last &lt;code&gt;-x&lt;/code&gt; line entry is really on one line; I&amp;rsquo;ve split it here for readability)&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ksdevice&lt;/code&gt; entry has changed over time (eg on CentOS 7 it was &lt;code&gt;eth0&lt;/code&gt;) but
it&amp;rsquo;s been consistent between Rocky 9 and Rocky 9.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;--machine&lt;/code&gt; entry is maybe not needed any more and might be a holdover
from older host OSes (I&amp;rsquo;m now using Rocky 8 and Rocky 9 as the hypervisor
OS).  Similarly the &lt;code&gt;--accelerate&lt;/code&gt; option may no longer be needed!&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-l&lt;/code&gt; flag is where &lt;code&gt;virt-install&lt;/code&gt; will try to download the installer
kernel/ramdisk from.  We&amp;rsquo;re using the files in the &lt;code&gt;kickstart&lt;/code&gt; tree.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-x&lt;/code&gt; flag specifies what is passed to the kernel as parameters.  In this
case we specify where to find the kickstart configuration, as well as the
network device, how to get an IP address and to use a serial console.&lt;/p&gt;

&lt;p&gt;Now in this installer I specify &lt;code&gt;--noreboot&lt;/code&gt; so that after the VM has been
built it&amp;rsquo;s shutdown.  This is so I can do some post-install VM tuning;
specifically reduce the memory configured.  Rocky Linux will run in a &lt;em&gt;lot&lt;/em&gt;
less memory than it needs to install (eg 512), so after the install has
completed I reset the memory requirements and restart the VM&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   virsh setmaxmem $machine 512M --config
   virsh setmem $machine 512M --config
   virsh start $machine
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The real magic starts in the kickstart file!&lt;/p&gt;

&lt;h3 id=&#34;rocky-8-kickstart-config&#34;&gt;Rocky 8 kickstart config&lt;/h3&gt;

&lt;p&gt;We&amp;rsquo;ll break this down into parts&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   install
   url --url https://dl.rockylinux.org/pub/rocky/8/BaseOS/x86_64/os
   poweroff

   lang en_US.UTF-8
   keyboard us

   network --onboot yes --device eth0 --bootproto dhcp --ipv6 auto

   rootpw  --iscrypted $6$...
   authconfig --enableshadow --passalgo=sha512

   firewall --disabled
   selinux --disabled

   timezone --utc America/New_York
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So far this is pretty understandable.  Note the &lt;code&gt;rootpw&lt;/code&gt; entry is
pre-encrypted (you could just that this from an existing &lt;code&gt;/etc/shadow&lt;/code&gt;
entry, for example) so there&amp;rsquo;s no plain text secrets.&lt;/p&gt;

&lt;p&gt;I also disable firewalld and SELinux (yeah yeah, security guy disabling
security&amp;hellip;)&lt;/p&gt;

&lt;p&gt;Now we get to creating the partitions; I create a 500M &lt;code&gt;/boot&lt;/code&gt;, a small
swap partition and set the rest to be an &lt;code&gt;ext4&lt;/code&gt;.  You can define whatever
layout you want here; it&amp;rsquo;s pretty simple!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   zerombr
   clearpart --all --initlabel
   part /boot --fstype=ext4 --asprimary --size=500
   part swap --asprimary --size=512
   part / --fstype=ext4 --asprimary --grow --size=1
   bootloader --location=mbr --driveorder=vda --append=&amp;quot; crashkernel=auto quiet&amp;quot; --timeout=0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next we define what packages we want.  I typically want to install as small
as possible, with some specific extras.  I also remove unnecessary firmware&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   repo --name=AppStream --mirrorlist https://mirrors.rockylinux.org/mirrorlist?repo=AppStream-8&amp;amp;arch=x86_64

   %packages
   @^minimal-environment
   python36
   wget
   ksh
   dos2unix
   logwatch
   tar
   postfix
   bind-utils
   bc
   -kdump
   -iwl100-firmware
   -iwl1000-firmware
   -iwl105-firmware
   -iwl135-firmware
   -iwl2000-firmware
   -iwl2030-firmware
   -iwl3160-firmware
   -iwl3945-firmware
   -iwl4965-firmware
   -iwl5000-firmware
   -iwl5150-firmware
   -iwl6000-firmware
   -iwl6000g2a-firmware
   -iwl6050-firmware
   -iwl7260-firmware
   %end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since I removed &lt;code&gt;kdump&lt;/code&gt;, we can also tell this to be disabled&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   %addon com_redhat_kdump --disable --reserve-mb=&#39;auto&#39;
   %end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then some post-install steps.  I&amp;rsquo;ll get to what the &amp;ldquo;post.tar&amp;rdquo; file
is later in this post because I use a consistent method for Rocky and Debian&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   %post
   exec 1&amp;gt;/root/ks-post.log 2&amp;gt;&amp;amp;1
   tail -f /root/ks-post.log &amp;gt; /dev/console &amp;amp;

   alternatives --set python /usr/bin/python3

   mkdir /tmp/post
   cd /tmp/post
   wget -q http://10.0.0.137/CentOS/kickstart/post_r8.tar
   tar xf post_r8.tar
   sh runme
   cd /tmp
   rm -rf post
   %end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;rsquo;s it!  The complete file is available &lt;a href=&#34;https://www.sweharris.org/kickstart/rocky8.cfg&#34;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&#34;rocky-9-kickstart-config&#34;&gt;Rocky 9 kickstart config&lt;/h3&gt;

&lt;p&gt;This is kinda the same deal, but with some minor differences.  Rather
than detail the whole file again, my config is available &lt;a href=&#34;https://www.sweharris.org/kickstart/rocky9.cfg&#34;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mostly the differences are in &lt;code&gt;url&lt;/code&gt; and &lt;code&gt;repo&lt;/code&gt; entries, as well as allocating
more space to &lt;code&gt;boot&lt;/code&gt; and swap.&lt;/p&gt;

&lt;h2 id=&#34;debian-linux&#34;&gt;Debian Linux&lt;/h2&gt;

&lt;p&gt;The Debian installer works in a different way to Redhat&amp;rsquo;s.  It exposes
things in a more &amp;ldquo;raw&amp;rdquo; level; essentially each part of the installer has
a tag for the questions it asks and you can &amp;ldquo;preseed&amp;rdquo; answers by defining
the tag type and value.  It&amp;rsquo;s also a little inconsistent around when it
reads the file, so some of the values need to be passed to the kernel for
them to be read.&lt;/p&gt;

&lt;p&gt;There are fewer variables that need to be considered for &lt;code&gt;virt-install&lt;/code&gt;;
basically just the OS version and codename&lt;/p&gt;

&lt;h3 id=&#34;debian-12-variables&#34;&gt;Debian 12 variables&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;   version=12
   codename=bookworm
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;debian-13-variables&#34;&gt;Debian 13 variables&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;   version=13
   codename=trixie
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;kicking-off-the-debian-install&#34;&gt;Kicking off the Debian install&lt;/h3&gt;

&lt;p&gt;This looks very similar to the Rocky one, but the &amp;ldquo;-x&amp;rdquo; options are a lot
different&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   virt-install \
     --noreboot \
     --vcpus=1 \
     --nographics \
     --accelerate \
     -v \
     -n $name \
     --os-variant=debian12 \
     --ram 1024 \
     --network=... \
     --disk ... \
     -l http://ftp.us.debian.org/debian/dists/$codename/main/installer-amd64/ \
     -x &amp;quot;console=tty0 console=ttyS0 auto
     url=http://10.0.0.137/CentOS/kickstart/debian$version.cfg
     language=en country=US locale=en_US.UTF-8 keymap=us
     netcfg/get_hostname=debian netcfg/get_domain=spuddy.org&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(that last &lt;code&gt;-x&lt;/code&gt; line entry is really on one line; I&amp;rsquo;ve split it here for readability)&lt;/p&gt;

&lt;p&gt;The &amp;ldquo;preseed&amp;rdquo; file is specified by the &lt;code&gt;auto url=...&lt;/code&gt; option.  But we also
need to specify other stuff (&lt;code&gt;language&lt;/code&gt;, &lt;code&gt;country&lt;/code&gt;, &lt;code&gt;locale&lt;/code&gt;, &lt;code&gt;keymap&lt;/code&gt;)
because the installer tries to use those values before the preseed file is
read.  Oddly enough we &lt;em&gt;also&lt;/em&gt; need to specify the hostname and domain name
here as well, even though we get real values from DHCP.&lt;/p&gt;

&lt;h3 id=&#34;debian-12-preseed-config&#34;&gt;Debian 12 preseed config&lt;/h3&gt;

&lt;p&gt;This is a much more hard-to-build file than the kickstart one.&lt;/p&gt;

&lt;p&gt;Lines beginning &lt;code&gt;d-i&lt;/code&gt; mean &amp;ldquo;debian-installer&amp;rdquo;.  There are also &lt;code&gt;tasksel&lt;/code&gt;
and &lt;code&gt;popularity-contest&lt;/code&gt; lines.  And because I&amp;rsquo;m installing &lt;code&gt;postfix&lt;/code&gt; we
also need some &lt;code&gt;postfix&lt;/code&gt; lines.  This took lots of trial and error and
reading docs and examples (and help from &lt;code&gt;r/debian&lt;/code&gt;).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   #_preseed_V1

   # These values all based on
   #   https://d-i.debian.org/manual/en.amd64/apbs04.html
   #   https://michael.kjorling.se/pages/debian-12-bookworm-preseed/preseed.cfg

   d-i debian-installer/language string en
   d-i debian-installer/country string US
   d-i debian-installer/locale string en_US.UTF-8
   d-i keyboard-configuration/xkb-keymap select us
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Those lines duplicate the options we passed on the kernel parameters; they may
not be needed!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   # Where to find the installer
   d-i mirror/protocol string http
   d-i mirror/country string manual
   d-i mirror/http/hostname string http.us.debian.org
   d-i mirror/http/directory string /debian
   d-i mirror/http/proxy string http://10.0.0.2:3142

   # Suite to install.
   d-i mirror/suite string bookworm
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here we&amp;rsquo;re defining where to install from; the &lt;code&gt;proxy&lt;/code&gt; line is telling the
installer to use the &lt;code&gt;apt-cacher-ng&lt;/code&gt; server.  We&amp;rsquo;re installing Debian 12
aka &amp;ldquo;bookworm&amp;rdquo;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Aside: I really dislike using codenames in configs.  It&amp;rsquo;s so much easier
to remember &amp;ldquo;11&amp;rdquo; or &amp;ldquo;12&amp;rdquo; or &amp;ldquo;13&amp;rdquo; rather than &amp;hellip; well, I don&amp;rsquo;t remember what
11 is; 12 is bookworm, 13 is trixie.  It&amp;rsquo;s cute, but it&amp;rsquo;s bad.  And, yes, I&amp;rsquo;m
staring very hard at Apple&amp;hellip;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;The config continues and is pretty easy to understand&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   d-i passwd/root-login boolean true
   d-i passwd/root-password-crypted password $6$...

   # To create a normal user account.
   d-i passwd/user-fullname string Stephen Harris
   d-i passwd/username string sweh
   d-i passwd/user-password-crypted password $6$...
   d-i passwd/user-uid string 500

   d-i time/zone string US/Eastern
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now we get to partitioning.  Debian comes with some default templates,
but they tend to put the OS at the beginning of the disk and the swap at the
end.  I wanted swap at the beginning so I could extend the disk and simply
resize/extend the partition if I needed more space.  So this will create a
1024M swap file and then the rest is a single ext4 root partition&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   d-i partman-auto/method string regular
   d-i partman-auto/expert_recipe string                         \
         boot-root ::                                            \
                 1024 1024 1024 linux-swap                       \
                         $primary{ }                             \
                         method{ swap } format{ }                \
                 .                                               \
                 1 1 -1 ext4                                     \
                         $primary{ } $bootable{ }                \
                         method{ format } format{ }              \
                         use_filesystem{ } filesystem{ ext4 }    \
                         mountpoint{ / }                         \
                 .
   d-i partman/confirm_write_new_label boolean true
   d-i partman/choose_partition select finish
   d-i partman/confirm boolean true
   d-i partman/confirm_nooverwrite boolean true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can then configure what additional repositories are in use:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   d-i apt-setup/cdrom/set-first boolean false
   d-i apt-setup/non-free-firmware boolean true
   d-i apt-setup/non-free boolean true
   d-i apt-setup/contrib boolean true
   d-i apt-setup/disable-cdrom-entries boolean true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we define the OS base (&amp;ldquo;standard&amp;rdquo; with &amp;ldquo;ssh-server&amp;rdquo;) along with any
additional packages; note that I chose &lt;code&gt;postfix&lt;/code&gt; as my mail server; that
will also need configuring later on.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   tasksel tasksel/first multiselect standard, ssh-server

   d-i pkgsel/include string ksh sudo curl postfix rsyslog binutils dump bsd-mailx apt-file rsync collectd-core
   d-i pkgsel/upgrade select full-upgrade

   popularity-contest popularity-contest/participate boolean false
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Grub information:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   d-i grub-installer/only_debian boolean true
   d-i grub-installer/bootdev  string /dev/vda

   d-i finish-install/reboot_in_progress note
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now comes the &lt;code&gt;postfix&lt;/code&gt; config&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   postfix postfix/mailname string spuddy.org
   postfix postfix/main_mailer_type string &#39;Internet with smarthost&#39;
   postfix postfix/relayhost string mailhost.spuddy.org
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then a post-install command that does something similar to the &lt;code&gt;%post&lt;/code&gt;
section of kickstart.  This command is run at the end of the installer.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   d-i preseed/late_command string chroot /target sh -c &amp;quot;cd /tmp &amp;amp;&amp;amp; /usr/bin/curl -o post.tar http://10.0.0.137/CentOS/kickstart/post_d12.tar &amp;amp;&amp;amp; /usr/bin/tar xf post.tar &amp;amp;&amp;amp; /bin/sh -x /tmp/debian-postinstall&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The complete file is available &lt;a href=&#34;https://www.sweharris.org/kickstart/debian12.cfg&#34;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&#34;debian-13-preseed-config&#34;&gt;Debian 13 preseed config.&lt;/h3&gt;

&lt;p&gt;This is almost identical, except the &lt;code&gt;mirror/suite&lt;/code&gt; refers to &lt;code&gt;trixie&lt;/code&gt;
and the &lt;code&gt;late_command&lt;/code&gt; refers to &lt;code&gt;post_d13.tar&lt;/code&gt;.  Just for completeness,
it&amp;rsquo;s &lt;a href=&#34;https://www.sweharris.org/kickstart/debian13.cfg&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;the-post-install-steps&#34;&gt;The post-install steps&lt;/h2&gt;

&lt;p&gt;For all 4 build types there&amp;rsquo;s a post-install step.  This primarily involves
downloading a tarball, extracting it, and running the script that&amp;rsquo;s inside
it.&lt;/p&gt;

&lt;p&gt;What this does is deploy some standard configurations to each machine;
e.g.  it ensures my account has a standard &lt;code&gt;$HOME&lt;/code&gt; (with my ssh public
keys), might add an additional repos (eg EPEL for Rocky), configures
postfix for my smarthost, creates email aliases so mail to my account
and to root is forwarded properly and so on.  Because it&amp;rsquo;s a full script
you can do almost anything; it runs inside the build &lt;code&gt;chroot&lt;/code&gt; environment.&lt;/p&gt;

&lt;p&gt;An example of this might be my Debian 12 script:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   # Extract all the files I want
   cd /
   /usr/bin/tar xvfp /tmp/files.tar
   /bin/rm /tmp/files.tar
   
   # Remove &amp;quot;quiet&amp;quot; from kernel boot params
   sed -i &#39;s/&amp;quot;quiet&amp;quot;/&amp;quot;&amp;quot;/&#39; /etc/default/grub
   
   # Ensure grub is updated with any changes that might have made
   /sbin/update-grub
   
   # Fix my account
   /usr/bin/chsh -s /bin/ksh sweh
   /sbin/usermod -a -G sudo sweh
   /sbin/usermod -a -G root sweh
   
   # Setup postfix correctly
   echo &#39;root: root@mailhost&#39; &amp;gt;&amp;gt; /etc/aliases
   /usr/bin/newaliases
   
   /usr/sbin/postconf append_dot_mydomain=yes
   /usr/sbin/postconf mydomain=spuddy.org
   /usr/sbin/postconf &#39;mydestination=$myhostname, localhost.$mydomain, localhost&#39;
   /usr/sbin/postconf &#39;myorigin=$myhostname&#39;
   /usr/sbin/postconf -X myhostname
   /usr/bin/systemctl enable postfix
   
   # Remove static hostname
   echo &amp;quot;&amp;quot; &amp;gt; /etc/hostname
   
   # Remove this annoying entry from hosts file
   sed -i &#39;/127.0.1.1/d&#39; /etc/hosts
   
   # Fix PAM SSH
   sed -i &#39;s/user_readenv=1//&#39; /etc/pam.d/sshd
   
   echo `date`: Post script completed
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;files.tar&lt;/code&gt; it refers to is embedded into the &lt;code&gt;post_d12.tar&lt;/code&gt; script
and contains things such as&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   ./etc/apt/apt.conf.d/00aptproxy
   ./etc/sudoers.d/sweh
   ./etc/sysctl.d/00-dmesg.conf
   ./etc/default/grub.d/console.cfg
   ./etc/default/grub.d/apparmor.cfg
   ./etc/logwatch/conf/services/zz-disk_space.conf
   ./etc/ntp.conf
   ./etc/cron.daily/need_patches
   ./home/sweh/.profile
   ./home/sweh/.envfile
   ./home/sweh/.forward
   ./home/sweh/.ssh/authorized_keys
   ./root/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(that&amp;rsquo;s not the complete list, just a sample)&lt;/p&gt;

&lt;p&gt;Basically, any &amp;ldquo;standard&amp;rdquo; changes you want deployed to all my VMs is
performed in this script, and it can be customised to each OS variant.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;What I&amp;rsquo;ve described here is suitable for a homelab.  But some of the same
concepts can be applied to enterprises as well.  For example, that kickstart
file could be modified to be regional specific to pick a local replica to
get the repos.  The post-install script could call out to something like
&lt;code&gt;ansbible&lt;/code&gt; or &lt;code&gt;puppet&lt;/code&gt; to do proper configuration management (even auto
install and configure something like Apache web server if the machine is
defined as &amp;ldquo;webserver&amp;rdquo; in an inventory system).  The automated install
options provided by Rocky (RedHat) and Debian are very flexible.&lt;/p&gt;

&lt;p&gt;In my case, I can just run &lt;code&gt;deb_install -13 new_host&lt;/code&gt; and it will create
the LV for disk space, and run &lt;code&gt;virt_install&lt;/code&gt; with all the required parameters.
5 minutes later I have a new fully patched VM to test and play with, with
sane default values.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>When automation is a problem</title>
      <link>https://www.sweharris.org/post/2025-07-17-automation/</link>
      <pubDate>Thu, 17 Jul 2025 08:39:28 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2025-07-17-automation/</guid>
      <description>

&lt;p&gt;In the past I&amp;rsquo;ve pushed for automation of server builds, of application
configuration.&lt;/p&gt;

&lt;p&gt;Indeed, for my home setup, I&amp;rsquo;ve been using &lt;code&gt;ansible&lt;/code&gt; for over a decade;
I still see a config file for CentOS 6 postfix dated 2015.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve started a migration from CentOS/Rocky Linux (i.e. RedHat) to Debian
for my personal servers.  And I&amp;rsquo;ve realised this automation is causing
me more problems than it&amp;rsquo;s solving:&lt;/p&gt;

&lt;h3 id=&#34;differences-between-distributions&#34;&gt;Differences between distributions&lt;/h3&gt;

&lt;p&gt;Debian is configured very differently to RedHat.  This shows in many
places, but one of the most obvious is with Apache.  With RedHat
the configuration files all live in &lt;code&gt;/etc/httpd&lt;/code&gt;.  With Debian it&amp;rsquo;s
&lt;code&gt;/etc/apache2&lt;/code&gt;.  With Debian you manage symlinks with commands
such as &lt;code&gt;a2enmod&lt;/code&gt; and &lt;code&gt;a2ensite&lt;/code&gt;; with RedHat it&amp;rsquo;s more &amp;ldquo;just put
stuff into the config directory&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Now you &lt;em&gt;can&lt;/em&gt; put stuff into the Debian directory, but it&amp;rsquo;s different
(&lt;code&gt;/etc/apache2/sites-enabled&lt;/code&gt; and &lt;code&gt;/etc/apache2/conf-enabled&lt;/code&gt;
and &lt;code&gt;/etc/apache2/mods-enabled&lt;/code&gt;, vs &lt;code&gt;/etc/httpd/conf.d&lt;/code&gt; and
&lt;code&gt;/etc/httpd/conf.modules.d&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;And the contents have to be different as well; eg the log directory on
RedHat Apache is just &lt;code&gt;logs/&lt;/code&gt; but on Debian its &lt;code&gt;${APACHE_LOG_DIR}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Apache is just one example.  Other tools have similar configuration
differences.&lt;/p&gt;

&lt;p&gt;All this means that the configs I built for RedHat pretty much need to be
rewritten from scratch for Debian.  It was bad enough having to deal with
differences between RHEL 6, 7, 8, 9 but there was sufficient consistency.&lt;/p&gt;

&lt;h2 id=&#34;maybe-everything-is-a-pet&#34;&gt;Maybe everything is a pet.&lt;/h2&gt;

&lt;p&gt;When I looked at all my playbooks I realised a large number of them were
targeting single machines.  Which kinda makes sense; in my home environment
every OS instance is doing something different; it might be my desktop, or
a media player, or a plex server, or a home assistant server, or a bastion
host, or a router, or&amp;hellip;&lt;/p&gt;

&lt;p&gt;Pretty much only two machines were configured &amp;ldquo;the same&amp;rdquo; (or close to,
allowing for different hosting providers).  Everything else was custom.&lt;/p&gt;

&lt;p&gt;My Apache config for my bastion &amp;ldquo;reverse proxy&amp;rdquo; is very different to my
config for the server hosting this blog.  (They&amp;rsquo;re on different OS releases,
to start with!).&lt;/p&gt;

&lt;p&gt;So although I had tried to automate the build for each of these pets,
I kinda never used those playbooks again &amp;lsquo;cos I never &lt;em&gt;rebuilt&lt;/em&gt; the server;
if there had been a failure I would have restored from backup.&lt;/p&gt;

&lt;h2 id=&#34;reduced-build-automation&#34;&gt;Reduced build automation&lt;/h2&gt;

&lt;p&gt;So rather than rewrite my playbooks and create either duplication (different
OSes with different playbooks and config files) or horrendous conditional
logic in the config files (which really makes it harder to read, and
brings in tech-debt which will need to be removed as I finally move off
the older OSes), I&amp;rsquo;m mostly doing things by hand.&lt;/p&gt;

&lt;p&gt;The Debian OS deployment, itself, is automated with netinstall and preseed
configurations.  In this preseed I have a post-install step that deploys
common configs (eg telling postfix to point to my mailhost), handles some
custom scripting and so on.&lt;/p&gt;

&lt;p&gt;But from then on, the upper layers are manual.  One server got a &lt;code&gt;docker&lt;/code&gt;
deployment; another got &lt;code&gt;grafana&lt;/code&gt; and &lt;code&gt;influxdb&lt;/code&gt; (the configs and data
for those got migrated from the old machine to the new); the reverse proxy
got &lt;code&gt;apache2&lt;/code&gt;; and so on.&lt;/p&gt;

&lt;h2 id=&#34;maintenance-automation&#34;&gt;Maintenance automation&lt;/h2&gt;

&lt;p&gt;There is still some requirement for automation.  Most commonly to
redeploy new TLS certificates every 80 days.  Because most of my
servers can&amp;rsquo;t be reached from the internet and because those that
&lt;em&gt;are&lt;/em&gt; accessible may not have DNS pointing to them (warm standby)
I can&amp;rsquo;t just use &lt;code&gt;certbot&lt;/code&gt; to manage them simply.  So, instead, I use
&lt;a href=&#34;https://github.com/dehydrated-io/dehydrated&#34;&gt;dehydrated&lt;/a&gt; to get the
certs and then deploy them to all the servers and services (apache,
postfix, grafana, etc etc) with a set of ansible playbooks.&lt;/p&gt;

&lt;p&gt;Whether I keep using ansible for this &amp;ldquo;maintenance&amp;rdquo; work or if I&amp;rsquo;ll write
a set of scripts that run via &lt;code&gt;ssh&lt;/code&gt; I&amp;rsquo;m not sure.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;In an enterprise environment there can be little doubt that automated
processes are a win.  They can allow for hands-off deployments; repeatable,
testable processes; controlled access and more.  An enterprise also shouldn&amp;rsquo;t
really have much in the way of pets (at the very least there should be a BC/DR
environment!).  Yes, if you have 1000 apps you might have 1000 playbooks,
but each app team should be maintaining their own.&lt;/p&gt;

&lt;p&gt;In a small business or a home environment, though, the case for full
automation isn&amp;rsquo;t so clear.  When each server is unique then maybe
documentation of how a server is built, along with good backups to enable
a restore in case of failure, might be a simpler and quicker solution.&lt;/p&gt;

&lt;p&gt;But even in my pet-heavy environment there is still a need for a level
of automation, just not full automation!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Bot scrapers DoS me?</title>
      <link>https://www.sweharris.org/post/2025-06-16-scrapy-dos/</link>
      <pubDate>Mon, 16 Jun 2025 10:53:54 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2025-06-16-scrapy-dos/</guid>
      <description>

&lt;p&gt;I have a routine that runs every 15 minutes on my home machine and polls
other of my servers and collates the results.&lt;/p&gt;

&lt;p&gt;Once or twice a day one of my machines, at linode, was refusing to talk.
It wasn&amp;rsquo;t causing a problem since the data is replicated and the system
catches up, but it was annoying.&lt;/p&gt;

&lt;p&gt;Digging around, the machine looked like it was working normally.  But I
found, in one log, that the machine had a load average of over 30 when
the problem happens.&lt;/p&gt;

&lt;p&gt;Now in the past when this occurred it was because of hardware issues at
linode.  But I wasn&amp;rsquo;t seeing anything in the logs.  Normally &lt;code&gt;sar&lt;/code&gt; data
would show excessive I/O loads or long service times, but everything looked
normal.  Indeed it was just showing a higher (75%) CPU usage in user space,
but still had over 20% idle time.&lt;/p&gt;

&lt;h2 id=&#34;cgi&#34;&gt;CGI&lt;/h2&gt;

&lt;p&gt;As luck would have it I was logged in while the problem occurred.  A &lt;code&gt;ps&lt;/code&gt;
showed many dozens of CGI scripts running.  Which is odd.&lt;/p&gt;

&lt;p&gt;Checking my Apache logs and I found entries like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;34.10.139.117 - - [03/Jun/2025:00:25:52 -0400] &amp;quot;GET /sf.pl?ACTION=SHOW&amp;amp;DETAIL=9780575050044 HTTP/1.1&amp;quot; 200 936 &amp;quot;https://spuddy.org/sf.pl&amp;quot; &amp;quot;Scrapy/2.11.2 (+https://scrapy.org)&amp;quot;
34.10.139.117 - - [03/Jun/2025:00:25:53 -0400] &amp;quot;GET /sf.pl?ACTION=SHOW&amp;amp;DETAIL=9780575052482 HTTP/1.1&amp;quot; 200 945 &amp;quot;https://spuddy.org/sf.pl&amp;quot; &amp;quot;Scrapy/2.11.2 (+https://scrapy.org)&amp;quot;
34.10.139.117 - - [03/Jun/2025:00:25:53 -0400] &amp;quot;GET /sf.pl?ACTION=SHOW&amp;amp;DETAIL=9780575055261 HTTP/1.1&amp;quot; 200 954 &amp;quot;https://spuddy.org/sf.pl&amp;quot; &amp;quot;Scrapy/2.11.2 (+https://scrapy.org)&amp;quot;
34.10.139.117 - - [03/Jun/2025:00:25:53 -0400] &amp;quot;GET /sf.pl?ACTION=SHOW&amp;amp;DETAIL=9780380756674 HTTP/1.1&amp;quot; 200 924 &amp;quot;https://spuddy.org/sf.pl&amp;quot; &amp;quot;Scrapy/2.11.2 (+https://scrapy.org)&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, that explains a lot.  But I thought I had a &lt;a href=&#34;https://en.wikipedia.org/wiki/Robots.txt&#34;&gt;robots.txt&lt;/a&gt; entry to stop this (after Google search indexer
started hitting it).&lt;/p&gt;

&lt;p&gt;Yup&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;User-agent: *
Disallow: /cds.pl
Disallow: /sf.pl
Disallow: /video.pl
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Looking at the web site for Scrapy I saw, quite predominantly featured,
that it has a feature &lt;code&gt;ROBOTSTXT_OBEY&lt;/code&gt; where this scraper can ignore the
robots.txt entries.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s a pretty arsehole thing to build into your bot, to be honest.&lt;/p&gt;

&lt;h2 id=&#34;block-by-ip&#34;&gt;Block by IP?&lt;/h2&gt;

&lt;p&gt;I originally thought of blocking by IP, but the scraper appears to be
hosted at Google cloud and changes IP addresses.&lt;/p&gt;

&lt;p&gt;In the past 2 weeks I&amp;rsquo;ve seen these sorts of volumes&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% sudo grep  -h Scrapy *access_log* | cut -d&#39; &#39; -f1 | sort | uniq -c | sort -nr
  74220 104.154.64.63
  60663 104.197.101.217
  54657 34.45.158.181
  50737 34.41.99.8
  50610 34.9.117.151
  49530 34.10.205.39
  38538 34.42.59.237
  38490 35.224.154.106
  30822 34.132.153.18
  23115 35.238.9.157
  23081 35.188.193.33
  15410 34.44.52.133
  15410 34.29.68.151
  15410 34.10.139.117
   7705 34.29.122.46
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&amp;rsquo;d be playing whack-a-mole if I went down this path!&lt;/p&gt;

&lt;h2 id=&#34;apache-rate-limiting-with-mod-evasive&#34;&gt;Apache rate limiting with mod_evasive&lt;/h2&gt;

&lt;p&gt;I mentioned this else-net and someone responded they&amp;rsquo;d seem similar behaviour
against their web server and had configured &lt;code&gt;nginx&lt;/code&gt; to start rate limiting.&lt;/p&gt;

&lt;p&gt;That sounded like a good idea.  To the best of my knowledge, Apache doesn&amp;rsquo;t
have this built in (I might be wrong! Let me know&amp;hellip;) but it looked like
a third party module, &lt;code&gt;mod_evasive&lt;/code&gt;, could do the job.&lt;/p&gt;

&lt;p&gt;I noticed that EPEL had this for RedHat 7, but not for 8 or 9.  So I downloaded
the &lt;a href=&#34;https://dl.fedoraproject.org/pub/archive/epel/7/source/tree/Packages/m/mod_evasive-1.10.1-22.el7.src.rpm&#34;&gt;SRPMS&lt;/a&gt; and used that to build an &lt;code&gt;rpm&lt;/code&gt; for
my servers using &lt;code&gt;mock&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&#34;config&#34;&gt;Config&lt;/h2&gt;

&lt;p&gt;After compiling and installing &lt;code&gt;mod_evasive&lt;/code&gt;, I created this configuration
(based on the defaults, all deployed by &lt;code&gt;ansible&lt;/code&gt;).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;LoadModule evasive20_module modules/mod_evasive24.so

&amp;lt;IfModule mod_evasive24.c&amp;gt;
    DOSHashTableSize    3097
    DOSPageCount        10
    DOSSiteCount        20
    DOSPageInterval     1
    DOSSiteInterval     5
    DOSBlockingPeriod   10
    DOSEmailNotify      sweh
&amp;lt;/IfModule&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;the-results&#34;&gt;The results.&lt;/h2&gt;

&lt;p&gt;Initially I was worried about false positive blocks; would I start blocking
legitimate spidering of my site (eg by google search).  So each time I
got a &amp;ldquo;blocked&amp;rdquo; alert I would log into the server and check it.&lt;/p&gt;

&lt;p&gt;A few iterations of this, and some code changes (changing the response
from 403 to 429; the email it sent out wasn&amp;rsquo;t quite right, and I wanted
to enhance the data in the email so I could see if this was a good block)
and I had something that seemed to mostly work.&lt;/p&gt;

&lt;p&gt;Now I get an alert that looks something like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  Subject: HTTP BLACKLIST 104.154.64.63

  mod_evasive HTTP Blacklisted 104.154.64.63
      URI: /sf.pl?ACTION=SHOW&amp;amp;DETAIL=9780441662517
    Agent: Scrapy/2.11.2 (+https://scrapy.org)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When I looked through my logs yesterday morning I saw, in 2 hours&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% awk &#39;$9==429&#39; sweh-ssl.access_log | wc -l
18460
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of those 17,940 were calls to a CGI.&lt;/p&gt;

&lt;p&gt;Looking more closely at the entries, the first block was at
&amp;ldquo;15/Jun/2025:05:19:17&amp;rdquo; and the last at &amp;ldquo;15/Jun/2025:05:21:49&amp;rdquo;.  So it
blocked 18,000 calls in 2 minutes.  That&amp;rsquo;s pretty good!&lt;/p&gt;

&lt;p&gt;Now it&amp;rsquo;s not perfect; I run Apache in prefork mode (&amp;lsquo;cos I&amp;rsquo;m so old
school!)  so each forked instance keeps its own state, which means that
if one web server process blocks a site another may let it through, or a
process terminates and a new one replaces it then it will have no state
and would allow traffic.  eg at &amp;ldquo;15/Jun/2025:05:19:54&amp;rdquo; it blocked 262
attempts but let through 3.&lt;/p&gt;

&lt;p&gt;But the number it blocks is really helping.&lt;/p&gt;

&lt;p&gt;Who would have thought a cheap linode could handle 260 requests per
second!  Of course it&amp;rsquo;s all in memory when it hits 429 land, but still&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;forks-of-mod-evasive&#34;&gt;Forks of mod_evasive&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve since checked on &lt;a href=&#34;https://github.com/jzdziarski/mod_evasive&#34;&gt;github&lt;/a&gt; and
I see there&amp;rsquo;s lots of forks of it.  I spotted one of those forks appears to
use shared memory to keep state so the prefork issue I&amp;rsquo;m seeing won&amp;rsquo;t happen.
But that fork also removes some functionality I like.&lt;/p&gt;

&lt;p&gt;For the moment, I think I&amp;rsquo;ll stick with this.&lt;/p&gt;

&lt;h2 id=&#34;side-effects&#34;&gt;Side effects&lt;/h2&gt;

&lt;p&gt;Funnily enough this has also been catching script kiddies running simple
bots against my site:&lt;/p&gt;

&lt;p&gt;eg&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;129.146.124.161 - - [15/Jun/2025:00:12:12 -0400] &amp;quot;GET /credentials.xml HTTP/1.1&amp;quot; 429 227 &amp;quot;http://spuddy.org/credentials.xml&amp;quot; &amp;quot;Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36&amp;quot;

13.74.158.147 - - [15/Jun/2025:14:33:13 -0400] &amp;quot;GET /wp-includes/Text/Diff/Engine/ HTTP/1.1&amp;quot; 429 227 &amp;quot;-&amp;quot; &amp;quot;-&amp;quot;

47.251.102.239 - - [15/Jun/2025:17:58:46 -0400] &amp;quot;GET /index.php?lang=../../../../../../../../tmp/index1 HTTP/1.1&amp;quot; 429 227 &amp;quot;-&amp;quot; &amp;quot;Custom-AsyncHttpClient&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;rsquo;s also spotted broken bots that keep requesting the same page (I&amp;rsquo;ve seen
this one before)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;117.159.55.9 - - [15/Jun/2025:13:48:21 -0400] &amp;quot;GET /images/emblem.gif HTTP/1.1&amp;quot; 429 227 &amp;quot;-&amp;quot; &amp;quot;Go-http-client/1.1&amp;quot;
117.159.55.9 - - [15/Jun/2025:13:48:22 -0400] &amp;quot;GET /images/emblem.gif HTTP/1.1&amp;quot; 429 227 &amp;quot;-&amp;quot; &amp;quot;Go-http-client/1.1&amp;quot;
117.159.55.9 - - [15/Jun/2025:13:48:22 -0400] &amp;quot;GET /images/emblem.gif HTTP/1.1&amp;quot; 429 227 &amp;quot;-&amp;quot; &amp;quot;Go-http-client/1.1&amp;quot;
117.159.55.9 - - [15/Jun/2025:13:48:22 -0400] &amp;quot;GET /images/emblem.gif HTTP/1.1&amp;quot; 429 227 &amp;quot;-&amp;quot; &amp;quot;Go-http-client/1.1&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And, of course, OpenAI&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;20.171.207.4 - - [14/Jun/2025:22:40:37 -0400] &amp;quot;GET /post/2018-01-04-meltdown_spectre/ HTTP/1.1&amp;quot; 429 227 &amp;quot;-&amp;quot; &amp;quot;Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GPTBot/1.2; +https://openai.com/gptbot)&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;ranting&#34;&gt;Ranting&lt;/h2&gt;

&lt;p&gt;Web scrapers should obey the wishes of the content creator.  &lt;code&gt;robots.txt&lt;/code&gt;
should be followed.  At the very least they should act to &lt;em&gt;not&lt;/em&gt; break the
remote server.  I know I can&amp;rsquo;t stop you stealing my stuff (and I&amp;rsquo;m resigned
to that; theft of intellectual property is a different blog post entirely),
but at least don&amp;rsquo;t break my machine.&lt;/p&gt;

&lt;p&gt;Also you don&amp;rsquo;t need to scrape the same page a gazillions times.  For
example,&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat *access_log* | grep -c 9780575050044
133
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You&amp;rsquo;ve requested details about one book 133 times in 2 weeks?  What the hell?&lt;/p&gt;

&lt;p&gt;This is just abusive behaviour.&lt;/p&gt;

&lt;p&gt;This web site is my hobby; it costs $20/month to run.  It&amp;rsquo;s arseholes like
this scraper that make this less fun.&lt;/p&gt;

&lt;p&gt;Heh, at least I get the satisfaction of knowing that it&amp;rsquo;s costing &lt;em&gt;you&lt;/em&gt; money
to do this!&lt;/p&gt;

&lt;p&gt;OK, rant over.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;The modern internet is basically out of control.  Mass theft of data for
AI purposes is prevalent.  I suspect that the majority of hits on my server
are from bots, and not humans.&lt;/p&gt;

&lt;p&gt;In the past 28 days, there were 771,000 hits on this web server (across the
various URLs it serves), 548,000 were from Scrapy.  Of the rest a quick
check based on the user-agent, 55% were trivially bots (scrapers, script
kiddies, RSS readers, whatever).   Some of those bots may be useful :-)&lt;/p&gt;

&lt;p&gt;Many of those bots are broken in various ways and can cause harm to victims.&lt;/p&gt;

&lt;p&gt;In amongst this noise are various so-called &amp;ldquo;white hat&amp;rdquo; organisations that
are &lt;em&gt;also&lt;/em&gt; scanning machines without permission.  At least they normally
obey &lt;code&gt;robots.txt&lt;/code&gt; and just cause noise in the logs.&lt;/p&gt;

&lt;p&gt;It seems clear that most of the traffic on the internet is just machines
talking to machines and not human eyeballs at all.&lt;/p&gt;

&lt;p&gt;Any website, even hobby ones like this, are going to need more
robust defenses against this brokenness.  Tools like &lt;code&gt;mod_evasive&lt;/code&gt;
are reactive, but if they react quickly enough then they can prevent
service degradation.  You&amp;rsquo;d need different tools if you want to prevent
data theft in the first place!&lt;/p&gt;

&lt;p&gt;And an enterprise that &lt;em&gt;needs&lt;/em&gt; to look at the logs to determine a real
attack&amp;hellip; good luck!  All this brokenness and &amp;ldquo;white hat&amp;rdquo; traffic is just
making your life harder.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>I asked ChatGPT to write me a program</title>
      <link>https://www.sweharris.org/post/2025-06-10-chatgpt-oauth/</link>
      <pubDate>Tue, 10 Jun 2025 08:10:49 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2025-06-10-chatgpt-oauth/</guid>
      <description>

&lt;p&gt;This post contains a lot of code, presented as close as possible to the
code ChatGPT gave me.  I&amp;rsquo;m including it here so people can see how good
or bad they think it is.  Where necessary I modified the code to make it
work, but it&amp;rsquo;s as close as possible.&lt;/p&gt;

&lt;p&gt;All this code makes the post look longer than it is. If you&amp;rsquo;re not interested
in the code then you can just skip over it and just read my words :-)&lt;/p&gt;

&lt;h2 id=&#34;the-problem&#34;&gt;The problem&lt;/h2&gt;

&lt;p&gt;I wanted to write a program to talk to the Fitbit API so I could get
data out of it (eg record of heart rate while I was exercising).  It&amp;rsquo;s
not too hard to do; you just need an authorization token and a &lt;code&gt;curl&lt;/code&gt;
command&lt;/p&gt;

&lt;p&gt;A quick hack&amp;rsquo;n&amp;rsquo;slash of code and I came up with something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/bin/ksh -p

d=${D:-$(date +&amp;quot;%Y-%m-%d&amp;quot;)}

case $1 in
  cal*) T=calories; D=1min; I=activities-calories-intraday ;;
     *) T=heart ; D=1sec; I=activities-heart-intraday ;;
esac

URL=https://api.fitbit.com/1/user/-/activities/$T/date/$d/$d/$D/time/00:00/23:59.json

A=&amp;quot;Bearer .....&amp;quot;

curl -H &amp;quot;Authorization: $A&amp;quot; $URL | jq -r &#39;.&amp;quot;&#39;$I&#39;&amp;quot;.dataset[]|(.value|tostring)+&amp;quot;,&amp;quot;+.time&#39;  | less
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The problem is in getting the bearer token.  This is oauth2 authentication.
It &lt;em&gt;could&lt;/em&gt; be done in shell script, but it&amp;rsquo;d be messy.&lt;/p&gt;

&lt;h2 id=&#34;the-proposed-solution&#34;&gt;The proposed solution&lt;/h2&gt;

&lt;p&gt;Instead of doing this in shell script, I decided to do it in GoLang.  I&amp;rsquo;d
previously done oauth2 in perl (ugh, over a decade ago!) to talk to Google
Calendar but I&amp;rsquo;m trying to use Go for stuff these days.&lt;/p&gt;

&lt;p&gt;So I did some searching and Go has oauth2 libraries (naturally).
It didn&amp;rsquo;t seem too hard.  There were even examples of code talking to
the Fitbit API.  But I couldn&amp;rsquo;t find any code to explain how to use the
refresh token.  This is essential for automated use (e.g. from a &lt;code&gt;cron&lt;/code&gt; job).&lt;/p&gt;

&lt;h2 id=&#34;let-s-ask-chatgpt&#34;&gt;Let&amp;rsquo;s ask ChatGPT&lt;/h2&gt;

&lt;p&gt;So I thought I&amp;rsquo;d ask AI to help.  Just the generic &lt;code&gt;chatgpt.com&lt;/code&gt;, without
a login; the bare bones generic free offering.  If it worked then I&amp;rsquo;d be
very impressed.  If it didn&amp;rsquo;t then at least my biases would be confirmed :-)&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Spoiler: it&amp;rsquo;s somewhere in between&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;I wasn&amp;rsquo;t going to &amp;ldquo;vibe code&amp;rdquo;, but use what I already knew to modify/fix
what the AI gave me.&lt;/p&gt;

&lt;h2 id=&#34;getting-the-oauth2-token&#34;&gt;Getting the oauth2 token&lt;/h2&gt;

&lt;p&gt;So I asked it &amp;ldquo;I need a program in GoLang to perform oauth2 authentication
from a CLI&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;And it provided a program that did this.  I noticed it was designed for
talking to Google endpoints, so I followed up with &amp;ldquo;what about for fitbit&amp;rdquo;.
The resulting code was almost correct!  Naturally it had places for hard-coded
credentials, and the redirect URL wasn&amp;rsquo;t quite right; but these are things
easily fixed.&lt;/p&gt;

&lt;p&gt;After a little bit of cleanup (and me adding a quick kludge so
I could make this a function) the code looked a bit like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
package main

import (
	&amp;quot;context&amp;quot;
	&amp;quot;fmt&amp;quot;
	&amp;quot;log&amp;quot;
	&amp;quot;net/http&amp;quot;
	&amp;quot;encoding/json&amp;quot;

	&amp;quot;golang.org/x/oauth2&amp;quot;
)

var (
	// Replace with your Fitbit app&#39;s credentials
	clientID     = &amp;quot;XXXXXX&amp;quot;
	clientSecret = &amp;quot;XXXXXX&amp;quot;
	redirectURL  = &amp;quot;http://localhost:8080&amp;quot;
)

// OAuth2 configuration for Fitbit
var oauth2Config = oauth2.Config{
	ClientID:     clientID,
	ClientSecret: clientSecret,
	RedirectURL:  redirectURL,
	Scopes:       []string{&amp;quot;activity&amp;quot;, &amp;quot;profile&amp;quot;}, // Adjust scopes as needed
	Endpoint: oauth2.Endpoint{
		AuthURL:  &amp;quot;https://www.fitbit.com/oauth2/authorize&amp;quot;,
		TokenURL: &amp;quot;https://api.fitbit.com/oauth2/token&amp;quot;,
	},
}

var oauth2StateString = &amp;quot;random_state_string&amp;quot; // A random string for security purposes

// Function to handle the OAuth2 flow
func getOAuth2Token() (*oauth2.Token, error) {
	channel := make(chan string)

	// Step 1: Generate the URL for the user to authenticate
	authURL := oauth2Config.AuthCodeURL(oauth2StateString, oauth2.AccessTypeOffline)
	fmt.Println(&amp;quot;Go to the following URL and authorize the application:&amp;quot;, authURL)

	// Step 2: Set up the web server to handle the redirect and capture the authorization code
	http.HandleFunc(&amp;quot;/&amp;quot;, func(w http.ResponseWriter, r *http.Request) {
		code := r.URL.Query().Get(&amp;quot;code&amp;quot;)
		if code == &amp;quot;&amp;quot; {
			channel &amp;lt;- &amp;quot;err_code&amp;quot;
			http.Error(w, &amp;quot;Code is missing&amp;quot;, http.StatusBadRequest)
			return
		}

		// Step 3: Exchange the code for an access token
		token, err := oauth2Config.Exchange(context.Background(), code)
		if err != nil {
			channel &amp;lt;- &amp;quot;err_exchange&amp;quot;
			http.Error(w, fmt.Sprintf(&amp;quot;Failed to exchange token: %v&amp;quot;, err), http.StatusInternalServerError)
			return
		}

		// Step 4: Output the access token
		fmt.Fprintf(w, &amp;quot;Access token: %s\n&amp;quot;, token.AccessToken)
		fmt.Printf(&amp;quot;Access token: %s\n&amp;quot;, token.AccessToken)
		channel &amp;lt;- &amp;quot;done&amp;quot;
	})

	// Start an HTTP server to handle the callback
	go http.ListenAndServe(&amp;quot;:8080&amp;quot;, nil)

	// Wait for the user to visit the URL and authenticate
	// time.Sleep(2 * time.Second)
	msg := &amp;lt;- channel
	fmt.Println(msg)

	return nil, nil
}

func main() {
	// Start OAuth2 token acquisition process
	_, err := getOAuth2Token()
	if err != nil {
		log.Fatalf(&amp;quot;Error during OAuth2 process: %v&amp;quot;, err)
	}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now this actually worked!  There&amp;rsquo;s a couple of places where it smells, though.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hard coding the FitBit endpoints instead of using &lt;code&gt;golang.org/x/oauth2/fitbit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;No handling of the state string&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But it worked.  It got me a bearer token that I could use.  That could
easily be used to persist the returned data so it could be used later&lt;/p&gt;

&lt;h2 id=&#34;how-to-use-this&#34;&gt;How to use this?&lt;/h2&gt;

&lt;p&gt;So the next question was &amp;ldquo;how do I use this to get data?&amp;rdquo; and it returned
some simple code.  Again it worked.  I&amp;rsquo;m not sure I had to mangle anything
here.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package main

import (
	&amp;quot;fmt&amp;quot;
	&amp;quot;log&amp;quot;
	&amp;quot;net/http&amp;quot;
	&amp;quot;io/ioutil&amp;quot;
)

func getUserProfile(accessToken string) {
	// Fitbit API endpoint for user profile
	url := &amp;quot;https://api.fitbit.com/1/user/-/profile.json&amp;quot;
	req, err := http.NewRequest(&amp;quot;GET&amp;quot;, url, nil)
	if err != nil {
		log.Fatalf(&amp;quot;Error creating request: %v&amp;quot;, err)
	}

	// Set the Authorization header with the access token
	req.Header.Set(&amp;quot;Authorization&amp;quot;, &amp;quot;Bearer &amp;quot;+accessToken)

	// Perform the request
	client := &amp;amp;http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Fatalf(&amp;quot;Error making request: %v&amp;quot;, err)
	}
	defer resp.Body.Close()

	// Read and print the response body
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalf(&amp;quot;Error reading response: %v&amp;quot;, err)
	}

	// Print the user profile
	fmt.Println(string(body))
}

func main() {
	// Replace this with the actual token you obtained during OAuth
	accessToken := &amp;quot;XXXXX&amp;quot;
	getUserProfile(accessToken)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There&amp;rsquo;s not really a lot to say there; it&amp;rsquo;s a simple enough http client.&lt;/p&gt;

&lt;h2 id=&#34;refresh-token&#34;&gt;Refresh token&lt;/h2&gt;

&lt;p&gt;But nowhere were we handling refresh tokens.  So I then asked &amp;ldquo;How do we handle
refresh tokens&amp;rdquo;&lt;/p&gt;

&lt;p&gt;More code.  This time it didn&amp;rsquo;t work properly because it was missing the
basicAuth token (I had to add that).  It&amp;rsquo;s also unnecessarily sending
the client secret.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package main

import (
	&amp;quot;fmt&amp;quot;
	&amp;quot;log&amp;quot;
	&amp;quot;net/http&amp;quot;
	&amp;quot;net/url&amp;quot;
	&amp;quot;strings&amp;quot;
	&amp;quot;time&amp;quot;
	&amp;quot;encoding/json&amp;quot;

	&amp;quot;golang.org/x/oauth2&amp;quot;
)

var (
	clientID     = &amp;quot;XXXXX&amp;quot;
        clientSecret = &amp;quot;XXXXX&amp;quot;
	// Replace with your refresh token obtained during initial OAuth
	refreshToken = &amp;quot;XXXXX&amp;quot;
)

// Fitbit OAuth2 token endpoint
var tokenURL = &amp;quot;https://api.fitbit.com/oauth2/token&amp;quot;

// Function to refresh the access token
func refreshAccessToken(refreshToken string) (*oauth2.Token, error) {
	// Prepare the data for the token request
	data := url.Values{}
	data.Set(&amp;quot;grant_type&amp;quot;, &amp;quot;refresh_token&amp;quot;)
	data.Set(&amp;quot;refresh_token&amp;quot;, refreshToken)
	data.Set(&amp;quot;client_id&amp;quot;, clientID)
	data.Set(&amp;quot;client_secret&amp;quot;, clientSecret)

	// Send the POST request to the token URL
	req, err := http.NewRequest(&amp;quot;POST&amp;quot;, tokenURL, strings.NewReader(data.Encode()))
	if err != nil {
		return nil, fmt.Errorf(&amp;quot;Error creating request: %v&amp;quot;, err)
	}
	req.Header.Set(&amp;quot;Content-Type&amp;quot;, &amp;quot;application/x-www-form-urlencoded&amp;quot;)
	req.SetBasicAuth(clientID,clientSecret)

	// Perform the request
	client := &amp;amp;http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf(&amp;quot;Error making request: %v&amp;quot;, err)
	}
	defer resp.Body.Close()

	// If the request failed, return an error
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf(&amp;quot;Failed to refresh token, status code: %d&amp;quot;, resp.StatusCode)
	}

	// Parse the response to get the new access token and refresh token
	var tokenResponse struct {
		AccessToken  string `json:&amp;quot;access_token&amp;quot;`
		RefreshToken string `json:&amp;quot;refresh_token&amp;quot;`
		TokenType    string `json:&amp;quot;token_type&amp;quot;`
		ExpiresIn    int    `json:&amp;quot;expires_in&amp;quot;`
	}

	// Decode the JSON response
	if err := json.NewDecoder(resp.Body).Decode(&amp;amp;tokenResponse); err != nil {
		return nil, fmt.Errorf(&amp;quot;Error decoding response: %v&amp;quot;, err)
	}

	// Return the new access token
	fmt.Printf(&amp;quot;New Access Token: %s\n&amp;quot;, tokenResponse.AccessToken)
	fmt.Printf(&amp;quot;New Refresh Token: %s\n&amp;quot;, tokenResponse.RefreshToken)

	// Optionally, update the stored refresh token, if Fitbit returns a new one
	// Update the refreshToken variable if necessary

	// Return the new token as an oauth2.Token
	return &amp;amp;oauth2.Token{
		AccessToken:  tokenResponse.AccessToken,
		RefreshToken: tokenResponse.RefreshToken,
		TokenType:    tokenResponse.TokenType,
		Expiry:       time.Now().Add(time.Duration(tokenResponse.ExpiresIn) * time.Second),
	}, nil
}

func main() {
	// Call the refresh function
	token, err := refreshAccessToken(refreshToken)
	if err != nil {
		log.Fatalf(&amp;quot;Error refreshing access token: %v&amp;quot;, err)
	}

	// Print the new access token
	fmt.Printf(&amp;quot;Refreshed Access Token: %s\n&amp;quot;, token.AccessToken)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It worked.  But something is rotten in the state of Denmark.&lt;/p&gt;

&lt;p&gt;Basically this is talking raw https to the Fitbit endpoints.  It&amp;rsquo;s sending
raw data, parsing JSON, doing everything itself.  It&amp;rsquo;s not using the provided
oauth2 libraries (except at the end, to create a token object).&lt;/p&gt;

&lt;p&gt;This can&amp;rsquo;t be the right way of doing it.&lt;/p&gt;

&lt;h2 id=&#34;the-right-way&#34;&gt;The right(?) way&lt;/h2&gt;

&lt;p&gt;It turns out the reason I was having trouble finding a good answer, and likely
the reason ChatGPT couldn&amp;rsquo;t do it, was because it&amp;rsquo;s not obvious.  There&amp;rsquo;s
a long &lt;a href=&#34;https://github.com/golang/oauth2/issues/84&#34;&gt;thread&lt;/a&gt; on this going
back 10 years.&lt;/p&gt;

&lt;p&gt;It appears the original developers didn&amp;rsquo;t even think the refresh token
could change &amp;lsquo;cos it&amp;rsquo;s optional in the spec and Google doesn&amp;rsquo;t seem
to change it.  So they embedded a refresh process inside the https
communication flow and used the refresh token to generate a new
AccessToken, but didn&amp;rsquo;t expose the new tokens to the caller!&lt;/p&gt;

&lt;p&gt;Many of the solutions presented in that thread involve creating wrapper
types with callback functions so the new tokens can be persisted
transparently from the main code.&lt;/p&gt;

&lt;p&gt;I decided to use a wrapper function instead, since I was going to
build this type of abstraction anyway.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;func call_fitbit_api(url string) []byte {
        // Get the oauth2 config and token
        conf := fitbit_config()
        token := fitbit_token()

        client := conf.Client(context.Background(), token)
        response, err := client.Get(url)
        check_or_die(err)

        check_refresh_token(client)

        body, err := io.ReadAll(response.Body)
        check_or_die(err)

        return body
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And there&amp;rsquo;s a bit of magic where we delve into the &lt;code&gt;client&lt;/code&gt; structure to
find the current oauth2 token.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;func check_refresh_token(client *http.Client) {
        // There&#39;s gotta be a better way to get the new token!
        nt, err := client.Transport.(*oauth2.Transport).Source.Token()
        check_or_die(err)

        if nt.AccessToken != configuration.AccessToken ||
           nt.RefreshToken != configuration.RefreshToken ||
           nt.Expiry != configuration.Expiry {
                configuration.AccessToken = nt.AccessToken
                configuration.RefreshToken = nt.RefreshToken
                configuration.Expiry = nt.Expiry
                save_config()
                fmt.Fprintf(os.Stderr,&amp;quot;Token refreshed&amp;quot;)
           }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Digging so deep into a structure also smells a little, but at least it&amp;rsquo;s
using the documented endpoints and I can&amp;rsquo;t find a better way.  (If you know
of one, let me know in the comments, please!)&lt;/p&gt;

&lt;h2 id=&#34;final-code&#34;&gt;Final code&lt;/h2&gt;

&lt;p&gt;The final code is on &lt;a href=&#34;https://github.com/sweharris/go-fitbit-get&#34;&gt;github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Do note that this code doesn&amp;rsquo;t protect the token at rest; it just
writes it out in the clear to the filesystem.  This isn&amp;rsquo;t meant to be
enterprise secure levels of code (you&amp;rsquo;d encrypt using the enterprise tools,
persist in a store somewhere), but for my home use.&lt;/p&gt;

&lt;p&gt;Now my shell script can become a lot simpler:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;BASE=https://api.fitbit.com/1/user/-

get_activity()
{
  fitbit_get $BASE/activities/$1/date/$day/$day/$2/time/00:00/23:59.json | jq -r &#39;.&amp;quot;&#39;$3&#39;&amp;quot;.dataset[]|(.value|tostring)+&amp;quot;,&amp;quot;+.time&#39;  | less
}

case $1 in
   heart|&amp;quot;&amp;quot;) get_activity heart 1sec activities-heart-intraday ;;
        cal) get_activity calories 1min activities-calories-intraday ;;
          *) echo Get what...
esac
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;So this both impressed and scared me.&lt;/p&gt;

&lt;p&gt;It provided commented code that almost worked.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s the sort of code I might have hacked up 20 years ago (who am I kidding;
I &lt;em&gt;did&lt;/em&gt; hack up this sort of code 20 years ago!).  And it would work.  Well,
mostly; there&amp;rsquo;s a potential race condition in the original refresh method
depending on how it&amp;rsquo;s called; eg &lt;code&gt;token.Valid()&lt;/code&gt; could return true but a
second later the token expires so the &lt;code&gt;GET&lt;/code&gt; request would fail.&lt;/p&gt;

&lt;p&gt;But it&amp;rsquo;s &lt;em&gt;bad&lt;/em&gt; code.  It&amp;rsquo;s the sort of code that would worry me if it
made it into an enterprise code base.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not sure many AppSec tools would pick up on this either, since it&amp;rsquo;s
a code quality issue and not a code security issue.  I know there are
code quality tools out there, but there are arguments that these don&amp;rsquo;t belong
in AppSec but in AppDev.  I also don&amp;rsquo;t know if they would pick up on this;
the refresh code was OK as code when looking at it as a http client and
JSON parser; it was just the wrong approach to the problem.&lt;/p&gt;

&lt;p&gt;All this tells me that ChatGPT won&amp;rsquo;t replace good developers.  We need them
to apply the sniff test to determine if generated code is of a sufficient
quality and where the &lt;em&gt;approach&lt;/em&gt; taken by the generator is the right one.&lt;/p&gt;

&lt;p&gt;That takes skill and experience.&lt;/p&gt;

&lt;p&gt;I kinda wonder whether a programming copilot would have done better, but
I&amp;rsquo;m not sure.  This feels like a training data issue, and I couldn&amp;rsquo;t find
good answers through regular searching.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>VNC into an existing X desktop</title>
      <link>https://www.sweharris.org/post/2025-06-08-vnc-x-desktop/</link>
      <pubDate>Sun, 08 Jun 2025 14:57:13 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2025-06-08-vnc-x-desktop/</guid>
      <description>

&lt;p&gt;When I was using a Mac as my media center player I liked that you could
&amp;ldquo;remote desktop&amp;rdquo; into it; basically VNC and got the existing desktop.
This meant I could use my local keyboard and monitor to control the machine
that was 20ft away across the room from me, in the odd case where the command
line wasn&amp;rsquo;t sufficient.&lt;/p&gt;

&lt;p&gt;As MacOS went on these occurrences got more frequent&amp;hellip; as did the BROKENNESS
of the VNC server; I would frequently just get a black screen.  &lt;em&gt;sigh&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But I&amp;rsquo;ve migrated away from MacOS to a Debian Linux desktop.
I&amp;rsquo;m now using &lt;code&gt;mpd&lt;/code&gt; as my music player (and have written
&lt;a href=&#34;https://github.com/sweharris/go-mpd-music&#34;&gt;go-mpd-music&lt;/a&gt;
to give me a command line similar to what I was used to, and
&lt;a href=&#34;https://github.com/sweharris/go-mpd-flirc&#34;&gt;go-mpd-flirc&lt;/a&gt; to let me use
an IR remote.&lt;/p&gt;

&lt;p&gt;The problem was the remote desktop.&lt;/p&gt;

&lt;p&gt;This turns out to be a hard thing for me to google, so I&amp;rsquo;m writing this
up in the hopes it might help someone else.&lt;/p&gt;

&lt;h2 id=&#34;vncserver&#34;&gt;vncserver&lt;/h2&gt;

&lt;p&gt;On Unix if you run &lt;code&gt;vncserver&lt;/code&gt; then it will create a &lt;em&gt;new&lt;/em&gt; desktop that
you can VNC into.  This is normally a good thing &amp;lsquo;cos it lets multiple
people all connect to the same machine, have their own desktops that
don&amp;rsquo;t conflict.  You don&amp;rsquo;t even need a desktop X session running.&lt;/p&gt;

&lt;p&gt;But that&amp;rsquo;s not what I want.&lt;/p&gt;

&lt;h2 id=&#34;x2vnc&#34;&gt;x2vnc&lt;/h2&gt;

&lt;p&gt;Totally not what we want; this lets you move your mouse and keyboard off
the edge of the screen and it will translate the motion/presses into VNC
events sent to a remote VNC server.  In this way you can share your your
keyboard/mouse between a Linux machine and another (eg Windows, running a
VNC server).&lt;/p&gt;

&lt;h2 id=&#34;x0vncserver&#34;&gt;x0vncserver&lt;/h2&gt;

&lt;p&gt;This is part of the &lt;a href=&#34;https://github.com/TigerVNC/tigervnc&#34;&gt;TigerVNC&lt;/a&gt; package
which may do what I want, but the description &amp;ldquo;an inefficient VNC server which continuously polls any X&amp;rdquo; didn&amp;rsquo;t make me want to look further.&lt;/p&gt;

&lt;h2 id=&#34;tigervnc-xorg-extension&#34;&gt;tigervnc Xorg extension&lt;/h2&gt;

&lt;p&gt;Ah, now this is what I want.  It&amp;rsquo;s meant to be more efficient than
the normal &amp;ldquo;scraper&amp;rdquo; method and it&amp;rsquo;s an Xorg module so is loaded automatically
when the X server starts.&lt;/p&gt;

&lt;p&gt;Except it&amp;rsquo;s very poorly documented and it took me a while to find out
how to deal with it.&lt;/p&gt;

&lt;p&gt;In the end, on Debian, it turned out to be quite simple:&lt;/p&gt;

&lt;h3 id=&#34;1-install&#34;&gt;1. Install&lt;/h3&gt;

&lt;p&gt;The package is part of the Debian 12 repo, so we can simply install it.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo apt install tigervnc-xorg-extension
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;2-configure&#34;&gt;2. Configure.&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;/etc/X11/xorg.conf.d/10-vnc.conf&lt;/code&gt; with the following contents:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Section &amp;quot;Module&amp;quot;
  Load &amp;quot;vnc&amp;quot;
EndSection

Section &amp;quot;Screen&amp;quot;
  Identifier &amp;quot;Screen0&amp;quot;
  Option &amp;quot;UserPasswdVerifier&amp;quot; &amp;quot;VncAuth&amp;quot;
  Option &amp;quot;PasswordFile&amp;quot; &amp;quot;/etc/tigervnc/passwd&amp;quot;
EndSection
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;3-create-a-password&#34;&gt;3. Create a password.&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;sudo vncpasswd /etc/tigervnc/passwd
Password:
Verify:
Would you like to enter a view-only password (y/n)? n
A view-only password is not used
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;4-restart-the-x-server&#34;&gt;4. Restart the X server&lt;/h3&gt;

&lt;p&gt;Probably easiest to reboot :-)&lt;/p&gt;

&lt;h3 id=&#34;5-check&#34;&gt;5. Check&lt;/h3&gt;

&lt;p&gt;After the reboot you can verify that the server is listening:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo netstat -anp | grep 5900
tcp        0      0 0.0.0.0:5900            0.0.0.0:*               LISTEN      1016/Xorg
tcp6       0      0 :::5900                 :::*                    LISTEN      1016/Xorg
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yup, port 5900 is the default VNC port!&lt;/p&gt;

&lt;p&gt;And that&amp;rsquo;s it.  You can now &lt;code&gt;vncviewer yourmachine:&lt;/code&gt; and the native desktop
will display.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;This might have been easier if I knew the magic words to search for,
but search results were full of entries around how to start a new X
session under VNC, how to manage the window manager inside that session
and the like.&lt;/p&gt;

&lt;p&gt;It was only luck that found me a reference to this Xorg plugin!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What do I recommend?  Generalist or specialist?</title>
      <link>https://www.sweharris.org/post/2025-05-07-generalist-specialist/</link>
      <pubDate>Wed, 07 May 2025 20:19:58 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2025-05-07-generalist-specialist/</guid>
      <description>

&lt;p&gt;Back in &lt;a href=&#34;https://www.sweharris.org/post/2018-10-08-career/&#34;&gt;2018&lt;/a&gt; I was asked about whether someone
should become a Unix specialist.&lt;/p&gt;

&lt;p&gt;In a similar vein, I saw a question on LinkedIn that asked whether someone
should become a generalist or a front-end specialist or a back-end specialist.&lt;/p&gt;

&lt;p&gt;Of course I had opinions :-)  This is an extended take on my quick reply
to the LinkedIn question.&lt;/p&gt;

&lt;h2 id=&#34;let-s-scope-this-a-bit-better&#34;&gt;Let&amp;rsquo;s scope this a bit better&lt;/h2&gt;

&lt;p&gt;I think, first, we need to think slightly wider than &amp;ldquo;front/backend&amp;rdquo;.
A true generalist is more of a &amp;ldquo;full stack&amp;rdquo; person.  By this I don&amp;rsquo;t mean
they need to have knowledge of VLSI design, but knowing about CPU cache
coherency might be useful.  They don&amp;rsquo;t need to know about datacenter
design, but being aware that some methods are less power efficient than
others can help.&lt;/p&gt;

&lt;p&gt;Definitely they should have knowledge from the platform layer up.  So if
you&amp;rsquo;re deploying to a Unix machine, having some Unix sysadmin skills would
be useful; if you&amp;rsquo;re deploying to a k8s cluster then having some skills
there helps.  They don&amp;rsquo;t need to know how to configure a Cisco switch, but
knowing TCP is a definite benefit.  Being able to create database schemas,
knowing when indexes are needed, monitor performance&amp;hellip;&lt;/p&gt;

&lt;p&gt;All these things are aspects a &amp;ldquo;full stack&amp;rdquo; developer should have.&lt;/p&gt;

&lt;h2 id=&#34;generalists&#34;&gt;Generalists&lt;/h2&gt;

&lt;p&gt;In my experience, I&amp;rsquo;ve found these people to be very valuable as part
of a team. They may not be the best front end person nor the best back
end person, but they know a bit of both. A good &amp;ldquo;full stack&amp;rdquo; person can
talk to both those specialists, and the sysadmin, and the DBA and the
network team and the firewall team and more. And, importantly, get those
people talking to each other.&lt;/p&gt;

&lt;p&gt;Because they have skills that overlap all these areas they can become
team leads. They also may have a better overview of the project because
they see how components fit together and how to do end-to-end analysis
of data flow.  Later may even become architects.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve been that generalist.  My first job kinda required it (managing
Unix systems, networking, vendor relations, telex systems, telecoms&amp;hellip;).
Although I was primarily a Unix person I was also an old school code
hacker; I wrote code in C, I wrote a complete shipboard general ledger
system in TurboPascal, later I wrote the first commercial Java app sold
in the UK (according to Sun Microsystems at the time, anyway!).  Then later
still an Oracle DBA, Window NT admin, Lotus Notes admin, web developer&amp;hellip;&lt;/p&gt;

&lt;p&gt;Having experience of all these things made me a more valuable person;
for example, as a security architect I could see how things fitted and
worked together; I could see the gaps and provide advice.  I doubt I would
even have reached that position if I had remained a Unix sysadmin.&lt;/p&gt;

&lt;h2 id=&#34;we-need-specialists&#34;&gt;We need specialists&lt;/h2&gt;

&lt;p&gt;But we need specialists.  We&amp;rsquo;ve seen what happens when a developer tries to
be a DBA (indeed one of the curses of the web is that it encourages this
mess).  The results are not as good, or sometimes miss some important
aspect that a specialist would pick up.&lt;/p&gt;

&lt;p&gt;So an employer needs both generalists and specialists on their team if
they want the best outcome.  They &lt;em&gt;could&lt;/em&gt; get by with just generalists
(less people to employee so cheaper), but the result may not be as good.
Similarly, without the generalist the higher level architecture may suffer.&lt;/p&gt;

&lt;p&gt;As time went on the technologies change; the DBA skills I learned for
Oracle 8 still mostly apply to the latest versions, but there&amp;rsquo;s a lot
more stuff that I&amp;rsquo;m not aware of.  So, for example, when evaluating the
security of ExaCS backups I relied on our senior DBAs to help fill in my
knowledge gaps.&lt;/p&gt;

&lt;p&gt;Similarly when looking at replacement Unix authentication tools I
relied on senior platform engineers to do the hard design work for the
infrastructure deployments.  The generalist (me) saw how things should
fit together (e.g. needing to enforce configurations, needing to integrate
with the enterprise password vault, needing identity governance) and got
all those teams working together; the specialists in each area worked
out how to do the implementations.&lt;/p&gt;

&lt;p&gt;A homelab could get me up to speed on some the technologies (especially
if they&amp;rsquo;re free!) but it only got me so far.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s a methodology used by some to try and classify people; an I-shaped
person is a specialist; they have deep knowledge in a specific discipline.
A &lt;a href=&#34;https://en.wikipedia.org/wiki/T-shaped_skills&#34;&gt;T-shaped&lt;/a&gt; person has
a broader knowledge base but with a focus on one specific discipline.
And then there&amp;rsquo;s M type people, who are multi-discipline.&lt;/p&gt;

&lt;p&gt;I like learning new things and also getting people to talk to each
other (&amp;ldquo;I don&amp;rsquo;t know that answer but you should talk to Fred Bloggs; he
runs that stuff and will know the answer&amp;rdquo;).  I&amp;rsquo;m an M-shaped person.&lt;/p&gt;

&lt;p&gt;But I feel it&amp;rsquo;s essential to have I and T-shaped people in an organisation.&lt;/p&gt;

&lt;p&gt;If I was starting over I think I&amp;rsquo;d follow the generalist path again.&lt;/p&gt;

&lt;p&gt;But not everyone is suited for it, especially if you want to be &amp;ldquo;the best&amp;rdquo;
at something. A generalist can be good at lots of things but there will
always be people better than you in each of those areas.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Decreasing social media footprint</title>
      <link>https://www.sweharris.org/post/2025-03-25-social-media/</link>
      <pubDate>Tue, 25 Mar 2025 09:47:25 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2025-03-25-social-media/</guid>
      <description>

&lt;h2 id=&#34;leaving-twitter&#34;&gt;Leaving twitter&lt;/h2&gt;

&lt;p&gt;And my social media footprint shrinks; I&amp;rsquo;ve closed my twitter account,
mostly &amp;lsquo;cos there&amp;rsquo;s very little left there to read.  Yesterday there
were only 5 or 6 new posts on the &amp;ldquo;Following&amp;rdquo; feed (I never used the
algorithmic feed); 90% of the likes my posts got were bots.   It really
was the text equivalent of a post-apocalyptic wasteland with howling
winds.&lt;/p&gt;

&lt;p&gt;I had always been careful about what accounts I followed, so the extreme
views that are reportedly on that platform rarely impinged on my
consciousness; on the occasions I did click on a tweet it became clear
that many of the replies were bots and misinformation or just plain hatred
(&amp;ldquo;never read the comments!&amp;rdquo;), so I rarely did that.&lt;/p&gt;

&lt;h2 id=&#34;social-media-history&#34;&gt;Social media history&lt;/h2&gt;

&lt;p&gt;I guess I&amp;rsquo;ve been on some form of social media (before it was
ever called that) since 1987, when I gained access to Usenet,
mailing lists, and (heh) online JANet BBS systems (&lt;a href=&#34;http://software.bbsdocumentary.com/UNIX/GENERIC/UNAXCESS/&#34;&gt;Bradford
UNaXcess&lt;/a&gt;,
anyone?).&lt;/p&gt;

&lt;p&gt;I remember the rush to LiveJournal when that started and then the mass
exodus when it got sold to Russia.  LJ was great in that it was a central
place where pretty much everyone posted.&lt;/p&gt;

&lt;p&gt;With the exodus came fragmentation; some people went to Dreamwidth, some
to Facebook, some to their own blogs.&lt;/p&gt;

&lt;p&gt;And that&amp;rsquo;s where I started to get tired of trying to keep up with people;
some accounts I used to read on LJ fell off my radar (especially those
who went to Facebook; I was never on that platform, never felt the need)
and eventually became forgotten in the mists of time.&lt;/p&gt;

&lt;p&gt;Twitter had its own &amp;ldquo;everyone there&amp;rdquo; vibe, but now it&amp;rsquo;s tumbleweed city
with everyone scattered to diverse platforms.&lt;/p&gt;

&lt;p&gt;And I don&amp;rsquo;t have the enthusiasm to start again on a new platform and
then hunt down all the people I used to follow and&amp;hellip;&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s just not worth the effort!&lt;/p&gt;

&lt;h2 id=&#34;where-am-i-now&#34;&gt;Where am I now?&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;m trying to think what social media accounts I have
left.  Hmmm&amp;hellip;  &lt;a href=&#34;https://sweh.dreamwidth.org&#34;&gt;Dreamwidth&lt;/a&gt;
(which is pretty much just there to act as an RSS reader),
&lt;a href=&#34;https://www.linkedin.com/in/sweharris/&#34;&gt;LinkedIn&lt;/a&gt;,
and&amp;hellip; err.  Does &lt;a href=&#34;https://www.reddit.com/user/sweharris/&#34;&gt;Reddit&lt;/a&gt; or
&lt;a href=&#34;https://unix.stackexchange.com/users/168757/stephen-harris&#34;&gt;Unix StackExchange&lt;/a&gt;
count?&lt;/p&gt;

&lt;p&gt;And there&amp;rsquo;s this blog, of course, but that&amp;rsquo;s not really social media.&lt;/p&gt;

&lt;h2 id=&#34;how-to-contact-me&#34;&gt;How to contact me&lt;/h2&gt;

&lt;p&gt;For the few people who used to use twitter DMs to contact me, you
probably have my mobile number and can text me (I don&amp;rsquo;t have encrypted
&lt;a href=&#34;https://www.sweharris.org/post/2025-02-25-why-no-encryption/&#34;&gt;messenger apps&lt;/a&gt;)&amp;hellip; or you can
find my email address on the &lt;a href=&#34;https://www.sweharris.org/about/&#34;&gt;About Me&lt;/a&gt; page!&lt;/p&gt;

&lt;p&gt;So after almost 38 years of online activity my presence is shrinking and
is now mostly this poorly maintained blog!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Five Years of COVID</title>
      <link>https://www.sweharris.org/post/2025-03-16-five-years-covid/</link>
      <pubDate>Sun, 16 Mar 2025 20:29:53 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2025-03-16-five-years-covid/</guid>
      <description>&lt;p&gt;So 5 years ago today was the day I told my boss I wasn&amp;rsquo;t going to come into
the office for a while, and would work from home.  Because I didn&amp;rsquo;t feel
comfortable.&lt;/p&gt;

&lt;p&gt;The company had made a plan; they were going to split the office into two
groups who would come in alternate weeks.  The idea was to reduce occupancy.
However I&amp;rsquo;d been seeing more and more in the news how bad COVID could be and
I didn&amp;rsquo;t want to risk being on the train for an hour each way as well as
being in the office.  After all I&amp;rsquo;d caught colds before and I &lt;em&gt;knew&lt;/em&gt;
Americans would come into the office sick (that&amp;rsquo;s a rant for another day).&lt;/p&gt;

&lt;p&gt;All of my direct team was in different locations to me (Texas, California,
North Caroline, Colorado, Georgia); it was really only a few secondary
teams that I met in person (in particular the AppSec team; their manager
tried to get onto the same weekly schedule as me &amp;lsquo;cos it gave us the
opportunity for informal chats and collaboration).  My access was via VDI
and I had sufficient equipment at home, so my boss just said &amp;ldquo;OK&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Now I didn&amp;rsquo;t expect this to be a long term thing; a few weeks, or a month or
two.  Then we&amp;rsquo;d all be back in the office.  So I didn&amp;rsquo;t take anything home
with me; personal stuff was still in the office.&lt;/p&gt;

&lt;p&gt;Shortly afterwards I was told that I&amp;rsquo;d just been in close contact with a
person who had COVID so I was meant to quarantine to avoid passing it on.
So I felt my decision to avoid the office was the right one.&lt;/p&gt;

&lt;p&gt;A few weeks later the company made most people work from home (there were
some jobs that were considered essential and had to be done from the office,
such as the print facilities and warehouse and datacenters, but most of us
were meant to work from home.  More justification for my decision.&lt;/p&gt;

&lt;p&gt;I wondered if I should get a dog to keep me company, but still thought
that this was just a temporary situation; it wouldn&amp;rsquo;t be fair on the dog
to get used to me being at home and then be left alone all day when I
finally returned to the office.&lt;/p&gt;

&lt;p&gt;And then the company decided to close that location down.  They were going
to consolidate their New York/New Jersey locations into a new state of the
art campus.  On a town hall meeting about this they said they didn&amp;rsquo;t have
any location in mind at present, but would make sure it was reachable by
public transit because they knew people in this area generally commuted
that way (especially those who worked in Manhattan and Jersey City).&lt;/p&gt;

&lt;p&gt;Get a dog?  Nah&amp;hellip; I still thought I&amp;rsquo;d be back in office; maybe not
immediately but within a year.&lt;/p&gt;

&lt;p&gt;I rearranged my house so that the PC I was working on was no longer in
my basement but moved up to the spare bedroom I was using as a library
(bookshelves on 3 walls; table with PC on the fourth).&lt;/p&gt;

&lt;p&gt;Then the new location was announced; and it was most definitely not
public transit friendly.  From my house it would need two trains and a bus
and a lot of walking; maybe 2.5 hours each way.  Hmm.  No way was I going
to commute there each day!&lt;/p&gt;

&lt;p&gt;It took a while (longer than planned) for the new office to be ready,
and eventually the &amp;ldquo;return of office&amp;rdquo; calls went out.  I explained
the problem to my boss (well, I&amp;rsquo;d already done this previously, so he
was already on the case), who was accommodating and his boss (the CISO)
was OK with it, so I became a permanent work from home.&lt;/p&gt;

&lt;p&gt;I switched from VDI (which had been really glitching; it&amp;rsquo;s hard to be on
a video meeting when your audio doesn&amp;rsquo;t work!) to a work laptop.  And,
honestly, it was so so much better.  I knew our VDI was under-powered and
over provisioned, but this was like night and day.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/2021-04-29-home-office.jpg&#34;&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/2021-04-29-home-office-small.jpg&#34; alt=&#34;Cramped&#34;&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;As you can see, this was a little cramped, but it worked.&lt;/p&gt;

&lt;p&gt;Oh, and COVID!  Yes!  I got vaccinated!  Because I&amp;rsquo;m considered obese, and
thus at higher risk, I was able to get the vaccine.  Spent a fair amount of
time reloading reloading reloading websites to find somewhere with an open
slot (&amp;ldquo;7 slots open! Sorry, all gone&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;I bought a bigger desk and two new monitors and a monitor arm, a better
light and I got a lot more space.  This was quite a comfortable work space.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/2021-06-22-new-home-office.jpg&#34;&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/2021-06-22-new-home-office-small.jpg&#34; alt=&#34;Space&#34;&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;And that&amp;rsquo;s kinda how I worked for the next 3 years.  I got sent a second
laptop (with Windows 11) for testing the build; I got sent a Macbook for
testing (I&amp;rsquo;m not a security tester; I just got a reputation for breaking
things so I would get sent this stuff) which made things complicated, but
this worked.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not much of a people person (very introverted) but I did miss the
occasional chat with people in person, or going down the pub.  But there
was no way I could get to the new office.&lt;/p&gt;

&lt;p&gt;I was fortunate; I had the space and I lived alone so I could set aside a
room for work, and close the door at the end of work day; this meant I could
keep work/life separation, which is vital for mental health.&lt;/p&gt;

&lt;p&gt;And, eventually, after 3 more years of this (so 4 years of WFH) I
&lt;a href=&#34;https://www.sweharris.org/post/2024-04-07-still-dunno/&#34;&gt;retired&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And now it&amp;rsquo;s 5 years in.  We&amp;rsquo;re no longer in a pandemic; COVID is &lt;em&gt;endemic&lt;/em&gt;.
This means it&amp;rsquo;s likely to be with us forever.  It&amp;rsquo;s hard to know how many
people are still dying of it, but &lt;a href=&#34;https://en.wikipedia.org/wiki/COVID-19_pandemic_in_the_United_States&#34;&gt;wikipedia&lt;/a&gt; seems to think that 41,000 people died
of it last year.  That&amp;rsquo;s a lot; probably more than those who died in car
crashes.&lt;/p&gt;

&lt;p&gt;So I still get vaccinated every year.  I don&amp;rsquo;t wear masks as often as I used
to because most places have good ventilation, but I do wear them on trains
or subways, or at the airport.&lt;/p&gt;

&lt;p&gt;I haven&amp;rsquo;t had COVID yet, but a lot of that is likely because I am mostly
at home, and don&amp;rsquo;t go to crowded places very often.  I&amp;rsquo;m almost (but
not quite) a hermit!&lt;/p&gt;

&lt;p&gt;I never did get that dog; maybe I should have!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Why I don&#39;t use encrypted messenger apps</title>
      <link>https://www.sweharris.org/post/2025-02-25-why-no-encryption/</link>
      <pubDate>Tue, 25 Feb 2025 08:40:44 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2025-02-25-why-no-encryption/</guid>
      <description>

&lt;h2 id=&#34;secure-messaging&#34;&gt;Secure messaging&lt;/h2&gt;

&lt;p&gt;A common question I get asked is &amp;ldquo;what secure messaging app do you use?&amp;rdquo;
and the answer of &amp;ldquo;none&amp;rdquo; gets some surprised looks; how can I be in cyber
security if I don&amp;rsquo;t use secure messaging?&lt;/p&gt;

&lt;p&gt;The answer is &amp;ldquo;convenience&amp;rdquo;, with a side of &amp;ldquo;risk analysis&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Back when Signal (on Android) did both secure messaging and SMS in the same
app then I used this.  When they removed this (because people might send
insecure messages by mistake) I stopped using it.  It&amp;rsquo;s inconvenient to have
to wonder &amp;ldquo;Does Fred have Signal?  Or WhatsApp?  Or is it just SMS?&amp;rdquo;.  I&amp;rsquo;ll
just use the lowest common denominator.&lt;/p&gt;

&lt;p&gt;Could my messages be intercepted?  Sure!  Am I worried?  Not really.  If the
Chinese (or the US!) want to know that I&amp;rsquo;m planning a pub trip then good for
them.&lt;/p&gt;

&lt;p&gt;Same for email; I&amp;rsquo;m not using encrypted/signed email (PGP, S/MIME,
whatever).  Yes, my mail servers can do TLS but that&amp;rsquo;s &amp;ldquo;opportunistic&amp;rdquo;
and they&amp;rsquo;ll happily fall back to plain text.&lt;/p&gt;

&lt;p&gt;But.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not a high value target; no one is going to go to the effort of grabbing
my stuff.  If it gets caught up in a high volume data theft (e.g. theft from
a telco) then &lt;em&gt;shrug&lt;/em&gt; nothing of value will have been taken.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s a slight caveat here; Google&amp;rsquo;s &amp;ldquo;Messages&amp;rdquo; app &lt;em&gt;can&lt;/em&gt; do
&lt;a href=&#34;https://support.google.com/messages/answer/10252671&#34;&gt;end-to-end encryption!&lt;/a&gt;
When using RCS and configured &lt;em&gt;and&lt;/em&gt; if the other party is also
using &amp;ldquo;Messages&amp;rdquo; and is properly configured then the conversation is encrypted.
At the moment it&amp;rsquo;s limited to Android users using Messages, but since Apple
is now embracing RCS maybe we&amp;rsquo;ll also see some cross-platform support in the
future?&lt;/p&gt;

&lt;h2 id=&#34;vpn-on-my-phone&#34;&gt;VPN on my phone&lt;/h2&gt;

&lt;p&gt;Nope, don&amp;rsquo;t use that either.  If I&amp;rsquo;m in Starbucks my phone is using mobile
data directly with no VPN to protect me.  But I&amp;rsquo;m not concerned because
pretty much every site my phone talks to is TLS protected.  This gives
encryption and a
&lt;a href=&#34;https://www.sweharris.org/post/2017-06-11-webcerts/&#34;&gt;level of identify verification&lt;/a&gt;
(&amp;ldquo;yes, this &lt;em&gt;is&lt;/em&gt; sweharris.com; the certificate says so!&amp;ldquo;).&lt;/p&gt;

&lt;p&gt;I don&amp;rsquo;t normally have WiFi turned on when I&amp;rsquo;m out of my house (automated
based on location) but even if I did and connected to a rogue hotspot then
I&amp;rsquo;m not too concerned; the traffic is still protected through TLS.  Sure
the bad guy might see my phone make a connection to my bank, or to my home
network; they might be able to see my DNS queries.  So from this meta data
they might be able to work up some sort of profile on me to use in social
engineering, but my data is secure.&lt;/p&gt;

&lt;p&gt;Again a minor caveat; I do have a VPN I run myself, but that&amp;rsquo;s normally off;
it&amp;rsquo;s to let me access my own IMAP server if I&amp;rsquo;m out of home and need access
to my email urgently.  Mostly I don&amp;rsquo;t need it.  And I don&amp;rsquo;t default-route
via the VPN, just my home subnet, so everything else would still go out
the normal way.&lt;/p&gt;

&lt;h2 id=&#34;vpn-at-home&#34;&gt;VPN at home&lt;/h2&gt;

&lt;p&gt;Why would I?   Again, most things are TLS protected.  I run my own DNS servers (ISC Bind) so I don&amp;rsquo;t hit my ISPs servers for that.  Sure they could sniff my
DNS traffic or they could see the TLS headers and so learn that I spend
far too much time looking at pr0n.  But so what?&lt;/p&gt;

&lt;p&gt;Yes, Verizon would release my details to the government on request, but then
so would most VPN providers.  I&amp;rsquo;m not gaining any security, just moving the
risk around.&lt;/p&gt;

&lt;p&gt;And getting worse network performance as a result.&lt;/p&gt;

&lt;p&gt;There are use cases for VPNs (especially if hoisting the Jolly Roger) but
security isn&amp;rsquo;t one of them.  So, no, I don&amp;rsquo;t use a public VPN.&lt;/p&gt;

&lt;p&gt;(As above, I do have a private VPN I run myself that I use to allow
services out of my home to reach into my private network)&lt;/p&gt;

&lt;h2 id=&#34;anti-virus&#34;&gt;Anti Virus&lt;/h2&gt;

&lt;p&gt;I do now have a Windows machine; I use it for gaming.  But the only protection
on it is the built in Microsoft Defender product.  I&amp;rsquo;m not hitting warez
sites, downloading dodgy software; I don&amp;rsquo;t even have Office products installed
so no Word Macro viruses here!  I don&amp;rsquo;t read email on this machine (I do that
on Linux using a terminal client, &amp;ldquo;mutt&amp;rdquo;).  Basically the risk vectors for
attacking and infecting this machine are very very small.  So Defender is
good enough for me.  Honestly, it&amp;rsquo;s probably good enough for most individuals.&lt;/p&gt;

&lt;h2 id=&#34;alexa-and-smart-home-stuff&#34;&gt;Alexa and smart home stuff&lt;/h2&gt;

&lt;p&gt;Yes, I&amp;rsquo;ve got spy bots in pretty much every room in my house, even in my main
bathroom (I use it for morning news from NPR and BBC, and to play music while
I&amp;rsquo;m showering).&lt;/p&gt;

&lt;p&gt;No, I&amp;rsquo;m not concerned about Bezos &lt;a href=&#34;https://www.sweharris.org/post/2017-01-02-always-listening/&#34;&gt;listening in on me&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have a lot of &lt;a href=&#34;https://www.sweharris.org/post/2021-08-08-home-automation/&#34;&gt;home automation&lt;/a&gt; and having
voice control over them is nice.  My MQTT server is not password protected,
but you have to be on my LAN or IoT networks to see it (guestnet can&amp;rsquo;t).&lt;/p&gt;

&lt;h2 id=&#34;a-rant&#34;&gt;A rant&lt;/h2&gt;

&lt;p&gt;And here is where I&amp;rsquo;m gonna rant about mobile email; because of the form
factor it&amp;rsquo;s very hard to get some of the information needed to determine
if an email is legitimate; it may not be easy to tell &lt;code&gt;Fred Bloggs &amp;lt;myfriend@their.email&amp;gt;&lt;/code&gt; from &lt;code&gt;Fred Bloggs &amp;lt;badguy@evil.badguy&amp;gt;&lt;/code&gt; on a mobile email app;
they both show as &amp;ldquo;Fred Bloggs&amp;rdquo;.  Grump!  And a similar rant for embedded
browsers in chat apps; they may not show URLs!&lt;/p&gt;

&lt;p&gt;So we need to be very aware of attacks on the human aspect; don&amp;rsquo;t
open random attachments, even from friends.  Don&amp;rsquo;t enter your password
into a site you&amp;rsquo;ve reached from a link in a chat message.  And so on.
Technology like secure messaging or VPNs won&amp;rsquo;t protect you from that
sort of stuff, anyway!&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Most of the things I don&amp;rsquo;t do are because of risk evaluation and what I
consider valuable.  Of course if I was negotiating a multi-billion dollar
deal then I&amp;rsquo;d want to do it securely, but &amp;ldquo;wanna go down the pub tonight?&amp;rdquo;&amp;hellip;
not so much.   If I was accessing corporate resources then a VPN or Zero
Trust tunnel or similar would be necessary.  But to access my bank account?
TLS is good enough.&lt;/p&gt;

&lt;p&gt;Everyone needs to look at their personal circumstances and decide what level
of protection they need.&lt;/p&gt;

&lt;p&gt;I honestly think that, for most individuals, the out-of-the-box technology
protections are now pretty good.  The bigger risks are &amp;ldquo;human factor&amp;rdquo; related,
such as phishing or scams.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Stop thinking of privilege in technical terms</title>
      <link>https://www.sweharris.org/post/2025-01-24-business-privilege/</link>
      <pubDate>Fri, 24 Jan 2025 09:14:47 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2025-01-24-business-privilege/</guid>
      <description>

&lt;p&gt;I recently saw a posting on LinkedIn that said something like &amp;ldquo;with zero
trust we can consider all access as privileged access&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;While this could be considered true, I also made the same argument 15+ years
ago before zero trust was a thing people cared about; my argument was &amp;ldquo;if I
can login to a server then I can run commands, impact applications (eg chew up
CPU), fork bomb, etc; surely that means &lt;em&gt;all&lt;/em&gt; access is privileged&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Now while that is true enough, it&amp;rsquo;s not necessarily a &lt;em&gt;helpful&lt;/em&gt; stance.
The term &amp;ldquo;privileged access&amp;rdquo; has a lot of connotations, especially in regulated
industries where auditors want you to have strong controls in place.&lt;/p&gt;

&lt;p&gt;After all, with zero trust in place your personal access your
email is something that&amp;rsquo;s evaluated and permissions need to be in place.
We don&amp;rsquo;t always consider this to be privileged.&lt;/p&gt;

&lt;h2 id=&#34;technology-view&#34;&gt;Technology view&lt;/h2&gt;

&lt;p&gt;So businesses may next start thinking about &lt;em&gt;how&lt;/em&gt; privileged access may
work.&lt;/p&gt;

&lt;p&gt;On a Unix machine having the ability to do things as &lt;code&gt;root&lt;/code&gt; is normally the
first place we end up.  If the company is smart they&amp;rsquo;ll use something like
&lt;code&gt;sudo&lt;/code&gt; (or equivalent) to provide some finer grained control.  Users log in
with a low privileges and then use these tools to escalate their privileges;
a user that can do this is a privileged user.  And then the control expands
to cover the &lt;code&gt;oracle&lt;/code&gt; account, the service/functional account used to run
your app, and so on.&lt;/p&gt;

&lt;p&gt;On Windows we might deploy a privileged escalation tool to do similar to what
Unix does, or we might have &amp;ldquo;admin&amp;rdquo; accounts in a privileged group and put
those passwords in a controlled vault.  On Oracle we might do similar with
DBA privileges.&lt;/p&gt;

&lt;p&gt;But in all of these solutions we&amp;rsquo;re looking at this from a technology
perspective; if the platform considers activity privileged then we classify
access to this as privileged.&lt;/p&gt;

&lt;h2 id=&#34;weakness-of-this&#34;&gt;Weakness of this&lt;/h2&gt;

&lt;p&gt;The problem with the technology view is that it brings a lot of people into
scope for stricter controls (e.g. more frequent recertification, enhanced
activity oversight) than is necessary.  It also frequently leads to &amp;ldquo;laziness&amp;rdquo;;
oh if I&amp;rsquo;ve got to jump through these hoops then I might as well just do &lt;code&gt;sudo su&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A simple example is from Solaris; on this platform (at least Solaris 8 and
before), &lt;code&gt;ifconfig -a&lt;/code&gt; &lt;em&gt;will not&lt;/em&gt; show the MAC addresses of the interfaces;
you need to be &lt;code&gt;root&lt;/code&gt; to see that information.  So now if you grant someone
&lt;code&gt;sudo ifconfig -a&lt;/code&gt; (being careful to ensure that&amp;rsquo;s all they can do!) you&amp;rsquo;ve
granted someone a &lt;em&gt;technology privilege&lt;/em&gt;, but are they really a privileged
user?&lt;/p&gt;

&lt;p&gt;Another example might be the &lt;code&gt;df&lt;/code&gt; command; if a mount point is hidden then
the disk may not show up in the output, but if run as &lt;code&gt;root&lt;/code&gt; it will.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% ls -ld /tmp/dir1
drwx------ 3 root root 4096 Aug 26 15:42 /tmp/dir1

% df | grep dir1

% sudo df | grep dir1
/dev/shm          249720       0    249720   0% /tmp/dir1/mountpoint
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Is this really privileged access?  Knowledge that the mountpoint exists
may be exposed elsewhere (eg &lt;code&gt;/proc/mounts&lt;/code&gt;); we really only need elevated
privileges because of how &lt;code&gt;df&lt;/code&gt; works (it can&amp;rsquo;t do a &lt;code&gt;stat()&lt;/code&gt; on the mountpoint
because the parent directory doesn&amp;rsquo;t allow the user access).&lt;/p&gt;

&lt;h2 id=&#34;business-privilege&#34;&gt;Business privilege&lt;/h2&gt;

&lt;p&gt;So let&amp;rsquo;s look at this from a business perspective, instead.&lt;/p&gt;

&lt;p&gt;The goal of all these controls is to provide the CIA triad; confidentiality,
integrity, availability.&lt;/p&gt;

&lt;p&gt;We need to evaluate the risk of activities under this umbrella, and what
is considered an unacceptable risk to one business may not be one to another.&lt;/p&gt;

&lt;p&gt;We might decide that &lt;code&gt;sudo ifconfig&lt;/code&gt; is privileged because you can make changes
(e.g. change IP address) but &lt;code&gt;sudo ifconfig -a&lt;/code&gt; is unprivileged because it&amp;rsquo;s
not exposing sensitive data.  This is a business decision.&lt;/p&gt;

&lt;p&gt;So now our definition of privilege can be rewritten in business terms;
perhaps something like &amp;ldquo;activity that exposes or modifies sensitive data,
or impact the running of the business&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;OK, that&amp;rsquo;s pretty weak but it&amp;rsquo;s a starting point; a customer can access
their own data (eg bank transactions) but that&amp;rsquo;s not considered privileged.
However a bank teller can access multiple people&amp;rsquo;s transactions and so is
privileged.&lt;/p&gt;

&lt;p&gt;So this definition can (and should!) be refined.  This is potentially hard.&lt;/p&gt;

&lt;p&gt;But it&amp;rsquo;s important to note that the way we&amp;rsquo;re defining this isn&amp;rsquo;t in
technology terms, it&amp;rsquo;s in business terms.&lt;/p&gt;

&lt;p&gt;Now we can look at access rules and determine if they&amp;rsquo;re &lt;em&gt;business&lt;/em&gt; privileged
or not.  We can take a risk based approach.&lt;/p&gt;

&lt;p&gt;Of course this does require help from the platforms we&amp;rsquo;re trying to control;
the finer grained the controls can be, the better we can limit access, and
the fewer people need to be considered &amp;ldquo;privileged&amp;rdquo;.&lt;/p&gt;

&lt;h2 id=&#34;entitlements-vs-privilege&#34;&gt;Entitlements vs privilege&lt;/h2&gt;

&lt;p&gt;In order to advance the discussion we need to change the terminology a
little as well.  In the opening statement (&amp;ldquo;all access may be considered
privileged&amp;rdquo;) we&amp;rsquo;re really conflating &lt;em&gt;entitlement&lt;/em&gt; with privilege.&lt;/p&gt;

&lt;p&gt;An entitlement is the ability to do something (read your email, get your
payslip from Workday, login to an application&amp;hellip;)&lt;/p&gt;

&lt;p&gt;A collection of entitlements may be consolidated into a role.  e.g.
&amp;ldquo;Unix system admin&amp;rdquo; may be a role that has entitlements of &amp;ldquo;can login as
themselves&amp;rdquo;, &amp;ldquo;can &lt;code&gt;sudo df&lt;/code&gt;&amp;rdquo; and similar.   People will have multiple roles,
and some of what are sometimes considered &amp;ldquo;birthright&amp;rdquo;; e.g. as an &amp;ldquo;Employee&amp;rdquo;
you automatically are granted &amp;ldquo;Can read email&amp;rdquo;, &amp;ldquo;can get their payslip&amp;rdquo;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that these are &lt;em&gt;business roles&lt;/em&gt; and not &lt;em&gt;technology roles&lt;/em&gt;.  Windows
has roles exposed as security groups (eg &amp;ldquo;Backup Operators&amp;rdquo;) which are
collections of entitlements (eg &amp;ldquo;Backup files and directories&amp;rdquo;, &amp;ldquo;Restore
files and directories&amp;rdquo;).  It&amp;rsquo;s important not to consider these as roles
from a business perspective; this is just a group of entitlements.&lt;br /&gt;
Note that entitlements and roles may be constrained in scope, and the
larger the company the more likely this will be; e.g. &amp;ldquo;Unix system admins in
North America&amp;rdquo; can &lt;em&gt;not&lt;/em&gt; login to EMEA systems.  This is why it&amp;rsquo;s important
to distinguish business roles from technology roles even if they have the
same name.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;A role may be considered privileged if it allows members of the role to
perform a business privileged action; &amp;ldquo;Bank teller&amp;rdquo; is a privileged role
because members can see transactions for multiple people.&lt;/p&gt;

&lt;p&gt;Finally a person is privileged if they are a member of a privileged role
&lt;em&gt;or&lt;/em&gt; if they have a business privileged action directly assigned to them.&lt;/p&gt;

&lt;p&gt;So now we could validly argue that the first statement isn&amp;rsquo;t really accurate;
not all entitlements are privileged so not all access is privileged.&lt;/p&gt;

&lt;p&gt;This all comes back to the definition of &amp;ldquo;privilege&amp;rdquo; as a business function
not a technology function.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;This is hard work.&lt;/p&gt;

&lt;p&gt;Defining and maintaining these roles isn&amp;rsquo;t easy; evaluating every entitlement
to determine if it&amp;rsquo;s business privileged or not (or if the business accepts
the risk of considering this non-privileged), whether the technology is
capable of creating sufficient fine grained access is hard and time consuming.
Role management, in particular, is very hard to get right.&lt;/p&gt;

&lt;p&gt;Even if you don&amp;rsquo;t define privilege along business lines, thinking in
business terms (business roles, instead of technology roles) can bring
benefits; you gain some ability to provide minimum necessary access to
systems, you can reduce audit overhead, access requests become simpler,
access is more normalized and can be automated easier.&lt;/p&gt;

&lt;p&gt;These benefits also apply to zero trust environments (indeed the rules may
be made simpler) and to zero standing access setups (which can control
if the entitlements are currently granted; your role determines &lt;em&gt;what&lt;/em&gt;
entitlements are available).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Comparison of all my screwdrivers</title>
      <link>https://www.sweharris.org/post/2025-01-11-screwdrivers/</link>
      <pubDate>Sat, 11 Jan 2025 15:10:53 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2025-01-11-screwdrivers/</guid>
      <description>

&lt;p&gt;This post may seem odd for this blog; after all, why would anyone be
interested in my screwdrivers?  After all, someone like &lt;a href=&#34;https://www.youtube.com/watch?v=845HUaWYSQA&#34;&gt;Project Farm&lt;/a&gt; did a scientific(ish) comparison of
various things and gives you a lot more data than I ever could.&lt;/p&gt;

&lt;p&gt;But we&amp;rsquo;re all human, and sometimes a subjective opinion is valuable.  And
as people know, I have opinions :-)  This may seem long but if you just want
my opinions on the LTT drivers then skip to the bottom.&lt;/p&gt;

&lt;p&gt;Anyway, one day I was re-organizing my cupboard when I realised that
I had a fair number of screwdrivers in my toolbox, loose on shelves,
in stacks in the cupboard.&lt;/p&gt;

&lt;p&gt;And then LTT had a deal on their &lt;a href=&#34;https://www.lttstore.com/products/precision-multi-bit-screwdriver-bundle&#34;&gt;precision driver and bit set&lt;/a&gt; so I got one of them.
Then later they had a deal on their &lt;a href=&#34;https://www.lttstore.com/products/screwdriver&#34;&gt;ratcheting screwdriver&lt;/a&gt; so I got one of them as well.  I didn&amp;rsquo;t &lt;em&gt;need&lt;/em&gt;
them, but I thought it&amp;rsquo;d be interesting to compare the hype against what I
already had.&lt;/p&gt;

&lt;p&gt;So now I have a lot of screwdrivers!&lt;/p&gt;

&lt;p&gt;&lt;a href=/screwdrivers/all_screwdrivers.jpg&gt;&lt;center&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/screwdrivers/small_all_screwdrivers.jpg&#34; alt=&#34;All&#34;&gt;
&lt;/div&gt;
&lt;/center&gt;&lt;/a&gt;
&lt;center&gt;(most images can be clicked for larger versions)&lt;/center&gt;&lt;/p&gt;

&lt;h2 id=&#34;stanley&#34;&gt;Stanley&lt;/h2&gt;

&lt;p&gt;When I moved to America in 2001 I didn&amp;rsquo;t bring any tools with me.  After all,
the electronic stuff (eg drills) wouldn&amp;rsquo;t work, and the rest I could get
easily once I was there.&lt;/p&gt;

&lt;p&gt;Just around the corner from the office where I worked was an old school
hardware shop.  I would sometimes pop in there at lunchtime to get stuff
I needed.&lt;/p&gt;

&lt;p&gt;The first kit I got were these Stanley drivers&lt;/p&gt;

&lt;p&gt;&lt;a href=/screwdrivers/stanley_fixed.jpg&gt;&lt;center&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/screwdrivers/small_stanley_fixed.jpg&#34; alt=&#34;Stanley&#34;&gt;
&lt;/div&gt;
&lt;/center&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What I hadn&amp;rsquo;t realised when I bought them was that two of the heads were
duplicated, just on longer shafts.  I tried comparing the head sizes to
other (labeled) heads, and I think this is what was in it.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;1/4&amp;quot; (SL7) with 4&amp;quot; and 6&amp;quot; shafts
3/16&amp;quot; (SL5) with 3&amp;quot; and 6&amp;quot; shafts
PH2 with 4&amp;quot; shafts
PH1 with 4&amp;quot; shafts
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;They&amp;rsquo;ve last well; some cosmetic marks near the tips but, other than
the limited head selection, they&amp;rsquo;re just fine.  And I&amp;rsquo;m not afraid to hit
the handle with a hammer :-)&lt;/p&gt;

&lt;h2 id=&#34;old-school-precision-drivers&#34;&gt;Old school precision drivers&lt;/h2&gt;

&lt;p&gt;Next I needed some precision screwdrivers.  Same store had these super duper
cheap sets.&lt;/p&gt;

&lt;p&gt;&lt;a href=/screwdrivers/oldschool_precision.jpg&gt;&lt;center&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/screwdrivers/small_oldschool_precision.jpg&#34; alt=&#34;oldschool precision&#34;&gt;
&lt;/div&gt;
&lt;/center&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ooh, fancy; tweezers and a magnifying glass!&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;PH1, PH0
1.4, 2.0, 2.4, 3.0mm flat head
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The lid hinge died pretty quickly, but duct tape to the rescue.&lt;/p&gt;

&lt;p&gt;The biggest annoyance with these is the handles somehow fail to give the
necessary grip on really tight screws and it can cause abrasion on your
fingers as you try and grip harder and harder to undo that stubborn thing.&lt;/p&gt;

&lt;h2 id=&#34;some-oddities&#34;&gt;Some oddities&lt;/h2&gt;

&lt;p&gt;&lt;a href=/screwdrivers/odd_drivers.jpg&gt;&lt;center&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/screwdrivers/small_odd_drivers.jpg&#34; alt=&#34;oddities&#34;&gt;
&lt;/div&gt;
&lt;/center&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&#34;stubby&#34;&gt;Stubby&lt;/h3&gt;

&lt;p&gt;At the same time I saw a stubby screwdriver; I wasn&amp;rsquo;t sure I had a need for
it, but for a few bucks it was worth getting.  The shaft is removable and
flippable; one side is a PH2 and the other is SL7&lt;/p&gt;

&lt;h3 id=&#34;bits-in-the-handle&#34;&gt;Bits in the handle&lt;/h3&gt;

&lt;p&gt;Also from this hardware store came my first &amp;ldquo;true&amp;rdquo; changeable heads driver.
In this one the bits were stored in the handle.  It&amp;rsquo;s next to the stubby
in the main picture.  The closure for this was a simple plastic clip that
was hard to open/close&amp;hellip; and eventually snapped off.  So now the handle
won&amp;rsquo;t stay closed.  But it kinda still works, and was convenient!  Pozidrive,
rather than Phillips bits.  Huh.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;PZ3, PZ2, PZ1
SL6, SL5, SL4
socket head adapter
10mm, 9mm, 8mm, 7mm, 6mm hex socket
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;helping-hands&#34;&gt;Helping Hands&lt;/h3&gt;

&lt;p&gt;I was buying a new house and needed a screwdriver quickly, so went into the
local CVS and bought this &lt;sup&gt;3&lt;/sup&gt;&amp;frasl;&lt;sub&gt;16&lt;/sub&gt;&amp;rdquo; (SL5); clear handle with blue stripes.&lt;/p&gt;

&lt;h3 id=&#34;yellow-flippable&#34;&gt;Yellow flippable&lt;/h3&gt;

&lt;p&gt;Pretty sure this came with some electronics kit (maybe a USB drive bay for
5.25&amp;rdquo; disks?).  The ends aren&amp;rsquo;t very accurate in their sizing and it kinda
looks like SL3.5 and somewhere between PH00 and PH000.&lt;/p&gt;

&lt;h2 id=&#34;curtis-kit&#34;&gt;Curtis kit&lt;/h2&gt;

&lt;p&gt;&lt;a href=/screwdrivers/curtis_kit.jpg&gt;&lt;center&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/screwdrivers/small_curtis_kit.jpg&#34; alt=&#34;curtis kit&#34;&gt;
&lt;/div&gt;
&lt;/center&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pretty sure this also came from the same hardware store.  It was an interesting
combination of things; a ratchet handle (with a grip that allowed more torque),
a set of changeable tips, an extension shaft, a pocket-clip small driver,
tweezers, spring claw, pocket flash light, electrical tape&amp;hellip;  such an odd
selection!&lt;/p&gt;

&lt;p&gt;The tool heads were also pretty varied; I didn&amp;rsquo;t have any Torx before.  So&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;SL6, SL4
PH2
PZ1 
T25, T20, T15, T10, T8
S3, S2, S1, S0
socket head adapter
12mm, 11mm, 10mm, 9mm, 8mm, 7mm, 6mm, 5mm hex socket
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This kit lasted well, and finally I had ratchet!  The most annoying part was
how the heads were stored.  Getting them out of those rubber holders can
be a pain, and the holder covers the marking that says what size the head is.&lt;/p&gt;

&lt;p&gt;Already I was starting to get duplicate drivers.&lt;/p&gt;

&lt;h2 id=&#34;ratcheting-drivers-face-off&#34;&gt;Ratcheting drivers face off!&lt;/h2&gt;

&lt;p&gt;&lt;a href=/screwdrivers/megapro_vs_ltt.jpg&gt;&lt;center&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/screwdrivers/small_megapro_vs_ltt.jpg&#34; alt=&#34;megapro vs ltt&#34;&gt;
&lt;/div&gt;
&lt;/center&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&#34;megapro-automotive-r&#34;&gt;Megapro Automotive R&lt;/h3&gt;

&lt;p&gt;I still wanted a &amp;ldquo;real&amp;rdquo; ratchet driver; the Curtis one was OK but the wide
handle and short shaft often meant I couldn&amp;rsquo;t use it when near the edges
of something.  I also didn&amp;rsquo;t trust it for real heavy duty stuff.&lt;/p&gt;

&lt;p&gt;So I got &lt;a href=&#34;https://www.amazon.com/gp/product/B004VJY1FQ/&#34;&gt;this&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This feels heavy in the hand; it feels like it means business.  And it&amp;rsquo;s
labeled &amp;ldquo;Automotive&amp;rdquo; so, in theory, it should hold up to hard work.&lt;/p&gt;

&lt;p&gt;The ratchet mechanism is smooth (I spent the next few days just playing with
it as a fidget toy!).  The hat that holds the bits is a bit hard to open but
it moves smoothly.  The handle has rubber strips and knobbly bits to maintain
a good grip.&lt;/p&gt;

&lt;p&gt;The provided heads are clearly also designed for heavy duty work; they&amp;rsquo;re
large!&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;PH3, PH2, PH1
S2
SL6, SL4
T30, T27, T25, T20, T15, T10
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These heads clip into the bit holder very easily and the markings on them
are easy enough to read.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s a standard &lt;sup&gt;1&lt;/sup&gt;&amp;frasl;&lt;sub&gt;4&lt;/sub&gt;&amp;rdquo; fit with a pretty strong magnet so I can use the tips
from the other drivers.&lt;/p&gt;

&lt;h3 id=&#34;ltt-retro&#34;&gt;LTT &amp;ldquo;Retro&amp;rdquo;&lt;/h3&gt;

&lt;p&gt;I wasn&amp;rsquo;t going to get this, but LTT were having a &amp;ldquo;mystery driver&amp;rdquo; sale.
I ended up with the &amp;ldquo;retro&amp;rdquo; driver.  And it&amp;rsquo;s clear how this was influenced
by the Megapro, but is &lt;em&gt;different&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;For starters, the LTT driver is smaller; the shaft is a little bit smaller,
the handle a little bit smaller, the bits a little bit smaller, the storage
hat a little bit smaller.  This makes it lighter.&lt;/p&gt;

&lt;p&gt;There are other changes as well; the handle is a new shape.  It&amp;rsquo;s not
rubber grippy like the Megapro, but has more of an angular design to help
maintain grip.  It also has a smaller neck which my middle finger falls
naturally into.  The storage hat is also easier to open and has extra
&amp;ldquo;grip&amp;rdquo; areas to make it even easier.&lt;/p&gt;

&lt;p&gt;Unfortunately either it&amp;rsquo;s the smaller bits (they&amp;rsquo;re about 5mm shorter), or
the plastic used, makes pushing the bits into the storage holder a little bit
hard.  I can only hope this plastic doesn&amp;rsquo;t get brittle as it ages because
I feel it might be a weak point.  I could be wrong, of course :-)&lt;/p&gt;

&lt;p&gt;The bits also are harder to see the markings on.  The black coating really
makes it difficult; you have to angle them &amp;lsquo;just right&amp;rsquo; in the light to
see the size.&lt;/p&gt;

&lt;p&gt;The other big change is on the ratchet itself; this is a little lighter.
Along with the knurling it&amp;rsquo;s a &lt;em&gt;lot&lt;/em&gt; easier to use this driver one handed
when the screw doesn&amp;rsquo;t yet have enough friction to let the ratchet work.
I can even turn the shaft with my thumb, alone; something the Megapro can&amp;rsquo;t
do.  For some reason they decided to reverse the direction that the ratchet
selector works; in theory the LTT way is more natural since it matches the
direction you will turn the handle, but it&amp;rsquo;s opposite to many others and so
is a little confusing.&lt;/p&gt;

&lt;p&gt;The bit set load is definitely more suited for computer work.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;SL6, SL4, SL2
PH2, PH1, PH0
S2, S1 
H4, H2.5, H2
magnetic screw catcher
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The extra size available on the megapro also allows it to have a separator
in the head, which I feel also helps manage the bit; the LTT storage head
skips that to reduce size and weight.&lt;/p&gt;

&lt;p&gt;&lt;a href=/screwdrivers/megapro_ltt_hat.jpg&gt;&lt;center&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/screwdrivers/small_megapro_ltt_hat.jpg&#34; alt=&#34;megapro ltt hat&#34;&gt;
&lt;/div&gt;
&lt;/center&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&#34;precision-drivers-face-off&#34;&gt;Precision drivers face off!&lt;/h2&gt;

&lt;h3 id=&#34;tekton-precision-kit&#34;&gt;Tekton Precision kit&lt;/h3&gt;

&lt;p&gt;The old school precision drivers I had were annoying me; I spotted
this on Amazon; &lt;a href=&#34;https://www.amazon.com/gp/product/B00VJYWRKW/&#34;&gt;TEKTON 28301 Tech Rescue Kit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=/screwdrivers/tekton_kit.jpg&gt;&lt;center&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/screwdrivers/small_tekton_kit.jpg&#34; alt=&#34;tekton&#34;&gt;
&lt;/div&gt;
&lt;/center&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a hell of a kit packaged into a small soft-shell case.  It
comes with a LOT of stuff!&lt;/p&gt;

&lt;p&gt;&lt;a href=/screwdrivers/tekton_kit_detail.jpg&gt;&lt;center&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/screwdrivers/small_tekton_kit_detail.jpg&#34; alt=&#34;tekton detail&#34;&gt;
&lt;/div&gt;
&lt;/center&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As well as the magnetic screwdriver shaft, very fine nosed tweezers,
a metal
spudger, a nylon spudger, a suction cup puller, and a magnetic screw holder, it has a large selection of tips&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;2.5mm, 1.5mm, 1mm slotted heads
PH1, PH0, PH00, PH000
PH1, PH0 3&amp;quot; shaft
T5, T4, T3 (star bits)
TR15, TR10, TR9, TR8, TR7, TR6 (tamper resistant star bits)
TR8, TR6 3&amp;quot; shaft
TRI1, TRI0 (tri-wing)
2mm, 1.5mm, 1.3mm hex
TA27, TA23, TA20, TA18 (triangle)
PL1.5, PL1.2, PL0.8 (pentalobe)
6.5mm, 5mm, 4mm, 3.5mm, 3mm nut drivers
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a great kit, and very cleverly put together; the bits are easy
to remove from the plastic holders, which are clearly marked, and they are
held in the case with velcro strips.  The driver handle is knurled to provide
a good grip.&lt;/p&gt;

&lt;p&gt;The biggest problem I have with this kit is that I was tempted to use it for
things I shouldn&amp;rsquo;t have; it&amp;rsquo;s a precision kit, not a general purpose kit!&lt;/p&gt;

&lt;h3 id=&#34;megapro-251precision&#34;&gt;MegaPro 251Precision&lt;/h3&gt;

&lt;p&gt;&lt;a href=/screwdrivers/megapro_precision.jpg&gt;&lt;center&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/screwdrivers/small_megapro_precision.jpg&#34; alt=&#34;megapro precision&#34;&gt;
&lt;/div&gt;
&lt;/center&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since I liked the larger MegaPro so much, I thought I&amp;rsquo;d try their precision
driver.  It wouldn&amp;rsquo;t replace the Tekton kit, but it might be useful as a
more portable &amp;ldquo;just need a screwdriver&amp;rdquo; tool.&lt;/p&gt;

&lt;p&gt;Unfortunately the storage hat is about all it has in common with the ratchet.
The heads are all &amp;ldquo;flip&amp;rdquo; style (each head has two tips) and they&amp;rsquo;re not easy
to get in/out of the shaft.&lt;/p&gt;

&lt;p&gt;&lt;a href=/screwdrivers/megapro_precision_hat.jpg&gt;&lt;center&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/screwdrivers/small_megapro_precision_hat.jpg&#34; alt=&#34;megapro precision hat&#34;&gt;
&lt;/div&gt;
&lt;/center&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The selection of heads is good&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;T15, T10
S3, S2.5, S2, S1.5
P2, P5
SP2.6
TA 2.3
TX5, TX4, TX3
TT15, TT10, TT8, TT6
PH2, PH1, PH0, PH00, PH000
SL3, SL2.5, SL2, SL1.5
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Unfortunately because of the double-sided nature they can&amp;rsquo;t be organized
in a sane manner so I&amp;rsquo;m always searching for the right one.&lt;/p&gt;

&lt;h3 id=&#34;ltt-precision&#34;&gt;LTT Precision&lt;/h3&gt;

&lt;p&gt;&lt;a href=/screwdrivers/ltt_precision_kit.jpg&gt;&lt;center&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/screwdrivers/small_ltt_precision_kit.jpg&#34; alt=&#34;ltt precision&#34;&gt;
&lt;/div&gt;
&lt;/center&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was combined deal; the driver and the bit set together.  It comes in
a storage box and the lid can be removed and is magnetic with compartments
so screws can be held together; especially useful when some kit has different
sized screws!&lt;/p&gt;

&lt;p&gt;The big hype from LTT about this driver was the spinning hat; so much time
was spent talking about how it can be a fidget spinner and it runs for a long
time and&amp;hellip; yeah, OK, it&amp;rsquo;s smooth, it&amp;rsquo;s clever.  But this is a screwdriver.
Unfortunately the storage head can only hold 3 bits, so this is very unlikely
to ever be used &amp;ldquo;on its own&amp;rdquo;; all the bits will live in the storage box along
with the driver.&lt;/p&gt;

&lt;p&gt;&lt;a href=/screwdrivers/ltt_precision_hat.jpg&gt;&lt;center&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/screwdrivers/small_ltt_precision_hat.jpg&#34; alt=&#34;ltt precision hat&#34;&gt;
&lt;/div&gt;
&lt;/center&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The box is much bigger and heavier than the Tekton kit.  If you&amp;rsquo;re gonna
throw it in a toolbox then it&amp;rsquo;ll probably last longer, but my use case is
less demanding; the smaller soft shell case wins.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s a lot of bits in this set and the base of each bit is smaller than
traditional; this lets them use a longer shaft on each one, which might make
it easier to get into hard-to-reach places.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;PH2, PH1, PH0, PH00, PH000, PH0000
SIM card ejector
P6, P5, P2
SP8, SP6, SP4
PZ1, PZ0
S2, S1, S0
TR26, TR20, TR15, TR10, TR9, TR8, TR7, TR6
T5, T4, T3, T2 
Standoff remover
TA3, TA2
Y1, Y0, Y00, Y000
SL4, SL3, SL2.5, SL2, SL1.5, SL1
H5, H3.5, H3, H2.5, H2, H1.5, H1.3, H0.9, H0.7
Magnet
hex socket 5 4 3.5 3 2.5
g socket 4.5 3.5
adapter to allow these to be used in a 1/4&amp;quot; driver
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As with the LTT ratcheting driver, it&amp;rsquo;s really hard to read the bit labeling;
it&amp;rsquo;s embedded into the foam of the storage case so there&amp;rsquo;s very little contrast
and hard to read.  The bits, themselves, are easier but the marking is hidden
when they&amp;rsquo;re in the case!&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;So that&amp;rsquo;s it; that&amp;rsquo;s all my screw drivers!&lt;/p&gt;

&lt;p&gt;Going forward I&amp;rsquo;m likely to use the MegaPro ratchet driver for &amp;ldquo;tough&amp;rdquo; work,
and the LTT ratchet for computer stuff.  I guess, in theory, I could swap
some of the LTT bits into the MegaPro storage hat, but keeping them separate
is probably easier.&lt;/p&gt;

&lt;p&gt;For precision work I&amp;rsquo;m conflicted.  The shape of the LTT handle is a
little bit better than the Tekton one.  But I&amp;rsquo;m also likely to want a
spudger when I&amp;rsquo;m taking things apart, so the LTT kit on its own just
isn&amp;rsquo;t sufficient.  I&amp;rsquo;ve tested and I could just swap over the handles;
use the Tekton bitset with the LTT handle.  That might be thing to do.&lt;/p&gt;

&lt;p&gt;Unfortunately I&amp;rsquo;m not sure the LTT stuff is value for money.&lt;/p&gt;

&lt;p&gt;The Tekton kit cost me $27 from Amazon; the LTT precision kit (including
tax+shipping) was $64.  Yes, the LTT kit has a lot more bits, but its missing
things needed to make it a &amp;ldquo;complete&amp;rdquo; kit.&lt;/p&gt;

&lt;p&gt;Similarly the MegaPro ratchet was $37, the LTT was $53 (which is
cheaper than normal because it was on sale; $40 vs $70, the rest being
tax+shipping).  This one is harder to pick; they&amp;rsquo;re both good drivers,
but the bit set on the LTT one is more suited for computer work.
Maybe there&amp;rsquo;s a different MegaPro with a different bit set that is closer!&lt;/p&gt;

&lt;p&gt;I do wish LTT would be better with contrast on their bit case and bits,
though!  For someone who can&amp;rsquo;t tell the difference these labels can be
very helpful.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>We don&#39;t need security products</title>
      <link>https://www.sweharris.org/post/2024-12-11-security-products/</link>
      <pubDate>Wed, 11 Dec 2024 19:54:02 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2024-12-11-security-products/</guid>
      <description>

&lt;p&gt;There&amp;rsquo;s a theme going around that you should create secure products, not buy security products.  And, as far as it goes, this is&amp;hellip;&lt;/p&gt;

&lt;p&gt;Well, actually it&amp;rsquo;s not good.&lt;/p&gt;

&lt;p&gt;My initial response was &amp;ldquo;Why not both?&amp;rdquo; We need to secure the products we develop.  There&amp;rsquo;s no doubt about that.  And we need to mitigate mistakes.  How do we do this?  Spoiler&amp;hellip; security products :-)&lt;/p&gt;

&lt;p&gt;In response to this I got a message &amp;ldquo;If you have secure products, you
do not need security products. And what you do not need, you definitely
should not run!&amp;rdquo;&lt;/p&gt;

&lt;p&gt;And at that point this rant was generated.&lt;/p&gt;

&lt;h2 id=&#34;rant&#34;&gt;Rant&lt;/h2&gt;

&lt;p&gt;See, how do you know your product is secure? &amp;lsquo;Cos as sure as the
sun will rise tomorrow (even if I might not see it &amp;lsquo;cos of the awful
weather&amp;hellip;) a developer will make a mistake; a core library will have
a bug (hi, OpenSSL!), a service will be misconfigured, a subsystem will
be left unsecured.&lt;/p&gt;

&lt;p&gt;Is your code provably correct?  Really?!  Does it depend on any external
libraries?  Are those libraries secure?  Will they &lt;em&gt;remain&lt;/em&gt; secure?  How many
new CVEs are generated against code we consume as part of our development
processes, and that may make our own code bad?  We may write the most perfect
code ever, but a vulnerability in a dependency can ruin it all.&lt;/p&gt;

&lt;p&gt;And we all have dependencies in our code bases.  For example, we sure
don&amp;rsquo;t want developers creating their own encryption systems; that&amp;rsquo;s hard
enough to get right for seasoned cryptographers (see, for example, some
of the failings of the newer post-quantum algorithms; see, for example,
how older algorithms are deprecated as attacks are discovered).  But we even
have more basic dependencies; how many maven libraries is your code bringing
in?  How much stuff has been cloned from github?&lt;/p&gt;

&lt;p&gt;And the inescapable truth is that developers are human (and &amp;ldquo;AI&amp;rdquo; assistants are
sub-human).  Humans make mistakes.&lt;/p&gt;

&lt;h2 id=&#34;so-what-do-we-need&#34;&gt;So what do we need?&lt;/h2&gt;

&lt;p&gt;Obviously we need to help our developers create better code.  We want
to improve the skills of our developers and make their code better.
So let&amp;rsquo;s alert them to mistakes they might be making.  A plugin in
their IDE?  Some static code analysis?  Hooks into the devops process to
block bad code from being promoted?  Even some training modules focused
on discovered weaknesses?  They&amp;rsquo;re all security products.&lt;/p&gt;

&lt;p&gt;What about those dependencies?  We need to track what modules a developer
is using and ensure they have no known vulnerabilities or (better) that any
known vulns aren&amp;rsquo;t in the execution path and so not impacted.  So now we
need tools that can do dependency analysis, compare what&amp;rsquo;s being used to what&amp;rsquo;s
good, and preferably block bad modules from the build.&lt;/p&gt;

&lt;p&gt;Oh, that module which was good last month&amp;hellip; it has a new CVSS 10 vuln; do we
know where that&amp;rsquo;s been deployed so we can target remediation?  More tools.&lt;/p&gt;

&lt;p&gt;What about identity and access management?  What about new classes of attack
(e.g. API issues)?  What about&amp;hellip;?&lt;/p&gt;

&lt;p&gt;Security tools can even provide mitigation against lower level attacks, such
as a DoS.  Or provide protection for third-party tools.  Do you put your
ILOMs and DRACs and every other out-of-band interface on the internet?  Or
do you limit them - eg via subnet routing, firewalls, etc.  Require a VPN
with MFA to reach them&amp;hellip; look, more security tools!&lt;/p&gt;

&lt;h2 id=&#34;reality&#34;&gt;Reality&lt;/h2&gt;

&lt;p&gt;The reality is that we strive for perfect code.  We all want to do the right
thing.  But we all can fail.  The larger the product, the more developers,
the increase in complexity&amp;hellip; the greater the risk.   And modern microservice
architectures are &lt;em&gt;complex&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Even the mythical 10x developer makes a mistake every now and then.&lt;/p&gt;

&lt;p&gt;So we create standard architectures to try and limit the risk.  We use
security tools to provide &amp;ldquo;belts and braces&amp;rdquo;, to provide depth, to
mitigate mistakes that &lt;em&gt;will&lt;/em&gt; happen.&lt;/p&gt;

&lt;p&gt;Sure, don&amp;rsquo;t run what you don&amp;rsquo;t need.  But you do need the &lt;em&gt;right&lt;/em&gt; security
tools.  You have limited resources, so pick wisely!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Stop changing technology</title>
      <link>https://www.sweharris.org/post/2024-10-20-technology-changing/</link>
      <pubDate>Sun, 20 Oct 2024 12:56:18 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2024-10-20-technology-changing/</guid>
      <description>

&lt;p&gt;One thing I&amp;rsquo;ve noticed, over the years, is the habit of people blaming
technology for the problems rather than taking a look at the processes
behind the problem.&lt;/p&gt;

&lt;h2 id=&#34;a-personal-example&#34;&gt;A personal example&lt;/h2&gt;

&lt;p&gt;A big example, for me, was when I was part of the Unix enterprise
authentication team.  The technology worked, and it worked &lt;em&gt;well&lt;/em&gt;.  It was
resilient, reliable, fast.  We literally turned off the infrastructure
in one datacenter and all the clients correctly failed over to the next
nearest one.&lt;/p&gt;

&lt;p&gt;But it had a bad reputation.  If you so much mentioned the word &amp;ldquo;Keon&amp;rdquo;
to some people then their eyes will start to twitch and they get a
haunted look.&lt;/p&gt;

&lt;p&gt;Because the &lt;em&gt;processes&lt;/em&gt; around configuring the environment were bad.
To build a new application you needed to think ahead and plan your
requirements; &amp;ldquo;these are my servers&amp;rdquo;, &amp;ldquo;these are my app team members&amp;rdquo;
and &amp;ldquo;they need these Unix permissions&amp;rdquo; (I know a lot of people don&amp;rsquo;t
like this, but I thought it reasonable; we can&amp;rsquo;t put servers on the
network without access controls).&lt;/p&gt;

&lt;p&gt;But it got worse.  You had to fill out a spreadsheet using complicated
jargon and half a dozen tabs, just to say this.  Then you had to attach
this to a &amp;ldquo;consulting request&amp;rdquo; in the corporate request system.  With a
5 day SLA and a high likelihood of the request being rejected.&lt;/p&gt;

&lt;p&gt;How do I know the process was bad?  Because &lt;em&gt;my&lt;/em&gt; request was rejected; not
because it was wrong but because the implementer missed the attachment!&lt;/p&gt;

&lt;p&gt;So when a new head of technology joined the company they heard all these
complaints about Keon and how it was so bad, and he planned to replace it.&lt;/p&gt;

&lt;p&gt;I just couldn&amp;rsquo;t convince him that replacing the technology stack would not
fix the &lt;em&gt;processes&lt;/em&gt;; it was the process that people hated.  Focus on that.&lt;/p&gt;

&lt;p&gt;Unfortunately the process side of the house wasn&amp;rsquo;t in his remit (that was
run by a different technology tower) so instead of working with that tower
(we could have created better tooling for the request system that would
have made both the requester&amp;rsquo;s life &lt;em&gt;and&lt;/em&gt; the implementer&amp;rsquo;s life better)
he treated it like a technology problem and tasked me with evaluating
replacement tools.&lt;/p&gt;

&lt;p&gt;(I soon moved out of that team and into the new cloud team)&lt;/p&gt;

&lt;h2 id=&#34;iterated-madness&#34;&gt;Iterated madness&lt;/h2&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;The definition of insanity is doing the same thing over and over
and expecting different results&amp;rdquo; &amp;ndash; Albert Einstein&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Elsewhere I&amp;rsquo;ve seen teams get stuck in a loop; they would buy the best
in breed technology for a solution and deploy it.  It would fail to
meet the requirements, so they would go back to the drawing board and
get replacement technology.  Rinse repeat.&lt;/p&gt;

&lt;p&gt;The underlying cause is that they were looking at this as a technology
delivery problem, and not as a service delivery problem.  The team
were technologists, so this kinda made sense; they were told &amp;ldquo;deploy X&amp;rdquo;
and they did.&lt;/p&gt;

&lt;p&gt;So the blame lies higher up the management tree; the VPs and SVPs who
didn&amp;rsquo;t see the bigger picture, who didn&amp;rsquo;t &lt;em&gt;understand&lt;/em&gt; the problem they
were told to solve, and who believed the vendors.&lt;/p&gt;

&lt;p&gt;The role that was missing was one of &amp;ldquo;service owner&amp;rdquo;.  What do we need
to do to make this a consumable service?  They could have saved millions
of dollars and reduced technology disruption just by having this bigger
picture.&lt;/p&gt;

&lt;h2 id=&#34;service-and-product-owners&#34;&gt;Service and Product owners&lt;/h2&gt;

&lt;p&gt;There are multiple ways this can be defined, but I look at it this way.&lt;/p&gt;

&lt;p&gt;The Product Owner is the one that owns the technology stack.  They&amp;rsquo;re the
one who is responsible for keeping it running, for ensuring it&amp;rsquo;s patched
and updated, for understanding the vendor technology road map for the
product, and for handling any integrations with other systems (request
system, change management, HR, etc).&lt;/p&gt;

&lt;p&gt;The Service Owner is the one that is responsible to the &lt;em&gt;users&lt;/em&gt; of the
product to ensure the business needs are met.  They create the overall
service road map that is &lt;em&gt;informed&lt;/em&gt; by the vendor road maps, but may also
takes into account customer complaints, service issues, etc.  It may
be the vendor product road map includes sprouting wings and flying, but
if you want to dig tunnels we may not implement that function&amp;hellip; unless
your service needs include rapid deployment to remote locations :-)&lt;/p&gt;

&lt;p&gt;These two owners should work tightly with each other; they may even be
the same person, but need not be.&lt;/p&gt;

&lt;p&gt;Each role is critical to the success of the service.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Technology is easy; process is hard&amp;rdquo; &amp;ndash; me&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;We deploy tools to meet a business need, not for the sake of deploying
them.  These tools are not standalone; they have inputs and outputs,
even if it&amp;rsquo;s just reporting to the CISO about what they&amp;rsquo;re doing, how
they&amp;rsquo;re reducing our risk, and how well they&amp;rsquo;re achieving those goals!&lt;/p&gt;

&lt;p&gt;So we need to look at this as a service and not a technology.  And when
the &lt;em&gt;service&lt;/em&gt; fails we need to look at it from a service perspective.
Is the technology to blame (it could be!), or are we using it wrong?
Even if the technology is wrong, is it because we didn&amp;rsquo;t deploy it
correctly and it can be fixed?&lt;/p&gt;

&lt;p&gt;Don&amp;rsquo;t just change the technology because it&amp;rsquo;s easy (for some values of
&amp;ldquo;easy&amp;rdquo;); look wider.  Find where the problem really is.&lt;/p&gt;

&lt;p&gt;The problem may be that you have the wrong people; it may be that you
have the wrong processes; it may be that you don&amp;rsquo;t actually understand
the problem!&lt;/p&gt;

&lt;p&gt;Replacing a technology stack will only fix the problem if the underlying
technology is wrong for this problem space, and if you&amp;rsquo;ve bought the best of
breed then it&amp;rsquo;s not likely.  You may have deployed it wrong (fix that) or
aren&amp;rsquo;t using it properly (ditto) but if you just replace it and hope this
time things will work out better&amp;hellip; well, that&amp;rsquo;s Einstein&amp;rsquo;s definition of
insanity.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Google killing adblockers</title>
      <link>https://www.sweharris.org/post/2024-09-12-manifestv2/</link>
      <pubDate>Thu, 12 Sep 2024 08:33:47 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2024-09-12-manifestv2/</guid>
      <description>

&lt;p&gt;Google has been threatening this for a while, but now they&amp;rsquo;re &lt;a href=&#34;https://developer.chrome.com/docs/extensions/develop/migrate/mv2-deprecation-timeline&#34;&gt;finally getting
around to it&lt;/a&gt;; they&amp;rsquo;re starting to remove Manifest v2 (MV2) from Chromium
(and thus Chrome, and likely many browsers based on chromium, which is
the majority of the browser space, these days!).&lt;/p&gt;

&lt;h2 id=&#34;what-does-this-mean&#34;&gt;What does this mean?&lt;/h2&gt;

&lt;p&gt;Chrome extensions use a set of APIs to talk to the browser engine.  The main
version that&amp;rsquo;s been in use for a number of years is &amp;ldquo;Manifest v2&amp;rdquo;.  This set
of APIs are extremely powerful and flexible and allow an extension to modify
almost every aspect of your browsing experience.  Extensions such as &lt;a href=&#34;https://chromewebstore.google.com/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm&#34;&gt;uBlock
Origin&lt;/a&gt; (uBO) and &lt;a href=&#34;https://chromewebstore.google.com/detail/noscript/doojmbjmlfjjnbmnoijecmcbfeoakpjm&#34;&gt;NoScript&lt;/a&gt; make use of this to inspect web pages
and modify them; e.g. to remove adverts, block JavaScript and so on.&lt;/p&gt;

&lt;p&gt;Google are removing this API and replacing it with a newer one (&amp;ldquo;Manifest v3&amp;rdquo;; MV3)
which is more limited in capabilities.  This will cause a number of extensions
to break, and may make it infeasible for them to operate at all.&lt;/p&gt;

&lt;p&gt;If you are on the beta, dev or canary channels then you&amp;rsquo;ll already be seeing
impact; it hasn&amp;rsquo;t yet reached the main stable channel, but it&amp;rsquo;s only a couple
of major releases away.&lt;/p&gt;

&lt;h2 id=&#34;why-are-they-doing-it&#34;&gt;Why are they doing it?&lt;/h2&gt;

&lt;p&gt;Google&amp;rsquo;s primary claims are around security and performance.  If a rogue
extension was deployed to your browser then with v2 it can see pretty much
everything; it could steal your bank login credentials (so always use MFA!)
or insert adverts or&amp;hellip; anything.  This is obviously bad.  By enforcing a
more limited API the risks are mitigated to some extent.&lt;/p&gt;

&lt;p&gt;Similarly extensions (even ones you want) can be slow because they can do
so much.  An extension with thousands of rules could slow down every web
page you go to, and take up lots of memory.  Chrome frequently gets the
blame for being a memory and CPU hog, but how much of this is the core
browser engine and how much is due to the dozen extensions people load?&lt;/p&gt;

&lt;h2 id=&#34;so-what-s-the-problem&#34;&gt;So what&amp;rsquo;s the problem?&lt;/h2&gt;

&lt;p&gt;Manifest v3 has strict limits which prevents uBO from being ported over.
Instead, the author has created a &lt;a href=&#34;https://chromewebstore.google.com/detail/ublock-origin-lite/ddkjiahejlhfcafbddmgiahcphecmpfh&#34;&gt;uBO Lite&lt;/a&gt;.  This has some
functionality changes and a lot of &lt;a href=&#34;https://github.com/uBlockOrigin/uBOL-home/wiki/Frequently-asked-questions-(FAQ)#filtering-capabilities-which-cant-be-ported-to-mv3&#34;&gt;limitations&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Possibly more importantly, filter rules are no longer updated from the internet
but are &lt;a href=&#34;https://github.com/uBlockOrigin/uBOL-home/wiki/Frequently-asked-questions-(FAQ)#when-do-filter-lists-update&#34;&gt;embedded into the extension&lt;/a&gt;.  The
rules are now only update when the extension is updated, and this may take
some time as it goes through the Google evaluation processes.  This could
mean that new advertising solutions may get through until the extension is
updated; with MV2 the extension could regularly update its lists.  In the
past I&amp;rsquo;ve seen sites such as twitter modify how ads are displayed, but then
a few hours later uBO rules update to handle this.&lt;/p&gt;

&lt;p&gt;And this is why people are worried about MV3 and why Google&amp;rsquo;s rationale
isn&amp;rsquo;t as persuasive; the feeling is that Google (the owner of the world&amp;rsquo;s
largest digital advertising platform) is deliberately trying to hobble
ad blockers.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ve seen ads used to propagate malware in the past, and
even NIST recommend &lt;a href=&#34;https://www.nist.gov/blogs/manufacturing-innovation-blog/maintaining-your-online-privacy&#34;&gt;&amp;ldquo;Use advertisement blocking extensions&amp;rdquo;&lt;/a&gt; as
part of safe web browsing, so there&amp;rsquo;s also a concern that Google are reducing
overall security; an ad blocker could mitigate a Chrome zero-day attack!&lt;/p&gt;

&lt;h2 id=&#34;what-can-we-do&#34;&gt;What can we do?&lt;/h2&gt;

&lt;p&gt;For the immediate future, keep an eye on your extensions.  If they get
disabled you may be able to temporarily re-enable them.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s definitely worth trying out MV3 extensions to see if they&amp;rsquo;re good enough.
It may be that you just don&amp;rsquo;t need the flexibility of the MV2 code, and the
new extension is fine.&lt;/p&gt;

&lt;p&gt;You could switch to another browser; Mozilla claims they have &lt;a href=&#34;https://blog.mozilla.org/addons/2024/03/13/manifest-v3-manifest-v2-march-2024-update/&#34;&gt;no plans to
deprecate MV2&lt;/a&gt; in Firefox, and many of the extensions you use on Chrome are
available for Firefox.&lt;/p&gt;

&lt;p&gt;There are some forks of Chromium that have built in ad blocking (e.g. Brave)
but some of these may come with other concerns.&lt;/p&gt;

&lt;p&gt;There are also some commercial Enterprise browsers out there with their
own ad-blocker engines which shouldn&amp;rsquo;t be impacted by this (I was involved
in the evaluation of one, and it was pretty good, but I try not to recommend
products!)&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://vivaldi.com/blog/manifest-v3-update-vivaldi-is-future-proofed-with-its-built-in-functionality/&#34;&gt;Vivaldi&lt;/a&gt; wants to keep MV2 functionality &amp;ldquo;for as long
as it&amp;rsquo;s still available in Chromium&amp;rdquo;, which may be until June 2025.&lt;/p&gt;

&lt;h2 id=&#34;getting-another-year-of-life&#34;&gt;Getting another year of life&lt;/h2&gt;

&lt;p&gt;Which brings us to another way of keeping going until June 2025.  Google are
granting Enterprises the ability to keep MV2 extensions by setting a
management policy.  We can make use of this even for unmanaged browsers!&lt;/p&gt;

&lt;p&gt;If you go to &lt;code&gt;about:policy&lt;/code&gt; in chrome and click on &amp;ldquo;Show policies with no
value set&amp;rdquo; then you&amp;rsquo;ll see an entry called &amp;ldquo;ExtensionManifestV2Availability&amp;rdquo;.
This can be used to &lt;a href=&#34;https://chromeenterprise.google/policies/?policy=ExtensionManifestV2Availability&#34;&gt;control if MV2 can be used&lt;/a&gt;.  The default value is
&amp;ldquo;browser default&amp;rdquo; but we can set this to 2 to force it to be on.&lt;/p&gt;

&lt;p&gt;How we do this will depend on your OS.&lt;/p&gt;

&lt;p&gt;Obviously Enterprises using the Manager tool can set it there.  But even
without this the policy can be set on a machine by machine basis.&lt;/p&gt;

&lt;p&gt;On Windows this is stored in the registry.  We can set it from an &lt;em&gt;admin&lt;/em&gt;
command line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;C:\Windows\System32&amp;gt;reg add HKLM\Software\Policies\Google\Chrome /v ExtensionManifestV2Availability /t REG_DWORD /d 2
The operation completed successfully.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On Linux if you view the policy logs (&amp;ldquo;more actions / view logs&amp;rdquo;) you should
see entries similar to&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[VERBOSE] Skipping mandatory platform policies because no policy file was found at: /etc/opt/chrome/policies/managed
[VERBOSE] Skipping recommended platform policies because no policy file was found at: /etc/opt/chrome/policies/recommended
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This tells us where the policy file needs to be placed.  It may be different
on Chromium.  In my case I was then able to do&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# mkdir -p /etc/opt/chrome/policies/managed
# echo &#39;{
  &amp;quot;ExtensionManifestV2Availability&amp;quot;: 2
}&#39; &amp;gt; /etc/opt/chrome/policies/managed/v2.json
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In both scenarios, if you go back to &lt;code&gt;about://policy&lt;/code&gt; and click on
&amp;ldquo;Reload policies&amp;rdquo; the value should show up.&lt;/p&gt;

&lt;p&gt;With luck this will let us keep using MV2 extensions until June 2025.&lt;/p&gt;

&lt;p&gt;This may come with a downside; Google are no longer accepting MV2 extensions
into their store so if there is a security issue found in an extension then
it may not get fixed.  So definitely &lt;em&gt;caveat emptor&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;These changes are at the machine level, so every user of the machine will
get this policy.&lt;/p&gt;

&lt;p&gt;Enterprises could set the registry via a GPO and update the local file on
Unix machines with their preferred management tool.&lt;/p&gt;

&lt;p&gt;Home users can do this manually.  It needs to be done on each machine,
so if you have more than one machine then remember to make this change
everywhere!&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;The MV2 deprecation is not popular.  It &lt;em&gt;may&lt;/em&gt; add some security benefits
against rogue extensions but it definitely has downsides for the more
privacy and security conscious folks.&lt;/p&gt;

&lt;p&gt;In the long run we might see a resurgence of alternate browsers and the
decline of Chromium based ones (much as Chrome killed Internet Explorer),
but given many end users are likely just using Edge on Windows I won&amp;rsquo;t
hold my breath.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>On 9/11 deniers</title>
      <link>https://www.sweharris.org/post/2024-09-11-nine-eleven/</link>
      <pubDate>Wed, 11 Sep 2024 15:49:31 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2024-09-11-nine-eleven/</guid>
      <description>&lt;p&gt;For some reason this year a lot more 9/&amp;ZeroWidthSpace;11 denialism has come across my
social media feeds.  I wonder if it&amp;rsquo;s because of the upcoming election.&lt;/p&gt;

&lt;p&gt;And I just can&amp;rsquo;t&amp;hellip;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;d had enough a decade ago and wrote something then; I&amp;rsquo;m repurposing it
here.&lt;/p&gt;

&lt;p&gt;I was working on Wall Street the day it happened, just half a mile
away. I&amp;rsquo;d only moved to the US 2 months earlier.&lt;/p&gt;

&lt;p&gt;I spoke to people who were at WTC as it happened. I consoled a man who
ran away rather than trying to help people, and thought this was a breach
of his identity as a Christian.&lt;/p&gt;

&lt;p&gt;When the towers collapsed the amount of dust caused a total black-out;
you couldn&amp;rsquo;t see anything outside of the windows. Afterwards I could
see a set of footprints in the dust, as if it was snow.&lt;/p&gt;

&lt;p&gt;Eventually we were told to leave the island and I had to walk home (about
6 miles in massive hot sun). I was really impressed; on the other side
of the Brooklyn Bridge all the office workers had brought out their water
coolers and stuff and were handing out water to us as we walked past.&lt;/p&gt;

&lt;p&gt;I still didn&amp;rsquo;t have any furniture in my apartment; a TV sitting on a
stand, but no sofa or chairs; only an office chair I was using for the
computer room (no tables for the computers either; they were sitting on
their boxes). No mobile phone (I bought one the following weekend!) but
I did have a landline that still worked.&lt;/p&gt;

&lt;p&gt;Not my happiest of days.&lt;/p&gt;

&lt;p&gt;Oddly, the next week I was scheduled for DSL install. I expected this
to be canceled &amp;lsquo;cos all telco technicians would be working to fix
Manhattan&amp;hellip; but, no! They actually installed it a day early!&lt;/p&gt;

&lt;p&gt;And then the denialism&amp;hellip;&lt;/p&gt;

&lt;p&gt;Please, just shut up.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s enough about that day and it&amp;rsquo;s consequences to be sorry
about. Deranged rantings from loons does not help.&lt;/p&gt;

&lt;p&gt;Whenever a &amp;ldquo;9/&amp;ZeroWidthSpace;11 truther&amp;rdquo; intrudes on my presence I get angry at that
idiot, where I would rather continue being sad for the pointless and
useless loss of life; those lost on that day, those of the emergency
services lost on that day (or as result of dust inhalation, etc), and
those lost overseas as a result of the war.&lt;/p&gt;

&lt;p&gt;All a waste of life. All pointless. All for nothing.&lt;/p&gt;

&lt;p&gt;I remember the heroes of the day; those office workings giving us water,
those who helped bolster spirits, and those who emergency workers who
rushed into peril to help those in need.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href=http://www.dorktower.com/files/2001/09/dorktower007.jpg&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/dorktower007.jpg&#34; alt=&#34;Dork Tower&#34;&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;I remember crying, I remember turning off the TV because I couldn&amp;rsquo;t
handle it any more.&lt;/p&gt;

&lt;p&gt;I remember talking with my parents back in England. I remember meeting
my girlfriend the next evening and taking part in the vigil at Washington
Square Park.&lt;/p&gt;

&lt;p&gt;I remember the despair at seeing hate graffiti in Manhattan the day
after. I remember the anger at the idiotic US government response. I
remember my girlfriend walking in marches to stop the war (I didn&amp;rsquo;t march
because I didn&amp;rsquo;t think it my place to march against the US government,
since I wasn&amp;rsquo;t a US citizen).&lt;/p&gt;

&lt;p&gt;I remember Fox News. I remember Fahrenheit 9/&amp;ZeroWidthSpace;11.&lt;/p&gt;

&lt;p&gt;I remember the parasites. I remember the stores opening to sell &amp;lsquo;personal
protection&amp;rsquo; against additional attacks; &amp;ldquo;office parachutes&amp;rdquo;, plastic to
seal windows against air-born infection, personal bio-suits. (There was
a store 2 blocks from the office)&lt;/p&gt;

&lt;p&gt;What I don&amp;rsquo;t need is you.&lt;/p&gt;

&lt;p&gt;Please&amp;hellip; shut up.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Yubikey 5 is broken! Panic! Or not</title>
      <link>https://www.sweharris.org/post/2024-09-05-broken-yubikey/</link>
      <pubDate>Thu, 05 Sep 2024 11:34:04 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2024-09-05-broken-yubikey/</guid>
      <description>

&lt;p&gt;I&amp;rsquo;d &lt;a href=&#34;https://www.sweharris.org/post/2022-11-17-yubikey/&#34;&gt;previously&lt;/a&gt; written about the Yubikey 5 and
how we could use it to solve various use cases and when to trust it.
Personally, I think it&amp;rsquo;s a great device for corporate authentication
solutions.&lt;/p&gt;

&lt;p&gt;But&amp;hellip;&lt;/p&gt;

&lt;p&gt;This week, Yubico released an &lt;a href=&#34;https://www.yubico.com/support/security-advisories/ysa-2024-03/&#34;&gt;advisory&lt;/a&gt; that stated that ECDSA private keys could be stolen
from a Yubikey 5 that&amp;rsquo;s running firmware older than 5.7.0  (or 2.4.0 for
the YubiHSM).  This is due to a flaw in the cryptographic libraries written
by Infineon and discovered by &lt;a href=&#34;https://ninjalab.io/wp-content/uploads/2024/09/20240903_eucleak.pdf&#34;&gt;NinjaLab&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;what-is-the-issue&#34;&gt;What is the issue?&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s a lot of maths involved in the NinjaLab document, but basically it
boils down to a certain action not being &amp;ldquo;time constant&amp;rdquo;.  This means a
successful action and a failed action can take different times.  This timing
can be observed, and this leads to a &lt;em&gt;side channel&lt;/em&gt; attack.  NinjaLab were
able to do this and recover the ECDSA private key embedded into the device.&lt;/p&gt;

&lt;p&gt;This is kinda bad; the promise of security keys is that the private key
can &lt;em&gt;never&lt;/em&gt; be leaked.  Now we have no guarantees!&lt;/p&gt;

&lt;p&gt;So time to panic?&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/dont_panic.jpg&#34; alt=&#34;Don&amp;#39;t Panic&#34;&gt;
&lt;/div&gt;

(Gratuitous Hitch Hikers Guide reference)
&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s look at the different authenticators on a yubikey and how they might
be impacted&lt;/p&gt;

&lt;h2 id=&#34;fido2&#34;&gt;FIDO2&lt;/h2&gt;

&lt;p&gt;FIDO2 can work in two ways.  When you register two a FIDO2 service a
unique public/private key is created.  The public key is sent to the server
and this is then used to verify you when you login.&lt;/p&gt;

&lt;p&gt;What changes is in how the private key is stored.&lt;/p&gt;

&lt;p&gt;The first are known as &amp;ldquo;non-discoverable&amp;rdquo; credentials.  Here the private
key is encrypted with an embedded key in the yubikey and the encrypted
key also sent to the server.  When you attempt to login you are sent back
the encrypted private key, the yubikey can then use the embedded key to
decrypt this and then authentication happens as normal.  This is nice
because it means that you can register your device with unlimited services;
no local storage is needed.  However to login you need to tell the remote
service who you are (typically requires a login) so it can send you the
encrypted key.&lt;/p&gt;

&lt;p&gt;The second is known as &amp;ldquo;discoverable&amp;rdquo; credentials.  Here the private key
is stored directly on the yubikey.  Of course this takes up space so only
a limited number can be stored.  The advantage is that we don&amp;rsquo;t need to login
to the remote service in order to get the private key, so it can be used for
true passwordless logins.&lt;/p&gt;

&lt;p&gt;You can see what discoverable credentials are on your machine by using
the yubikey manager (you need to be Admin in Windows).&lt;/p&gt;

&lt;p&gt;e.g using a test token from &lt;a href=&#34;https://www.token2.com/tools/fido2-demo&#34;&gt;token2.com&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;C:\Program Files\Yubico\YubiKey Manager&amp;gt;ykman fido credentials list
Enter your PIN:
Credential ID  RP ID           Username                                        Display name                             
63cd48c8...    www.token2.com  token2_user_66d9dff6baa59_445105966d9dff6baa97  token2_user_66d9dff6baa59_445105966d9dff6baa97

C:\Program Files\Yubico\YubiKey Manager&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So there&amp;rsquo;s a potential difference in exposure between these credentials, and
it&amp;rsquo;s up to the server to decide what type to use.&lt;/p&gt;

&lt;p&gt;With a discoverable token then the attacker can see what sites are available
for access and which &lt;em&gt;may not&lt;/em&gt; need a password (&amp;lsquo;cos true passwordless) but
they will need the PIN.  If they have the PIN then they could retrieve the
private key for this site.&lt;/p&gt;

&lt;p&gt;For non discoverable tokens the attacker could register your key to another
site; they choose the username and password and a retrieve the master private
key.  They would still need the PIN, but this would allow them to attack
multiple sites&amp;hellip; if they knew what they were and your login details!&lt;/p&gt;

&lt;h2 id=&#34;what-about-otp-static-secrets-piv-and-pgp&#34;&gt;What about OTP, static secrets, PIV and PGP?&lt;/h2&gt;

&lt;p&gt;OTP doesn&amp;rsquo;t do this type of calculation.  It&amp;rsquo;s based on a seed value
and a generator function.  This is not impacted.&lt;/p&gt;

&lt;p&gt;Static secrets don&amp;rsquo;t do this either&amp;hellip; but if someone has your yubikey then
they can just press the button to get the secret.  Don&amp;rsquo;t use static secrets!&lt;/p&gt;

&lt;p&gt;Now, by default, PIV and PGP modes uses RSA keys for device attestation.
These are not impacted.  However a corporation &lt;em&gt;could&lt;/em&gt; replace those
attestation certs and so use ECDSA, but I&amp;rsquo;ve never thought this a good
idea; the nice thing with using the inbuilt keys from Yubico is that
you can use an off-the-shelf device straight from packaging and sent to
an user.&lt;/p&gt;

&lt;p&gt;PIV and PGP operations, however, could be done using ECDSA keys.  PIV mode
requires a PIN and PGP can be configured to use one.  Operations on RSA keys
aren&amp;rsquo;t impacted.&lt;/p&gt;

&lt;h2 id=&#34;how-easy-is-the-attack&#34;&gt;How easy is the attack?&lt;/h2&gt;

&lt;p&gt;Firstly, in order to do this attack you need access to the yubikey itself.
This isn&amp;rsquo;t that big a deal; indeed it&amp;rsquo;s recommended that people have a &lt;em&gt;backup&lt;/em&gt;
key that&amp;rsquo;s stored somewhere secure in case they lose the first one.  How
often is that backup key checked?  But physical access is needed.&lt;/p&gt;

&lt;p&gt;NinjaLab claims they only need access to the key for a few minutes, but
that doesn&amp;rsquo;t include the time needed to take apart the key, hook up into
the internals and then reseal the key afterwards.  Of course if the attacker
doesn&amp;rsquo;t care if the key is noticed as missing&amp;hellip;&lt;/p&gt;

&lt;p&gt;You need pretty expensive equipment (maybe $11,000 worth according to
&lt;a href=&#34;https://arstechnica.com/security/2024/09/yubikeys-are-vulnerable-to-cloning-attacks-thanks-to-newly-discovered-side-channel/&#34;&gt;ars Technica&lt;/a&gt;) to get the data.
I could see this coming down in price.&lt;/p&gt;

&lt;p&gt;For non-discoverable credentials you need to know what service the key has
been registered to.&lt;/p&gt;

&lt;p&gt;You may need a username and password to the service, and a PIN to access
the credential.&lt;/p&gt;

&lt;p&gt;So it&amp;rsquo;s not &lt;em&gt;easy&lt;/em&gt; to do, but it&amp;rsquo;s not out of the realm of possibility.
ars thinks &amp;ldquo;nation-state&amp;rdquo; level attackers but there may be more than
that if the return is more than the cost.&lt;/p&gt;

&lt;h2 id=&#34;mitigations&#34;&gt;Mitigations&lt;/h2&gt;

&lt;p&gt;I believe a PIN will help block attacks because it&amp;rsquo;s another thing the
attacker needs to have in order to perform the side channel attack.
As long as the PIN isn&amp;rsquo;t set to the default value, of course!  Yubikeys
only allow limited number of PIN retries before the application is locked
and the secrets unreadable.  PINs are harder to get than username/password
information because the UI presented makes it harder to be phished.  But
it&amp;rsquo;s not impossible and keylogger malware would have access.&lt;/p&gt;

&lt;p&gt;So definitely ensure any yubikeys in your environment are configured to
require PINs and that the PIN isn&amp;rsquo;t set to the default.  Note than &amp;ldquo;PIN&amp;rdquo; is
a bit of a misnomer for yubikey; it can contain more than numbers, so allow
alphanumerics in whatever app you provide for management of PIV/PGP certs.&lt;/p&gt;

&lt;p&gt;Obviously use of RSA keys, rather than ECDSA, will block this attack.&lt;/p&gt;

&lt;p&gt;Train staff to report missing keys immediately and have processes (SOC or
even helpdesk) to revoke the token.&lt;/p&gt;

&lt;p&gt;Require staff to verify they know where the backup key is (maybe force them
to use it once a month?).&lt;/p&gt;

&lt;p&gt;Wrap keys with tamper-evident seals with unique numbers (this will be annoying
since it means off-the-shelf keys aren&amp;rsquo;t allowed, and it&amp;rsquo;s not enforceable,
but it&amp;rsquo;d help) so that evidence of the key being taken apart is obvious.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;It seems that the &amp;ldquo;big&amp;rdquo; risk is U2F/FIDO mode.  Exposure could allow an
attacker to authenticate as a user.  But it&amp;rsquo;s not necessarily easy.&lt;/p&gt;

&lt;p&gt;Do you need to worry about it?  Or this is just yet another theoretical
attack?  That&amp;rsquo;s a risk management decision.  Use of these &amp;ldquo;vulnerable&amp;rdquo;
keys will still prevent most attacks on your users.  It&amp;rsquo;s a targeted
well financed attacker that&amp;rsquo;s the worry.&lt;/p&gt;

&lt;p&gt;It may be that you would want to take a tiered approach; staff with
access to highly sensitive data may need a new key with fixed firmware,
but staff who just use it to access their laptop to read email don&amp;rsquo;t
need an upgrade.&lt;/p&gt;

&lt;p&gt;Hmm, I wonder how many vulnerable devices are still in the supply chain?
I assume anything bought direct will have the new firmware, but what
about if you buy from Amazon; will they still have old keys warehoused?&lt;/p&gt;

&lt;p&gt;The main question I have, though, is where &lt;em&gt;else&lt;/em&gt; this chipset and library
has been used?  What other devices may be vulnerable?&lt;/p&gt;

&lt;p&gt;After all, it&amp;rsquo;s not the first time NinjaLab have &lt;a href=&#34;https://arstechnica.com/information-technology/2021/01/hackers-can-clone-google-titan-2fa-keys-using-a-side-channel-in-nxp-chips/&#34;&gt;broken hardware tokens&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And, of course, remember
&lt;a href=https://xkcd.com/538/&gt;538
&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/xkcd-security.png&#34; alt=&#34;XKCD&#34;&gt;
&lt;/div&gt;

&lt;/a&gt;
&lt;/center&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Crowdstrike issues</title>
      <link>https://www.sweharris.org/post/2024-07-19-crowdstrike/</link>
      <pubDate>Fri, 19 Jul 2024 14:28:30 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2024-07-19-crowdstrike/</guid>
      <description>

&lt;p&gt;I was asked about today&amp;rsquo;s &lt;a href=&#34;https://www.theregister.com/2024/07/19/crowdstrike_falcon_sensor_bsod_incident&#34;&gt;Crowdstrike issues&lt;/a&gt; on Windows.&lt;/p&gt;

&lt;p&gt;Naturally I have some thoughts&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;what-went-wrong-what-i-know&#34;&gt;What went wrong?  What I know.&lt;/h2&gt;

&lt;p&gt;Crowdstrike is an EDR (Endpoint Detection and Response) tool.  (Well,
they claim &amp;ldquo;XDR&amp;rdquo;, but that&amp;rsquo;s marketing).  It has an agent component
and a set of rule sets (called &amp;ldquo;channel file&amp;rdquo;).  The agent has both
user space and kernel space components to better give visibility into
what is happening on the machine, and to be able to block bad things.
It&amp;rsquo;s &lt;em&gt;not&lt;/em&gt; an AV solution (&amp;ldquo;Oh, this is a known bad file; we&amp;rsquo;ll block it&amp;rdquo;)
but it intercepts calls at runtime and determines if this is legitimate
behaviour or not.&lt;/p&gt;

&lt;p&gt;So Crowdstrike can act both as a visibility tool (it can tell you &lt;em&gt;every&lt;/em&gt;
process ever executed on your machines) and a defense tool (block bad stuff).&lt;/p&gt;

&lt;p&gt;Now, in common with a lot of tools like this we need to keep both the agent
and the channel files up to date; the agent needs to handle platform changes (eg
a change in drivers or kernel structures) and the channel files need to be kept up
to date to handle new threats and attacks.&lt;/p&gt;

&lt;p&gt;Many organisations have requirements around roll out of new agents (e.g. test
in a lab and then do a risk-based deployment; e.g. to dev then qa/cat and
finally to prod) to minimise production outages.&lt;/p&gt;

&lt;p&gt;In the case of Crowdstrike the channel files are automatically updated and this
is where the problem occurred.  Something in the channel files deployed at 04:09
UTC broke Windows causing it to BSOD.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Crowdstrike deployed a new set of files at 05:27 UTC and so any machine
off network in that window should not have been impacted.  Hopefully!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;complications&#34;&gt;Complications&lt;/h2&gt;

&lt;p&gt;This isn&amp;rsquo;t a one-off BSOD; it also crashes the machine early in the reboot
process; potentially too early for the agent to pick up the fixed update.
(I&amp;rsquo;ve seen a tweet where someone claimed multiple reboots did resolve it
through luck, but that was just a one-off).  So, essentially, this will
require human intervention on every affected machine.&lt;/p&gt;

&lt;p&gt;Crowdstrike have &lt;a href=&#34;https://www.crowdstrike.com/blog/statement-on-falcon-content-update-for-windows-hosts/&#34;&gt;provided instructions&lt;/a&gt;
on how to fix and delete the bad file.&lt;/p&gt;

&lt;p&gt;OK, that&amp;rsquo;s painful but it&amp;rsquo;s not impossible.  Especially on servers.&lt;/p&gt;

&lt;p&gt;More worrying could be end user devices (laptops, VDIs, etc) that are impacted.
These instructions are not the sort of thing you&amp;rsquo;d expect your typical
end user to perform; they may not even have the necessary knowledge (no local
admin access).  And yet more complication is that it&amp;rsquo;s more likely for end
user devices will have Bitlocker on them!  Devices in the office can have
help desk people run around and do the work, but what about those working
from home?  Or salesmen in the field?&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Because of when the bad files were pushed, We can hope that a lot of these
machines were shutdown or in standby mode and so missed the update!  Well,
in EMEA and AMER regions, anyway.  APAC will have been in the middle of
the work day.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;haven-t-we-seen-this-before&#34;&gt;Haven&amp;rsquo;t we seen this before?&lt;/h2&gt;

&lt;p&gt;Yes!  In 2019 a &lt;a href=&#34;https://www.theregister.com/2019/10/15/blue_screen_of_death_symantec/&#34;&gt;Symantec SEP
update&lt;/a&gt;
did almost exactly the same thing.  AV tools have, in the past, also tried
quarantining windows components because of bad signature files.&lt;/p&gt;

&lt;h2 id=&#34;so-we-shouldn-t-auto-download-new-rules&#34;&gt;So we shouldn&amp;rsquo;t auto-download new rules?&lt;/h2&gt;

&lt;p&gt;Definitely agents should have a planned deployment.  But what about the rules?
This is where we need to look at the risks.&lt;/p&gt;

&lt;p&gt;So what do up-to-date rules give us?  Protection against the latest attacks;
you may defended before you&amp;rsquo;re even aware of the threat because companies
like Crowdstrike had lots of threat intelligence streams and see indicators
of compromise and create rules to defend against them very early!  It may not
defend you against a novel zero-day attack, but it should prevent a day-1
attack.&lt;/p&gt;

&lt;p&gt;The question you need to ask yourself is &lt;em&gt;how many&lt;/em&gt; of these attacks have
been defended against, and how much it would have cost to recover (dollars,
reputation, lost current/future customers&amp;hellip;).  How quickly would a
compromise spread?  Do you have secondary controls that would minimise
impact?&lt;/p&gt;

&lt;p&gt;You do have a measure of that, right?  You are monitoring your EDR logs to
see what has been prevented; what are day-1?  Many potential attacks may
already be prevented by other tools (eg mail gateways blocking malware),
so the day-1 risk might not be as high as it could be.  But it&amp;rsquo;s not zero,
otherwise we wouldn&amp;rsquo;t need tools like this!&lt;/p&gt;

&lt;p&gt;You also need to look into how quickly your team would be able to validate
new channel files.  Are you able to perform a test suite daily?  Or would
new rules be delayed a week?  How much can you automate this?  Basically
how big would your vulnerability window be.&lt;/p&gt;

&lt;p&gt;EDITED TO ADD based on feedback elsewhere.  We also need to consider
cost of remediation.  In this type of outage you have a level
of comfort that no sensitive data was accessed.  (Unless it&amp;rsquo;s a
&lt;a href=&#34;https://en.wikipedia.org/wiki/SolarWinds#SUNBURST&#34;&gt;solarwinds&lt;/a&gt; type
issue&amp;hellip;).  An exploit that wasn&amp;rsquo;t prevented due to having out of date
rules has additional monetary cost (patching, investigation, regulatory
reporting, law enforcement, etc) that may go on long after the event
was detected.&lt;/p&gt;

&lt;p&gt;These three factors (window, number of attacks prevented, cost) all weigh
into the risk.&lt;/p&gt;

&lt;p&gt;On the other side we have the risk of outages like this.   Impact is
massive, but since it seems almost &lt;em&gt;everybody&lt;/em&gt; is impacted (yeah,
an exaggeration, but not much of one) the chance of it causing you
reputational impact and customer loss is a lot less.&lt;/p&gt;

&lt;p&gt;What I do believe is that companies that provide rule sets like this (EDR, AV,
etc) should provide the &lt;em&gt;option&lt;/em&gt; to allow companies to decide for themselves.
Perhaps they could run their own &amp;ldquo;day 0&amp;rdquo; and &amp;ldquo;day 1 deferred&amp;rdquo; channels; a
company could have most machines on &amp;ldquo;day 1&amp;rdquo; with a set of test machines on
&amp;ldquo;day 0&amp;rdquo;; if a test machine blows up they can hit the big red switch to halt
production deployments.&lt;/p&gt;

&lt;h2 id=&#34;so-if-we-should-keep-doing-updates-how-do-we-mitigate-this&#34;&gt;So if we should keep doing updates, how do we mitigate this?&lt;/h2&gt;

&lt;p&gt;Traditional active-active or even warm-standby DR systems would have also
picked up the new rules and died at the same time as production.  Oops!
So if your vendor product &lt;em&gt;does&lt;/em&gt; have staggered &amp;ldquo;day 0&amp;rdquo; and &amp;ldquo;day 1&amp;rdquo;
type channels then it&amp;rsquo;s worth thinking about having the prod/dr systems
on different schedules.  It may even be worth thinking about having DR &lt;em&gt;ahead&lt;/em&gt;
of production so if they die it won&amp;rsquo;t cause outages.&lt;/p&gt;

&lt;p&gt;We also need to think about disk snapshots; could we roll back the machine
to a state before it got the bad files?  On a VM this is perfectly possible,
but we need to be aware than any changes will be lost; audit logs, activity
logs etc will be lost.  These might be critical (regulatory) so get those
logs off the machine ASAP (streaming to a remote store; put them on a NAS
share; something&amp;hellip;).  Try to make what &lt;em&gt;changes&lt;/em&gt; on a machine to be as small
as possible.&lt;/p&gt;

&lt;p&gt;Could we automate deployments?  How quickly can you spin up new
infrastructure and deploy your apps?  If you&amp;rsquo;re in a modern shop with
effective CI/CD pipelines this may already be part of your deployment
process (especially in the cloud); recovery is &amp;ldquo;deploy new!&amp;rdquo;&lt;/p&gt;

&lt;p&gt;Or, similarly, how much of the app needs to be deployed locally, vs
stored on a NAS?  If a new VM can be spun up and connects to a P: drive
(P for aPP!) and auto-starts&amp;hellip;&lt;/p&gt;

&lt;p&gt;What about old-school cold-standby instances that just get sync&amp;rsquo;d once a day?&lt;/p&gt;

&lt;p&gt;What about &amp;ldquo;dual boot&amp;rdquo; scenarios, similar to how appliances get handled?
A TiVo (for example) has two OS partitions; an active one and an inactive.
When an update comes in it gets written to the inactive partition, validated,
and then the &amp;ldquo;active&amp;rdquo; flag gets switched.  We can&amp;rsquo;t quite do this with
Windows but possibly a second partition that&amp;rsquo;s sync&amp;rsquo;d from &amp;ldquo;active&amp;rdquo; on a
nightly basis and a boot loader that will allow for booting from that second
partition.&lt;/p&gt;

&lt;p&gt;End users also need to be thought about; if we make their device as close to
zero-permanence as possible (all data files stored on OneDrive or Google Drive
or NAS; nothing on C:) then if that dies we can spin up new VDIs (even cloudy
ones like Windows365 or Amazon Workspaces) and get the back working again.
At least email and chat and common stuff&amp;hellip;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m just spit-balling ideas here!&lt;/p&gt;

&lt;p&gt;There will always be edge cases, but if we can standardize and make the
endpoint as &amp;ldquo;irrelevant&amp;rdquo; as possible (basically just provide compute power)
then recovery becomes quicker.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;It&amp;rsquo;s easy to point fingers at Crowdstrike and say &amp;ldquo;you fucked up&amp;rdquo;.
Well, they did!  It will be interesting to see what went wrong,
and what controls they put in place to prevent a similar occurrence.
Other companies in the same areas (EDR, AV, etc) also need to learn
these lessons so they don&amp;rsquo;t suffer the same problems in the future.&lt;/p&gt;

&lt;p&gt;But as a customer you don&amp;rsquo;t want to be too nervous and change your
processes.  You need to evaluate the risk.  It&amp;rsquo;s very possible this
once-in-a-blue-moon event is less damaging than other courses of action.&lt;/p&gt;

&lt;p&gt;Get the data, evaluate your environment, determine what mitigations you
can put in place and &lt;em&gt;then&lt;/em&gt; come up with a plan.  Don&amp;rsquo;t just take the
easy path of deferring rule updates for a day or two (or seven!) because
that might expose you to greater risk than getting regular updates pushed
live to prod!&lt;/p&gt;

&lt;p&gt;Having the option would be nice, though.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Building a home router</title>
      <link>https://www.sweharris.org/post/2024-07-18-home-router-redux/</link>
      <pubDate>Thu, 18 Jul 2024 14:52:43 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2024-07-18-home-router-redux/</guid>
      <description>

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;WARNING: technical content ahead!  There&amp;rsquo;s also a tonne of config files,
which make this page look longer than it really is, but hopefully they&amp;rsquo;ll
help other people who want to do similar work.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Back in 2017 I described &lt;a href=&#34;https://www.sweharris.org/post/2017-05-07-home-grown-router/&#34;&gt;how to build a home router&lt;/a&gt; based on CentOS 7.&lt;/p&gt;

&lt;p&gt;C7 is now out of date, so I figured it was time to rebuild it, this time using
Rocky Linux 9.  That should give me another 8 years of security patches!&lt;/p&gt;

&lt;p&gt;My requirements were mostly the same, but I wasn&amp;rsquo;t going to use WiFi on the
machine; I&amp;rsquo;d already &lt;a href=&#34;https://www.sweharris.org/post/2020-07-25-extending_router/&#34;&gt;replaced that with Access Points&lt;/a&gt;.  I also wasn&amp;rsquo;t so much with IPv6 any more; this is mostly because
the Hurricane Electric &lt;a href=&#34;https://tunnelbroker.net&#34;&gt;tunnelbroker&lt;/a&gt; IP addresses
were on a lot of &amp;ldquo;low reputation&amp;rdquo; lists, and I was getting annoyed with that.
I still use IPv6 but only specific machines, with a static configuration,
use it.&lt;/p&gt;

&lt;p&gt;I figured it was also time to get a new machine.  There are a LOT of cheap
hand-sized computers, these days, including some dual port ones.  I went
for a &lt;a href=&#34;https://www.amazon.com/dp/B0CW38KGWJ&#34;&gt;CTone Mini PC&lt;/a&gt;; 8GB RAM, 256Gb
SSD, dual 1Gbit NICs.  Sounded perfect.  Unfortunately it wasn&amp;rsquo;t.  It uses
RTL chipsets, which appear to be less performant than the existing machine
with Intel NICs; it &lt;em&gt;worked&lt;/em&gt; but speed test results were consistently 100Mbit/s
slower.  So I got a new SSD for my old machine and built fresh on that.  If
I failed to get it to work then I could just put the old SSD back in.  The new
slow machine isn&amp;rsquo;t wasted though; it&amp;rsquo;s now a backup just in case my primary
ever fails.&lt;/p&gt;

&lt;h2 id=&#34;basic-networking&#34;&gt;Basic networking&lt;/h2&gt;

&lt;h3 id=&#34;requirements&#34;&gt;Requirements&lt;/h3&gt;

&lt;p&gt;At home I have 3 VLANS; 10 (LAN), 11 (guestnet), 12 (IoT).  Although I no
longer need to (no wireless) I&amp;rsquo;m going to keep using bridges for everything
and I&amp;rsquo;m going to keep using the old name.&lt;/p&gt;

&lt;p&gt;So, to summarize, the result would look something like&lt;/p&gt;

&lt;table border=1&gt;
&lt;tr&gt;
  &lt;th&gt;Use&lt;/th&gt;
  &lt;th&gt;Bridge&lt;/th&gt;
  &lt;th&gt;Interface&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;Internet&lt;/td&gt;
  &lt;td&gt;br-wan&lt;/td&gt;
  &lt;td&gt;enp2s0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;LAN&lt;/td&gt;
  &lt;td&gt;br-lan&lt;/td&gt;
  &lt;td&gt;enp3s0.10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;Guest&lt;/td&gt;
  &lt;td&gt;br-guest&lt;/td&gt;
  &lt;td&gt;enp3s0.11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;IoT&lt;/td&gt;
  &lt;td&gt;br-iot&lt;/td&gt;
  &lt;td&gt;enp3s0.12&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;For simplicity, I&amp;rsquo;m going to assign &lt;code&gt;enp2s0&lt;/code&gt; to &lt;code&gt;$WAN&lt;/code&gt;, and &lt;code&gt;enp3s0&lt;/code&gt; to &lt;code&gt;$LAN&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&#34;wan&#34;&gt;WAN&lt;/h3&gt;

&lt;p&gt;First we need to make sure there&amp;rsquo;s no existing connections defined from the
OS install.  This can be done with the &lt;code&gt;nmcli con show&lt;/code&gt; command.  If you
see anything like &lt;code&gt;Wired connection 1&lt;/code&gt; then you should delete them with
&lt;code&gt;nmcli con del ...&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;You will lose network access doing this, so make sure you&amp;rsquo;re on the
console!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Bridges are created with &lt;code&gt;nmcli connection add type bridge ...&lt;/code&gt; and interfaces
are associated with it with &lt;code&gt;nmcli connection add type bridge-slave ...&lt;/code&gt;
commands.&lt;/p&gt;

&lt;p&gt;So the WAN interface would be created with&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;nmcli device set $WAN autoconnect yes

nmcli connection add type bridge con-name br-wan ifname br-wan bridge.stp no ipv4.method auto ipv4.dns &amp;quot;10.0.0.1 10.0.0.5&amp;quot; ipv4.dns-search &amp;quot;spuddy.org&amp;quot; ipv6.method disabled
nmcli connection add type bridge-slave con-name $WAN ifname $WAN master br-wan
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this I am hard-coding my internal DNS servers (this machine and my backup
DNS server) and DNS search path.&lt;/p&gt;

&lt;p&gt;Woohoo!  At this point the machine should(!) have internet access.&lt;/p&gt;

&lt;h3 id=&#34;internal-vlans&#34;&gt;Internal VLANs&lt;/h3&gt;

&lt;p&gt;Similarly we can define the 3 VLANs and bridges.  &lt;code&gt;br-lan&lt;/code&gt; will have a static
IPv6 address, but the rest just have IPv4.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;nmcli device set $LAN autoconnect no

nmcli connection add type bridge con-name br-lan ifname br-lan bridge.stp no ip4 10.0.0.1/24 ipv6.method manual ipv6.address 2001:470:1f07:dc4::1/64
nmcli connection add type vlan con-name $LAN.10 ifname $LAN.10 vlan.parent $LAN vlan.id 10 slave-type bridge master br-lan
nmcli device set $LAN.10 autoconnect yes

nmcli connection add type bridge con-name br-guest ifname br-guest bridge.stp no ip4 10.100.100.1/24 ipv6.method disabled
nmcli connection add type vlan con-name $LAN.11 ifname $LAN.11 vlan.parent $LAN vlan.id 11 slave-type bridge master br-guest
nmcli device set $LAN.11 autoconnect yes

nmcli connection add type bridge con-name br-iot ifname br-iot bridge.stp no ip4 10.100.200.1/24 ipv6.method disabled
nmcli connection add type vlan con-name $LAN.12 ifname $LAN.12 vlan.parent $LAN vlan.id 12 slave-type bridge master br-iot
nmcli device set $LAN.12 autoconnect yes
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can now see how this looks:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# nmcli dev
DEVICE     TYPE      STATE                   CONNECTION
br-wan     bridge    connected               br-wan
br-lan     bridge    connected               br-lan
br-guest   bridge    connected               br-guest
br-iot     bridge    connected               br-iot
enp2s0     ethernet  connected               enp2s0
enp3s0.10  vlan      connected               enp3s0.10
enp3s0.11  vlan      connected               enp3s0.11
enp3s0.12  vlan      connected               enp3s0.12
lo         loopback  connected (externally)  lo
enp3s0     ethernet  disconnected            --
enp1s0     ethernet  unavailable             --

# nmcli con
NAME              UUID                                  TYPE       DEVICE
br-wan            0102b304-effc-4437-a70a-aa3360d4d3e0  bridge     br-wan
br-lan            acf41256-e68b-40a8-a85a-944eb95035a6  bridge     br-lan
br-guest          a3c962bb-e605-46aa-8d43-7cb9db4ebad1  bridge     br-guest
br-iot            f7715bbd-1a7c-41fb-bfb0-5ddc2900048a  bridge     br-iot
enp2s0            e966376e-39e5-4789-aaaa-5a2c0154323d  ethernet   enp2s0
enp3s0.10         bfd85eca-989c-499c-89d2-cb4f57d0cde9  vlan       enp3s0.10
enp3s0.11         a63e60ce-e808-499e-bfb1-aedb5ee83541  vlan       enp3s0.11
enp3s0.12         2d775836-ab3b-4ccb-a120-c32e2ec0efc7  vlan       enp3s0.12
lo                f63cce44-1aed-467f-bd27-96348e58c8f2  loopback   lo
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we install the old &lt;code&gt;bridge-utils&lt;/code&gt; package (from EPEL) we can also see
very simply the bridge configurations&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% brctl show
bridge name     bridge id               STP enabled     interfaces
br-guest        8000.000db9439cce       no              enp3s0.11
br-iot          8000.000db9439cce       no              enp3s0.12
br-lan          8000.000db9439cce       no              enp3s0.10
br-wan          8000.000db9439ccd       no              enp2s0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And IP addresses can be seen with &lt;code&gt;ip -4 a&lt;/code&gt;.  So far so good!&lt;/p&gt;

&lt;h3 id=&#34;config-files&#34;&gt;Config files.&lt;/h3&gt;

&lt;p&gt;NetworkManager is not meant to be manipulated via config files (I much prefer
the old &lt;code&gt;/etc/sysconfig/network-scripts&lt;/code&gt;) but there are files we can look at,
in &lt;code&gt;/etc/NetworkManager/system-connections&lt;/code&gt;.  e.g.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% ls /etc/NetworkManager/system-connections/
br-guest.nmconnection  br-wan.nmconnection     enp3s0.11.nmconnection
br-iot.nmconnection    enp2s0.nmconnection     enp3s0.12.nmconnection
br-lan.nmconnection    enp3s0.10.nmconnection
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;ipv6&#34;&gt;IPv6&lt;/h3&gt;

&lt;p&gt;Hurricane Electric IPv6 tunnels are very easy to set up.  You need three
values; the tunnelbroker endpoint IPv4 address, and the two IPv6 address
associated with each end.  These will probably be &amp;hellip;.::2 for your end,
and &amp;hellip;.::1 for their end.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;nmcli connect add type ip-tunnel ifname he-sit mode sit remote $ipv4address ipv4.method disabled ipv6.method manual ipv6.address $connection::2/64 ipv6.gateway $connection::1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will show up under &lt;code&gt;nmcli con&lt;/code&gt; and &lt;code&gt;nmcli dev&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% nmcli dev | grep he-sit
he-sit     iptunnel  connected               ip-tunnel-he-sit

% nmcli con | grep he-sit
ip-tunnel-he-sit  6840bf43-8275-4ccc-88a1-6ff16caabea2  ip-tunnel  he-sit
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The tunnel should come up (if your IPv4 address is correct on the HE end)
and we can see this in &lt;code&gt;ip -6 a&lt;/code&gt; output&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
24: he-sit@NONE: &amp;lt;POINTOPOINT,NOARP,UP,LOWER_UP&amp;gt; mtu 1480 state UNKNOWN qlen 1000
    inet6 _connection_::2/64 scope global noprefixroute
       valid_lft forever preferred_lft forever
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If all is going well, &lt;code&gt;ping6 google.com&lt;/code&gt; should work!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;PING google.com(lga25s41-in-x0e.1e100.net (2607:f8b0:4006:80f::200e)) 56 data bytes
64 bytes from lga25s41-in-x0e.1e100.net (2607:f8b0:4006:80f::200e): icmp_seq=1 ttl=119 time=9.21 ms
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now HE uses your IPv4 address to validate the tunnel is allowed to be
established.  If you&amp;rsquo;re on a dynamic IP then a simple script that calls
their API would work.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;PASS=YOUR_PASSWORD
USERID=YOUR_USERNAME
GTUNID=YOUR_TUNNEL_ID
HOST=https://$USERID:$PASS@ipv4.tunnelbroker.net

newip=$1

# Check to see what the end point currently is
x=$(wget -q --no-check-certificate -O - $HOST/tunnelInfo.php?tid=$GTUNID | sed -n &#39;s/^.*&amp;lt;clientv4&amp;gt;\(.*\)&amp;lt;.*$/\1/p&#39;)

if [ &amp;quot;x$x&amp;quot; == &amp;quot;x$newip&amp;quot; ]
then
  echo Tunnel IP is already correct
  exit
fi

wget -q --no-check-certificate -O - &amp;quot;$HOST/nic/update?hostname=$GTUNID&amp;amp;myip=$newip&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;firewalls-and-routing&#34;&gt;Firewalls and routing&lt;/h2&gt;

&lt;p&gt;That&amp;rsquo;s the low level plumbing done.  Now to make it look like a router&lt;/p&gt;

&lt;h3 id=&#34;forwarding&#34;&gt;Forwarding&lt;/h3&gt;

&lt;p&gt;Routers need to forward packets&amp;hellip;  This is done by setting &lt;code&gt;sysctl&lt;/code&gt; options.
They can be made to persist by putting them into a config file; e.g.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat /etc/sysctl.d/forward.conf
net.ipv4.ip_forward = 1
net.ipv4.conf.all.forwarding = 1
net.ipv6.conf.all.forwarding = 1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At this point the 3 VLANs can see each other.  Unrestricted and there&amp;rsquo;s no
internet access, but we&amp;rsquo;re getting there!&lt;/p&gt;

&lt;h2 id=&#34;firewalld&#34;&gt;firewalld&lt;/h2&gt;

&lt;p&gt;RL9 has two ways that can manipulate network table rules; the first is
&lt;code&gt;firewalld&lt;/code&gt;, and the second is to use &lt;code&gt;nftables&lt;/code&gt; directly.&lt;/p&gt;

&lt;p&gt;I prefer &lt;code&gt;nftables&lt;/code&gt;, so we need to disable &lt;code&gt;firewalld&lt;/code&gt; and enable `nftables&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# systemctl disable --now firewalld
# systemctl mask firewalld
# systemctl enable --now nftables
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;nftables&#34;&gt;nftables&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;m going to look at this similarly to how &lt;code&gt;iptables&lt;/code&gt; did it.  We have
standard rules (INPUT/OUTPUT/FORWARD) we have to look at them from the
perspective of the router. INPUT rules are those that impact packets that
are targeted at the router; OUTPUT rules are those that originate from
the router; FORWARD rules are those that pass &lt;em&gt;through&lt;/em&gt; the router. This
gets important for NAT where the packet targets the router&amp;rsquo;s external
IP address.  Similarly for NAT rules we have PREROUTING and POSTROUTING.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nftables&lt;/code&gt; has a bit more &amp;ldquo;fluff&amp;rdquo; needed to create the necessary structures,
so that&amp;rsquo;s where we start&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Clear out all the rules
flush ruleset

# Create empty structures
add table ip filter
add table ip nat
add table ip6 filter
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&amp;rsquo;m also going to define some structures that we&amp;rsquo;ll use later.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;add map nat fport { type inet_service : interval ipv4_addr . inet_service ; flag
s interval; }
add set ip nat reflect { type inet_service; }
add set ip nat this_host { type ipv4_addr; }

add set ip6 filter my_hosts { type ipv6_addr; }
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;ipv4&#34;&gt;IPv4&lt;/h3&gt;

&lt;p&gt;We can now start building the IPv4 rules.  Let&amp;rsquo;s create the 3 standard chains
and 2 more chains that will be used for logging of packets&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;add chain ip filter INPUT { type filter hook input priority 0; policy accept; }
add chain ip filter OUTPUT { type filter hook output priority 0; policy accept; }
add chain ip filter FORWARD { type filter hook forward priority 0; policy accept; }

# Log rules for input and forwarding
add chain ip filter LOGGER
add chain ip filter LOGGERF
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The logging rules are pretty simple.  We limit how many can be sent, to
avoid DoSing ourselves with log messages!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Logging rule for INPUT drops
add rule ip filter LOGGER limit rate 2/minute burst 5 packets counter log prefix &amp;quot;IPTables-Dropped: &amp;quot;
add rule ip filter LOGGER counter drop

# Logging rule for FORWARD drops
add rule ip filter LOGGERF limit rate 2/minute burst 5 packets counter log prefix &amp;quot;IPTables-Dropped-Forward: &amp;quot;
add rule ip filter LOGGERF counter drop
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we can handle INPUT rules (remember, this is traffic meant for this
machine, and it may come from any of the VLANs or internet).  We want to
allow all traffic from the LAN; guestnet and IoT have limited access.
Everything else should be blocked.  Remember, we&amp;rsquo;re only talking about
traffic targeting the router; we&amp;rsquo;ll get to port forwarding later.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Allow traffic for established connections, blocking invalid header format
add rule ip filter INPUT ct state related,established counter accept
add rule ip filter INPUT ct state invalid counter drop

# All localhost traffic allowed
add rule ip filter INPUT iifname &amp;quot;lo&amp;quot; counter accept

# The LAN can see this machine
add rule ip filter INPUT iifname &amp;quot;br-lan&amp;quot; counter accept

# Allow the world to ping this machine (amongst other things)
add rule ip filter INPUT ip protocol icmp counter accept

# Let guestnet and IoT see DNS servers on this machine (tcp+udp)
add rule ip filter INPUT iifname &amp;quot;br-guest&amp;quot; tcp dport 53 counter accept
add rule ip filter INPUT iifname &amp;quot;br-guest&amp;quot; udp dport 53 counter accept
add rule ip filter INPUT iifname &amp;quot;br-guest&amp;quot; tcp dport 853 counter accept
add rule ip filter INPUT iifname &amp;quot;br-guest&amp;quot; udp dport 853 counter accept

# IoT may also need NTP access
add rule ip filter INPUT iifname &amp;quot;br-iot&amp;quot; tcp dport 53 counter accept
add rule ip filter INPUT iifname &amp;quot;br-iot&amp;quot; udp dport 53 counter accept
add rule ip filter INPUT iifname &amp;quot;br-iot&amp;quot; udp dport 123 counter accept

# Log block traffic; this could be noisy, so only enable it if you
# want lots of logs!
## add rule ip filter INPUT counter jump LOGGER

# Block all other incoming traffic
add rule ip filter INPUT counter drop
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;OUTPUT rules are very simple.  We allow everything, because this is just
for traffic that originated on this machine.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;add rule ip filter OUTPUT ct state related,established counter accept
add rule ip filter OUTPUT ct state invalid counter drop
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we need to allow traffic from our internal networks to see the internet.
I&amp;rsquo;m also going to add a special rule; if my mobile is on guestnet then it
can see the whole of the WAN.&lt;/p&gt;

&lt;p&gt;There are also some other special rules (eg allow guests to see my printer)
that we need to handle&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Allow established connections to work, blocking invalid header format
add rule ip filter FORWARD ct state related,established counter accept
add rule ip filter FORWARD ct state invalid counter drop

# Allow the LAN to see the world
add rule ip filter FORWARD iifname &amp;quot;br-lan&amp;quot; counter accept

# Allow return traffic for NAT&#39;d connections to work
add rule ip filter FORWARD iifname &amp;quot;br-wan&amp;quot; ct status dnat counter accept

# Allow my mobile devices to have access to everything
add rule ip filter FORWARD iifname &amp;quot;br-guest&amp;quot; ip saddr 10.100.100.8 counter accept

# Allow guestnet to see the printer
add rule ip filter FORWARD iifname &amp;quot;br-guest&amp;quot; ip daddr 10.0.0.10 counter accept

# Allow guestnet devices to see my MQTT server
add rule ip filter FORWARD iifname &amp;quot;br-guest&amp;quot; oifname &amp;quot;br-lan&amp;quot; tcp dport 1883 counter accept

# Allow guestnet to see the internet
add rule ip filter FORWARD iifname &amp;quot;br-guest&amp;quot; oifname &amp;quot;br-wan&amp;quot; counter accept

# Allow IoT devices to see my MQTT server
add rule ip filter FORWARD iifname &amp;quot;br-iot&amp;quot; oifname &amp;quot;br-lan&amp;quot; tcp dport 1883 counter accept

# Allow ESP8266 devices on IoT to be network updates
# (The process causes the ESP8266 to call back to a webserver on the host)
add rule ip filter FORWARD iifname &amp;quot;br-iot&amp;quot; oifname &amp;quot;br-lan&amp;quot; tcp dport 8266 counter accept

# Allow IoT devices to see the internet
add rule ip filter FORWARD iifname &amp;quot;br-iot&amp;quot; oifname &amp;quot;br-wan&amp;quot; counter accept

# Allow marked traffic (ie reflected traffic) to reach the destination
add rule ip filter FORWARD meta mark 100 counter accept

# Log and block all other forwarded traffic
add rule ip filter FORWARD counter jump LOGGERF
add rule ip filter FORWARD counter drop
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;nat&#34;&gt;NAT&lt;/h3&gt;

&lt;p&gt;OK!  We have connectivity on the internal network, now we need to set up the
NAT rules to allow the internal network to SNAT (source NAT) to reach the
internet, and to allow the internet to DNAT (destination NAT) to allow it
to reach specific internal services.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s also an odd edge-case.  If you&amp;rsquo;re on the guest network and try to
reach an internal service via the external IP address (e.g. a web server)
then it all breaks.  This is because the incoming traffic doesn&amp;rsquo;t arrive
via the &lt;code&gt;br-wan&lt;/code&gt; interface and so isn&amp;rsquo;t NAT&amp;rsquo;d.  In &lt;code&gt;iptables&lt;/code&gt; days we used
a set of &amp;ldquo;reflection&amp;rdquo; rules (see the earlier blog entry about this).  With
&lt;code&gt;nftables&lt;/code&gt; we can be smarter.  We can set up some rules that use sets and
maps to hold the information.&lt;/p&gt;

&lt;p&gt;So to define incoming port connections and those we want reflected:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Port forwarding for incoming traffic

add element nat fport { 80 : 10.0.0.100 . 80 }   # http
add element nat fport { 443 : 10.0.0.100 . 443 } # https
add element nat fport { 22 : 10.0.0.110 . 22 }   # ssh
add element nat fport { 6881-6999 : 10.0.0.120 . 6881-6999 } # RL9 torrents

# These ports should be reflected.  Basically the ports from fport that
# people might want to access
add element nat reflect { 80, 443, 22 }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We&amp;rsquo;re now in a position to define a set of rules&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;add chain ip nat INPUT { type nat hook input priority 100; policy accept; }
add chain ip nat OUTPUT { type nat hook output priority -100; policy accept; }
add chain ip nat PREROUTING { type nat hook prerouting priority -100; policy accept; }
add chain ip nat POSTROUTING { type nat hook postrouting priority 100; policy accept; }

# Log specific incoming traffic
add rule ip nat PREROUTING iifname &amp;quot;br-wan&amp;quot; tcp dport 22 limit rate 2/minute burst 5 packets counter log prefix &amp;quot;IPTables-New-SSH: &amp;quot;

# Tag internal reflection traffic
add rule ip nat PREROUTING ip saddr 10.0.0.0/8 ip daddr @this_host tcp dport @reflect mark set 100

# DNAT incoming traffic from the internet (or internal send to br-wan address)
add rule ip nat PREROUTING ip daddr @this_host ip protocol tcp dnat ip  addr . port to tcp dport map @fport

# Do NAT on egress traffic to the internet
add rule ip nat POSTROUTING oifname &amp;quot;br-wan&amp;quot; counter masquerade

# Also NAT marked traffic from internal to external IP
add rule ip nat POSTROUTING meta mark 100 counter masquerade
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;this-host&#34;&gt;@this_host&lt;/h3&gt;

&lt;p&gt;You might have noticed the &lt;code&gt;@this_host&lt;/code&gt; rules.  This refers to the set we
defined earlier&amp;hellip; but we haven&amp;rsquo;t populated it, yet!&lt;/p&gt;

&lt;p&gt;There are two rules that work by have a &lt;code&gt;PREROUTING&lt;/code&gt; rule detect traffic
designed for reflection, and this sets a mark on it; the &lt;code&gt;POSTROUTING&lt;/code&gt; rule
detects this mark and ensures the traffic is masqueraded (SNAT&amp;rsquo;d).&lt;/p&gt;

&lt;p&gt;The other rule using &lt;code&gt;@this_host&lt;/code&gt; is the general incoming forwarding rule,
which uses the &lt;code&gt;fport&lt;/code&gt; map we filled out earlier.  This catches both internet
and VLAN initiated traffic that&amp;rsquo;s trying to hit this machine and ensures
they&amp;rsquo;re both forwarded (DNAT&amp;rsquo;d) to the right target.&lt;/p&gt;

&lt;p&gt;However, this set needs to hold the external IP address of the machine.
We can set it in two places.&lt;/p&gt;

&lt;h4 id=&#34;dhcp-hooks&#34;&gt;dhcp hooks&lt;/h4&gt;

&lt;p&gt;Whenever the &lt;code&gt;br-wan&lt;/code&gt; interface gets assigned an address from DHCP we can
arrange for a script to be called.  This can simply populate the external
IP address (passed as a variable) into the set:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat /etc/NetworkManager/dispatcher.d/nft_host
#!/bin/sh

if [ &amp;quot;$1&amp;quot; == &amp;quot;br-wan&amp;quot; -a -n &amp;quot;$DHCP4_IP_ADDRESS&amp;quot; ]
then
  nft &amp;quot;flush set nat this_host;add element nat this_host { $DHCP4_IP_ADDRESS }&amp;quot;
  echo `date`: Put $DHCP4_IP_ADDRESS into set
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;cron-job&#34;&gt;cron job&lt;/h4&gt;

&lt;p&gt;Just in case the hook doesn&amp;rsquo;t fire properly, or if you reload the rules (and
so have an empty set) we can also run a cron job every 5 minutes that can
check the &lt;code&gt;br-wan&lt;/code&gt; IP address, and if it&amp;rsquo;s not in the set we add it.  I call
this script &lt;code&gt;reflect&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/bin/sh

export PATH=/sbin:$PATH

export DHCP4_IP_ADDRESS=$(ip -4 address show dev br-wan | sed -n &#39;s/ *inet \([0-9.][0-9.]*\)\/.*/\1/p&#39;)

# Check to see if this is in the NFT ruleset
if [ -z &amp;quot;$(nft list set ip nat this_host | grep &amp;quot;{ $DHCP4_IP_ADDRESS }&amp;quot;)&amp;quot; ]
then
  /etc/NetworkManager/dispatcher.d/nft_host br-wan dhcp4-change
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;ipv6-1&#34;&gt;IPv6&lt;/h2&gt;

&lt;p&gt;Phew, that was a lot of work.  IPv6 is a lot simpler; we allow any
machine on the LAN to see the internet on IPv6 and we only allow a limited
subset of external machines (machines I own) to be able to reach in from
the internet.&lt;/p&gt;

&lt;p&gt;We can specify the trusted machines by putting them in the &lt;code&gt;my_hosts&lt;/code&gt; set&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# My IPv6 hosts

add element ip6 filter my_hosts { \
  XXXX:XXXX:XXXX:XXXX:1, \
  YYYY:YYYY::YYYY:YYYY:YYYY:YYYY, \
  ZZZZ:ZZZ:ZZ:ZZ:ZZZZ:ZZZZ:ZZZZ:0 \
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now the IPv6 rules are pretty simple:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;add chain ip6 filter INPUT { type filter hook input priority 0; policy accept; }
add chain ip6 filter OUTPUT { type filter hook output priority 0; policy accept;
 }
add chain ip6 filter FORWARD { type filter hook forward priority 0; policy accept; }

add rule ip6 filter INPUT ct state related,established counter accept
add rule ip6 filter INPUT ct state invalid counter drop
add rule ip6 filter INPUT iifname &amp;quot;lo&amp;quot; counter accept
add rule ip6 filter INPUT iifname &amp;quot;br-lan&amp;quot; counter accept

add rule ip6 filter INPUT meta l4proto ipv6-icmp counter accept

add rule ip6 filter INPUT ip6 saddr @my_hosts counter accept

add rule ip6 filter INPUT counter drop

add rule ip6 filter OUTPUT ct state related,established counter accept
add rule ip6 filter OUTPUT ct state invalid counter drop

add rule ip6 filter FORWARD ct state related,established counter accept
add rule ip6 filter FORWARD ct state invalid counter drop
add rule ip6 filter FORWARD iifname &amp;quot;br-lan&amp;quot; counter accept

add rule ip6 filter FORWARD meta l4proto ipv6-icmp icmpv6 type destination-unreachable counter accept
add rule ip6 filter FORWARD meta l4proto ipv6-icmp icmpv6 type packet-too-big counter accept
add rule ip6 filter FORWARD meta l4proto ipv6-icmp icmpv6 type time-exceeded counter accept
add rule ip6 filter FORWARD meta l4proto ipv6-icmp icmpv6 type parameter-problem counter accept

add rule ip6 filter FORWARD ip6 saddr @my_hosts counter accept

add rule ip6 filter FORWARD counter drop
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;get-this-to-load-on-reboot&#34;&gt;Get this to load on reboot&lt;/h2&gt;

&lt;p&gt;What I do is have a complete list of all my rules in a file; I&amp;rsquo;ll include
it below.  We can then load this with the single command &lt;code&gt;nft -f &amp;lt;filename&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Earlier we ran &lt;code&gt;systemctl enable --now nftables&lt;/code&gt;.  This picks up
&lt;code&gt;/etc/sysconfig/nftables.conf&lt;/code&gt; so we can now save the new rules&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nft list ruleset &amp;gt; /etc/sysconfig/nftables.conf&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Of course after reloading the rules, &lt;code&gt;@this_host&lt;/code&gt; is empty so we also need
to run the &lt;code&gt;reflect&lt;/code&gt; command (or wait for the cron job).&lt;/p&gt;

&lt;p&gt;We can do all of this in one line&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nft -f nft.rules ; nft list ruleset &amp;gt;| /etc/sysconfig/nftables.conf ; reflect&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&#34;the-final-nft-ruleset&#34;&gt;The final nft ruleset&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;# Load this rules with
#   nft -f &amp;lt;this file&amp;gt;
# Save the rules so they apply on reboot with
#   nft list ruleset &amp;gt; /etc/sysconfig/nftables.conf
#
# In one command
#
#   nft -f nft ; nft list ruleset &amp;gt;| /etc/sysconfig/nftables.conf ; reflect
#
# Remember to configure nftables to start at boot time, and to disable
# firewalld
#
# systemctl disable --now firewalld
# systemctl mask firewalld
# systemctl enable --now nftables

###############################################################################

# Clear out all the rules
flush ruleset

# Create empty structures
add table ip filter
add table ip nat
add table ip6 filter

add map nat fport { type inet_service : interval ipv4_addr . inet_service ; flags interval; }
add set ip nat reflect { type inet_service; }
add set ip nat this_host { type ipv4_addr; }

add set ip6 filter my_hosts { type ipv6_addr; }

###############################################################################

# This should be the only configuration needed

# Port forwarding for incoming traffic

add element nat fport { 80 : 10.0.0.100 . 80 }   # http
add element nat fport { 443 : 10.0.0.100 . 443 } # https
add element nat fport { 22 : 10.0.0.110 . 22 }   # ssh
add element nat fport { 6881-6999 : 10.0.0.120 . 6881-6999 } # RL9 torrents

# These ports should be reflected.  Basically the ports from fport that
# people might want to access
add element nat reflect { 80, 443, 22 }

# My IPv6 hosts

add element ip6 filter my_hosts { \
  XXXX:XXXX:XXXX:XXXX:1, \
  YYYY:YYYY::YYYY:YYYY:YYYY:YYYY, \
  ZZZZ:ZZZ:ZZ:ZZ:ZZZZ:ZZZZ:ZZZZ:0 \
}

###############################################################################

# This ruleset is split into two parts; ip and ip6

###############################################################################
#
# IPv4
#
###############################################################################

# Basic rules:
#   LAN can see everything
#   Guestnet and IoT network can see a few internal resources (eg DNS)
#     and the internet
#   Outside world can see a few exposed services


# Define the 3 standard filters:
#     INPUT: Traffic targeting this machine
#    OUTPUT: Traffic originating from this machine
#   FORWARD: Traffic goin through this machine

add chain ip filter INPUT { type filter hook input priority 0; policy accept; }
add chain ip filter OUTPUT { type filter hook output priority 0; policy accept; }
add chain ip filter FORWARD { type filter hook forward priority 0; policy accept; }

# Log rules for input and forwarding
add chain ip filter LOGGER
add chain ip filter LOGGERF

######
###### Logging rules
######

# Logging rule for INPUT drops
add rule ip filter LOGGER limit rate 2/minute burst 5 packets counter log prefix &amp;quot;IPTables-Dropped: &amp;quot;
add rule ip filter LOGGER counter drop

# Logging rule for FORWARD drops
add rule ip filter LOGGERF limit rate 2/minute burst 5 packets counter log prefix &amp;quot;IPTables-Dropped-Forward: &amp;quot;
add rule ip filter LOGGERF counter drop

######
###### INPUT rules
######

# Allow traffic for established connections, blocking invalid header format
add rule ip filter INPUT ct state related,established counter accept
add rule ip filter INPUT ct state invalid counter drop

# All localhost traffic allowed
add rule ip filter INPUT iifname &amp;quot;lo&amp;quot; counter accept

# The LAN can see this machine
add rule ip filter INPUT iifname &amp;quot;br-lan&amp;quot; counter accept

# Allow the world to ping this machine (amongst other things)
add rule ip filter INPUT ip protocol icmp counter accept

# Let guestnet and IoT see DNS servers on this machine (tcp+udp)
add rule ip filter INPUT iifname &amp;quot;br-guest&amp;quot; tcp dport 53 counter accept
add rule ip filter INPUT iifname &amp;quot;br-guest&amp;quot; udp dport 53 counter accept
add rule ip filter INPUT iifname &amp;quot;br-guest&amp;quot; tcp dport 853 counter accept
add rule ip filter INPUT iifname &amp;quot;br-guest&amp;quot; udp dport 853 counter accept

add rule ip filter INPUT iifname &amp;quot;br-iot&amp;quot; tcp dport 53 counter accept
add rule ip filter INPUT iifname &amp;quot;br-iot&amp;quot; udp dport 53 counter accept
add rule ip filter INPUT iifname &amp;quot;br-iot&amp;quot; udp dport 123 counter accept

# Log block traffic; this could be noisy, so only enable it if you
# want lots of logs!
## add rule ip filter INPUT counter jump LOGGER

# Block all other incoming traffic
add rule ip filter INPUT counter drop

######
###### OUTPUT rules
######

# Output is easy; we let this machine talk to anything
add rule ip filter OUTPUT ct state related,established counter accept
add rule ip filter OUTPUT ct state invalid counter drop

######
###### FORWARD rules
######

# Allow established connections to work, blocking invalid header format
add rule ip filter FORWARD ct state related,established counter accept
add rule ip filter FORWARD ct state invalid counter drop

# Allow the LAN to see the world
add rule ip filter FORWARD iifname &amp;quot;br-lan&amp;quot; counter accept

# Allow the VPN to see everything
add rule ip filter FORWARD iifname &amp;quot;tun0&amp;quot; counter accept

# Allow return traffic for NAT&#39;d connections to work
add rule ip filter FORWARD iifname &amp;quot;br-wan&amp;quot; ct status dnat counter accept

# Allow guestnet to see external DNS servers
add rule ip filter FORWARD iifname &amp;quot;br-guest&amp;quot; tcp dport 53 counter accept
add rule ip filter FORWARD iifname &amp;quot;br-guest&amp;quot; udp dport 53 counter accept
add rule ip filter FORWARD iifname &amp;quot;br-guest&amp;quot; tcp dport 853 counter accept
add rule ip filter FORWARD iifname &amp;quot;br-guest&amp;quot; udp dport 853 counter accept

add rule ip filter FORWARD iifname &amp;quot;br-iot&amp;quot; tcp dport 53 counter accept
add rule ip filter FORWARD iifname &amp;quot;br-iot&amp;quot; udp dport 53 counter accept

# Allow my mobile devices to have access to everything
add rule ip filter FORWARD iifname &amp;quot;br-guest&amp;quot; ip saddr 10.100.100.8 counter accept

# Allow guestnet to see the printer
add rule ip filter FORWARD iifname &amp;quot;br-guest&amp;quot; ip daddr 10.0.0.10 counter accept

# Allow guestnet devices to see my MQTT server
add rule ip filter FORWARD iifname &amp;quot;br-guest&amp;quot; oifname &amp;quot;br-lan&amp;quot; tcp dport 1883 counter accept

# Allow guestnet to see the internet
add rule ip filter FORWARD iifname &amp;quot;br-guest&amp;quot; oifname &amp;quot;br-wan&amp;quot; counter accept

# Allow IoT devices to see my MQTT server
add rule ip filter FORWARD iifname &amp;quot;br-iot&amp;quot; oifname &amp;quot;br-lan&amp;quot; tcp dport 1883 counter accept

# Allow ESP8266 devices on IoT to be network updates
# (The process causes the ESP8266 to call back to a webserver on the host)
add rule ip filter FORWARD iifname &amp;quot;br-iot&amp;quot; oifname &amp;quot;br-lan&amp;quot; tcp dport 8266 counter accept

# Allow IoT devices to see the internet
add rule ip filter FORWARD iifname &amp;quot;br-iot&amp;quot; oifname &amp;quot;br-wan&amp;quot; counter accept

# Allow marked traffic (ie reflected traffic) to reach the destination
add rule ip filter FORWARD meta mark 100 counter accept

# Log and block all other forwarded traffic
add rule ip filter FORWARD counter jump LOGGERF
add rule ip filter FORWARD counter drop

######
###### NAT rules
######

add chain ip nat INPUT { type nat hook input priority 100; policy accept; }
add chain ip nat OUTPUT { type nat hook output priority -100; policy accept; }
add chain ip nat PREROUTING { type nat hook prerouting priority -100; policy accept; }
add chain ip nat POSTROUTING { type nat hook postrouting priority 100; policy accept; }

# Log specific incoming traffic
add rule ip nat PREROUTING iifname &amp;quot;br-wan&amp;quot; tcp dport 22 limit rate 2/minute burst 5 packets counter log prefix &amp;quot;IPTables-New-SSH: &amp;quot;

# Tag internal reflection traffic
add rule ip nat PREROUTING ip saddr 10.0.0.0/8 ip daddr @this_host tcp dport @reflect mark set 100

# DNAT incoming traffic from the internet (or internal send to br-wan address)
add rule ip nat PREROUTING ip daddr @this_host ip protocol tcp dnat ip  addr . port to tcp dport map @fport

# Do NAT on egress traffic to the internet
add rule ip nat POSTROUTING oifname &amp;quot;br-wan&amp;quot; counter masquerade

# Also NAT marked traffic from internal to external IP
add rule ip nat POSTROUTING meta mark 100 counter masquerade

###############################################################################
#
# IPv6
#
###############################################################################

# IPv6 is simpler; there&#39;s no NAT involved.  We allow LAN to see the
# world and only allow trusted external machines to see in to LAN

add chain ip6 filter INPUT { type filter hook input priority 0; policy accept; }
add chain ip6 filter OUTPUT { type filter hook output priority 0; policy accept; }
add chain ip6 filter FORWARD { type filter hook forward priority 0; policy accept; }

add rule ip6 filter INPUT ct state related,established counter accept
add rule ip6 filter INPUT ct state invalid counter drop
add rule ip6 filter INPUT iifname &amp;quot;lo&amp;quot; counter accept
add rule ip6 filter INPUT iifname &amp;quot;br-lan&amp;quot; counter accept

add rule ip6 filter INPUT meta l4proto ipv6-icmp counter accept

add rule ip6 filter INPUT ip6 saddr @my_hosts counter accept

add rule ip6 filter INPUT counter drop

add rule ip6 filter OUTPUT ct state related,established counter accept
add rule ip6 filter OUTPUT ct state invalid counter drop

add rule ip6 filter FORWARD ct state related,established counter accept
add rule ip6 filter FORWARD ct state invalid counter drop
add rule ip6 filter FORWARD iifname &amp;quot;br-lan&amp;quot; counter accept

add rule ip6 filter FORWARD meta l4proto ipv6-icmp icmpv6 type destination-unreachable counter accept
add rule ip6 filter FORWARD meta l4proto ipv6-icmp icmpv6 type packet-too-big counter accept
add rule ip6 filter FORWARD meta l4proto ipv6-icmp icmpv6 type time-exceeded counter accept
add rule ip6 filter FORWARD meta l4proto ipv6-icmp icmpv6 type parameter-problem counter accept

add rule ip6 filter FORWARD ip6 saddr @my_hosts counter accept

add rule ip6 filter FORWARD counter drop
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Work/Life Balance</title>
      <link>https://www.sweharris.org/post/2024-07-11-work-life/</link>
      <pubDate>Thu, 11 Jul 2024 08:32:26 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2024-07-11-work-life/</guid>
      <description>

&lt;p&gt;This isn&amp;rsquo;t my normal tech-ish posting; this is a more personal view at
how Corporate America and tech startups and the like are &lt;em&gt;abusing&lt;/em&gt; their
workforce.  I don&amp;rsquo;t mean the sort of abuse seen in the service industry
(below minimum wages needing to be supplemented with tips; excessive
overtime; all that stuff).  I&amp;rsquo;m talking about white collar tech jobs.
The sort of jobs I did; likely the sort of jobs you&amp;rsquo;re doing (if you&amp;rsquo;re
reading this blog); office workers&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;quiet-quitting&#34;&gt;Quiet quitting&lt;/h2&gt;

&lt;p&gt;The phrase &amp;ldquo;quiet quitting&amp;rdquo; appeared a lot in the press over the past few
years; it&amp;rsquo;s probably peaked in public consciousness but is now there as
a back ground thought.  It colours attitudes; &amp;ldquo;Oh Harry is leaving at 5 on
the dot every day&amp;hellip;&amp;rdquo;&lt;/p&gt;

&lt;p&gt;The thing is, this isn&amp;rsquo;t new.  It&amp;rsquo;s not a Gen-Z or a Millennial thing.  I&amp;rsquo;m
at the older edge of Gen-X and I&amp;rsquo;d been &amp;ldquo;quiet quitting&amp;rdquo; for a couple of
decades.&lt;/p&gt;

&lt;p&gt;I started my first job in July 1990.  I enjoyed what I was doing and I was
learning a lot.  I was still mostly a 9-5 in the office (just because
that was expected commute times) but I would sometimes stay late.
I remember one Sunday, around 1:30pm, just as we were at the table
for our Sunday Dinner when the phone rang; one of my users was having
trouble dialing into the computer so he couldn&amp;rsquo;t work (time critical).
I was able to talk him through the alternate connection; he was happy.
I was happy to have helped.  Everybody won.&lt;/p&gt;

&lt;p&gt;My second job was a bit like that; again mostly 9-5 but one weekend a
server had died (it was a known Solaris kernel bug) so I went into the
office (a 1.5hr commute) to restart it.  Another weekend (the Saturday
before Christmas) the firewall died, so again I went in to fix it.
And there was the long Easter 4-day weekend I spent upgrading &amp;lsquo;Orrible
Financials.  Ugh.&lt;/p&gt;

&lt;p&gt;Basically I would go &amp;ldquo;above and beyond&amp;rdquo; in emergency situations, but my
daily work was mostly a 9-5.&lt;/p&gt;

&lt;p&gt;When I moved to America my attitude changed a little; I was no longer in
an operations role, so it was less likely for me to have to do emergency
work.  When I was &amp;ldquo;level 4&amp;rdquo; (with good L2 and L3 teams running my stuff)
only my boss had my cellphone number; only he was allowed to contact me.
My 8:20-5 (&amp;lsquo;cos of train times) slowly became a 8:20-4:45 (so I could
catch the 5:30 train).&lt;/p&gt;

&lt;p&gt;Yes, I still did &amp;ldquo;emergency&amp;rdquo; stuff (e.g. the early 2010s JPMC data breach
had me working late hours analysing audit logs, building up a profile
of activity performed by the attackers, demonstrating where controls had
blocked them and where we were blind) but my &amp;ldquo;BAU&amp;rdquo; activity was strictly
time bound.&lt;/p&gt;

&lt;p&gt;In my last job, before COVID, it was closer to 8:35-4:20 (so I could catch
the 4:55 train).  Even when I worked from home I was strict 8:20-4:20.
I resented people creating 8am meetings (and frequently missed them)
and 4-5 meetings.  Nope.&lt;/p&gt;

&lt;p&gt;I was essentially &amp;ldquo;quiet quitting&amp;rdquo; but the work got done&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;corporate-mis-incentives&#34;&gt;Corporate mis-incentives&lt;/h2&gt;

&lt;p&gt;And this is where modern corporate behaviour has made the type of working
hours I did become important enough to flag up and cast it as a moral
failing of the workers.&lt;/p&gt;

&lt;p&gt;For the past decade or more the motto of Corporate America appears to be
&amp;ldquo;Do More With Less&amp;rdquo;.  Workers are encouraged to do more work (oh, but don&amp;rsquo;t
work harder; work smarter!) with less resources and less time.  That
person now working 9-5 and not willing to go above and beyond&amp;hellip; that person
is dragging the company down.  Why can&amp;rsquo;t you just stay that extra half
hour?  Don&amp;rsquo;t you care about the company?&lt;/p&gt;

&lt;p&gt;NO.&lt;/p&gt;

&lt;p&gt;I don&amp;rsquo;t care.  The company is not my family; it&amp;rsquo;s not my friend.  I have
a commercial agreement with the company; &amp;ldquo;work these hours, do your job,
get paid $$$&amp;ldquo;.  You want to alter the deal?  It goes both ways; you&amp;rsquo;re
not Darth Vader, you don&amp;rsquo;t get to do this.&lt;/p&gt;

&lt;p&gt;And this is where the mis-incentive&amp;rsquo;s start to show.  I frequently hear
&amp;ldquo;I need you to work more hours and log that time on your time sheets
so I can show to senior management the need for extra headcount&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;The argument goes &amp;ldquo;if all my people are working at 125% then I need 25%
more people&amp;rdquo;.   But it doesn&amp;rsquo;t work that way; if you&amp;rsquo;re working at 125%
the company will happily defer the &amp;ldquo;get more people&amp;rdquo; part because that
impacts the bottom line.  And defer it.  And defer it.  And suddenly
9-6 has become the new norm.&lt;/p&gt;

&lt;p&gt;Worse, people get RIF&amp;rsquo;d (Reduction In Force; basically their job is
terminated to reduce costs).  And people who voluntarily leave don&amp;rsquo;t
have their positions opened for a replacement.  It&amp;rsquo;s pretty much a
one-way-ratchet; resources get tighter and tighter.&lt;/p&gt;

&lt;p&gt;Because the company is measuring &amp;ldquo;work completed&amp;rdquo; and seeing the numbers
look good they have no reason to add more resources.&lt;/p&gt;

&lt;p&gt;A better measure should be the backlog of work that doesn&amp;rsquo;t get done.
Everyone works their 9-5 and incomplete work is incomplete.&lt;/p&gt;

&lt;p&gt;Now the story goes, &amp;ldquo;My staff are working 100% but there&amp;rsquo;s work that isn&amp;rsquo;t
getting done because there&amp;rsquo;s too much to do.  I need more staff.&amp;rdquo;  The
company has incentive to get those people because the work not being done
is costing and hurting the bottom line (or is declared not important and
so not needing to be done).&lt;/p&gt;

&lt;p&gt;But, instead, they claim &amp;ldquo;These young kids don&amp;rsquo;t want to do hard work
any more!  They&amp;rsquo;re lazy!  Quiet quitting is the new scourge!&amp;rdquo; all in an
attempt to guilt you to overwork yourself for &lt;em&gt;their&lt;/em&gt; dollar.&lt;/p&gt;

&lt;h2 id=&#34;work-to-live&#34;&gt;Work to live&lt;/h2&gt;

&lt;p&gt;A number of years ago I was on a quarterly all hands meeting, and the big
boss was asked how he felt about work-life balance.  The answer disgusted
me; basically it went something like &amp;ldquo;Yes, I believe in work-life balance
but if you&amp;rsquo;re on vacation and not keeping up with your emails then you&amp;rsquo;re
not doing your job.  I always read my emails&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;&amp;lt;internal screaming commenced&amp;gt;&lt;/p&gt;

&lt;p&gt;The vast majority of us need a paycheck in order to live.  In America you
also need it to obtain health care (a rant for another day).  But that&amp;rsquo;s
where it should end.  For most of us, your job is not your life.  You
need to be able to switch off at the end of the work day and be &lt;em&gt;you&lt;/em&gt;, not
corporate drone 1275567.  The company doesn&amp;rsquo;t care about you as &amp;ldquo;you&amp;rdquo;, they
just care about you as that drone.  All those &amp;ldquo;health programs&amp;rdquo; they run
are for their bottom line (fewer people using the health plan results in
lower costs) even if they sell it as a &amp;ldquo;we care&amp;rdquo; benefit.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Aside: HR isn&amp;rsquo;t your friend; they&amp;rsquo;re there to protect the company from legal issues.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Quiet quitting shouldn&amp;rsquo;t even be a concept.  Instead we should be framing
this in terms of rejecting corporate abuse; of rejecting the &amp;ldquo;work harder,
peon&amp;rdquo; mentality.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;re first and foremost human beings (&amp;ldquo;Hi to you future AIs reading this!&amp;rdquo;)
and need to treat &lt;em&gt;ourselves&lt;/em&gt; as such.&lt;/p&gt;

&lt;p&gt;(Of course if you pick a job where you get 6 figure bonuses because you&amp;rsquo;re
expected to be in crunch mode 24x7 then that&amp;rsquo;s the choice you made; most of
us didn&amp;rsquo;t choose that life!)&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;It&amp;rsquo;s easy for me to say &amp;ldquo;quiet quitting is good&amp;rdquo; (especially since I&amp;rsquo;m now
retired!) because my job was never really at risk.  I always got my work
done; my boss was always happy; I got &amp;ldquo;exceeds&amp;rdquo; ratings.&lt;/p&gt;

&lt;p&gt;Not everyone is in this position, though.  Some people are desperate to
keep their job and would struggle without it (especially in America where
so many things are tied to work).  So I&amp;rsquo;m not going to tell anyone not
to work that 125%.  I am hoping that you realise what is being done to
you and, perhaps, be on the lookout for another job which might get you
out of the abusive relationship with your employer (yeah yeah &amp;ldquo;better the
Devil you know&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;And, may I whisper it in your ear, consider a union for your work space?
The pendulum has swung back so far that union protections may be
warranted!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>API Security at the gateway</title>
      <link>https://www.sweharris.org/post/2024-06-12-api-security/</link>
      <pubDate>Wed, 12 Jun 2024 09:07:22 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2024-06-12-api-security/</guid>
      <description>

&lt;p&gt;When it comes to talking about API Security there are many facets and paths
the conversation can take.&lt;/p&gt;

&lt;p&gt;We might want to talk about from an AppDev security perspective; after
all, an API is just code, so your SAST/DAST type processes apply.&lt;/p&gt;

&lt;p&gt;We might want to talk about it in terms of authentication; after all, you
need credentials to access an API and there&amp;rsquo;s many different ways this
can be done (Basic Auth, mutual TLS, Oauth, HMAC&amp;hellip;); this would also
include when anonymous APIs &lt;em&gt;are&lt;/em&gt; OK!&lt;/p&gt;

&lt;p&gt;We might want to talk about it in encryption terms; is TLS enough or
should we do payload or field level encryption?&lt;/p&gt;

&lt;p&gt;We might&amp;hellip;&lt;/p&gt;

&lt;p&gt;I want to talk about it in terms of the &lt;em&gt;gateway&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&#34;wafs&#34;&gt;WAFs&lt;/h1&gt;

&lt;p&gt;Normally a WebApp needs to be behind a WAF in order to provide some protection
in depth; the WAF can block abusive behaviour before it even enters your
network, so common attacks (SQL injection, volumetric, buffer overflow, etc)
can easily be prevents.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Side note: This doesn&amp;rsquo;t mean your app never needs worry about this; WAFs
can be bypassed.  This is just another layer of protection!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;In a large organisation we typically find WAFs become centralised and under
control of a specialist team.  This adds some friction to the development
process, but there&amp;rsquo;s a lot of benefits; e.g. this team has more experience in
understanding attacks and can craft rules to block new ones; the WAFs can
alert to the SOC; centralised logging can assist in forensics&amp;hellip;  Also
it&amp;rsquo;s important to note that not all WAFs protect as well; if an app team
spins up their own (eg AWS WAF, or even Apache with modsecurity) we have
the management problem (how do we ensure the latest rules are deployed; how
to we get visibility/alerts to the SOC; how do we even know the AppDev
team deployed properly? And is this WAF providing the same level of
protection that the centrally managed ones provide?).&lt;/p&gt;

&lt;p&gt;The problem with WAFs is that they are more focused on WebApp type
traffic.  APIs work differently; yes, they&amp;rsquo;re still https requests
and so suffer some of the same problems (SQL injection, overflow) but
there&amp;rsquo;s also new challenges; e.g this is highlighted by the &lt;a href=&#34;https://owasp.org/API-Security/editions/2023/en/0x11-t10/&#34;&gt;OWASP API Top 10&lt;/a&gt; being different
to the standard OWASP Top 10.&lt;/p&gt;

&lt;h1 id=&#34;waap&#34;&gt;WAAP&lt;/h1&gt;

&lt;p&gt;In recognition of this, some WAF vendors have tried to introduction some
level of API protection into the same product, resulting in &amp;ldquo;Web Application
and API Protection&amp;rdquo; (WAAP) products.  Different vendors have different
levels of maturity when it comes to API Security, and few actually describe
&lt;em&gt;what&lt;/em&gt; they actually do.  It can sometimes be a marketing term, just so
they can tick a box on a Gartner score card.&lt;/p&gt;

&lt;p&gt;If you already have a WAF vendor that claims they can do WAAP then
definitely look at the functionality; it may be sufficient for your
needs.&lt;/p&gt;

&lt;h1 id=&#34;security-at-the-api-gateway&#34;&gt;Security at the API Gateway&lt;/h1&gt;

&lt;p&gt;Many APIs go through a gateway, which can do some sanity checking,
routing of requests to different backend systems, enforce authentication
requirements, and so on.  Since these gateways act as an ingress point
into your application (and thus your network and environment) this is
another place where it potentially makes sense to centralize.&lt;/p&gt;

&lt;p&gt;And with a centralised API Gateway comes the ability to add security
controls and make it a Policy Enforcement Point (PEP).  Advanced API
Gateways even have data flows that can be hooked into and process
flows defined.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s a number of benefits to providing API Security at this layer;
all the &amp;ldquo;centralised WAF&amp;rdquo; arguments apply but, in addition, we&amp;rsquo;re already
doing TLS termination here so we can do inspection and enforcement
without adding any noticeable additional latency to the request (an
external WAF or WAAP means another TLS decrypt, resend which will add
delays).  AppDevs seem to care about the performance of their APIs,
for some reason, so now we have the ability to add security without
making them cry.&lt;/p&gt;

&lt;h1 id=&#34;what-should-an-api-security-gateway-offer&#34;&gt;What should an API Security Gateway offer?&lt;/h1&gt;

&lt;h3 id=&#34;inventory&#34;&gt;Inventory&lt;/h3&gt;

&lt;p&gt;Since the solution sees all the traffic (request, response) it can
automatically build up a list of endpoints being called and the types
of data each endpoint handles.  It would be able to classify each
and flag those that handle sensitive information
(&amp;ldquo;Oh, this handles PCI data&amp;rdquo;, &amp;ldquo;that&amp;rsquo;s an SSN&amp;rdquo;, &amp;ldquo;Name and address seen!&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;A solution could also be able to &lt;em&gt;compare&lt;/em&gt; this discovered inventory
to the published specs (eg OpenAPI) and determine if they match or
if you have endpoints that aren&amp;rsquo;t part of the published spec, or you
publish endpoints that don&amp;rsquo;t actually exist.&lt;/p&gt;

&lt;p&gt;It could also track changes in the inventory over time and alert on
important changes (&amp;ldquo;Huh, this endpoint is now returning SSNs where it
didn&amp;rsquo;t before&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;Another useful output would be related to the performance of each
endpoint; the system has timings for how long each request/response took.
This could potentially help developers detect bottlenecks (wow, a
security tool &lt;em&gt;helping&lt;/em&gt; developers?  Unheard of!).&lt;/p&gt;

&lt;h3 id=&#34;attack-detection&#34;&gt;Attack detection&lt;/h3&gt;

&lt;p&gt;This is where an API Specific solution can distinguish itself from a WAF.
APIs tend to be called in a pattern of behaviour; an app would call
A, B, C, D in order.  The solution could learn this.  If it then sees
traffic going A, D then we have an anomaly.&lt;/p&gt;

&lt;p&gt;Because the solution sees traffic it could also detect when endpoints
are being abused (eg if the response size goes up massively in volume,
or if the number of requests to an endpoint increases; seeing authentication
tokens being used from an unexpected source; excessive &amp;ldquo;fail&amp;rdquo; responses
potentially indicating an enumeration attack).&lt;/p&gt;

&lt;p&gt;Many of the OWASP API Top 10 issues can be detected just by analysing
the traffic.&lt;/p&gt;

&lt;p&gt;Of course it also should do all the standard WAF-like stuff (SQL injection,
buffer overflow, bot detection, volumetric attacks etc etc).&lt;/p&gt;

&lt;h3 id=&#34;alerting&#34;&gt;Alerting&lt;/h3&gt;

&lt;p&gt;This should go without saying; what&amp;rsquo;s the point of having all this
detection if it can&amp;rsquo;t alert the SOC, or call a SOAR, or even just log
high fidelity events to a SIEM.&lt;/p&gt;

&lt;h3 id=&#34;blocking&#34;&gt;Blocking&lt;/h3&gt;

&lt;p&gt;Once these alerts and logs have been validated and a level of confidence
in the results have been achieved then the system should be able to
automatically block bad traffic.&lt;/p&gt;

&lt;p&gt;This blocking needs to be smart, though.  Blocking by IP address is
kinda pointless; attackers use botnets and change source IPs on a regular
basis.  Blocking one IP will just result in a new one starting up a short
while later.  This is lesson learned from WAF management.&lt;/p&gt;

&lt;p&gt;Instead the blocking needs to be done on patterns; is there something
about the requests that can be used?  Is there something about the
&lt;em&gt;sequence&lt;/em&gt; of requests that can be used?&lt;/p&gt;

&lt;p&gt;This is likely to be biggest differentiator between products; if the
vendor just says &amp;ldquo;yes, we can automatically configure the firewall to
block IP addresses&amp;rdquo; then you might want to look elsewhere.&lt;/p&gt;

&lt;h3 id=&#34;dast&#34;&gt;DAST&lt;/h3&gt;

&lt;p&gt;Since the system has discovered API endpoints &lt;em&gt;and&lt;/em&gt; potentially has a Spec
file, it has a lot of information that can be used to generate automated
testing of the endpoints.  It can call them with known bad data; test
against the OWASP issues (BOLA - Broken Object Level Authorizations -
being a common one).&lt;/p&gt;

&lt;p&gt;Results of these tests could be fed into existing vulnerability management
processes and so tracked to remediation.&lt;/p&gt;

&lt;h1 id=&#34;what-characteristics-do-we-need&#34;&gt;What characteristics do we need?&lt;/h1&gt;

&lt;h3 id=&#34;speed&#34;&gt;Speed&lt;/h3&gt;

&lt;p&gt;I&amp;rsquo;ve already mentioned that developers will cry if we slow down their
apps, so a lot of the processing for all the above should be offloaded
from the gateway.&lt;/p&gt;

&lt;p&gt;Ideally part of the &amp;ldquo;process flow&amp;rdquo; should fork off
an asynchronous copy of the data and response and send it to a processing
server.  In this way the original data flow is barely impacted.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/API_Gateway.png&#34; alt=&#34;Inside Safe&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Obviously in an enterprise environment you&amp;rsquo;d have multiple servers
behind a load balancer for performance and resiliency.  It also
makes sense to put the processing server network-close to the gateway,
especially since some of the &amp;ldquo;should this be blocked&amp;rdquo; logic &lt;em&gt;could&lt;/em&gt; be
run on this server and the gateway just makes a call-out to it.&lt;/p&gt;

&lt;h3 id=&#34;redaction&#34;&gt;Redaction&lt;/h3&gt;

&lt;p&gt;This is important, especially if (as in the above picture) we&amp;rsquo;re sending
data to the cloud.  We don&amp;rsquo;t want to send PCI scoped data to the cloud
(unless you want to include that as part of your CDE).  This is where
the processing server also helps; it can perform the analysis and then
redact or hash the data before it&amp;rsquo;s sent upstream.&lt;/p&gt;

&lt;p&gt;The upstream systems will need to have something to correlate on, so the
redaction process needs to be consistent (e.g. same credit card number
always get hashed to a consistent value) but the raw data itself need not
be sent.&lt;/p&gt;

&lt;h3 id=&#34;configuration-promotion&#34;&gt;Configuration promotion&lt;/h3&gt;

&lt;p&gt;No matter how good the auto-detection of sensitive data is, the system
may make mistakes (eg miss one thing, or incorrectly classify an element).
The system needs to allow for custom overrides.&lt;/p&gt;

&lt;p&gt;Now for safety the developers should be able to verify and set these
overrides when developing the code or testing in QA.  After all, real
data shouldn&amp;rsquo;t be used here (you don&amp;rsquo;t use real data in DEV&amp;hellip;).&lt;/p&gt;

&lt;p&gt;Ideally we&amp;rsquo;d then want an automated way of promoting the resulting
configuration and classification of fields to production &lt;em&gt;before&lt;/em&gt; the
new code gets promoted.  Otherwise there&amp;rsquo;s a risk of sensitive data
being exposed by mistake.&lt;/p&gt;

&lt;h3 id=&#34;multi-team&#34;&gt;Multi-team&lt;/h3&gt;

&lt;p&gt;In a large enterprise you may have multiple development teams working on
different code, potentially in totally different lines of business.  And
there&amp;rsquo;s no reason why the Card Issuer team should be able to see the
details (or even change the classification configuration) for the
Investment Banking trading APIs.&lt;/p&gt;

&lt;p&gt;Your AppSec team has possibly already solved this issue (e.g. only allowing
teams to see their own SAST/DAST results) so being able to re-use their
solution (Active Directory groups&amp;hellip; it&amp;rsquo;s nearly always AD groups!) would
be nice.&lt;/p&gt;

&lt;h3 id=&#34;api-driven&#34;&gt;API Driven&lt;/h3&gt;

&lt;p&gt;It&amp;rsquo;s all well and good having pretty UIs, but management of the platform
itself needs to be automatable.  We might want to automate the
association of developer team to endpoints, we might want to automate
updated classifications, or override blocking rules, or&amp;hellip;&lt;/p&gt;

&lt;p&gt;The system must be API driven, with full documentation.&lt;/p&gt;

&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;

&lt;p&gt;There&amp;rsquo;s a lot here and it covers a lot of areas.  Some parts of it impact
the AppSec team (DAST, vulnerability management, code promotion,
automation), other parts impact the network security team (attack
detection and blocking), other parts impact the development team (seeing
their inventory, allowing them to classify endpoints, performance metrics).
And, of course the SOC and related teams are also impacted.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Aside: We&amp;rsquo;re going to see more of this; the &amp;ldquo;siloed&amp;rdquo; approach to security is
going away as solutions cross more and more boundaries.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;I feel a solution like this is going to be critical; API attacks are
extremely common as more and more applications become API driven (WebApp,
mobile apps, b2b tools&amp;hellip;).  The API is what exposes your data.  We
need a WAF-like solution!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Imposter Syndrome</title>
      <link>https://www.sweharris.org/post/2024-06-04-imposter/</link>
      <pubDate>Tue, 04 Jun 2024 10:40:19 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2024-06-04-imposter/</guid>
      <description>

&lt;p&gt;We all know what imposter syndrome is.  We may all have suffered from it
at some point.  I know I did.&lt;/p&gt;

&lt;p&gt;We may even know, rationally, that this isn&amp;rsquo;t a sensible thing.  One
good representation of this was from &lt;a href=&#34;https://x.com/rundavidrun/status/587671657193455616&#34;&gt;David Whittaker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/imposter.jpg&#34; alt=&#34;Inside Safe&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Yet despite this whenever I started a new job I was always worried that
I wasn&amp;rsquo;t the right person for it; that I&amp;rsquo;d fail to deliver.  I feared
messing up and getting called out as being incompetent.&lt;/p&gt;

&lt;p&gt;As I grew into the role and started to deliver products and saw how my
work improved the company my confidence would grow and I would be more
comfortable; &amp;ldquo;OK, I can do this job.&amp;rdquo;&lt;/p&gt;

&lt;h2 id=&#34;soft-deliverables&#34;&gt;Soft deliverables&lt;/h2&gt;

&lt;p&gt;This is great when there&amp;rsquo;s hard deliverables; something you can point to
and say &amp;ldquo;I did this&amp;rdquo;.  When you see people using the stuff you create.
When you overhear people talking to each other about it.&lt;/p&gt;

&lt;p&gt;But what do you do when your deliverables are less concrete?  When you
don&amp;rsquo;t build but influence, or direct; when you build strategy; when
people ask you for advice and your answers can affect a multi-million
dollar project.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s the situation I found myself in when I joined my last job.  I&amp;rsquo;d
moved from an engineering role to an Enterprise IT Architect role.&lt;/p&gt;

&lt;p&gt;Now a good engineer (and I like to think I&amp;rsquo;m a good engineer) must also
have architecture skills.  The decisions that I was used to making
pretty much only impacted my deliverables (the users of my products
didn&amp;rsquo;t care about the internals, just the results).  It helped I was
mostly a sole-contributor of code and not part of a larger programming
team so I could refactor as I learned about the solution.&lt;/p&gt;

&lt;p&gt;But now?  Umm.  I was part of a team that was responsible for the security
of a large company; one of the oldest, possibly the largest, fintech
company in the US; one that handled almost half of all credit card transactions
in the US; one that ran the largest debit card network in the US.  If I
advised teams wrong and we got compromised as a result&amp;hellip; I didn&amp;rsquo;t want
to think about the consequences.&lt;/p&gt;

&lt;p&gt;As time went on I grew a bit more confident.  I also encouraged the rest
of the team to chat a lot on IM (we were distributed across the globe;
I was the only one in my location).  This chat group was for both
random nonsense, griping at management, laughing at bad vendor presentations,
and also a &amp;ldquo;help&amp;rdquo; resource; if I wasn&amp;rsquo;t sure about something then I could
ask the team for their opinion.&lt;/p&gt;

&lt;p&gt;But I didn&amp;rsquo;t have anything concrete I could point to; &amp;ldquo;I did this&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Worse, as I got exposure to more parts of the company, I got the feeling
I was annoying more and more people.  I tried not to be a &amp;ldquo;no, you can&amp;rsquo;t
do this&amp;rdquo; type person and tried to help them come to a good solution,
but there are always &lt;a href=&#34;https://www.sweharris.org/post/2023-08-05-blame-security/&#34;&gt;problem teams&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve been a blocker, more than once; I&amp;rsquo;ve demonstrated solutions had
problems (one team leading to the CISO having words with a VP of another
team); I&amp;rsquo;ve probably antagonized people.  I know I&amp;rsquo;ve spent many a sleepless
night worrying about meetings I&amp;rsquo;ve had, or were about to have, and how they
could go better.&lt;/p&gt;

&lt;h2 id=&#34;self-deception-self-deprecation&#34;&gt;Self deception, self deprecation&lt;/h2&gt;

&lt;p&gt;Because of a lack of hard deliverables, I had no way of measuring myself.&lt;/p&gt;

&lt;p&gt;Of course my year-end self evaluation was full of &amp;ldquo;I did this&amp;rdquo;, &amp;ldquo;I did
that&amp;rdquo;, &amp;ldquo;I did the other&amp;rdquo; but these were just words.&lt;/p&gt;

&lt;p&gt;I find it hard to accept praise.  My boss said I was doing a good job.
More words.  Apparently the CISO was happy with my work (although I
rarely spoke directly with him).  Yet more words.  Where was the objective
truth?&lt;/p&gt;

&lt;p&gt;So I would joke, downplay my contributions, say things like &amp;ldquo;I have
&lt;a href=&#34;https://en.wiktionary.org/wiki/opinions_are_like_assholes&#34;&gt;opinions&lt;/a&gt; on
lots of things; for some reason people want to listen to them&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;I really didn&amp;rsquo;t believe I was making things better; at best I was just
stopping things getting worse.&lt;/p&gt;

&lt;h2 id=&#34;yet-i-get-tributes&#34;&gt;Yet I get tributes&lt;/h2&gt;

&lt;p&gt;After I announced I was leaving the company and taking early retirement
a number of people sent me messages (both in public and in private).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;you have always been a voice of reason&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;I learned more from you than you realize.  I truly appreciate everything you&amp;rsquo;ve done.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;you and your brilliance will be greatly missed.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;definitely learned a lot by just listening&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;will miss your expertise and guidance&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;I&amp;rsquo;ll miss having you around Stephen, always a pillar of reason and knowledge&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;I cannot think of a time when I disagreed with you at first, that by the end of the conversation you had not convinced me with facts and logic to move my position. THANK YOU FOR THAT! So few people here do that&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;I also want to thank you for the times I was able to work with you. At least for myself, as you had hoped, I did learn a lot. Not in as much around &amp;ldquo;facts&amp;rdquo; or raw technical knowledge (there was plenty of that) but how to look at a problem, problem solve and think it through to a solution (or as close as we could get to one&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;I will personally miss you and even though we don&amp;rsquo;t collaborate as much as I want lately (my fault, not yours), I somehow feel that part of &amp;ldquo;the good&amp;rdquo; of the company will now be missing.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;i will miss the expertise and that you don&amp;rsquo;t succumb to a flashy dashboard and ask the hard questions&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;You will be missed - you are one of the wiser / smarter people here.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;It&amp;rsquo;s sad that we couldn&amp;rsquo;t work  more together. Really enjoyed that and it&amp;rsquo;s definitely a loss for the company.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;So many thoughts, sadness for losing you as part of this team, gratitude for everything we&amp;rsquo;ve built here together, excited for you getting out of this place and hopefully enjoying a well-deserved retirement. I can&amp;rsquo;t imagine where I&amp;rsquo;d be without you, and am humbled everyday seeing how we&amp;rsquo;ve both learned and grown together the last (almost!) 10 years.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;The legendary journey has been etched in history. It was a privilege to cross path with you.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Ha. I don&amp;rsquo;t mind you bugging me. You are at least well reasoned and thorough&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There were also some tributes paid on the weekly leadership call, from
SVPs and VPs.  I didn&amp;rsquo;t record them verbatim, but they included things
like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Helped me immensely&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;We wouldn&amp;rsquo;t be where we are without Stephen.  He changed the way the cyber
org works, and we created a whole new team because of him.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;It wasn&amp;rsquo;t until I was leaving that I started to believe what people were
saying; people I thought I had annoyed, people I had said &amp;ldquo;no&amp;rdquo; to, people
who I thought just ignored me or saw my role as a speed bump stopping them
working&amp;hellip; all of them were giving me unsolicited praise.&lt;/p&gt;

&lt;p&gt;Which really highlights the difference between my self evaluation and
the reality.  Right up until the end I wasn&amp;rsquo;t sure I was doing a good
job, nor making things better.&lt;/p&gt;

&lt;p&gt;In the long long distant past of usenet I had a signature:
&lt;pre&gt;
      The truth is the truth, and opinion just opinion.  But what is what?
       My employer pays to ignore my opinions; you get to do it for free.
&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;Maybe I was wrong and people did pay attention to my opinions after all!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>I still dunno what I want to do</title>
      <link>https://www.sweharris.org/post/2024-04-07-still-dunno/</link>
      <pubDate>Sun, 07 Apr 2024 19:14:25 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2024-04-07-still-dunno/</guid>
      <description>

&lt;p&gt;Recently I wrote about &lt;a href=&#34;https://www.sweharris.org/post/2024-03-25-i-dunno&#34;&gt;how I got here&lt;/a&gt; without
knowing what it was I wanted to do.&lt;/p&gt;

&lt;p&gt;That was a prelude to the other half of the equation; I may not know what
I want, but I do know what I &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; want.&lt;/p&gt;

&lt;p&gt;At this moment in my life, I don&amp;rsquo;t to work.  At all.  I want to have the
luxury to be able to lie in, to read a book, to stay up late hacking on
some code or whatever&amp;hellip;&lt;/p&gt;

&lt;p&gt;I find myself &lt;em&gt;resenting&lt;/em&gt; having to get up to work.  And I had a fantasy
of deleting work apps off my phone and how happy that made me.&lt;/p&gt;

&lt;p&gt;So I quit.  I&amp;rsquo;ve not just quit this job, I&amp;rsquo;ve quit the whole concept of
work.  I&amp;rsquo;ve taken early retirement.&lt;/p&gt;

&lt;p&gt;So how can I afford to do this, at the age of 55?&lt;/p&gt;

&lt;h2 id=&#34;i-got-lucky&#34;&gt;I got lucky&lt;/h2&gt;

&lt;p&gt;Obviously a young white boy in England, even from a working class
background, in the 1980s had benefits, including a world class free
education; I got to go to Oxford!  The first of my family to ever get
to University.  And that led to sponsorship and paid summer work, and
my first job and&amp;hellip;&lt;/p&gt;

&lt;p&gt;Being smart helped, of course.  Not falling into the wrong crowd.
Having parents who both worked and were able to support me during my
education and were happy with me being at home.  Selling my UK house and
transferring the money to the US at a peak pound/dollar rate meaning I
was able to pay off my US mortgage.&lt;/p&gt;

&lt;p&gt;Yeah, I got lucky.&lt;/p&gt;

&lt;h2 id=&#34;frugal-and-fire&#34;&gt;Frugal.  And FIRE.&lt;/h2&gt;

&lt;p&gt;In other respects I&amp;rsquo;ve been planning this for a couple of decades
or more.  I&amp;rsquo;m not sure when I first thought about retiring at 55; moving
to America definitely put those plans on hold &amp;lsquo;cos I didn&amp;rsquo;t know if this
was going to be permanent or temporary (fortunately the relationship
with my darling Lady is still going strong, so it became permanent!).&lt;/p&gt;

&lt;p&gt;But I&amp;rsquo;ve always spent less than I earned.  I lived with my parents until
I was 30, so was able to save up a good percentage of the purchase price
of my house (smaller mortgage, easier to pay off sooner).  When my salary
increased above inflation (promotion, new job, whatever) my outgoings didn&amp;rsquo;t
really go up to match.&lt;/p&gt;

&lt;p&gt;Heh, I even remember as a kid when we went on holiday to the Isle of Wight,
I&amp;rsquo;d saved up my pocket money so I had 20p per night to spend on sweets
and stuff&amp;hellip; and I would buy a 5p bag of gobstoppers.  At the end of the
two weeks I had enough money to buy stuff at the camp gift store.&lt;/p&gt;

&lt;p&gt;So I haven&amp;rsquo;t bought fancy cars, I don&amp;rsquo;t buy expensive whiskey, I
count every penny, almost literally!  I wrote programs to track all my
expenditure and could tell you, to the penny, where everything went. I
still use those programs today!  I would agonize over every &amp;ldquo;luxury&amp;rdquo;
expenditure (where luxury might have been $50 or less).&lt;/p&gt;

&lt;p&gt;Today, at age 55, I earn really good money.  But my total outgoings
were the third lowest in any year in over a decade.  One of my programs
shows yearly outgoings by category over the past 12 years; last year
was a lot less than 2011, despite things going up (eg property taxes,
house insurance).&lt;/p&gt;

&lt;p&gt;It definitely helps to have paid off the mortgage and not to have a
wife or kids; those three things can really increase costs.  As
a result, I&amp;rsquo;ve been saving a lot.&lt;/p&gt;

&lt;p&gt;Apparently this is now known as FIRE (Financial Independence, Retire Early).
I didn&amp;rsquo;t quite do &lt;a href=&#34;https://www.investopedia.com/terms/f/financial-independence-retire-early-fire.asp&#34;&gt;Lean FIRE&lt;/a&gt;,
but not too far short!&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve written more programs and tried to have been conservative in my
estimates (higher than average inflation, lower levels of investment
returns, higher amounts of tax&amp;hellip; and high levels of medical expenses).
I estimate my savings should last at least 45 years, possibly 55 years or
more.  And that doesn&amp;rsquo;t take into account what I&amp;rsquo;ll get on that sad day
when my Mum passes on.&lt;/p&gt;

&lt;h2 id=&#34;the-future&#34;&gt;The future&lt;/h2&gt;

&lt;p&gt;I now feel confident enough that I can afford to live without any new
income, and that resentment I feel each morning doesn&amp;rsquo;t have to be
put up with.  So why suffer it?&lt;/p&gt;

&lt;p&gt;As for what I&amp;rsquo;m going to do&amp;hellip; &amp;ldquo;I dunno&amp;rdquo;.  Story of my life.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not a big one for travel.  I&amp;rsquo;m also not a sun lover (indeed me and
the Sun don&amp;rsquo;t get along; it gave me skin cancer!).  So I don&amp;rsquo;t expect
to do much of that.&lt;/p&gt;

&lt;p&gt;I have a backlog of techie things I&amp;rsquo;d like to do; incomplete projects,
unwritten code, stuff like that.  Both retro computing
(my &lt;a href=&#34;https://sweh.spuddy.org/Beeb/&#34;&gt;BBC Micro&lt;/a&gt;) and modern.&lt;/p&gt;

&lt;p&gt;Maybe I&amp;rsquo;ll actually do some NYC tourism; I&amp;rsquo;ve lived here for over 20 years
and not really done the tourist thing!&lt;/p&gt;

&lt;p&gt;Or maybe I&amp;rsquo;ll just laze around and re-read the 1400+ SciFi books I have on
my shelves, re-watch the 3500+ DVDs (movies and TV shows), learn how to
play video games (beyond Backgammon).&lt;/p&gt;

&lt;p&gt;And maybe&amp;hellip; maybe I&amp;rsquo;ll get bored.  If I do then perhaps I&amp;rsquo;ll dip my
toe back into the workforce; consulting, perhaps?&lt;/p&gt;

&lt;h2 id=&#34;last-day-at-work&#34;&gt;Last day at work&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve given a couple of months notice; I expect my last day to be May 31st.&lt;/p&gt;

&lt;p&gt;The first thing I&amp;rsquo;ll do, after that, is turn off the alarm and have a lie in.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>New Trek</title>
      <link>https://www.sweharris.org/post/2024-04-04-new_trek/</link>
      <pubDate>Thu, 04 Apr 2024 20:43:17 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2024-04-04-new_trek/</guid>
      <description>

&lt;p&gt;So I don&amp;rsquo;t do much &amp;ldquo;streaming&amp;rdquo;.  I&amp;rsquo;m old school; if I like a show then
I&amp;rsquo;ll buy it (or get it as a present) on physical media&amp;hellip; BluRay or 4K
these days.&lt;/p&gt;

&lt;p&gt;This meant I hadn&amp;rsquo;t seen much of New Trek.  A few years back I got Picard
Season 1 on BluRay, then season 2.  But this year I&amp;rsquo;ve received/bought a
lot of the new stuff, and I thought I might write down my thoughts and
opinions.  I&amp;rsquo;m going to do this in (mostly) the order I watched them in.&lt;/p&gt;

&lt;p&gt;Note that everything is my opinion.  I&amp;rsquo;m not the God of Trek; I&amp;rsquo;m not
even part of fandom.  I&amp;rsquo;m just a fan (if you don&amp;rsquo;t grok the difference,
don&amp;rsquo;t worry).&lt;/p&gt;

&lt;h2 id=&#34;picard&#34;&gt;Picard&lt;/h2&gt;

&lt;p&gt;Season 1 was not Star Trek.  It was generic SciFi with a cut&amp;rsquo;n&amp;rsquo;paste Trek
overlay.  It wasn&amp;rsquo;t &lt;em&gt;bad&lt;/em&gt; SciFi, it just wasn&amp;rsquo;t Trek.  It could have been
so much more.&lt;/p&gt;

&lt;p&gt;Season 2 was worse.  Oh let&amp;rsquo;s explore Picard&amp;rsquo;s past and hidden trauma.  WTF?
Where did any of this come from.  This was terrible.&lt;/p&gt;

&lt;p&gt;Season 3&amp;hellip; ah, now we&amp;rsquo;re talking.  Yes, it leaned very heavily on TNG
to hit its emotional points.  But it worked.  The flashback scenes worked
well, the character interactions worked&amp;hellip; it worked.  The attack vector&amp;hellip;
OK, Trek has never been the most consistent; I&amp;rsquo;ll give that a pass.  Not
the worst technobabble the show has ever produced!  And a lovely callback
to TOS.  You can (mostly) watch Season 3 without 1 and 2, and enjoy it.&lt;/p&gt;

&lt;p&gt;Actually, yeah; skip seasons 1 and 2; watch 3.&lt;/p&gt;

&lt;h2 id=&#34;short-treks&#34;&gt;Short Treks&lt;/h2&gt;

&lt;p&gt;I got this on a whim.  And I&amp;rsquo;m glad I did.  These are short stories
(it&amp;rsquo;s in the name) but they&amp;rsquo;re very very well done.  Some of them are
preludes to later series, but they&amp;rsquo;re not necessary pre-watching.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s some good fun stuff here.  And some stories with a big emotional
impact.  Great story telling.  Recommended.&lt;/p&gt;

&lt;h2 id=&#34;prodigy&#34;&gt;Prodigy&lt;/h2&gt;

&lt;p&gt;So I caught an episode of this on Nickelodeon and thought &amp;ldquo;wait, what?&amp;rdquo;
and programmed my TiVo to catch all of them.&lt;/p&gt;

&lt;p&gt;This is a kids animated show.  But it&amp;rsquo;s Trek.  It&amp;rsquo;s &lt;em&gt;GOOD&lt;/em&gt; Trek.  So 11
episodes.. where is episode 12?  (time passes).  C&amp;rsquo;mon, where&amp;rsquo;s the rest?
(google google) Oh, it&amp;rsquo;s only on Paramount+.  Oh, and they deleted it, so
you can&amp;rsquo;t even see it there?  Oh yay, it&amp;rsquo;s on BluRay&amp;hellip; Christmas present!&lt;/p&gt;

&lt;p&gt;And, yes, the second half of the season is just as good as the first.&lt;/p&gt;

&lt;p&gt;Why the hell Paramount decided to cancel (and delete) the show boggles
my mind; this was excellent story telling.  Grump.&lt;/p&gt;

&lt;h2 id=&#34;strange-new-worlds&#34;&gt;Strange New Worlds&lt;/h2&gt;

&lt;p&gt;I watched the first episode and realised it came after Discovery so
I quickly ordered that and put this on the back-burner&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;discovery&#34;&gt;Discovery&lt;/h2&gt;

&lt;p&gt;I wasn&amp;rsquo;t sure what to think of this going in.  I&amp;rsquo;d just had the call-back
from SNW.  OK, it&amp;rsquo;s pre-TOS which is always something to be careful of
(because of breaking the very fragile continuity there is).  And it kinda
worked; yeah yeah the control panels are far advanced of what TOS had,
but that&amp;rsquo;s just a &amp;ldquo;visualization&amp;rdquo;; it does the same thing, it works the same,
it&amp;rsquo;s just a touch panel rather than physical crap.&lt;/p&gt;

&lt;p&gt;And the magic drive system&amp;hellip;  yeah, how they gonna not break continuity
there?  Let&amp;rsquo;s leave that aside&amp;hellip;&lt;/p&gt;

&lt;p&gt;Season 1 is good Trek.  It fills in a part of the time line that doesn&amp;rsquo;t
really contradict anything.  It&amp;rsquo;s well done.  And they even have a
rationale for why this magic drive doesn&amp;rsquo;t show up else where.  Heh.&lt;/p&gt;

&lt;p&gt;Season 2 is even better.  This is a great show and a great story line.
It starts with a puzzle and we follow the clues and encounter contradictions
and problems and you think you know what&amp;rsquo;s going on (I&amp;rsquo;d guessed who
the Red Angel was) we get a reversal that kills that guess&amp;hellip;  this is
a great season.  And the call-back to &amp;ldquo;The Cage&amp;rdquo; from TOS is excellent.&lt;/p&gt;

&lt;p&gt;And then Season 3&amp;hellip; it&amp;rsquo;s the consequence of season 2&amp;hellip; and I didn&amp;rsquo;t feel
it.  I can see what they&amp;rsquo;re trying to do; I can understand the story.  But
it just doesn&amp;rsquo;t work for me.  Far too much &amp;ldquo;post apocalyptic&amp;rdquo; type of story
for me, and it wasn&amp;rsquo;t well told.&lt;/p&gt;

&lt;p&gt;(I haven&amp;rsquo;t watched season 4 yet; that&amp;rsquo;s on my wish list)&lt;/p&gt;

&lt;h2 id=&#34;strange-new-worlds-for-real-this-time&#34;&gt;Strange New Worlds (for real this time)&lt;/h2&gt;

&lt;p&gt;OK, now we&amp;rsquo;ve done Discovery the scenario makes more sense.  Why Pike is
who he is (his back story) is told in Discovery season 2.&lt;/p&gt;

&lt;p&gt;But I&amp;rsquo;m afraid this isn&amp;rsquo;t a good show.&lt;/p&gt;

&lt;p&gt;Well, it&amp;rsquo;s good Trek.  It&amp;rsquo;s very good Trek.  As a prelude to TOS (Pike was
the captain before Kirk) it&amp;rsquo;s good.  As an episodic TV show it&amp;rsquo;s good.&lt;/p&gt;

&lt;p&gt;But that&amp;rsquo;s the problem; &amp;ldquo;episodic&amp;rdquo;.  Every other New Trek (except Short
Treks) has been a season-long story arc.  Strange New Worlds is very much
a throw back.  It&amp;rsquo;s the same reason I consider &lt;a href=&#34;https://www.sweharris.org/post/2015-04-22-voyager/&#34;&gt;voyager&lt;/a&gt; to be the worst of the original Trek era.&lt;/p&gt;

&lt;p&gt;(To be totally open; I still have 4 episodes of Season 2 to go, but
I&amp;rsquo;m not expecting things to change based on the previous episodes)&lt;/p&gt;

&lt;p&gt;Every episode of SNW is excellent.  But there&amp;rsquo;s no direction.  When TOS
was created episode TV was the norm; in the 2020s we expect more.  And
SNW doesn&amp;rsquo;t give that &amp;ldquo;more&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;SNW could have been a perfect bridge between Enterprise and TOS; Discovery
had already set the pattern.  But no real story arc?  Disappointing.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;m the sort of person who if they like a show then they&amp;rsquo;ll want it
on physical media.  If I &lt;em&gt;did&lt;/em&gt; have Paramount+ then I&amp;rsquo;d still have
bought most of this.&lt;/p&gt;

&lt;p&gt;None of the New Trek is &lt;em&gt;bad&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If I was to make a recommendation, I&amp;rsquo;d skip Picard seasons 1 and 2.  Strange
New Worlds is missable, but it&amp;rsquo;s no worse than a lot of shows.  Prodigy
and Short Treks are unexpected fun.&lt;/p&gt;

&lt;p&gt;I haven&amp;rsquo;t seen Lower Decks (yet!) so I can&amp;rsquo;t comment on that.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>I dunno what I want to do</title>
      <link>https://www.sweharris.org/post/2024-03-25-i-dunno/</link>
      <pubDate>Mon, 25 Mar 2024 13:39:36 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2024-03-25-i-dunno/</guid>
      <description>

&lt;p&gt;One of the most annoying interview questions is &amp;ldquo;where do you see yourself
in five years time?&amp;ldquo;.  I hate it.  I have no vision of the future like
this.   Hell, I barely know what I want to do tomorrow.&lt;/p&gt;

&lt;h2 id=&#34;i-m-good-at-foreseeing-the-future-honest&#34;&gt;I&amp;rsquo;m good at foreseeing the future, honest!&lt;/h2&gt;

&lt;p&gt;So my first job, straight out of uni, was with a small Greek shipping
company.  I learned a lot there &amp;lsquo;cos I had to do it all.  But I thought
the internet would be a fad; you can do all you want with email and UUCP
and store&amp;rsquo;n&amp;rsquo;forward systems.  Why would we need complicated TCP connections
to every desktop?  That&amp;rsquo;s unnecessary.&lt;/p&gt;

&lt;p&gt;My second job was at a web publishing company (oh, look; internet!),
where I went from Unix SA and networking to Oracle DBA to Windows SA to
Lotus Notes Admin&amp;hellip; there&amp;rsquo;s no way I could have foreseen that path.&lt;/p&gt;

&lt;p&gt;My third job quickly led to an approximately 50% salary increase in a matter
of months (promotion).  So that house I had just bought&amp;hellip; I could pay off
the mortgage in 10 years, rather than 25.&lt;/p&gt;

&lt;p&gt;But then I fell in love, and moved to America.  Yeah,
like that was on my plan! 5 years?  That wasn&amp;rsquo;t even within 2
years.&lt;/p&gt;

&lt;p&gt;I stayed at that job for 17 years, but kept moving departments
(SA, engineer, automation, config reporting, access management,
security engineering, cloud security&amp;hellip;) whenever I started to get
bored, or whenever the organisation needed me to do something else.
The advantage of a good mega-corp is that there are plenty of internal
movement opportunities.&lt;/p&gt;

&lt;p&gt;My fourth (and current) job came out of the blue as the result of a call
from a friend asking me for help.&lt;/p&gt;

&lt;p&gt;None of this has been planned. I just drifted around; solve this problem,
solve that problem then move on (hopefully leaving the place better than
when I started) when I start to get bored.&lt;/p&gt;

&lt;h2 id=&#34;doing-stuff-i-enjoy&#34;&gt;Doing stuff I enjoy&lt;/h2&gt;

&lt;p&gt;I remember telling my boss in my second job that I was thinking of
leaving; he asked if there was anything that could be done; what would I
like to do, what could they do to keep me.   I had no idea, no answer.
I told him that if I knew what it was that&amp;rsquo;d keep me interested then
I&amp;rsquo;d already be doing it.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s not too far off.  I&amp;rsquo;ve always been pretty lucky to be able to do
skunkworks type stuff; play with things and then tell other people about
it.  Normally they found it useful &amp;lsquo;cos I would build it to make &lt;em&gt;my&lt;/em&gt; life
easier, so it solved problems that other people were also having.&lt;/p&gt;

&lt;h2 id=&#34;looking-back-to-look-forward&#34;&gt;Looking back to look forward&lt;/h2&gt;

&lt;p&gt;If I look back at my career then I can see a pretty good progression;
although none of it was planned.  Even my very first job was unplanned;
my university tutor mentioned that a lecturer in another college wanted
to talk to me; that lecturer had a friend who was looking for a Unix SA
for his company; I interviewed and got the job.&lt;/p&gt;

&lt;p&gt;All the different roles I&amp;rsquo;ve had mean that I get a better holistic
view of problems; I&amp;rsquo;m not stuck in a single mindset rut, not focused on
a single technology solution.  I&amp;rsquo;ve seen a lot, made a number of mistakes,
learned from them and can put all this together to design new solutions
or spot gaps/problems with proposals from others.&lt;/p&gt;

&lt;p&gt;And it&amp;rsquo;s by looking back that I come up with answers to that annoying
interview question.&lt;/p&gt;

&lt;p&gt;So in that second job I&amp;rsquo;d brought in Big Brother to monitor the web
servers and network.  Then I wrote some Kermit scripts to talk to the
pager gateways so BB could page me if there was a problem.  Which I
then opened to the whole team so they could page each other without
needing to phone the paging center.  Then I added more monitoring, and
added Netware pings (so the Netware team got alerts when their aging
repurposed desktop-as-server machines fell over).&lt;/p&gt;

&lt;p&gt;My first job I managed 3 machines; my second job 20 machines.  When it
came to my third job interview I was able to describe that automation and
monitoring, and said I wanted to automate and manage bigger environments;
I ended up starting by automating 550-ish servers.  When I left that
job my software was running in 65,000 servers.&lt;/p&gt;

&lt;p&gt;Which then led to the answer for my fourth job; &amp;ldquo;I&amp;rsquo;ve done scale from
tiny to mega; now I want more complicated problems&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;They were true answers, but they weren&amp;rsquo;t the whole truth.  I didn&amp;rsquo;t
really know what I wanted to do in 5 years; I just don&amp;rsquo;t do that type
of planning.&lt;/p&gt;

&lt;h2 id=&#34;privilege&#34;&gt;Privilege&lt;/h2&gt;

&lt;p&gt;I try to take care that my decisions aren&amp;rsquo;t overly risky (although that
move to America was definitely one!) so I don&amp;rsquo;t &lt;em&gt;break&lt;/em&gt; my potential future,
but that&amp;rsquo;s my normal conservative approach to everything.&lt;/p&gt;

&lt;p&gt;But I&amp;rsquo;ve got to acknowledge an amount of privilege at work, here.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve never &lt;em&gt;failed&lt;/em&gt;, but I knew I had a safety net if I had (especially in
the early days); I lived at home until I was 30 so never had to worry
about keeping paying rent or getting food on the table; I lived in the
UK so didn&amp;rsquo;t have to worry about expensive medical bills; I&amp;rsquo;m smarter
than the average bear; and I got &lt;em&gt;lucky&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;It&amp;rsquo;s clear that I&amp;rsquo;m not a visionary, and that I&amp;rsquo;ve never had a plan.
I&amp;rsquo;ve never said &amp;ldquo;this is where I want to be&amp;rdquo;.  I&amp;rsquo;ve just gone where the
tides have taken me.&lt;/p&gt;

&lt;p&gt;So now I&amp;rsquo;m asking myself&amp;hellip; what do I want to do tomorrow?  And the answer
is &amp;ldquo;I dunno; let&amp;rsquo;s see what comes up!&amp;rdquo;&lt;/p&gt;

&lt;p&gt;And that&amp;rsquo;s OK.&lt;/p&gt;

&lt;p&gt;For me.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>MQTT, Home Assistant, Hue emulation working together</title>
      <link>https://www.sweharris.org/post/2024-03-11-mqtt_light/</link>
      <pubDate>Mon, 11 Mar 2024 17:11:06 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2024-03-11-mqtt_light/</guid>
      <description>

&lt;p&gt;A number of years ago I wrote a &lt;a href=&#34;https://github.com/sweharris/huebridge-shell&#34;&gt;Hue Bridge
Emulator&lt;/a&gt; that would let
you emulate light bulbs in shell script in such a way that these devices
could be controlled by Alexa (and so used in routines and the like).  It
worked well.&lt;/p&gt;

&lt;p&gt;But recently Amazon appear to be changing how hue bridges are detected.
The big challenge appears to be it wants the server to listen on port 80.
This is annoying for a number of reasons, including that it needs privileges
to bind to that port, &lt;em&gt;and&lt;/em&gt; it may conflict with a web server already on
that port.&lt;/p&gt;

&lt;p&gt;Now I also run &lt;a href=&#34;https://www.home-assistant.io/&#34;&gt;Home Assistant&lt;/a&gt; which has
an inbuilt Hue emulator.  So I figured we can use that functionality, &lt;em&gt;and&lt;/em&gt;
let you control more things through HA which don&amp;rsquo;t normally have integrations.
A simple example might be &lt;a href=&#34;https://github.com/sweharris/mqttlight_bridge/blob/main/screen_on_off&#34;&gt;turning your screen on/off&lt;/a&gt;;
have a &amp;ldquo;bed time&amp;rdquo; routine that turns your screen off!&lt;/p&gt;

&lt;p&gt;We do this by configuring a light in a MQTT configuration, and have
code to subscribe to topics so it sees when to turn/off or (optionally)
change brightness.  It will pass this data down to your program (which
could be a shell script) and update MQTT status topics with any feedback from
the program.&lt;/p&gt;

&lt;p&gt;In theory this could all be done from shell scripts (eg using &lt;code&gt;mqttcli&lt;/code&gt;
commands and coprocesses and more) but I feel this approach is simpler;
your program only needs to deal with stdin/stdout and doesn&amp;rsquo;t need to
care about MQTT at all.&lt;/p&gt;

&lt;h2 id=&#34;configuring-home-assistant-for-mqtt&#34;&gt;Configuring Home Assistant for MQTT&lt;/h2&gt;

&lt;p&gt;You need to set up (if you haven&amp;rsquo;t already) the MQTT integration.  Running
an MQTT broker and configuring the integration is beyond the scope of this
doc.  I, personally, use &lt;code&gt;mosquitto&lt;/code&gt; as the broker; it comes with many
Linux distributions and is easy to install.&lt;/p&gt;

&lt;p&gt;Now we need to define a light.  This is done in the &lt;code&gt;mqtt:&lt;/code&gt; section of
&lt;code&gt;configuration.yaml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After manually configuring MQTT instances the way I&amp;rsquo;m describing here you
will need to tell HA to reload the configuration (e.g from Developer tools),
or else restart HA totally.&lt;/p&gt;

&lt;p&gt;There are two kinds of lights we can model:&lt;/p&gt;

&lt;h3 id=&#34;on-off-only&#34;&gt;On/Off only&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;mqtt:
  light:
  - name: &amp;quot;Test Light&amp;quot;
    command_topic: &amp;quot;mqttlight/test/command&amp;quot;
    state_topic: &amp;quot;mqttlight/test/state&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this light it will create a new &lt;code&gt;light.&lt;/code&gt; entity in HA (probably &lt;code&gt;light.test_light&lt;/code&gt;).  If you click the ON button it will send an &amp;ldquo;ON&amp;rdquo; message to
&lt;code&gt;mqttlight/test/command&lt;/code&gt;.  The state of the button will be reported back to
HA on &lt;code&gt;mqttlight/test/state&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&#34;on-off-with-brightness&#34;&gt;On/Off with brightness&lt;/h3&gt;

&lt;p&gt;This emulates a dimmer switch; it has on/off and brightness controls.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mqtt:
  light:
  - name: &amp;quot;Test Light&amp;quot;
    command_topic: &amp;quot;mqttlight/test/command&amp;quot;
    state_topic: &amp;quot;mqttlight/test/state&amp;quot;
    brightness_command_topic: &amp;quot;mqttlight/test/bright_command&amp;quot;
    brightness_state_topic: &amp;quot;mqttlight/test/bright_state&amp;quot;
    brightness_scale: 100
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;exposing-these-lights-to-alexa-maybe-even-google&#34;&gt;Exposing these lights to Alexa (maybe even Google?)&lt;/h3&gt;

&lt;p&gt;Once the MQTT entries have been configured you will be able to see the
entity IDs in Settings / Devices / Entities.  If you search for the name
you set you&amp;rsquo;ll see it show in the entity list.  We&amp;rsquo;ll need this.&lt;/p&gt;

&lt;p&gt;Now in &lt;code&gt;configuration.yaml&lt;/code&gt; we need to tell HA to expose these lights to
Alexa, via the &lt;code&gt;emulated_hue&lt;/code&gt; configuration.   I normally don&amp;rsquo;t expose
&lt;em&gt;every&lt;/em&gt; device, just the ones I select:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;emulated_hue:
  listen_port: 80
  expose_by_default: false
  entities: !include emulated_hue.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This lets me use a new file &lt;code&gt;emulated_hue.yaml&lt;/code&gt; to list the devices I want.
You don&amp;rsquo;t need to have it as an included file, I just find it simpler this
way.&lt;/p&gt;

&lt;p&gt;The contents of this file are now the entities we want to expose.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;light.test_light:
  name: &amp;quot;Test light with brightness&amp;quot;
  hidden: false
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The entity ID is the one we found earlier; the name is the how we want this
light to show in Alexa.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s it!  That&amp;rsquo;s the whole &lt;code&gt;emulated_hue&lt;/code&gt; configuration.&lt;/p&gt;

&lt;p&gt;Changing this file requires a full HA restart.&lt;/p&gt;

&lt;p&gt;The emulated_hue setup can be made a lot more complex; such setups are described in the &lt;a href=&#34;https://www.home-assistant.io/integrations/emulated_hue/&#34;&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you&amp;rsquo;ve started it you should be able to confirm the bulb shows up by
talking to the emulated hue endpoint.&lt;/p&gt;

&lt;p&gt;e.g.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% curl http://your_ha_ip_address:80/api/v2/lights | jq .
{
  &amp;quot;1&amp;quot;: {
    &amp;quot;state&amp;quot;: {
      &amp;quot;on&amp;quot;: true,
      &amp;quot;reachable&amp;quot;: true,
      &amp;quot;mode&amp;quot;: &amp;quot;homeautomation&amp;quot;,
      &amp;quot;bri&amp;quot;: 1
    },
    &amp;quot;name&amp;quot;: &amp;quot;Test light with brightness&amp;quot;,
    &amp;quot;uniqueid&amp;quot;: &amp;quot;00:42:af:28:ad:f5:e0:ea-de&amp;quot;,
    &amp;quot;manufacturername&amp;quot;: &amp;quot;Home Assistant&amp;quot;,
    &amp;quot;swversion&amp;quot;: &amp;quot;123&amp;quot;,
    &amp;quot;type&amp;quot;: &amp;quot;Dimmable light&amp;quot;,
    &amp;quot;modelid&amp;quot;: &amp;quot;HASS123&amp;quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(&lt;code&gt;jq&lt;/code&gt; is a nice command that make the JSON look pretty).&lt;/p&gt;

&lt;p&gt;You can now tell Alexa to discover new devices&amp;hellip; and it should(!) work.&lt;/p&gt;

&lt;p&gt;More complex &lt;code&gt;emulated_hue&lt;/code&gt; setups are described in the &lt;a href=&#34;https://www.home-assistant.io/integrations/emulated_hue/&#34;&gt;HA documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;communication-between-bridge-and-program&#34;&gt;Communication between bridge and program&lt;/h2&gt;

&lt;p&gt;The communication patterns are asynchronous.  The bridge can send
commands to the program and the program can send status updates back
to the bridge at any time.  It&amp;rsquo;s a very simple protocol.&lt;/p&gt;

&lt;h3 id=&#34;commands&#34;&gt;Commands:&lt;/h3&gt;

&lt;p&gt;There&amp;rsquo;s only one command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;LIGHT#name#on/off#brightness&lt;/code&gt;  &amp;ndash; Set the light named &amp;ldquo;name&amp;rdquo; to the
on/off status and the brightness (0-100).  The name must not contain a #
since that is used as the separator.  If either the on/off or brightness
values are - or missing then that value should be left unchanged.&lt;/p&gt;

&lt;p&gt;examples:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;LIGHT#test##70
LIGHT#test#on#
LIGHT#test#on#70
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;status-updates&#34;&gt;Status Updates:&lt;/h3&gt;

&lt;p&gt;The child can send two messages to the bridge.  These are best sent
periodically (e.g. every 5 seconds).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;LIST#name1#name2#name3 ...&lt;/code&gt;  &amp;ndash; This can be used to tell the
bridge of the complete set of lights being controlled.  For example, if
you have an environment where devices may join and leave (a mobile
phone, perhaps?) then this can be used as a way of refreshing the bridge&amp;rsquo;s
knowledge and to stop telling clients about lights that no longer exist.&lt;/p&gt;

&lt;p&gt;The bridge uses this list to filter out what messages seen on MQTT topics
should be sent to the child program or not.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;LIGHT#name#on/off#brightness&lt;/code&gt; &amp;ndash; This is the current state of
the light.  When this is sent it will trigger an update of the relevant
MQTT topics.  The brightness may be left blank if it&amp;rsquo;s not relevant.  If
this is a new light then it will be added to the list seen from the &lt;code&gt;LIST&lt;/code&gt;
command.&lt;/p&gt;

&lt;p&gt;e.g.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;LIST#monitor
LIGHT#monitor#ON#
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Importantly, the name of the light sent in the LIGHT command will be used
to create the topic name.  e.g.  &lt;code&gt;LIGHT#monitor#ON#&lt;/code&gt; will cause an ON message
to be sent on topic &lt;code&gt;mqttlight/monitor/status&lt;/code&gt;.   This &lt;em&gt;is&lt;/em&gt; case sensitive;
&amp;ldquo;monitor&amp;rdquo; is different to &amp;ldquo;Monitor&amp;rdquo;&lt;/p&gt;

&lt;h2 id=&#34;running-the-program&#34;&gt;Running the program&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;Usage of ./mqttlight_bridge:
  -app string
        Application to run
  -base string
        MQTT Base (default &amp;quot;mqttlight&amp;quot;)
  -debug
        Allow CLI entry to child
  -pass string
        MQTT Password
  -port int
        MQTT Port (default 1883)
  -server string
        MQTT server (default &amp;quot;localhost&amp;quot;)
  -user string
        MQTT Username
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;-app&lt;/code&gt; value is mandatory, the rest are optional.  If your MQTT broker
requires a username and password then these should be specified.&lt;/p&gt;

&lt;h2 id=&#34;examples&#34;&gt;Examples&lt;/h2&gt;

&lt;p&gt;Two simple example scripts are provided in the source repo.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;small-example&lt;/code&gt; - acts as a simple light called &amp;ldquo;test&amp;rdquo; which can be turned
on or off and have the brightness changed&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;screen_on_off&lt;/code&gt; - an On/Off light that uses &lt;code&gt;xset q&lt;/code&gt; to determine if the
monitor is on or off, and &lt;code&gt;xset dpms&lt;/code&gt; to change the state.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;possible-gotchas&#34;&gt;Possible gotchas&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve sometimes seen that changing the brightness from the Alexa app may
cause two updates to be sent; the brightness value and &lt;em&gt;then&lt;/em&gt; an ON message.
This would cause two commands to be sent to the child&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  LIGHT#name##brightness
  LIGHT#name#ON#
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;you should be careful that actions taken in response to &amp;ldquo;ON&amp;rdquo; without a
brightness value should not change the brightness by mistake.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve seen Home Assistant get confused; I originally created an &lt;code&gt;mqtt&lt;/code&gt; light
as on/off and then later changed it to one with brightness.  HA then wasn&amp;rsquo;t
sure how to present it; the GUI presented on/off and brightness slider, and
the slider did change cause a brightness command to be sent&amp;hellip; but it never
reflected the actual brightness.   I found I had to stop HA and edit the
&lt;code&gt;.storage/core.restore_state&lt;/code&gt; to remove the existing entry for the light
before it would pick up the new definition.&lt;/p&gt;

&lt;h2 id=&#34;building-the-code&#34;&gt;Building the code.&lt;/h2&gt;

&lt;p&gt;This uses pretty simple GoLang and so should compile and work on any of the
main supported platforms (Linux, MacOS, Windows, etc).  You obviously need
the &lt;a href=&#34;https://go.dev/dl/&#34;&gt;GoLang compiler&lt;/a&gt; and &lt;code&gt;git&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;An example session might look like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git clone https://github.com/sweharris/mqttlight_bridge
Cloning into &#39;mqttlight_bridge&#39;...
remote: Enumerating objects: 18, done.
remote: Counting objects: 100% (18/18), done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 18 (delta 2), reused 15 (delta 2), pack-reused 0
Unpacking objects: 100% (18/18), done.
$ cd mqttlight_bridge/
$ go mod tidy
$ go build
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;rsquo;s it!   The &lt;code&gt;go mod tidy&lt;/code&gt; may download modules from github and
golang sites if the dependencies are not present.&lt;/p&gt;

&lt;p&gt;You can now use the program; e.g.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;./mqttlight_bridge -app ./screen_on_off -server mqtt_server
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I have a love/hate relationship with Home Assistant.  I think it&amp;rsquo;s a
very useful program and my home automation is totally dependent on it.
I&amp;rsquo;m just that much of a fan of its internal architecture; I would much
preferred a decoupled setup.  Indeed, using MQTT in this way is very
decoupled; we can restart the bridge code and the child app and Home
Assistant doesn&amp;rsquo;t care.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m annoyed that Amazon keeps changing what they expected for a &amp;ldquo;fake hue&amp;rdquo;
setup, but at least Home Assistant can fill in the gap!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Blame Security</title>
      <link>https://www.sweharris.org/post/2023-08-05-blame-security/</link>
      <pubDate>Sat, 05 Aug 2023 18:04:04 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2023-08-05-blame-security/</guid>
      <description>

&lt;p&gt;Else-net there was a discussion on how &amp;ldquo;security&amp;rdquo; is generally seen as
a blocker; they&amp;rsquo;re seen as gate keepers and people who just say &amp;ldquo;no&amp;rdquo;,
or who may be focused on regulatory compliance and not actual security.&lt;/p&gt;

&lt;p&gt;Who needs &lt;a href=&#34;https://en.wikipedia.org/wiki/List_of_Dilbert_characters#Mordac&#34;&gt;Mordac, the Preventer Of Information Services&lt;/a&gt;
when you have a security team?!

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/mordac.gif&#34; alt=&#34;Mordac&#34;&gt;
&lt;/div&gt;
&lt;/p&gt;

&lt;p&gt;The thing is, &amp;ldquo;security&amp;rdquo; isn&amp;rsquo;t a monolith, and it&amp;rsquo;s not a one way street.&lt;/p&gt;

&lt;h2 id=&#34;many-teams&#34;&gt;Many teams&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve only really seen security from a megacorp perspective, both from
the companies I&amp;rsquo;ve worked for and the people from other companies
I&amp;rsquo;ve spoken with over the years.&lt;/p&gt;

&lt;p&gt;And there is no one security team in these situations; there&amp;rsquo;s a whole
diverse group of teams; maybe all under the CISO, maybe not!&lt;/p&gt;

&lt;p&gt;So there might be&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a team of risk managers (look at gaps, evaluating them, documenting
risks, track remediation).&lt;/li&gt;
&lt;li&gt;a team for firewall governance (ensure there&amp;rsquo;s no free-for-all access
in/out of the company)&lt;/li&gt;
&lt;li&gt;a team handling application security (enabling shift-left, if they&amp;rsquo;re
good!)&lt;/li&gt;
&lt;li&gt;&amp;hellip; handling email security&lt;/li&gt;
&lt;li&gt;&amp;hellip; for encryption&lt;/li&gt;
&lt;li&gt;&amp;hellip; for network security (honeypots, deception, packet flows, etc etc)&lt;/li&gt;
&lt;li&gt;&amp;hellip; WAFs&lt;/li&gt;
&lt;li&gt;&amp;hellip; Identity and Access Management&lt;/li&gt;
&lt;li&gt;&amp;hellip; data loss protection&lt;/li&gt;
&lt;li&gt;&amp;hellip; data discovery&lt;/li&gt;
&lt;li&gt;&amp;hellip; SOC&lt;/li&gt;
&lt;li&gt;&amp;hellip; Incident response&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;hellip; and more.&lt;/p&gt;

&lt;p&gt;Each company will have its own structure, of course.  It&amp;rsquo;s not fixed in
stone.&lt;/p&gt;

&lt;p&gt;Regulatory compliance is really a small part of all of this, and may not
even be under the CISO.  In my opinion, a company focused on compliance
isn&amp;rsquo;t a company that cares about security.  They will be breached because
they see it as a box ticking exercise.&lt;/p&gt;

&lt;p&gt;Now some of those teams may run their own technology, others may use
tools provided by the core technology area (e.g. firewall governance
team may merely control the rulesets with the technology network team
actually &lt;em&gt;running&lt;/em&gt; the firewalls).&lt;/p&gt;

&lt;p&gt;I work in security architecture.  I&amp;rsquo;m a generalist.  Part of that job is
to ensure these security teams are doing things that further the security
goals of the company and that all those teams aren&amp;rsquo;t duplicating efforts
(&amp;lsquo;cos strict delineation of areas isn&amp;rsquo;t really possible; there&amp;rsquo;s always
overlap; e.g. email security team has a DLP requirement for outgoing
email), and to provide consulting services (e.g. to the risk managers to
help them understand the problems so they can provide better evaluations).&lt;/p&gt;

&lt;p&gt;And, of course, in a megacorp for some teams are better than others.&lt;/p&gt;

&lt;p&gt;Which leads to another part of my job; working with the business units
(BUs) to assist them in building suitable solutions.&lt;/p&gt;

&lt;p&gt;Over the years I&amp;rsquo;ve found there are two main types of BU teams; those
that want to do the right thing, and those that just want to deploy as
fast as possible and just see security as a hindrance.&lt;/p&gt;

&lt;p&gt;The first kind I work well with; I can explain my logic, they can
explain their solutions, we can work out what needs to be done to be
secure (rather than just compliant).  I rarely need to point at the
standards and rules with these teams because they care.  And we build
good solutions together.  We have a virtuous circle; they&amp;rsquo;re more
willing to come to me early in their design cycle and we get better
results, faster.  A recent comment from BU team member was long the
lines of &amp;ldquo;Thanks for the long and detailed response; that makes perfect
sense, and I think I can see a solution path for our use case&amp;rdquo;.  I&amp;rsquo;ve
had an SVP from one of those teams call me the best security person he&amp;rsquo;s
ever worked with.  But this only works because they are willing to take
that extra step.&lt;/p&gt;

&lt;p&gt;The other type of team, though&amp;hellip; they&amp;rsquo;re a problem.  If it&amp;rsquo;s not in the
standards they won&amp;rsquo;t do it.  They push back because it might be hard,
because it&amp;rsquo;ll cost money, because they just want to meet deadlines,
because they&amp;rsquo;ve never been held to account before and they have over
a decade of &amp;ldquo;do their own thing&amp;rdquo;.  These teams I sometimes have had to
rule by dictate.  If they&amp;rsquo;re not willing to work with me to help define
a better outcome then I &lt;em&gt;have&lt;/em&gt; to be the blocker.  This is a vicious
circle, and one I dislike.&lt;/p&gt;

&lt;p&gt;In some ways we can classify these teams as those following the spirit
of the law (&amp;ldquo;we need to protect our data and systems&amp;rdquo;) vs those that
follow the letter of the law (&amp;ldquo;we need to be compliant&amp;rdquo;).  I so much
prefer the first.&lt;/p&gt;

&lt;p&gt;At the end of the day my goal is to help the BUs operate in a secure
manner; I&amp;rsquo;m not here to block, I&amp;rsquo;m here to help.  But I&amp;rsquo;m not able to
force them to engage constructively; &amp;ldquo;tell me where in the standards I
have to do this&amp;rdquo; is not conducive to a meaningful discussion.  In the
past I&amp;rsquo;ve joked that my job is saying &amp;ldquo;Don&amp;rsquo;t be stupid; don&amp;rsquo;t be stupid;
I said don&amp;rsquo;t &amp;hellip; oh God, you were stupid weren&amp;rsquo;t you?&amp;ldquo;.&lt;/p&gt;

&lt;p&gt;Every mega corp will have both types of team.  Fortunately the second
type is getting less prevalent, as technology changes.  For example, teams
that are refactoring for cloud or for k8s or for automation tend to want
to use modern CI/CD processes and want to do it correctly from the start.&lt;/p&gt;

&lt;h2 id=&#34;hide-behind-security&#34;&gt;Hide behind security&lt;/h2&gt;

&lt;p&gt;Sometimes teams blame security even when it&amp;rsquo;s nothing to do with us;
it might be an easy way of punting work that&amp;rsquo;s hard, for example.&lt;/p&gt;

&lt;p&gt;Or teams may interpret requirements in the worst way and assume there&amp;rsquo;s
nothing they can do; &amp;ldquo;We can&amp;rsquo;t do FOO because the standard says BAR&amp;rdquo;.
That&amp;rsquo;s even worse when that team provides services to other teams (e.g.
central technology teams providing services to BUs) because the impact
is magnified.&lt;/p&gt;

&lt;p&gt;Security can also be the front man for other teams; rules and requirements
can come from legal and compliance teams (who aren&amp;rsquo;t security).  We get
the blame for stuff because we&amp;rsquo;re the ones who have to implement it;
&amp;ldquo;No you can&amp;rsquo;t record Zoom meetings because security said turn it off&amp;rdquo;;
it was legal who said turn it off &amp;lsquo;cos Zoom recordings didn&amp;rsquo;t meet their
records retention policies, we just had to implement it for them.&lt;/p&gt;

&lt;p&gt;Security can end up getting the blame for things that aren&amp;rsquo;t our fault.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;I tell people I don&amp;rsquo;t really care too much about compliance; good
security practices (mostly) result in compliant solutions anyway!
So I try to push for good security practices.  Okay, I do keep
some primary stuff in mind (e.g. PCI) but most of that is baseline
bare minimum; you can be PCI compliant but not secure.&lt;/p&gt;

&lt;p&gt;But I can&amp;rsquo;t do it alone.&lt;/p&gt;

&lt;p&gt;Security can only collaborate with teams that &lt;em&gt;want&lt;/em&gt; to collaborate.
I need teams to work with me; a &amp;ldquo;help me help you&amp;rdquo; type scenario.&lt;/p&gt;

&lt;p&gt;Maybe it&amp;rsquo;s not &lt;em&gt;all&lt;/em&gt; my fault, after all!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Digital Safe version 3</title>
      <link>https://www.sweharris.org/post/2023-06-13-digital_safe_3/</link>
      <pubDate>Tue, 13 Jun 2023 18:01:27 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2023-06-13-digital_safe_3/</guid>
      <description>

&lt;p&gt;&lt;a href=&#34;https://www.sweharris.org/post/2021-05-18-digital_safe_2/&#34;&gt;Previously&lt;/a&gt; I had modified a digital
safe to be controlled via an ESP8266; basically a WiFi safe.&lt;/p&gt;

&lt;p&gt;I was asked if I could create a firmware for it that made it
act like a timer safe; something along the lines of a &lt;a href=&#34;https://www.thekitchensafe.com/&#34;&gt;Kitchen
Safe&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I decided to take the opportunity to build (yet another) safe, using the
combined esp/relay board.  Without any soldering, I&amp;rsquo;m sure I can make a
cleaner more reliable build!&lt;/p&gt;

&lt;h2 id=&#34;requirements&#34;&gt;Requirements&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.amazon.com/dp/B09LV9ZWCC&#34;&gt;A cheap Safe&lt;/a&gt; (Amazon link)&lt;/li&gt;
&lt;li&gt;An ESP8266 relay board.&lt;/li&gt;
&lt;li&gt;A 1N4001 Diode&lt;/li&gt;
&lt;li&gt;Cables&lt;/li&gt;
&lt;li&gt;Power Supply&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main relay board looks something like this
&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v3/esp8266-relay.jpg&#34; alt=&#34;relay board&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not going to link to a seller, &amp;lsquo;cos sellers seem to change a lot.  I&amp;rsquo;ve
found searching &amp;ldquo;esp8266 hw-622&amp;rdquo; tends to find sellers.&lt;/p&gt;

&lt;p&gt;This board comes in a couple of versions; the biggest difference is
whether headers at the top left are present. I recommend getting them
pre-installed because these boards don&amp;rsquo;t have USB connectivity; you
program them using a 3.3V serial adapter connected to them.&lt;/p&gt;

&lt;h2 id=&#34;the-safe&#34;&gt;The Safe&lt;/h2&gt;

&lt;p&gt;This time I picked a safe with a slot in the top. The normal idea is
that the safe can be locked and then money added.  It&amp;rsquo;s about $33.
There&amp;rsquo;s a lot of similar models on Amazon.&lt;/p&gt;

&lt;p&gt;The internals on this safe are a little different to what I&amp;rsquo;ve seen
before. Previously there was a simple plunger solenoid. This time the
lock rotates.&lt;/p&gt;

&lt;p&gt;In the locked position it looks like this.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v3/inside_safe_new_lock_solenoid.jpg&#34; alt=&#34;internals&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;When almost totally open we can see it&amp;rsquo;s rotated down out of the way&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v3/inside_safe_lock_solenoid_part_open.jpg&#34; alt=&#34;Inside Safe&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;This would appear to fix a major issue of the previous design; the old
one is susceptible to hitting it hard to send the plunger down, or even
a strong magnet.&lt;/p&gt;

&lt;p&gt;Of course the metal is still very thin so it&amp;rsquo;s not a high security safe!&lt;/p&gt;

&lt;p&gt;Open the safe cover and disconnect the solenoid wire as we did in the
v2 safe. I made a small hole in the door near the battery compartment
so it can exit there. That&amp;rsquo;s it.  That&amp;rsquo;s the only modification!&lt;/p&gt;

&lt;p&gt;Put the cover back on.&lt;/p&gt;

&lt;p&gt;At this stage I recommend programming the esp8266 with the safe
software. It&amp;rsquo;s easier to get to the contacts.&lt;/p&gt;

&lt;p&gt;It works just fine with the existing &lt;a href=&#34;https://github.com/sweharris/digi-safe-v2&#34;&gt;software&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To do that we need to power it. So let&amp;rsquo;s talk about this. These boards can
typically be powered from 7V up to 20V, if not higher. The power supply
will also power the solenoid. I measured the coil at 18 ohms, so I think
any power supply 500mA or higher would do; maybe call it 750mA for safety?&lt;/p&gt;

&lt;p&gt;Now I had some spare 2.1mm x 5mm power pigtails spare.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v3/power_cable.jpg&#34; alt=&#34;Inside Safe&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;These aren&amp;rsquo;t optimal for this job because they&amp;rsquo;re not designed for
&amp;ldquo;panel&amp;rdquo; work, but they do the job.&lt;/p&gt;

&lt;p&gt;Connect the red wire to the right side, and the black to the left&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v3/esp8266-relay-power.jpg&#34; alt=&#34;Inside Safe&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Now you can program it using the Arduino software and your 3.3v serial adapter.&lt;/p&gt;

&lt;p&gt;Hook it up to your network and test the safe software works. You&amp;rsquo;ll hear
the relay clicking. Remember to change the configuration so it uses &amp;ldquo;4&amp;rdquo;
(GPIO4) as the trigger.&lt;/p&gt;

&lt;h2 id=&#34;putting-it-all-together&#34;&gt;Putting it all together&lt;/h2&gt;

&lt;p&gt;First I jammed the power cable through one of the mounting holes on
the back. This was harder than it should have been because it&amp;rsquo;s not
a panel mount option. And the hole was just a little too small so I
stuck a screw driver in and bent the metal slightly to make it bigger.&lt;/p&gt;

&lt;p&gt;It still sticks out but it&amp;rsquo;s good enough.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v3/safe_back.jpg&#34; alt=&#34;Inside Safe&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Now we need to add a diode to the output. This is to prevent &amp;ldquo;back
current&amp;rdquo; from potentially damaging the ESP8266 (when I tried without
the diode the board would reboot maybe 1 time out of 3). Almost any
diode should work; I used a 1N4001. This needs to connect between the
convenient 5V output at the bottom of the &amp;ldquo;common&amp;rdquo; on the relay. The
stripe side of the diode should be at the relay end.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v3/esp8266-relay-diode.jpg&#34; alt=&#34;Inside Safe&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Now we just need wires going from the negative power at the top of the
board and from the far right relay connection at the bottom of the board
to go to the solenoid cable.&lt;/p&gt;

&lt;p&gt;And that&amp;rsquo;s really it!&lt;/p&gt;

&lt;p&gt;This is what a diagram of the wiring looks like. Did I just scribble
something on a piece of paper? Yes, I did!&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v3/wiring_diagram.jpg&#34; alt=&#34;Inside Safe&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Yeah, there&amp;rsquo;s two wires going to the negative power; just jam them
into the same hole.&lt;/p&gt;

&lt;p&gt;To mount this I used some 3mm plastic stick-on standoffs. And I figured
I could stick it to the roof of the safe!&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v3/safe_top.jpg&#34; alt=&#34;Inside Safe&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;This makes the whole thing very clean.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v3/safe_inside.jpg&#34; alt=&#34;Inside Safe&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;This is a lot simpler than the v2 build; no soldering, no holding it
together with duct tape; just a few wires!&lt;/p&gt;

&lt;h2 id=&#34;software&#34;&gt;Software&lt;/h2&gt;

&lt;p&gt;As mentioned, the old &lt;a href=&#34;https://github.com/sweharris/digi-safe-v2&#34;&gt;software&lt;/a&gt;
will work; just set it so GPIO 4 is used for the relay.&lt;/p&gt;

&lt;p&gt;But we want a timer safe.&lt;/p&gt;

&lt;p&gt;The problem I had, here, was in determining the current time.  Of course
we could just use NTP, but if I wanted to defeat the lock then I&amp;rsquo;d just
set up DHCP to point to a &amp;ldquo;rogue&amp;rdquo; time server that claimed it was in the
future, and the safe would open.  That&amp;rsquo;s not good.&lt;/p&gt;

&lt;p&gt;I realized I didn&amp;rsquo;t need to save the &lt;em&gt;time&lt;/em&gt;, just how long the lock had
to run for; time conversions could be done in the browser.  Of course we
still had to worry about power outages, so every 5 minutes I would save
the &amp;ldquo;time left&amp;rdquo; into the EEPROM.&lt;/p&gt;

&lt;p&gt;Except&amp;hellip; Every 5 minutes would be 288 times a day.  ESP8266 doesn&amp;rsquo;t have
EEPROM; it emulates it with a fixed space in the flash memory.&lt;/p&gt;

&lt;p&gt;I &lt;a href=&#34;https://design.goeszen.com/mitigating-flash-wear-on-the-esp8266-or-any-other-microcontroller-with-flash.html&#34;&gt;saw&lt;/a&gt; that the flash typically has 100,000
write cycles.  That means we&amp;rsquo;re reaching the limit in 347 days; less than
a year.&lt;/p&gt;

&lt;p&gt;It seems that the SPIFFS (and LittleFS) filesystem that can be used with
the ESP8266 has built in wear leveling.  Using the 4M1M memory model
this allocates 1M to the filesystem.  Assuming we use 512 bytes to store
data and the meta-data, good wear leveling should means this lasts over
1000 years (if I did the maths right!); at the very least it should exceed
the life of the safe.&lt;/p&gt;

&lt;p&gt;So that&amp;rsquo;s what I did; saved the &amp;ldquo;time left&amp;rdquo; value in a SPIFFS file.&lt;/p&gt;

&lt;p&gt;I then thought I could be clever; why not provide more &amp;ldquo;fun&amp;rdquo;&amp;hellip; instead
of setting an &amp;ldquo;open time&amp;rdquo;, why not allow for a time range and pick a
value between those times?  And for additional uncertainty, why not hide
the timer?&lt;/p&gt;

&lt;p&gt;Of course time can be added to the safe even when it&amp;rsquo;s running.&lt;/p&gt;

&lt;p&gt;This software can be built with the standard Arduino tool set with the
esp8266 libraries loaded.  To make it simpler I embed the HTML inside the
code (as an include file) rather than using SPIFFS.  That way there&amp;rsquo;s
just one image to flash and not two.  Yes, we&amp;rsquo;re using SPIFFS to store
time left, but in this way we can update the software easily (even over
the network) because it&amp;rsquo;s just the one image.  The code is small enough
that it still fits.&lt;/p&gt;

&lt;p&gt;The solenoid lock is always kept in the locked position unless the &amp;ldquo;open&amp;rdquo;
function is selected.  Open can not be selected if the timer is still
running.&lt;/p&gt;

&lt;p&gt;When the safe software is first loaded it will create a WiFi Access Point
called something like &amp;ldquo;Safe-123456&amp;rdquo; (the exact name will depend on the
MAC address of your board).  You should connect your phone or
laptop to that access point.&lt;/p&gt;

&lt;p&gt;This will let you go to &lt;code&gt;http://192.168.4.1&lt;/code&gt; or (if you&amp;rsquo;re lucky)
&lt;code&gt;http://safe.local&lt;/code&gt; and that will display the WiFi configuration
screen.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/change_ap.png&#34; alt=&#34;Change AP&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Enter your WiFi SSID and password.  In 5 seconds the software will reboot
and the safe will connect to your local network.  It will attempt to get
an address by DHCP.&lt;/p&gt;

&lt;p&gt;If it is unable to connect to the network after 60 seconds then it will
give up and start up the Safe-123456 access point again and allow you to
change the network details and try again.&lt;/p&gt;

&lt;p&gt;Once the safe is on your network it will broadcast the name &amp;ldquo;safe.local&amp;rdquo;
via mDNS (aka zeroconf, Bonjour, Rendezvous).  If your machine supports
this then you should be able to go to &lt;a href=&#34;http://safe.local&#34;&gt;http://safe.local&lt;/a&gt; otherwise you may
need to check your router to find the IP address that was assigned to it.&lt;/p&gt;

&lt;p&gt;Opening the web page in a browser should give you a menu on the left and
a larger status box on the right.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v3/menu.png&#34; alt=&#34;Main Menu&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;The first thing you should do is go to the &amp;ldquo;Change Safe Authentication
Details&amp;rdquo; link.  Here you can set a username
and password for your safe.  It&amp;rsquo;s recommended you do this so that only
authorised people on your network can reach this interface.  After setting
the password you should be prompted to login before doing any more work.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/set_auth.png&#34; alt=&#34;Set Authentication&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Next you may need to go to the &amp;ldquo;Safe Connection Details&amp;rdquo; screen.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v3/connection.png&#34; alt=&#34;Set Authentication&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Here is where you can change the WiFi network (if necessary) and the
pin the relay is connected to.  For the board I&amp;rsquo;m using in this build
this needs to be set to 4 (GPIO4 aka D2).  The v2 board used GPIO12 (D6).&lt;/p&gt;

&lt;p&gt;Setting the &amp;ldquo;Safe name&amp;rdquo; will change the name broadcast via mDNS.  So in
this example my safe can now be seen at &amp;ldquo;safe3.local&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Elsewhere on the menu you&amp;rsquo;ll see some options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Open safe&amp;rdquo; lets you open the solenoid so the door can be opened.
This will
not work if the safe is locked.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&amp;ldquo;Enable Safe Network Update&amp;rdquo; will let you update the firmware remotely,
using BasicOTA.   If you set a safe password (as recommended above) then
the same password is needed for this update.  Now you can&amp;rsquo;t do an update
if the safe is locked because then you could just replace the software with
one that just always opens the safe!&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&amp;ldquo;Disable Safe Network Update&amp;rdquo; turns the enable off again&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And then the main &amp;ldquo;Status&amp;rdquo; screen.  This is where the action occurs.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v3/unlocked.png&#34; alt=&#34;Set Authentication&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Here you can add time to the safe; if it&amp;rsquo;s already running a timer then
this time will be used to extend the lock.  If you just enter a &amp;ldquo;Min&amp;rdquo;
set of values then this is the time that would be used.  If you enter
a &amp;ldquo;Max&amp;rdquo; then the safe will pick a random time between those two values.&lt;/p&gt;

&lt;p&gt;While locked it will tell you when the expected unlock time is, and how
long is left.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v3/locked.png&#34; alt=&#34;Set Authentication&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;But if you select the &amp;ldquo;hidden&amp;rdquo; option then you won&amp;rsquo;t know&amp;hellip;
&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v3/hidden.png&#34; alt=&#34;Set Authentication&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;And that&amp;rsquo;s it!&lt;/p&gt;

&lt;p&gt;The new software is at &lt;a href=&#34;https://github.com/sweharris/esp8266-timer-safe&#34;&gt;github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It seems to do what the original Kitchen Safe does, plus more.  And possibly
cheaper!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Terrahawks Noughts and Crosses</title>
      <link>https://www.sweharris.org/post/2023-05-27-terrahawks/</link>
      <pubDate>Sat, 27 May 2023 21:14:49 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2023-05-27-terrahawks/</guid>
      <description>

&lt;p&gt;&lt;style&gt;
table {
  table-layout: fixed ;
  width: 100% ;
  border-collapse: collapse;
  border-style: hidden;
}
td {
  width: 1 ;
  border: visible;
}
&lt;/style&gt;
Yes, this is a blog about a very old TV show.&lt;/p&gt;

&lt;p&gt;I went down a rabbit hole.  A very stupid rabbit hole.  A meaningless
rabbit hole.&lt;/p&gt;

&lt;p&gt;There was a 1983 Gerry Anderson puppet show &amp;ldquo;Terrahawks&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;It wasn&amp;rsquo;t as good as his older stuff (e.g. the original Thunderbirds).  Maybe
I was also that little bit older when I first watched it (I would have been
around 15 when it started).&lt;/p&gt;

&lt;p&gt;Earth was under attack by an alien, Zelda.  Earth&amp;rsquo;s defenders has robotic spheres (&amp;ldquo;Zeroids&amp;rdquo;).  Zelda had cubes.&lt;/p&gt;

&lt;p&gt;At the end of each episode there was a game of noughts and crosses, with
the zeroids playing the &amp;ldquo;O&amp;rdquo; and the cubes playing the &amp;ldquo;X&amp;rdquo; (&amp;lsquo;cos they had an
X mark on top of them).&lt;/p&gt;

&lt;p&gt;&lt;center&gt;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/terrahawks.png&#34; alt=&#34;game animation&#34;&gt;
&lt;/div&gt;

&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Since I recently got the box set (it was cheap) I had to analyse the games.
Joshua (Wargames) would wipe the floor with both teams, but let&amp;rsquo;s see.&lt;/p&gt;

&lt;p&gt;There were 39 episodes.  Each game started with the Zeroids (O) going first.&lt;/p&gt;

&lt;p&gt;This make it easy to create a notation for recording the games; just number
the squares and record the order they&amp;rsquo;re filled in.  The first square is
always an &amp;ldquo;o&amp;rdquo; and then they alternate &amp;ldquo;x&amp;rdquo; and &amp;ldquo;o&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;So the number 3975142 would result in this game.  Yay zeroids win!&lt;/p&gt;

&lt;table cols=7 border=1 cellpadding=8px bordercolor=#0000ff&gt;
&lt;tr&gt;&lt;th valign=bottom align=center&gt;1&lt;/th&gt;
&lt;th valign=bottom align=center&gt;2&lt;/th&gt;
&lt;th valign=bottom align=center&gt;3&lt;/th&gt;
&lt;th valign=bottom align=center&gt;4&lt;/th&gt;
&lt;th valign=bottom align=center&gt;5&lt;/th&gt;
&lt;th valign=bottom align=center&gt;6&lt;/th&gt;
&lt;th valign=bottom align=center&gt;7&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Now to complicate things, the cubes cheat.  they might move at the end
and knock the zeroids out of place to claim a win.  eg &amp;ldquo;2158647 8-7&amp;rdquo;
Indeed, the only way the cubes won was by cheating like this.&lt;/p&gt;

&lt;table cols=8 border=1 cellpadding=8px bordercolor=#0000ff&gt;
&lt;tr&gt;&lt;th valign=bottom align=center&gt;1&lt;/th&gt;
&lt;th valign=bottom align=center&gt;2&lt;/th&gt;
&lt;th valign=bottom align=center&gt;3&lt;/th&gt;
&lt;th valign=bottom align=center&gt;4&lt;/th&gt;
&lt;th valign=bottom align=center&gt;5&lt;/th&gt;
&lt;th valign=bottom align=center&gt;6&lt;/th&gt;
&lt;th valign=bottom align=center&gt;7&lt;/th&gt;
&lt;th valign=bottom align=center&gt;8&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt; &lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;You can see an &lt;a href=&#34;https://www.youtube.com/watch?v=GOLUbTrQvdQ&#34;&gt;example video&lt;/a&gt; of this in action; this is from the first episode.&lt;/p&gt;

&lt;h2 id=&#34;what-i-learned&#34;&gt;What I learned&lt;/h2&gt;

&lt;p&gt;It turns out there were only 13 different games.  Episodes would repeat.
I guess the animation was too expensive for 39 games.&lt;/p&gt;

&lt;p&gt;Except there&amp;rsquo;s only 38 games, &amp;lsquo;cos one episode (&amp;ldquo;A Christmas Miracle&amp;rdquo;) didn&amp;rsquo;t end in a game, but with Sergeant Major Zero on his perch dressed as Santa.&lt;/p&gt;

&lt;p&gt;Not every game was repeated evenly, either.  The game in the first episode never got repeated; other games maybe 3 or 4 times.&lt;/p&gt;

&lt;p&gt;All in all the score was 19:19.&lt;/p&gt;

&lt;p&gt;As a kid I kinda hoped the winner represented who came out on top in the episode, but there really doesn&amp;rsquo;t seem to be any correlation between the game winner and the episode.&lt;/p&gt;

&lt;p&gt;Which makes sense, since the Terrahawks were normally on the defensive.&lt;/p&gt;

&lt;h2 id=&#34;what-i-missed&#34;&gt;What I missed&lt;/h2&gt;

&lt;p&gt;Now I had vaguely wondered about symmetry.  Noughts and Crosses boards
have rotational and reflectional symmetry.  What I&amp;rsquo;d missed was that the
character animations only had reflectional symmetry in the Y axis.  So
I could have sat down and worked this out, rather than being lazy.&lt;/p&gt;

&lt;p&gt;When I posted my early learnings to &lt;a href=&#34;https://twitter.com/sweharris/status/1649212343367114752&#34;&gt;twitter&lt;/a&gt; I was lucky enough for the actual artist to pick
up on this and reply.  How cool is that!&lt;/p&gt;

&lt;p&gt;He confirmed that there were only 7 games animated; 6 were reflections
and the first episode was the only one with a unique game.  He even
has a &lt;a href=&#34;https://www.youtube.com/watch?v=fWm_BpnbffY&#34;&gt;youtube video&lt;/a&gt; on this.&lt;/p&gt;

&lt;h2 id=&#34;the-games&#34;&gt;The games&lt;/h2&gt;

&lt;p&gt;Oh, if people care, these are the episodes for each game.&lt;/p&gt;

&lt;h3 id=&#34;1459238&#34;&gt;1459238&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;1.05 The Ugliest Monster Of All&lt;/li&gt;
&lt;li&gt;2.06 My Kingdom For A ZEAF&lt;/li&gt;
&lt;li&gt;3.04 Space Cyclops&lt;/li&gt;
&lt;/ul&gt;

&lt;table cols=7 border=1 cellpadding=8px bordercolor=#0000ff&gt;
&lt;tr&gt;&lt;th valign=bottom align=center&gt;1&lt;/th&gt;
&lt;th valign=bottom align=center&gt;2&lt;/th&gt;
&lt;th valign=bottom align=center&gt;3&lt;/th&gt;
&lt;th valign=bottom align=center&gt;4&lt;/th&gt;
&lt;th valign=bottom align=center&gt;5&lt;/th&gt;
&lt;th valign=bottom align=center&gt;6&lt;/th&gt;
&lt;th valign=bottom align=center&gt;7&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;h3 id=&#34;1523746-6-9-3-6&#34;&gt;1523746 6-9 3-6&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;1.01 Expect The Unexpected&lt;/li&gt;
&lt;/ul&gt;

&lt;table cols=8 border=1 cellpadding=8px bordercolor=#0000ff&gt;
&lt;tr&gt;&lt;th valign=bottom align=center&gt;1&lt;/th&gt;
&lt;th valign=bottom align=center&gt;2&lt;/th&gt;
&lt;th valign=bottom align=center&gt;3&lt;/th&gt;
&lt;th valign=bottom align=center&gt;4&lt;/th&gt;
&lt;th valign=bottom align=center&gt;5&lt;/th&gt;
&lt;th valign=bottom align=center&gt;6&lt;/th&gt;
&lt;th valign=bottom align=center&gt;7&lt;/th&gt;
&lt;th valign=bottom align=center&gt;8&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt; &lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;h3 id=&#34;1795362&#34;&gt;1795362&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;1.09 Thunder Path&lt;/li&gt;
&lt;li&gt;2.04 The Ultimate Menace&lt;/li&gt;
&lt;li&gt;2.11 Cry UFO&lt;/li&gt;
&lt;/ul&gt;

&lt;table cols=7 border=1 cellpadding=8px bordercolor=#0000ff&gt;
&lt;tr&gt;&lt;th valign=bottom align=center&gt;1&lt;/th&gt;
&lt;th valign=bottom align=center&gt;2&lt;/th&gt;
&lt;th valign=bottom align=center&gt;3&lt;/th&gt;
&lt;th valign=bottom align=center&gt;4&lt;/th&gt;
&lt;th valign=bottom align=center&gt;5&lt;/th&gt;
&lt;th valign=bottom align=center&gt;6&lt;/th&gt;
&lt;th valign=bottom align=center&gt;7&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;h3 id=&#34;2158647-8-7&#34;&gt;2158647 8-7&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;2.08 Cold Finger&lt;/li&gt;
&lt;li&gt;2.13 Ma&amp;rsquo;s Monsters&lt;/li&gt;
&lt;li&gt;3.12 The Sporilla&lt;/li&gt;
&lt;/ul&gt;

&lt;table cols=8 border=1 cellpadding=8px bordercolor=#0000ff&gt;
&lt;tr&gt;&lt;th valign=bottom align=center&gt;1&lt;/th&gt;
&lt;th valign=bottom align=center&gt;2&lt;/th&gt;
&lt;th valign=bottom align=center&gt;3&lt;/th&gt;
&lt;th valign=bottom align=center&gt;4&lt;/th&gt;
&lt;th valign=bottom align=center&gt;5&lt;/th&gt;
&lt;th valign=bottom align=center&gt;6&lt;/th&gt;
&lt;th valign=bottom align=center&gt;7&lt;/th&gt;
&lt;th valign=bottom align=center&gt;8&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt; &lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;h3 id=&#34;2358469-8-9&#34;&gt;2358469 8-9&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;1.11 Mind Monster&lt;/li&gt;
&lt;li&gt;3.06 Child&amp;rsquo;s Play&lt;/li&gt;
&lt;li&gt;3.13 Gold&lt;/li&gt;
&lt;/ul&gt;

&lt;table cols=8 border=1 cellpadding=8px bordercolor=#0000ff&gt;
&lt;tr&gt;&lt;th valign=bottom align=center&gt;1&lt;/th&gt;
&lt;th valign=bottom align=center&gt;2&lt;/th&gt;
&lt;th valign=bottom align=center&gt;3&lt;/th&gt;
&lt;th valign=bottom align=center&gt;4&lt;/th&gt;
&lt;th valign=bottom align=center&gt;5&lt;/th&gt;
&lt;th valign=bottom align=center&gt;6&lt;/th&gt;
&lt;th valign=bottom align=center&gt;7&lt;/th&gt;
&lt;th valign=bottom align=center&gt;8&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt; &lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;h3 id=&#34;3657218&#34;&gt;3657218&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;1.03 Thunder-Roar&lt;/li&gt;
&lt;li&gt;2.01 Operation SAS&lt;/li&gt;
&lt;li&gt;3.07 Jolly Roger One&lt;/li&gt;
&lt;/ul&gt;

&lt;table cols=7 border=1 cellpadding=8px bordercolor=#0000ff&gt;
&lt;tr&gt;&lt;th valign=bottom align=center&gt;1&lt;/th&gt;
&lt;th valign=bottom align=center&gt;2&lt;/th&gt;
&lt;th valign=bottom align=center&gt;3&lt;/th&gt;
&lt;th valign=bottom align=center&gt;4&lt;/th&gt;
&lt;th valign=bottom align=center&gt;5&lt;/th&gt;
&lt;th valign=bottom align=center&gt;6&lt;/th&gt;
&lt;th valign=bottom align=center&gt;7&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;h3 id=&#34;3975142&#34;&gt;3975142&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;1.10 From Here To Infinity&lt;/li&gt;
&lt;li&gt;3.02 First Strike&lt;/li&gt;
&lt;/ul&gt;

&lt;table cols=7 border=1 cellpadding=8px bordercolor=#0000ff&gt;
&lt;tr&gt;&lt;th valign=bottom align=center&gt;1&lt;/th&gt;
&lt;th valign=bottom align=center&gt;2&lt;/th&gt;
&lt;th valign=bottom align=center&gt;3&lt;/th&gt;
&lt;th valign=bottom align=center&gt;4&lt;/th&gt;
&lt;th valign=bottom align=center&gt;5&lt;/th&gt;
&lt;th valign=bottom align=center&gt;6&lt;/th&gt;
&lt;th valign=bottom align=center&gt;7&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;h3 id=&#34;4517328-2-3&#34;&gt;4517328 2-3&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;1.04 Happy Madeday&lt;/li&gt;
&lt;li&gt;2.09 Unseen Menace&lt;/li&gt;
&lt;li&gt;3.08 Runaway&lt;/li&gt;
&lt;/ul&gt;

&lt;table cols=8 border=1 cellpadding=8px bordercolor=#0000ff&gt;
&lt;tr&gt;&lt;th valign=bottom align=center&gt;1&lt;/th&gt;
&lt;th valign=bottom align=center&gt;2&lt;/th&gt;
&lt;th valign=bottom align=center&gt;3&lt;/th&gt;
&lt;th valign=bottom align=center&gt;4&lt;/th&gt;
&lt;th valign=bottom align=center&gt;5&lt;/th&gt;
&lt;th valign=bottom align=center&gt;6&lt;/th&gt;
&lt;th valign=bottom align=center&gt;7&lt;/th&gt;
&lt;th valign=bottom align=center&gt;8&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt; &lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;h3 id=&#34;5873149&#34;&gt;5873149&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;2.02 Ten Top Pop&lt;/li&gt;
&lt;li&gt;3.01 Two For The Price Of One&lt;/li&gt;
&lt;li&gt;3.09 Space Samurai&lt;/li&gt;
&lt;li&gt;3.11 Operation Zero&lt;/li&gt;
&lt;/ul&gt;

&lt;table cols=7 border=1 cellpadding=8px bordercolor=#0000ff&gt;
&lt;tr&gt;&lt;th valign=bottom align=center&gt;1&lt;/th&gt;
&lt;th valign=bottom align=center&gt;2&lt;/th&gt;
&lt;th valign=bottom align=center&gt;3&lt;/th&gt;
&lt;th valign=bottom align=center&gt;4&lt;/th&gt;
&lt;th valign=bottom align=center&gt;5&lt;/th&gt;
&lt;th valign=bottom align=center&gt;6&lt;/th&gt;
&lt;th valign=bottom align=center&gt;7&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;h3 id=&#34;5891367&#34;&gt;5891367&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;1.02 Expect The Unexpected Part 2&lt;/li&gt;
&lt;li&gt;1.13 To Catch A Tiger&lt;/li&gt;
&lt;li&gt;2.05 Midnight Blue&lt;/li&gt;
&lt;li&gt;3.05 Doppelganger&lt;/li&gt;
&lt;/ul&gt;

&lt;table cols=7 border=1 cellpadding=8px bordercolor=#0000ff&gt;
&lt;tr&gt;&lt;th valign=bottom align=center&gt;1&lt;/th&gt;
&lt;th valign=bottom align=center&gt;2&lt;/th&gt;
&lt;th valign=bottom align=center&gt;3&lt;/th&gt;
&lt;th valign=bottom align=center&gt;4&lt;/th&gt;
&lt;th valign=bottom align=center&gt;5&lt;/th&gt;
&lt;th valign=bottom align=center&gt;6&lt;/th&gt;
&lt;th valign=bottom align=center&gt;7&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;h3 id=&#34;6539128-2-1&#34;&gt;6539128 2-1&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;1.07 The Gun&lt;/li&gt;
&lt;li&gt;2.03 Play It Again SRAM&lt;/li&gt;
&lt;li&gt;3.10 Timewarp&lt;/li&gt;
&lt;/ul&gt;

&lt;table cols=8 border=1 cellpadding=8px bordercolor=#0000ff&gt;
&lt;tr&gt;&lt;th valign=bottom align=center&gt;1&lt;/th&gt;
&lt;th valign=bottom align=center&gt;2&lt;/th&gt;
&lt;th valign=bottom align=center&gt;3&lt;/th&gt;
&lt;th valign=bottom align=center&gt;4&lt;/th&gt;
&lt;th valign=bottom align=center&gt;5&lt;/th&gt;
&lt;th valign=bottom align=center&gt;6&lt;/th&gt;
&lt;th valign=bottom align=center&gt;7&lt;/th&gt;
&lt;th valign=bottom align=center&gt;8&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt; &lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;h3 id=&#34;7453289-2-1-3-2-5-6-4-5&#34;&gt;7453289 2-1 3-2 5-6 4-5&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;1.08 Gunfight At Oakys Corral&lt;/li&gt;
&lt;li&gt;2.07 Zero&amp;rsquo;s Finest Hour&lt;/li&gt;
&lt;li&gt;2.10 Space Giant&lt;/li&gt;
&lt;/ul&gt;

&lt;table cols=8 border=1 cellpadding=8px bordercolor=#0000ff&gt;
&lt;tr&gt;&lt;th valign=bottom align=center&gt;1&lt;/th&gt;
&lt;th valign=bottom align=center&gt;2&lt;/th&gt;
&lt;th valign=bottom align=center&gt;3&lt;/th&gt;
&lt;th valign=bottom align=center&gt;4&lt;/th&gt;
&lt;th valign=bottom align=center&gt;5&lt;/th&gt;
&lt;th valign=bottom align=center&gt;6&lt;/th&gt;
&lt;th valign=bottom align=center&gt;7&lt;/th&gt;
&lt;th valign=bottom align=center&gt;8&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt; &lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt; &lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;h3 id=&#34;9651287-2-3-1-2-5-4-6-5&#34;&gt;9651287 2-3 1-2 5-4 6-5&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;1.06 Close Call&lt;/li&gt;
&lt;li&gt;2.12 The Midas Touch&lt;/li&gt;
&lt;li&gt;3.03 Terratomb&lt;/li&gt;
&lt;/ul&gt;

&lt;table cols=8 border=1 cellpadding=8px bordercolor=#0000ff&gt;
&lt;tr&gt;&lt;th valign=bottom align=center&gt;1&lt;/th&gt;
&lt;th valign=bottom align=center&gt;2&lt;/th&gt;
&lt;th valign=bottom align=center&gt;3&lt;/th&gt;
&lt;th valign=bottom align=center&gt;4&lt;/th&gt;
&lt;th valign=bottom align=center&gt;5&lt;/th&gt;
&lt;th valign=bottom align=center&gt;6&lt;/th&gt;
&lt;th valign=bottom align=center&gt;7&lt;/th&gt;
&lt;th valign=bottom align=center&gt;8&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=ff0000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&amp;nbsp;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#c0c0c0&#34;&gt;&lt;font color=0000ff&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
  &lt;table border=1&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt; &lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center style=&#34;background-color:#d0d000&#34;&gt; &lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=800000&gt;x&lt;/font&gt;&lt;/td&gt;&lt;td align=center&gt;&lt;font color=000080&gt;o&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;h3 id=&#34;no-game-picture-of-zero-dressed-as-santa&#34;&gt;No game! Picture of Zero dressed as Santa!&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;1.12 A Christmas Miracle&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;You can see each game is 7 moves long, and if no one (well, the zeroids)
has won after 7 moves then the cubes cheat.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s also very clear to see the symmetry in the last 2 (&amp;ldquo;7453289 2-1 3-2 5-6 4-5&amp;rdquo; and &amp;ldquo;9651287 2-3 1-2 5-4 6-5&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;The show wasn&amp;rsquo;t as good as I remembered, but the music and how it sync&amp;rsquo;d to
the end-game was clever and fun.&lt;/p&gt;

&lt;p&gt;Apparently the American broadcast never got this.  How unfortunate&amp;hellip;&lt;/p&gt;

&lt;p&gt;And now I have the end credit theme tune stuck in my head.&lt;/p&gt;

&lt;p&gt;Oh, and if you want the source that generates the really bad HTML that
draws the game boards, it&amp;rsquo;s &lt;a href=&#34;https://www.sweharris.org/Scripts/draw_terrahawks&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Using network namespaces for ipv4 only</title>
      <link>https://www.sweharris.org/post/2023-04-29-netns-ip4only/</link>
      <pubDate>Sat, 29 Apr 2023 14:23:35 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2023-04-29-netns-ip4only/</guid>
      <description>

&lt;h2 id=&#34;the-problem&#34;&gt;The problem&lt;/h2&gt;

&lt;p&gt;I use the &lt;a href=&#34;https://www.speedtest.net/apps/cli&#34;&gt;Ookla Speedtest CLI&lt;/a&gt; in a
cron job to get an idea of the speed of my internet connection (Verizon
FIOS), and spot if there are problems.  Why?  Because why not :-)&lt;/p&gt;

&lt;p&gt;It let&amp;rsquo;s me draw graphs like this.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/speedtest-graph.png&#34; alt=&#34;Speedtest&#34;&gt;
&lt;/div&gt;


&lt;p&gt;However, recently I was starting to get error messages that the command
wasn&amp;rsquo;t able to reach speedtest.net to get the configuration.  It wasn&amp;rsquo;t
happening every time; sometimes it would go hours without issue, other
times it would fail 3 or 4 times in succession.&lt;/p&gt;

&lt;p&gt;When I looked into this, it turned out that the code was preferring IPv6
over IPv4.  Now my home network is dual stack with IPv6 being provided
by a &lt;a href=&#34;https://tunnelbroker.net/&#34;&gt;HEnet tunnel&lt;/a&gt;.  Because tunnels aren&amp;rsquo;t
necessarily as performant as native networking I configure my machines
to prefer IPv4; e.g. setting &lt;code&gt;gai.conf&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;precedence ::ffff:0:0/96  100
scopev4 ::ffff:0.0.0.0/96       14
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;However it seems this program is ignoring that.  When I ran &lt;code&gt;speedtest&lt;/code&gt;
manually I could see using the tunnel!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ speedtest

   Speedtest by Ookla

      Server: Greenlight Networks - Binghamton, NY (id: 3156)
         ISP: Hurricane Electric IPv6 Tunnel Broker
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;solution-attempt-1&#34;&gt;Solution attempt 1&lt;/h2&gt;

&lt;p&gt;So my first attempt to solve this was to use
&lt;a href=&#34;https://www.sweharris.org/post/2017-03-05-ld-preload/&#34;&gt;LD_PRELOAD&lt;/a&gt; to intercept the name resolver
calls and force it to only return IPv4 addresses.  This is what &lt;code&gt;gai.conf&lt;/code&gt;
is meant to do (&lt;code&gt;getaddrinfo(3)&lt;/code&gt;) but let&amp;rsquo;s force it.&lt;/p&gt;

&lt;p&gt;Fortunately someone had &lt;a href=&#34;https://gist.githubusercontent.com/winny-/7367518/raw/f098ef540c7ebbb9e148055365cec4205c4484c9/force-inet4-or-inet6.c&#34;&gt;already done the hard work&lt;/a&gt;
so I just took their code.  And it worked well with &lt;code&gt;telnet&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;e.g. &lt;code&gt;LD_PRELOAD=$PWD/force_ipv6.so telnet speedtest.net 80&lt;/code&gt; would force IPv6 and &lt;code&gt;LD_PRELOAD=$PWD/force_ipv4.so telnet speedtest.net 80&lt;/code&gt; would force IPv4.&lt;/p&gt;

&lt;p&gt;Except this was wasted time; the &lt;code&gt;speedtest&lt;/code&gt; binary is statically compiled
(was it written in Go?) and so &lt;code&gt;LD_PRELOAD&lt;/code&gt; has no affect.  Oops!&lt;/p&gt;

&lt;h2 id=&#34;solution-attempt-2&#34;&gt;Solution attempt 2&lt;/h2&gt;

&lt;p&gt;So if we can&amp;rsquo;t make the application work how we want, maybe we can change
the run time environment.&lt;/p&gt;

&lt;p&gt;This is exactly what Linux namespaces do.  Namespaces are one the core
underlying technologies that allow solutions like docker to run; it helps
isolate applications from each other, and there are multiple different
namespaces (cgroups, IPC, network, mount, PID, user, UTS).&lt;/p&gt;

&lt;p&gt;For what we need here, a network namespace is all we need.&lt;/p&gt;

&lt;p&gt;Network namespaces can be created and entered with the &lt;code&gt;ip netns&lt;/code&gt; command.
I&amp;rsquo;m going to call this namespace &lt;code&gt;ip4only&lt;/code&gt;; it&amp;rsquo;s nicely descriptive!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ip netns del ip4only
ip netns add ip4only
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In order to let the namespace talk to the rest of the network it needs
a &lt;code&gt;veth&lt;/code&gt; endpoint inside the namespace.  This basically creates a virtual
&amp;ldquo;point to point&amp;rdquo; connection, and you can place one end inside the namespace
and leave the other in the &amp;ldquo;root&amp;rdquo; namespace.  Let&amp;rsquo;s call the two network
points &lt;code&gt;ip4only-root&lt;/code&gt; and &lt;code&gt;ip4only-ns&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ip link add ip4only-root type veth peer name ip4only-ns
ip link set ip4only-ns netns ip4only
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now each interface needs an IP address.  Let&amp;rsquo;s use the 192.168.200.0/24
network.  And while we&amp;rsquo;re at it we can add a loopback and a default
route inside the container.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ip addr add 192.168.200.1/24 dev ip4only-root
ip link set ip4only-root up

ip netns exec ip4only ip addr add 192.168.200.2/24 dev ip4only-ns
ip netns exec ip4only ip link set ip4only-ns up
ip netns exec ip4only ip link set lo up
ip netns exec ip4only ip route add default via 192.168.200.1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So how does this look?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$  ip addr show dev ip4only-root
22: ip4only-root@if21: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether ee:f6:02:dc:35:90 brd ff:ff:ff:ff:ff:ff link-netns ip4only
    inet 192.168.200.1/24 scope global ip4only-root
       valid_lft forever preferred_lft forever

$ sudo ip netns exec ip4only sh
# ip addr
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
21: ip4only-ns@if22: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 86:58:d8:c4:b7:47 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.200.2/24 scope global ip4only-ns
       valid_lft forever preferred_lft forever
    inet6 fe80::8458:d8ff:fec4:b747/64 scope link 
       valid_lft forever preferred_lft forever

# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.200.1   0.0.0.0         UG    0      0        0 ip4only-ns
192.168.200.0   0.0.0.0         255.255.255.0   U     0      0        0 ip4only-ns

# ping -c 1 192.168.200.1
PING 192.168.200.1 (192.168.200.1) 56(84) bytes of data.
64 bytes from 192.168.200.1: icmp_seq=1 ttl=64 time=0.036 ms

--- 192.168.200.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.036/0.036/0.036/0.000 ms

# exit
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It &lt;em&gt;looks&lt;/em&gt; like it has an IPv6 address, but this is just a &amp;ldquo;link local&amp;rdquo;
one and isn&amp;rsquo;t used for access to the wider network.&lt;/p&gt;

&lt;p&gt;Of course this network can&amp;rsquo;t reach the internet because nothing knows
how to get to the 192.116.200.2 address.  We can solve that with some
NATting in the root.&lt;/p&gt;

&lt;p&gt;Since I have no &lt;code&gt;iptable&lt;/code&gt; rules on this machine I can build a simple
set.  In my case &lt;code&gt;br-lan&lt;/code&gt; is the bridge I have connected to my LAN
network, so the rules would look something like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward

# Flush forward rules, policy DROP by default.
iptables -P FORWARD DROP
iptables -F FORWARD

# Flush nat rules.
iptables -t nat -F

# Enable masquerading of 192.168.200.0
iptables -t nat -A POSTROUTING -s 192.168.200.0/255.255.255.0 -o br-lan -j MASQUERADE

# Allow forwarding between br-lan and ip4only-root
iptables -A FORWARD -i br-lan -o ip4only-root -j ACCEPT
iptables -A FORWARD -o br-lan -i ip4only-root -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now, with all of that, the namespace can reach the internet&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo ip netns exec ip4only ping -c 1 www.google.com
PING www.google.com (142.251.40.132) 56(84) bytes of data.
64 bytes from lga25s80-in-f4.1e100.net (142.251.40.132): icmp_seq=1 ttl=117 time=4.47 ms

--- www.google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 4.474/4.474/4.474/0.000 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we try to use ipv6 then we get an error&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo ip netns exec ip4only ping -6 -c 1 www.google.com
connect: Network is unreachable
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Great, this is working!&lt;/p&gt;

&lt;h2 id=&#34;reducing-permissions&#34;&gt;Reducing permissions.&lt;/h2&gt;

&lt;p&gt;Unfortunately to enter a namespace with &lt;code&gt;ip netns exec&lt;/code&gt; requires root
and the command we run inside the namespace is run as root (we can
see that from the prompt changing from &lt;code&gt;$&lt;/code&gt; to &lt;code&gt;#&lt;/code&gt; in the earlier output).&lt;/p&gt;

&lt;p&gt;Fortunately we don&amp;rsquo;t &lt;em&gt;need&lt;/em&gt; root if we have the &lt;code&gt;cap_sys_admin&lt;/code&gt; permission.&lt;/p&gt;

&lt;p&gt;This is easily to do with a simple C program:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// ip4only
//   gcc -o ip4only ip4only.c
//   sudo setcap cap_sys_admin+ep ./ip4only
//
// Now we can do &amp;quot;ip4only command&amp;quot; (eg &amp;quot;ip4only ip addr&amp;quot;)
// and it will run in the ip4only network namespace

// We need this for setns()
#define _GNU_SOURCE

#include &amp;lt;fcntl.h&amp;gt;
#include &amp;lt;sched.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;

#define errExit(msg) { perror(msg); exit(EXIT_FAILURE); }

int main(int argc, char *argv[])
{ 
  int fd;

  if (argc &amp;lt; 2)
  {
      fprintf(stderr, &amp;quot;%s cmd args...\n&amp;quot;, argv[0]);
      exit(EXIT_FAILURE);
  }

  // To set a namespace we need to have an open file handle.
  // Network namespaces live in /var/run/netns so that&#39;s easy
  
  fd = open(&amp;quot;/var/run/netns/ip4only&amp;quot;, O_RDONLY);
  if (fd == -1)
    errExit(&amp;quot;open&amp;quot;);

  // Join the namespace
  if (setns(fd, 0) == -1)
    errExit(&amp;quot;setns&amp;quot;);

  // Run the specified command
  execvp(argv[1], &amp;amp;argv[1]);

  // If we got here, there&#39;s an error!
  errExit(&amp;quot;execvp&amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;rsquo;s all there is to it.  We can see it works by trying to access IPv6;
we expect it to fail.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ip4only telnet -6 www.google.com 80
Trying 2607:f8b0:4006:820::2004...
telnet: connect to address 2607:f8b0:4006:820::2004: Network is unreachable
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;and-it-works&#34;&gt;And it works.&lt;/h2&gt;

&lt;p&gt;I can now do &lt;code&gt;ip4only speedtest&lt;/code&gt; and it now connects every time using IPv4&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ip4only speedtest

   Speedtest by Ookla

      Server: DediPath - Secaucus, NJ (id: 22774)
         ISP: Verizon Fios
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;There is a side effect; &amp;ldquo;ping&amp;rdquo; no longer has the permissions it
needs to run, and it gives a &lt;code&gt;socket: Operation not permitted&lt;/code&gt;
error.  However if an application isn&amp;rsquo;t trying to use DGRAM or RAW
sockets then this type of configuration is a nice way of using
namespaces and capabilities to force the application into an IPv4
only setup.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>ChatGPT and Calculators</title>
      <link>https://www.sweharris.org/post/2023-03-04-chatgpt/</link>
      <pubDate>Sat, 04 Mar 2023 20:30:23 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2023-03-04-chatgpt/</guid>
      <description>

&lt;p&gt;This is one of my infrequent &amp;ldquo;philosophical&amp;rdquo; type posts.  An earlier version
of this appeared on LinkedIn.&lt;/p&gt;

&lt;p&gt;There was a LinkedIn post along the lines of &amp;ldquo;are we treating ChatGPT
today like we used to treat calculators in the past&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;In my mind the question is &amp;ldquo;what skill do we believe is valuable that
ChatGPT will replace&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;The parallels between how we treated calculators in a school setting
(&amp;ldquo;no you can&amp;rsquo;t use them for homework&amp;rdquo;) vs how we&amp;rsquo;re treating ChatGPT
(&amp;ldquo;no you can&amp;rsquo;t use them for homework&amp;rdquo;) needs a deeper dive.&lt;/p&gt;

&lt;h2 id=&#34;calculators&#34;&gt;Calculators&lt;/h2&gt;

&lt;p&gt;40 years ago we believed mental arithmetic was important; calculators
and now computers show that&amp;rsquo;s not true.  Well, to an extent.&lt;/p&gt;

&lt;p&gt;I grew up during that period; we were taught how to use calculators,
but we weren&amp;rsquo;t allowed to take them into maths exams; we were expected
to know basic rules and be able to derive solutions.  We even had a book
of common formulas and log tables and so on.&lt;/p&gt;

&lt;p&gt;So it might be fair to ask &amp;ldquo;Do I need to know the derivative
of &lt;code&gt;sin(x^2)&lt;/code&gt;?&amp;ldquo;.  40 years ago I could do that using the Chain Rule.
30 years ago I had a calculator that could do it.  Today?  I&amp;rsquo;ve no idea.
But I can google it&amp;hellip;  (oh, right; &lt;code&gt;d/dx f(g(x)) = f&#39;(g(x)) . g&#39;(x)&lt;/code&gt;
so the answer is &lt;code&gt;cos(x^2).2x&lt;/code&gt;).  I&amp;rsquo;ve never needed to know that since
leaving education.&lt;/p&gt;

&lt;p&gt;However, it might also be fair to ask &amp;ldquo;Do I need to know what is 7*12?&amp;ldquo;.
Now I can also use a computer for this, but I &lt;em&gt;do&lt;/em&gt; know the answer;
it&amp;rsquo;s useful in &amp;ldquo;7 ft 5 inches is 89 inches&amp;rdquo; type manner; I do simple
arithmetic all the time.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s also useful to act as a sanity check; if the computer does a bunch of
calculations you may be able to do some rough approximations to determine
if the answer is &lt;em&gt;sane&lt;/em&gt;.  Computers make mistakes.  Just ask &lt;a href=&#34;https://en.wikipedia.org/wiki/British_Post_Office_scandal&#34;&gt;British
Post Masters&lt;/a&gt;.
People have gone to prison because of belief that the computer was
right.&lt;/p&gt;

&lt;p&gt;So we may have been right 40 years ago to have concerns around the use
of calculators; or perhaps more accurately around the blind trust that
the machine always gave the right result.&lt;/p&gt;

&lt;h2 id=&#34;chatgpt&#34;&gt;ChatGPT&lt;/h2&gt;

&lt;p&gt;What skill will ChatGPT replace?  Is it a skill we consider important;
or will it just lead to enforcing the &lt;em&gt;real&lt;/em&gt; skill (critical thinking)
vs the mundane (data collation)?&lt;/p&gt;

&lt;p&gt;Now there&amp;rsquo;s also a qualitative difference between the two; 2+3=5 whether
you do it by hand or by computer. But can we evaluate ChatGPT output
the same way?&lt;/p&gt;

&lt;p&gt;Given we know that current generation AI solutions give false answers
very easily (see
&lt;a href=&#34;https://www.theverge.com/2023/2/8/23590864/google-ai-chatbot-bard-mistake-error-exoplanet-demo&#34;&gt;Google Bard&amp;rsquo;s demo day issues&lt;/a&gt;)
there&amp;rsquo;s a definite need for critical thinking.&lt;/p&gt;

&lt;p&gt;But without the knowledge base, how can you be critical?  I can do a simple
approximation in my head of a shopping bill and get something close to the
total; &amp;ldquo;OK, the till receipt is probably accurate&amp;rdquo;.  But how can I evaluate
what an AI tells me about a topic I don&amp;rsquo;t know anything about?&lt;/p&gt;

&lt;p&gt;Modern AI systems are kinda a black box; we train them with a bunch of
data with known results, and the system learns to adjust variables so
that it can better evaluate.  Eventually the goal is that they can be
fed new (known) data and come up with the right results; we then let
it be used on unknown data.&lt;/p&gt;

&lt;p&gt;The problem is that we don&amp;rsquo;t know &lt;em&gt;what&lt;/em&gt; happens inside the box.  A
&lt;a href=&#34;https://menloml.com/2020/01/11/recognizing-a-ruler-instead-of-a-cancer/&#34;&gt;trial last decade&lt;/a&gt;
on detecting skin cancer based on pictures had a good result on the
training and validation data.  But it turned out that the system was
using the presence of a &lt;em&gt;ruler&lt;/em&gt; to determine if a mark was cancerous
or not.  This is a great example of bias in the training data (pictures
of cancerous marks were likely to be taken by a doctor and to have a
ruler on it for sizing purposes) and led to the black box using totally
the wrong data; of course it did well against the verification data!&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Too many people believe &amp;ldquo;&amp;lsquo;cos the computer said so&amp;rdquo; already (see the earlier
post-office scandal).  Add in some
&lt;a href=&#34;https://www.forbes.com/sites/bernardmarr/2022/09/30/the-problem-with-biased-ais-and-how-to-make-ai-better/&#34;&gt;biases&lt;/a&gt;
that may be encoded into the AI because of training data.  Add in
attackers deliberately tainting training data&amp;hellip;&lt;/p&gt;

&lt;p&gt;And I&amp;rsquo;m not going to even get into melt-downs, like a Microsoft AI chatbot
&lt;a href=&#34;https://www.theverge.com/2016/3/24/11297050/tay-microsoft-chatbot-racist&#34;&gt;going full racist&lt;/a&gt;
after interacting on twitter.  That&amp;rsquo;s a different problem entirely.&lt;/p&gt;

&lt;p&gt;In my mind the challenge with a technology like ChatGPT is in how can
we verify the output?  We&amp;rsquo;ve developed tools against &amp;ldquo;Deep Fake&amp;rdquo; videos
because there are discontinuities.  But when the output can only be
evaluated by a human?  Hmm&amp;hellip;&lt;/p&gt;

&lt;p&gt;I foresee a variation of the email spam wars; spambots will do better to
bypass filters; filters will get better to block the bots&amp;hellip; rinse, repeat.&lt;/p&gt;

&lt;p&gt;Who needs Tucker Carlson when the computer can make up the lies customised
to your desires and you have no way of knowing if they&amp;rsquo;re true or false?&lt;/p&gt;

&lt;p&gt;This is the challenge we have to face.  That is the critical skill we
need to retain.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Looking at YubiKey 5</title>
      <link>https://www.sweharris.org/post/2022-11-17-yubikey/</link>
      <pubDate>Thu, 17 Nov 2022 08:53:43 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2022-11-17-yubikey/</guid>
      <description>

&lt;p&gt;I don&amp;rsquo;t normally write about specific products, but I was asked to take a look
at the YubiKey series (primarily 4 and 5) and write up a summary of when and
how it can be used.&lt;/p&gt;

&lt;p&gt;This is timely, because CISA is pushing for access management enhancements
and recently published a chart for &lt;a href=&#34;https://cisa.gov/sites/default/files/publications/fact-sheet-implementing-phishing-resistant-mfa-508c.pdf&#34;&gt;phishing resistance&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I thought this interesting; typically I&amp;rsquo;ve looked at this from a &lt;em&gt;user&lt;/em&gt;
perspective (&amp;ldquo;can I use this to secure access to my bank account?&amp;rdquo;).  But
this time I needed to look at it from an Enterprise perspective
(&amp;ldquo;Is it safe to allow our employees to use this to access our systems?&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s a different set of challenges and requirements.  As a user I could
take a risk (&amp;ldquo;Eh, I can store the password in an encrypted text file and
trust no one can access my machine&amp;rdquo;), but from an enterprise perspective
we can&amp;rsquo;t necessarily trust the employee to make the right decision;
they&amp;rsquo;re not security professionals and may expose the company to risk.&lt;/p&gt;

&lt;h2 id=&#34;lots-of-authenticators&#34;&gt;Lots of authenticators&lt;/h2&gt;

&lt;p&gt;YubiKey supports a number of authenticators, and they have different
characteristics.   Some of them are suitable for passwordless, others
may only be suitable for MFA and others&amp;hellip; probably shouldn&amp;rsquo;t be used,
at least for workforce authentication, but may be good for customers
(eg Harry logging into his bank account).   I&amp;rsquo;m going to summarize as
best I can.  This has got a little long, but there is a table at the end!&lt;/p&gt;

&lt;p&gt;Note that the YubiKey supports all of these at the same time.  So we
need to make sure we know what mode is being used at any time.&lt;/p&gt;

&lt;p&gt;I might have got some things wrong.  Let me know in the comments if you
spot something!&lt;/p&gt;

&lt;h2 id=&#34;u2f&#34;&gt;U2F&lt;/h2&gt;

&lt;p&gt;U2F (Universal Second Factor) is a strong phishing resistant token.&lt;/p&gt;

&lt;p&gt;When registering a device with a URL the YubiKey generates a key pair
using the target protocol, hostname, part as part of the seed value
(along with embedded encryption key that&amp;rsquo;s unique the YubiKey) to
generate the keys.  This means that &lt;code&gt;abc.example.com&lt;/code&gt; will get
a different keypair to &lt;code&gt;abc.example.org&lt;/code&gt;.  The public key (and
&amp;ldquo;handle&amp;rdquo;) is  sent to the remote server and that&amp;rsquo;s what is stored
as your authentication token.  This handle may include the private key
encrypted with the encryption key embedded into the YubiKey.&lt;/p&gt;

&lt;p&gt;When you then try to login to a site the protocol/hostname/port and
handle are sent to the key.  The YubiKey will verify the handle matches
the protocol/hostname/port and was issued by this key.  It will then use
the decrypted private key to complete a standard public key authentication
process.  If a different key was used then the embedded information is
different so the generated key would change, so the server can be sure
the person has possession of the same key that was used for registration.
Similarly if a different URL was used then the protocol/hostname/port
would be different and so the handle wouldn&amp;rsquo;t validate; a MITM
on a phishing URL wouldn&amp;rsquo;t be able to intercept the response and use
that to login to a real site.  MITM is possible at registration time, of
course, so a user could think they were using secure MFA when they&amp;rsquo;re
really not.&lt;/p&gt;

&lt;p&gt;U2F may be implemented by software and so not be strong (encryption keys
could be copied to multiple places, for example).  There is an attestation
process available, where the public key sent from the YubiKey is signed
with the vendor attestation key.  This means that it&amp;rsquo;s possible to verify
that the U2F key is &amp;ldquo;strong&amp;rdquo;.   Without this attestation we can not be
sure the device presented is a hardware token or a piece of software
with copied keys.  With attestation it may be suitable as a 2nd factor,
but without we can&amp;rsquo;t assume it&amp;rsquo;s strong.  We may allow it for customer
authentication without attestation; &amp;ldquo;If Harry wants to use a weak MFA
device then it&amp;rsquo;s his lookout!&amp;rdquo;&lt;/p&gt;

&lt;h2 id=&#34;fido2&#34;&gt;FIDO2&lt;/h2&gt;

&lt;p&gt;FIDO2 is very similar to U2F. It&amp;rsquo;s an evolution of it, and
the specs are backwardly compatible.  However FIDO2 introduces some new
functions.  In particular it allows for forcing the user to prove they are
the authorized holder of the device; typically this is a PIN or biometric.&lt;/p&gt;

&lt;p&gt;By default YubiKeys do not protect FIDO tokens, but when the UV (User
Verification) flag is set then the user will be asked to set a PIN or
biometric.  With YubiKey 4 the PIN is minimum 4 characters, with YubiKey
5 the PIN is minimum 6 characters.  Note the PIN need not be just digits;
any normal alphanumeric can be used.  After 3 failed PIN attempts the
device needs to be removed and reinserted.  After 8 failed PIN attempts
the token is locked.  Unlocking requires a &amp;ldquo;master reset&amp;rdquo; and removes
the private key, so effectively invalidates the token.&lt;/p&gt;

&lt;p&gt;As with U2F there is an attestation process.  With attestation and UV
then this becomes a viable passwordless solution.  With attestation but
no UV then it may only be used as a 2nd factor.  Without attestation at
all then we may only use it for customer authentication, same as U2F.&lt;/p&gt;

&lt;p&gt;Since the attestation and UV requirements are set by the server (on
registration and login) it&amp;rsquo;s possible for different services to have
different stances.  This could get confusing.  We can not simply say
&amp;ldquo;FIDO2 is good for passwordless&amp;rdquo;; we must say &amp;ldquo;FIDO2 with device
attestation and restriction to YubiKey and with User Verification
is good&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Microsoft Azure AD can perform FIDO2 authentication and
appears to have the &lt;a href=&#34;https://learn.microsoft.com/en-us/azure/active-directory/authentication/howto-authentication-passwordless-security-key#fido-security-key-optional-settings&#34;&gt;necessary configuration options&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Windows desktops can be configured to support &lt;a href=&#34;https://learn.microsoft.com/en-us/azure/active-directory/authentication/howto-authentication-passwordless-security-key-windows&#34;&gt;FIDO2 authentication&lt;/a&gt;,
but the machines must be Azure AD (or hybrid) joined.  Simple
domain-joined machines can not do this.  There are other limitations.&lt;/p&gt;

&lt;p&gt;Apple have committed to supporting FIDO.&lt;/p&gt;

&lt;p&gt;Non-web based applications can use FIDO2 via &amp;ldquo;out of band&amp;rdquo; mechanisms;
e.g. the user may get sent a link (SMS, Email, copy&amp;rsquo;n&amp;rsquo;paste&amp;hellip;)
that they enter into a browser and complete authentication there.
This obviously requires application changes.&lt;/p&gt;

&lt;p&gt;Both Android and iOS devices also provide native FIDO2 authentication
mechanisms.  In testing on my Android device with the UV flag set I was
prompted to fingerprint.&lt;/p&gt;

&lt;h2 id=&#34;piv-smart-card&#34;&gt;PIV (Smart Card)&lt;/h2&gt;

&lt;p&gt;In PIV mode, the YubiKey acts as a smart card.  A
public/private key is stored on the key as certificates.  The certificate
is signed by a CA trusted by the service.  Essentially this follows a
similar process to client-side authentication in mTLS; the server can
validate the public key matches requirements (signed by a CA, contains
the right metadata, etc) and then do standard public key cryptography
to verify the private key is present.&lt;/p&gt;

&lt;p&gt;YubiKeys automatically protect the certificates with a PIN (see FIDO2
about PINs); the PIN can not be removed (YubiKey bio devices don&amp;rsquo;t
support PIV mode at present).  The private key can not be extracted from
the device.   Because this is a certificate based process the keys can
expire (and so need renewal) and a CRL (certificate revocation list)
is available.&lt;/p&gt;

&lt;p&gt;The key can be put onto the card in two different ways.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The first is that an external program can generate the key pair, get it
signed by the CA, then put them on the card.  This is problematic because
it means the private key will live (for at least a small time) outside
of the secure device and so could be copied.  We also don&amp;rsquo;t necessarily
have a way to verify the device is a trusted YubiKey and not an emulator.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;The second is to have the YubiKey generate the key pair, and the CSR
(certificate signing request).  This generation process comes with
an optional attestation process, which can be used to prove the keys
were generated by a YubiKey and not a piece of software; the CA signing
process can perform the validation and only sign the cert if it passes.
The signed certificate can then be placed back on the device.  In this
way we can be sure that the private key was securely generated on the
YubiKey and can not be copied.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We should require the YubiKey generation process be followed, and never
store private keys outside of the secure device.  When the key is used
the user is prompted for their PIN/biometric.  This gives us sufficient
trust to let the YubiKey in PIV mode be used for passwordless access.&lt;/p&gt;

&lt;p&gt;Windows supports PIV mode using the built in smart card services.&lt;/p&gt;

&lt;p&gt;MacOS can support smart card logins, but on Intel Macs this may not
work well with FileVault disk encryption since that needs the password
to decrypt the disk.  It&amp;rsquo;s possible m1/m2 based Macs solve this a
different way.  Macs may also have limited PIN support (numeric only).&lt;/p&gt;

&lt;p&gt;Web authentication is also possible (most browsers support this) but
the server needs to ensure the certificate is signed by the proper CA
(same as with mTLS).&lt;/p&gt;

&lt;h2 id=&#34;hotp-totp-static-passwords&#34;&gt;HOTP / TOTP / Static passwords&lt;/h2&gt;

&lt;p&gt;These three authenticators are lumped
together since they use the same mechanism.   Essentially the device
acts as a USB keyboard and types the &amp;ldquo;secret&amp;rdquo;.  This is very
flexible. There is no PIN protection.&lt;/p&gt;

&lt;p&gt;YubiKeys come with two slots.  The first is accessed with a quick
&amp;ldquo;short&amp;rdquo; press.  The second requires a &amp;ldquo;long&amp;rdquo; press (maybe
3 seconds?).  Since these are just &amp;ldquo;typing&amp;rdquo; they are not phishing
resistant, and are just a &amp;ldquo;something you have&amp;rdquo; factor.&lt;/p&gt;

&lt;p&gt;Each slot can be configured with HOTP/TOTP/Static credentials.&lt;/p&gt;

&lt;h3 id=&#34;hotp&#34;&gt;HOTP&lt;/h3&gt;

&lt;p&gt;&amp;ldquo;Out of the Box&amp;rdquo; slot 1 is configured with a Yubico
managed HOTP seed.  When you single press the device will
&amp;ldquo;type&amp;rdquo; a one-time value that changes each time and adds
the RETURN; eg&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    cccccbbbubrtvbkjrrjhrkdgbcjfichivdihefvlujrt
    cccccbbbubrtrgndglnnltrcekljgnfibikhkrnvivrj
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This value is &lt;a href=&#34;https://developers.yubico.com/OTP/Specifications/OTP_validation_protocol.html&#34;&gt;documented&lt;/a&gt;, and Yubico provide an &lt;a href=&#34;https://developers.yubico.com/OTP/&#34;&gt;API&lt;/a&gt; for this built in seed.&lt;/p&gt;

&lt;p&gt;The first part (&lt;code&gt;cccccbbbubrt&lt;/code&gt; in this case) is the device identity;
the remaining part of the value encodes things like &amp;ldquo;number of
presses&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Being HOTP the value changes each time you press, based on the number of
times you&amp;rsquo;ve pressed.   The validation server needs to keep track of
the &amp;ldquo;last press&amp;rdquo; count for the device and only approve the login if
the &amp;ldquo;new press&amp;rdquo; contains a count that is greater than the last value.
This prevents replay attacks.&lt;/p&gt;

&lt;p&gt;Using the built in seed it is possible to call the public Yubico API
to validate the value.   This is very simple, and even doable as a
&lt;a href=&#34;https://github.com/sweharris/yubikey-otp-sh&#34;&gt;shell script&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It becomes very easy to create a self-service onboarding process.  To
register the device the user merely needs to tap the button (and so
&amp;ldquo;type&amp;rdquo; the current code).  The server can validate this (hence attest it
is a YubiKey) via the Yubico API and save the device ID.  For login
the server simply needs to validate the code (again via the API) and
verify the device ID matches the one saved.&lt;/p&gt;

&lt;p&gt;This does have an external dependency on the Yubico servers being
available in order to use this, but it provides a good and simple &amp;ldquo;out
of the box&amp;rdquo; experience.  You can use any off-the-shelf YubiKey (that
supports HOTP) plug it in and self-register.  We can be confident that it
is a YubiKey being used; the call to the Yubico API verifies
this is a YubiKey and not another device.&lt;/p&gt;

&lt;p&gt;The seed can be replaced with a corporate owned one and you can run your
own verification server,  but then we have management complications (how
to generate a unique seed for each device; how to ensure the device is
a real YubiKey) so I don&amp;rsquo;t recommend this.  I&amp;rsquo;d say that you should only
do this if you&amp;rsquo;re worried about the Yubico server availability.&lt;/p&gt;

&lt;p&gt;If the default seed is over-written then it can not be restored; only
YubiKey can do this.  If a &amp;ldquo;smart&amp;rdquo; (dumb) user uses the YubiKey manager
(on a personal machine, for example) to delete the seed then they will
no longer be able to use it for Yubico HOTP authentication.&lt;/p&gt;

&lt;h3 id=&#34;totp&#34;&gt;TOTP&lt;/h3&gt;

&lt;p&gt;TOTP mode is similar to HOTP but uses &amp;ldquo;time based&amp;rdquo; rather than a
count of touches.  Since the YubiKey doesn&amp;rsquo;t have a built in clock it
works in conjunction with the YubiKey Authenticator application. I think
the authenticator app also stores an encrypted form of the TOTP seed
(because of limited storage on the YubiKey, but I&amp;rsquo;m not sure of this).
It will talk to the YubiKey and pass the time (and the encrypted seed? Not
sure) to the YubiKey; the YubiKey performs the calculations and returns
the current value to the app which the user can then type or copy/paste.&lt;/p&gt;

&lt;p&gt;The problem with TOTP is in how the seed is copied; it&amp;rsquo;s generally
exposed to the user (eg QR code) so they could screen shot it and add it
to multiple authenticators.  We also have no guarantee they are using
a YubiKey and not some other program such as google authenticator.
This makes it unsuitable for authentication for employees.  Although
I&amp;rsquo;ve seen similar mistakes with &lt;a href=&#34;https://www.sweharris.org/post/2019-06-09-softtoken&#34;&gt;RSA SecurID softtokens&lt;/a&gt;&amp;hellip;&lt;/p&gt;

&lt;h3 id=&#34;static-passwords&#34;&gt;Static Passwords&lt;/h3&gt;

&lt;p&gt;And finally a slot can be configured for static passwords.  I guess if
you have a 28 character password then it might make sense?   Storing a
password in this way changes the password from &amp;ldquo;something you know&amp;rdquo;
to &amp;ldquo;something you have&amp;rdquo; because possession of the YubiKey is all
you need to use the password.   Unfortunately we can&amp;rsquo;t stop a YubiKey
being used this way, but this isn&amp;rsquo;t a problem unique to these devices;
any &amp;ldquo;auto-typing&amp;rdquo; HID device could do this.  We just have to trust
people aren&amp;rsquo;t knowledgeable enough (or stupid enough) to do this.
One YubiKey uniqueness, though, is that because the same device can
possess the password and MFA (eg HOTP in slot 1 and password in slot 2)
then MFA may be reduced to a single &amp;ldquo;have&amp;rdquo; factor; &amp;ldquo;long press
for the password, short press for the MFA&amp;rdquo;.   Yet another reason to
move to passwordless!&lt;/p&gt;

&lt;h2 id=&#34;pgp&#34;&gt;PGP&lt;/h2&gt;

&lt;p&gt;I include this for completeness, because YubiKeys can support it.  PGP is
a tool for signing/encrypting email.  It requires a public/private key.
Typically these are stored on the filesystem, protected with passphrases.&lt;/p&gt;

&lt;p&gt;With a YubiKey the private key can be generated/stored on the device
and are protected with a PIN similar to PIV mode.  This makes it possible
to have stronger protections on this key.&lt;/p&gt;

&lt;p&gt;However, many organisations need to have an enterprise managed encryption
solution (potentially with a corporate master key) for legal and compliance
reasons.  Individuals using PGP would break that.&lt;/p&gt;

&lt;p&gt;It is possible to
configure some ssh clients to use gpg-agent (instead of ssh-agent) and
so effectively use the YubiKey as a store for your ssh private key but
it&amp;rsquo;s not a supported configuration on all clients, and &lt;a href=&#34;https://www.sweharris.org/post/2016-09-05-sshkeys/&#34;&gt;I don&amp;rsquo;t think
humans should use ssh keys to access servers&lt;/a&gt;
unless you have strong management processes in place.&lt;/p&gt;

&lt;p&gt;So, really, we might not want use this functionality for authentication.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;This got long, because a YubiKey can do so much!  Here&amp;rsquo;s a quick table
of my conclusions.&lt;/p&gt;

&lt;style&gt;
th,td {
  padding: 2px;
}
&lt;/style&gt;

&lt;table border=1 align=center&gt;
  &lt;tr&gt;&lt;th bgcolor=&#39;#eeeeee&#39; colspan=2&gt;U2F&lt;/th&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Phish Resistant&lt;/td&gt;&lt;td&gt;Y&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Passwordless&lt;/td&gt;&lt;td&gt;N&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;PIN Protected&lt;/td&gt;&lt;td&gt;N&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Attestable&lt;/td&gt;&lt;td&gt;Y&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Authenticator Type&lt;/td&gt;&lt;td&gt;&#34;Have&#34;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Interfaces&lt;/td&gt;&lt;td&gt;Primarily Browser&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Suitability&lt;/td&gt;&lt;td&gt;2nd factor if attested&lt;/td&gt;&lt;/tr&gt;

  &lt;tr&gt;&lt;th bgcolor=&#39;#eeeeee&#39; colspan=2&gt;FIDO 2&lt;/th&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Phish Resistant&lt;/td&gt;&lt;td&gt;Y&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Passwordless&lt;/td&gt;&lt;td&gt;Y*&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;PIN Protected&lt;/td&gt;&lt;td&gt;Y*&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Attestable&lt;/td&gt;&lt;td&gt;Y&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Authenticator Type&lt;/td&gt;&lt;td&gt;&#34;Have&#34; + &#34;Know&#34; (PIN)/&#34;Are&#34; (Biometric)&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Interfaces&lt;/td&gt;&lt;td&gt;Browser, Desktop login&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Suitability&lt;/td&gt;&lt;td&gt;2nd factor if attested; passwordless if attested and UV enforced&lt;/td&gt;&lt;/tr&gt;

  &lt;tr&gt;&lt;th bgcolor=&#39;#eeeeee&#39; colspan=2&gt;PIV (Smart Card)&lt;/th&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Phish Resistant&lt;/td&gt;&lt;td&gt;Y&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Passwordless&lt;/td&gt;&lt;td&gt;Y*&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;PIN Protected&lt;/td&gt;&lt;td&gt;Y&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Attestable&lt;/td&gt;&lt;td&gt;Y&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Authenticator Type&lt;/td&gt;&lt;td&gt;&#34;Have&#34; + &#34;Know&#34; (PIN)&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Interfaces&lt;/td&gt;&lt;td&gt;Browser, Desktop login&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Suitability&lt;/td&gt;&lt;td&gt;Passwordless if key generated on device&lt;/td&gt;&lt;/tr&gt;

  &lt;tr&gt;&lt;th bgcolor=&#39;#eeeeee&#39; colspan=2&gt;HOTP&lt;/th&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Phish Resistant&lt;/td&gt;&lt;td&gt;N&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Passwordless&lt;/td&gt;&lt;td&gt;N&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;PIN Protected&lt;/td&gt;&lt;td&gt;N&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Attestable&lt;/td&gt;&lt;td&gt;Y*&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Authenticator Type&lt;/td&gt;&lt;td&gt;&#34;Have&#34;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Interfaces&lt;/td&gt;&lt;td&gt;Keyboard typing&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Suitability&lt;/td&gt;&lt;td&gt;2nd factor with Yubico default seed&lt;/td&gt;&lt;/tr&gt;

  &lt;tr&gt;&lt;th bgcolor=&#39;#eeeeee&#39; colspan=2&gt;TOTP&lt;/th&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Phish Resistant&lt;/td&gt;&lt;td&gt;N&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Passwordless&lt;/td&gt;&lt;td&gt;N&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;PIN Protected&lt;/td&gt;&lt;td&gt;N&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Attestable&lt;/td&gt;&lt;td&gt;N&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Authenticator Type&lt;/td&gt;&lt;td&gt;&#34;Have&#34;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Interfaces&lt;/td&gt;&lt;td&gt;Keyboard typing&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Suitability&lt;/td&gt;&lt;td&gt;None&lt;/td&gt;&lt;/tr&gt;

  &lt;tr&gt;&lt;th bgcolor=&#39;#eeeeee&#39; colspan=2&gt;Static passwords&lt;/th&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Phish Resistant&lt;/td&gt;&lt;td&gt;N&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Passwordless&lt;/td&gt;&lt;td&gt;N&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;PIN Protected&lt;/td&gt;&lt;td&gt;N&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Attestable&lt;/td&gt;&lt;td&gt;N&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Authenticator Type&lt;/td&gt;&lt;td&gt;&#34;Have&#34;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Interfaces&lt;/td&gt;&lt;td&gt;Keyboard typing&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Suitability&lt;/td&gt;&lt;td&gt;None&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt;
  &lt;tr&gt;&lt;th bgcolor=&#39;#eeeeee&#39; colspan=2&gt;PGP&lt;/th&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Phish Resistant&lt;/td&gt;&lt;td&gt;n/a&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Passwordless&lt;/td&gt;&lt;td&gt;N&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;PIN Protected&lt;/td&gt;&lt;td&gt;Y&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Attestable&lt;/td&gt;&lt;td&gt;n/a&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Authenticator Type&lt;/td&gt;&lt;td&gt;&#34;Have&#34; + &#34;Know&#34; (PIN)&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Interfaces&lt;/td&gt;&lt;td&gt;OpenPGP&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td align=&#34;right&#34;&gt;Suitability&lt;/td&gt;&lt;td&gt;n/a&lt;/td&gt;&lt;/tr&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;It&amp;rsquo;s important to note that this is just looking at what a YubiKey can
provide.  There are other solutions in this problem space, including
applications on your mobile device that receive push notifications.
Some of these just act as second factors, others can be completely
passwordless.&lt;/p&gt;

&lt;p&gt;However, sometimes you may not be able to use mobile devices (e.g. if you
are in a call center where they&amp;rsquo;re not allowed in, or if you have employees
who do not wish to install work related stuff on their personal devices).&lt;/p&gt;

&lt;p&gt;In those scenarios a YubiKey or one of their competitors can provide a good
strong solution.  Just ensure you understand how to manage them and what
their characteristics are.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Search This Site</title>
      <link>https://www.sweharris.org/search/</link>
      <pubDate>Sat, 23 Jul 2022 11:26:31 -0400</pubDate>
      
      <guid>https://www.sweharris.org/search/</guid>
      <description>&lt;p&gt;&lt;link href=&#34;https://www.sweharris.org/_pagefind/pagefind-ui.css&#34; rel=&#34;stylesheet&#34;&gt;
&lt;script src=&#34;https://www.sweharris.org/_pagefind/pagefind-ui.js&#34; type=&#34;text/javascript&#34;&gt;&lt;/script&gt;
&lt;div id=&#34;search&#34;&gt;&lt;/div&gt;
&lt;script src=&#34;https://www.sweharris.org/search.js&#34; type=&#34;text/javascript&#34;&gt;&lt;/script&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Microservice Security</title>
      <link>https://www.sweharris.org/post/2022-06-26-microservice_security/</link>
      <pubDate>Sun, 26 Jun 2022 11:14:12 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2022-06-26-microservice_security/</guid>
      <description>

&lt;p&gt;Recently I was invited to be part of a &lt;a href=&#34;https://events.rfg100.com/DesigningforMicroservicesSecurityRequirements&#34;&gt;panel on Microservice Security&lt;/a&gt;.
The fools!  Normally on these panels they want you to talk for 5-ish
minutes; unfortunately I came up with about 15 minutes worth of material!&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s perfect for a blog :-)&lt;/p&gt;

&lt;h2 id=&#34;older-designs&#34;&gt;Older designs&lt;/h2&gt;

&lt;p&gt;Before I talk about microservices I want to take a look at older designs&lt;/p&gt;

&lt;h3 id=&#34;monoliths&#34;&gt;Monoliths.&lt;/h3&gt;

&lt;p&gt;A &amp;ldquo;monolith&amp;rdquo; is pretty much an &amp;ldquo;all in one&amp;rdquo; application.  It may combine
the UI, the app layer, the storage layer&amp;hellip; all bundled together.
I mean, who hasn&amp;rsquo;t written 10,000+ lines of spaghetti C code?&lt;/p&gt;

&lt;p&gt;In a monolith we had data structures, but we didn&amp;rsquo;t really have much
in the way of data segregation.  Persistent data structures were
pretty much global in scope.  We could try and normalize access to these
structures, e.g. using library functions, but the &lt;em&gt;app&lt;/em&gt; couldn&amp;rsquo;t enforced
this; instead we attempted to control things via code reviews&amp;hellip; &amp;ldquo;why are
you setting &lt;code&gt;foo.bar&lt;/code&gt; rather than calling library function &lt;code&gt;do_magic()&lt;/code&gt;?&amp;rdquo;&lt;/p&gt;

&lt;p&gt;Now from a security perspective this wasn&amp;rsquo;t really too much of an
issue; only the app internals could see it, anyway.  Well, except it
encouraged bad programming techniques and could have led to hidden
bugs pretty easily, especially if modules got out of sync on the data
structure formats!&lt;/p&gt;

&lt;h3 id=&#34;object-oriented-programming&#34;&gt;Object Oriented Programming&lt;/h3&gt;

&lt;p&gt;This introduced the idea of public and private elements.  Now we &lt;em&gt;can&lt;/em&gt;
hide things and enforce access through &amp;ldquo;approved&amp;rdquo; public interfaces,
or methods.  You can no longer set &lt;code&gt;foo.bar&lt;/code&gt; directly, but instead
have to call &lt;code&gt;Foo.do_magic()&lt;/code&gt;.  This can definitely help ensure data
consistency and reduce bugs.&lt;/p&gt;

&lt;p&gt;However, those public methods are, well, &lt;em&gt;public&lt;/em&gt;.  If I can see the
object then I can call those methods.&lt;/p&gt;

&lt;p&gt;But it&amp;rsquo;s still not really a security issue, for the same reason; only
the app could see those methods.&lt;/p&gt;

&lt;h3 id=&#34;three-tier-apps&#34;&gt;Three tier apps&lt;/h3&gt;

&lt;p&gt;Now we&amp;rsquo;re starting to separate components.  No longer do we have a
monolith, and what used to be methods internal to the app may be exposed
to the wider network.  This brings in a set of security challenges.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to we ensure the app tier is only called from the correct display
tier?&lt;/li&gt;
&lt;li&gt;How to ensure the DB is only reached from the app?&lt;/li&gt;
&lt;li&gt;How to stop the expected data flow from being bypassed?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We might look at firewalls to do some of this.  If you can&amp;rsquo;t
&lt;em&gt;see&lt;/em&gt; the service endpoint then you can&amp;rsquo;t call the functions.
However this is limited and gets hard to manage at scale.
Unless your environment has been designed from day 1 for
&lt;a href=&#34;https://www.sweharris.org/post/2016-06-20-microsegmentation/&#34;&gt;micro-segmentation&lt;/a&gt; and defined
communication paths you probably have a relatively standard &amp;ldquo;open&amp;rdquo;
&lt;a href=&#34;https://www.sweharris.org/post/2017-11-05-3tier-network/&#34;&gt;3 tier network&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So the common solution is to require &lt;em&gt;authentication&lt;/em&gt; between the
tiers; e.g. the web tiers authenticates to the app tier; the app tier
authenticates to the database.&lt;/p&gt;

&lt;p&gt;And remember that the network may also need to be protected; data in
transit may need to be encrypted if it contains sensitive components.
Yes, even inside your own datacenter!&lt;/p&gt;

&lt;h3 id=&#34;multi-component-apps&#34;&gt;Multi-component apps&lt;/h3&gt;

&lt;p&gt;Docker was a big driver of this, but it&amp;rsquo;s also used elsewhere.  The idea
is to allow component re-use in a simple &amp;ldquo;Lego build&amp;rdquo; design.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&amp;ldquo;OK, let&amp;rsquo;s spin up an app with a memcached container, oh&amp;hellip; let&amp;rsquo;s also
use mysql, nginx, redis, mosquitto&amp;hellip; and 6 different containers for
my app.&amp;rdquo;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is really a generalized case of the 3-tier app.  So we can use the
same type of solution.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication; each component must know that the call has come from
an authorized source&lt;/li&gt;
&lt;li&gt;Encryption in transit&lt;/li&gt;
&lt;li&gt;And let&amp;rsquo;s not forget input validation!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of just doing this in a couple of places we might need to do
this in a dozen places.  This is getting complicated&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;finally-micro-services&#34;&gt;Finally, micro-services&lt;/h2&gt;

&lt;p&gt;Really, a micro-service design is just a generalized form of
multi-component apps&lt;/p&gt;

&lt;p&gt;Instead of monolith exposing functions to other parts of the application,
each micro-service dedicated to a particular function or group of
functions.  And these functions may be exposed to the &lt;em&gt;network&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;NOW we care about the security of the function.  They can be
reached from outside of the application.&lt;/p&gt;

&lt;p&gt;In some cases this exposure is deliberate.  These functions should be
considered &amp;ldquo;public&amp;rdquo;.  They&amp;rsquo;re meant to be the interface between the
application and the application clients (whether they&amp;rsquo;re internal to
your organisation or external to the org doesn&amp;rsquo;t really matter; they&amp;rsquo;re
external to the &lt;em&gt;application&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;In other cases this expose must be prevented.  These functions should
be considered &amp;ldquo;private&amp;rdquo;.  But are they?&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This public/private terminology is similar to that for Object Oriented
Programming.  It means public or private to the application&amp;hellip; however
that is defined.  I am NOT talking about &amp;ldquo;private&amp;rdquo; to the organisation.
Think zero trust :-)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;How do we ensure these private interfaces are kept private?
How do we ensure that public interfaces are only used by authorized
consumers?&lt;/p&gt;

&lt;p&gt;And we have the same answers..  authentication, encryption, input validation&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;well-we-can-do-better&#34;&gt;Well, we can do better&amp;hellip;&lt;/h2&gt;

&lt;p&gt;All that is hard work.&lt;/p&gt;

&lt;p&gt;Fortunately modern technologies can assist in newer designs that can help enforce the separation between public and private endpoints&lt;/p&gt;

&lt;p&gt;Some examples of this include&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Private network structures (eg docker-compose) so that the backend
components (memcached, etc) aren&amp;rsquo;t exposed off the local machine; for
single-app machines this may be sufficient to make an endpoint private.
Docker swarm took that to a multi-machine level but required oversight
for multi-app.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;k8s; containers inside a pod can talk to each other.  Great for
private communication.  Containers in other pods have to talk via public
interfaces.   Need to balance scalability of individual micro-services
to pod-level scalability and easier communication&amp;hellip;&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Container network constructs; e.g. istio can act as a gateway
between pods that will transparently do TLS encryption and can do mTLS
authentication; set the rules as to what pods can talk to what other
pods and it&amp;rsquo;s enforced by the infrastructure.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How you deploy stuff can answer some of the security concerns raised by
going to micro-services.&lt;/p&gt;

&lt;h2 id=&#34;some-other-complications&#34;&gt;Some other complications&lt;/h2&gt;

&lt;p&gt;These aren&amp;rsquo;t necessarily security issues, but to be kept in mind&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Every public endpoint needs to be considered an API to your application.
It defines a contract to your consumers.  If you change your call (data
structure, functionality, parameters, whatever) you need to treat it as
an API change.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Change control gets harder; should each microservice have its own
SDLC lifecycle?  Be registered in your app inventory?&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Knowing how to &amp;ldquo;right size&amp;rdquo; your microservices is a skill.  If you
go too granular then you get a lot of overhead (even if it&amp;rsquo;s just
communication overhead!  A network call is orders of magnitude slower
than a local app function call) and lose performance and may have
more paperwork.  If you go too coarse then then you may not get the
independent scalability you desire.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Micro-services require you to think about what endpoints are considered
public and what are private.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Any network port that is exposed &amp;ldquo;off&amp;rdquo; the machine is automatically
public.  Even those only on localhost may be public on a multi-app machine&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Authentication, Authorization, Encryption, AUDITING&amp;hellip; these need to
be enforced at every exposed endpoint!  SDLC processes should be leveraged
to help validate this.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Remember, data flows can be initiated differently from what your app
expects; you may expect calls A-&amp;gt;B-&amp;gt;C-&amp;gt;D but an outsider might call C
directly if it&amp;rsquo;s public; you need to handle that.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a &lt;em&gt;lot&lt;/em&gt; to keep in mind; not only must the code be written, but
knowledge of networking, scaling, performance, encryption, authentication&amp;hellip;&lt;/p&gt;

&lt;p&gt;This really highlights the importance of
&lt;a href=&#34;https://www.sweharris.org/post/2019-07-07-devsecops/&#34;&gt;SecDevSecOpsSec&lt;/a&gt;.  A proper architecture
design at the beginning can simplify the solution and take some load
off the development team.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Secure your cloud</title>
      <link>https://www.sweharris.org/post/2022-03-04-cloud-russians/</link>
      <pubDate>Fri, 04 Mar 2022 06:48:32 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2022-03-04-cloud-russians/</guid>
      <description>

&lt;p&gt;I got asked another question.  I&amp;rsquo;m going to paraphrase the question for
this blog entry.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Given the Russian invasion of Ukraine and the response of other nations (sanctions, asset confiscation, withdrawal of services, isolation of the Russian banking system&amp;hellip;) there is a chance of enhanced cyber attacks against Western banking infrastructure in retaliation.  How can we be 100% sure our cloud environments are secure from this?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Firstly, I want to dispel the &amp;ldquo;100%&amp;rdquo; myth.  No security is 100%.
Your on-prem environment isn&amp;rsquo;t 100% secure.  The cost would become
prohibitive and potentially greater than the value of the asset&amp;rsquo;s you&amp;rsquo;re
protecting.  Instead you perform an analysis and reduce the risks to
a level you are comfortable with, at a price you&amp;rsquo;re willing to pay.
These risk reduction strategies may include preventative controls,
detective controls, impact mitigation strategies and more.&lt;/p&gt;

&lt;p&gt;So the question, really, is &amp;ldquo;Are we sure our controls and strategies
are good enough&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Now there hasn&amp;rsquo;t yet been any confirmed reports of high
threat attacks against financial institutions (going by the
&lt;a href=&#34;https://www.cisa.gov/uscert/ncas/alerts/aa22-054a&#34;&gt;CISA&lt;/a&gt;
reports), the UK GCHQ &lt;a href=&#34;https://www.theguardian.com/technology/2022/feb/23/uk-firms-warned-russia-cyberwar-spillover-ukraine-critical-infrastructure&#34;&gt;held a
rountable&lt;/a&gt;
to discuss the threat to critical infrastructure.&lt;/p&gt;

&lt;p&gt;So what makes the cloud different?  That&amp;rsquo;s a massive topic because &amp;ldquo;cloud&amp;rdquo;
is too generic a term.  I&amp;rsquo;m not going to talk about SaaS offerings like
Workday, Salesforce and the like (although these are important and may
contain sensitive data, so make sure they &lt;em&gt;are&lt;/em&gt; controlled!).&lt;/p&gt;

&lt;p&gt;And that includes O365!  If you&amp;rsquo;ve outsourced your Exchange environment
to Microsoft (and who hasn&amp;rsquo;t?  It&amp;rsquo;s convenient) this could be a critical
dependency&amp;hellip; can you still operate if your email is down? Your Teams
chat is down?  Your very phone system (integrated into Teams) is down?&lt;/p&gt;

&lt;p&gt;But that&amp;rsquo;s not where I&amp;rsquo;m going; Instead I&amp;rsquo;ll focus on primary cloud
application environments such as AWS, Azure or GCP.&lt;/p&gt;

&lt;h2 id=&#34;shadow-it&#34;&gt;Shadow IT&lt;/h2&gt;

&lt;p&gt;Infrastructure sitting on-prem automatically gains a level of protection
by being behind corporate firewalls.  It can&amp;rsquo;t be reached from the outside
(&amp;ldquo;you can&amp;rsquo;t hack what you can&amp;rsquo;t reach&amp;rdquo;) and it shouldn&amp;rsquo;t be able to make
outgoing connections; firewalls control egress as well as ingress!&lt;/p&gt;

&lt;p&gt;And your processes better require CMDB registration before firewalls
will be opened (&amp;ldquo;no you can&amp;rsquo;t talk to the database from the app tier;
firewall blocked!&amp;ldquo;; &amp;ldquo;no you can&amp;rsquo;t talk to the web proxy!&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;Even if the server isn&amp;rsquo;t in your CMDB it gains these protections.&lt;/p&gt;

&lt;p&gt;But cloud Shadow IT&amp;hellip;  now a whole environment could be spun and
exposed to the internet.  This may not (should not!) have full access
to on-prem resources and so may have a limited blast radius, but it may
receive a data feed from on-prem services and so store or process data
sensitive data.&lt;/p&gt;

&lt;p&gt;And these environments won&amp;rsquo;t gain &lt;em&gt;any&lt;/em&gt; of the traditional on-prem
protections.  They&amp;rsquo;re open, exposed&amp;hellip; and we may not even know they&amp;rsquo;re
there!&lt;/p&gt;

&lt;p&gt;There are services you can sign up for that scan the internet and &lt;em&gt;try&lt;/em&gt;
to work out the owner (eg based on the TLS certificate information&amp;hellip; if
it has an OU=yourbank then it may assign that to YourBank).  They&amp;rsquo;re not
always very accurate initially, and so have a cleanup cost.  But once it&amp;rsquo;s
clean any new &amp;ldquo;Hey, we just found this!&amp;rdquo; change should trigger a review&amp;hellip;
is it another false-positive or did someone spin up shadow IT?&lt;/p&gt;

&lt;h2 id=&#34;borders&#34;&gt;Borders&lt;/h2&gt;

&lt;p&gt;Which leads into knowing your borders.  Again, on-prem datacenters have
traditionally been built with a &amp;ldquo;hard shell and soft chewy center&amp;rdquo;.  We
have a well defined border.  But with the cloud&amp;hellip; ah, there&amp;rsquo;s a lot more
borders than you may think.  And they may change!  Last year I even showed
that &lt;a href=&#34;https://www.sweharris.org/post/2021-05-06-dlp/&#34;&gt;Alexa could be used to exfiltrate data!&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This may be the worst part of the cloud; stuff is now exposed to the
internet that, really, shouldn&amp;rsquo;t be.  This may include data stores,
control planes and more.  Since these things may be exposed to the hostile
internet, access control, auditing and &lt;em&gt;monitoring&lt;/em&gt; become critical&lt;/p&gt;

&lt;h2 id=&#34;data-stores&#34;&gt;Data Stores&lt;/h2&gt;

&lt;p&gt;Here&amp;rsquo;s another area where the cloud is different.  Once again, traditional
on-prem stores gain a level of protection just by being on-prem.
The cloud&amp;hellip; this may expose your data stores directly to the internet!
Indeed a number of years ago there was almost a new breach notification
every week because someone had left data in an open S3 bucket.  Yay.&lt;/p&gt;

&lt;p&gt;Cloud service providers (CSP) have matured since then and a number of
these services now have private endpoints that are exposed only to your
VPC, but you need to verify that every data store you have configured
(S3, RDS, DynamoDB&amp;hellip;)  are all set up securely.  If any &lt;em&gt;are&lt;/em&gt; exposed
to the internet then you need to verify they are properly restricted
via IAM policies!&lt;/p&gt;

&lt;p&gt;Another area the cloud is different at is activity monitoring; your
tradition DAM (Database Activity Monitoring) solution may not work,
because it may require an agent installation on the server or similar.
We can be limited by what the CSPs service provides&amp;hellip; and this is
variable and different across CSPs, and even different between offerings
within a CSP!  If there &lt;em&gt;is&lt;/em&gt; a breach (eg bad IAM policies, or a pivot
from a trusted server) can you track what data the attacker has seen?&lt;/p&gt;

&lt;p&gt;But it&amp;rsquo;s not all complications.  Just by being separated from the
primary desktop environment, cloud data stores are less susceptible
to things like ransomware or wiperware.  These typically get into
an environment via the desktop, and local disks and NAS mounted
volumes may quickly be encrypted or data erased.  Your cloud block
storage and cloud databases are sufficiently removed.  These type of
attacks are a common tactic, and the CISA are claiming that Sandworm
(aka Fancy Bear), suspected of being associated with the GRU, have
&lt;a href=&#34;https://www.cisa.gov/uscert/ncas/alerts/aa22-054a&#34;&gt;new malware&lt;/a&gt;.
This organisation has a history of ransomware and wiperware, including
NotPetya.&lt;/p&gt;

&lt;h2 id=&#34;control-plane&#34;&gt;Control Plane&lt;/h2&gt;

&lt;p&gt;And here is where we start to wince.  The control plane is possibly the
most sensitive part of an infrastructure; you can create VMs, destroy VMs,
look at their data, modify permissions&amp;hellip; lots of stuff.&lt;/p&gt;

&lt;p&gt;Your on-prem control plane may even be on a separate network segment
because it&amp;rsquo;s so sensitive.  But the cloud one?  That&amp;rsquo;s exposed to the
internet and can not be changed.  It&amp;rsquo;s &lt;em&gt;designed&lt;/em&gt; to be accessible
everywhere.&lt;/p&gt;

&lt;p&gt;The best you can do, here, is to ensure your access control policies
are tightly locked down, and auditing and monitoring is in place.&lt;/p&gt;

&lt;h2 id=&#34;iam&#34;&gt;IAM&lt;/h2&gt;

&lt;p&gt;For a lot of CSP native services, IAM is the core of the access control.
It controls &lt;em&gt;everything&lt;/em&gt;.  Who can access what.  What resources are
exposed.  Where access is allowed from.&lt;/p&gt;

&lt;p&gt;If you mess up your IAM policies, you&amp;rsquo;re asking for a world of hurt.&lt;/p&gt;

&lt;p&gt;And it&amp;rsquo;s not simple.  Looking at an AWS IAM policy is like staring into
the abyss; do it too long and it&amp;rsquo;ll stare back at you and you&amp;rsquo;ll start
seeing the whole world as a JSON policy!&lt;/p&gt;

&lt;p&gt;Fortunately tooling now exists for this.  Even better, the &lt;em&gt;API&lt;/em&gt; nature
of the cloud means that access need not be so static.  We can move from
the traditional &amp;ldquo;minimum necessary access&amp;rdquo; through &amp;ldquo;just in time access&amp;rdquo;
all the way to &amp;ldquo;zero standing access&amp;rdquo;.  You want access to the cloud
control plane?  Jump through these hoops, do some MFA, and you&amp;rsquo;ll get
the access you need&amp;hellip; and we&amp;rsquo;ll remove it in 2 hours time.  In AWS you
don&amp;rsquo;t even need an account; just assume a role.&lt;/p&gt;

&lt;p&gt;As with networking &amp;ldquo;you can&amp;rsquo;t attack what you can&amp;rsquo;t reach&amp;rdquo;, you can&amp;rsquo;t
login to accounts without access.&lt;/p&gt;

&lt;p&gt;This tooling can also help with IAM role analysis; are people over
permissioned?  Are people granted permissions who never use the account?
Can we define RBAC models?&lt;/p&gt;

&lt;p&gt;I don&amp;rsquo;t expect many companies are at this stage, today (when we&amp;rsquo;re
supposedly worried), but it&amp;rsquo;s a target they should be looking at.&lt;/p&gt;

&lt;p&gt;But even without this zero standing access control, we already know how
to control IAM access, monitor it.  It&amp;rsquo;s a critical area, considering what
it controls (including the control plane!) so we&amp;rsquo;ve put controls in place.&lt;/p&gt;

&lt;h2 id=&#34;network-segmentation&#34;&gt;Network Segmentation&lt;/h2&gt;

&lt;p&gt;Now here is another area the cloud can be better than on-prem.  Because of
the Infrastructure as Code (IaC) nature of a cloud environment it&amp;rsquo;s very
easy to create &lt;em&gt;macro&lt;/em&gt; segmentation between applications.  Instead of the
nice chewy center of your traditional datacenter we now have a honey comb.
East-West traffic can be controlled.&lt;/p&gt;

&lt;p&gt;This helps control the blast radius if an application is compromised
(again, you can&amp;rsquo;t attack what you can&amp;rsquo;t reach).  But, further, it makes
it easier to &lt;em&gt;shut down&lt;/em&gt; access.  If an application with access into
your core services (e.g. the mainframe) gets compromised it is &lt;em&gt;easy&lt;/em&gt;
to block all traffic to/from that application.  We&amp;rsquo;ve now contained the
problem, prevented further infiltration into the environment and blocked
further data exfiltration.&lt;/p&gt;

&lt;p&gt;The out-of-band nature of the control plane also now means you can easily
snapshot the service and preserve it for forensic analysis.&lt;/p&gt;

&lt;p&gt;The cloud can make the whole DFIR process &lt;em&gt;easier&lt;/em&gt; than on-prem.
Suspicious behaviour can even pre-emptively start snapshotting and
tracking of activity before a breach occurs.&lt;/p&gt;

&lt;h2 id=&#34;modern-security-tooling&#34;&gt;Modern security tooling&lt;/h2&gt;

&lt;p&gt;The cloud makes it possible to do security in new ways.&lt;/p&gt;

&lt;p&gt;For a traditional VM in your datacenter you need to do a credentialed scan
of the environment to see what&amp;rsquo;s really going on.  This may be remote
initiated (eg via ssh), or using an agent.  And now we have to worry
about coverage (are my agents on every machine?  Are they working?).
Which requires an accurate CMDB.  How frequently is that updated?
Are decomm&amp;rsquo;d assets removed?  What about machines that are powered down?&lt;/p&gt;

&lt;p&gt;The cloud, though&amp;hellip; it can tell you an accurate &amp;ldquo;as of now&amp;rdquo; inventory
of resources you have, and their state.  And you can &lt;em&gt;snapshot&lt;/em&gt; the
disks (whether the instance is running or not) and scan the snapshot
for malware or insecure software or dodgy entries in log files or&amp;hellip;&lt;/p&gt;

&lt;p&gt;Spin up a new VM and you get scanned even without needing to worry
about agents!&lt;/p&gt;

&lt;p&gt;Add in information from network flow logs and you can start to build
connectivity graphs between assets, and help determine &lt;em&gt;actual&lt;/em&gt; risk to
a vulnerability.&lt;/p&gt;

&lt;p&gt;Of course it&amp;rsquo;s not a panacea.  They can&amp;rsquo;t see inside the &lt;em&gt;running&lt;/em&gt; box,
so fileless malware won&amp;rsquo;t be detected.  They also can&amp;rsquo;t see images from
filesystems they don&amp;rsquo;t understand.  They can&amp;rsquo;t read locally encrypted
disks (eg via dm-crypt).  And they can&amp;rsquo;t see process execution.  You still
need agent/credentialed scans for that.  The best of both worlds is using
the &amp;ldquo;ambient&amp;rdquo; security at the CSP layer, enhanced with data from agents.&lt;/p&gt;

&lt;p&gt;But just having the ability to scan something &lt;em&gt;because it is there&lt;/em&gt; is
a massive change in security.  It&amp;rsquo;s now &amp;ldquo;ambient&amp;rdquo; to the environment;
something that just happens with no additional effort.&lt;/p&gt;

&lt;h2 id=&#34;cvss-isn-t-necessarily-good&#34;&gt;CVSS isn&amp;rsquo;t necessarily good.&lt;/h2&gt;

&lt;p&gt;Many risk controls are based around a CVE.  &amp;ldquo;Oh no; this has a 9.5 rating!
Fix now!&amp;ldquo;.  But this isn&amp;rsquo;t necessarily an accurate definition of your
actual risk.  &amp;ldquo;Yes, log4j is sitting on this box, in a directory called
/opt/myapp_oldversion with a permission of 000.&amp;rdquo;  But I&amp;rsquo;m not at risk.&lt;/p&gt;

&lt;p&gt;This new tooling now lets us look at vulnerabilities in a different way.
Let&amp;rsquo;s say we have a Apache RCE.  We find this on 10,000 machines.  Do we
need to patch them all ASAP?  Well, we can look at the risk.  Internet
exposed services are clearly &amp;ldquo;fix yesterday&amp;rdquo;.  Non-internet facing is
still at risk (eg insider attack) but could be lowered in priority.&lt;/p&gt;

&lt;p&gt;But how do we know if something is internet exposed?  The connectivity
graph can help here; &amp;ldquo;yep, this goes through a firewall, through a WAF,
through a load balancer&amp;hellip; even though it only has an internal IP address,
it&amp;rsquo;s internet exposed!&amp;rdquo;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not sure any tooling is really that good, at the moment, and even
the modern tools can&amp;rsquo;t see inside non-native configurations (e.g. if
you have a Palo Alto virtual appliance then the tooling has no idea
about connectivity).  So our scope to &lt;em&gt;automate&lt;/em&gt; this is more limited.&lt;/p&gt;

&lt;p&gt;But even if we do come up with a good risk score for each instance based
on the best data, is this the right thing?&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s a number of known vulnerabilities without a CVE at all.  And,
of course, there&amp;rsquo;s always a zero day.&lt;/p&gt;

&lt;p&gt;Using CVEs and risk scores to target remediation activities and thus lower
your risk is good.  But it&amp;rsquo;s not, in my opinion, sufficient.  It&amp;rsquo;s just
another part of a defence-in-depth strategy, along with firewalls, WAFs,
auditing and the rest.&lt;/p&gt;

&lt;p&gt;Your threat intelligence feeds tell you that there&amp;rsquo;s a new attack on
a component; your ambient security tools tell you we have a lot of
vulnerable components; we program the WAF to block traffic matching
detected patterns and then use risk scoring to prioritize remediation.&lt;/p&gt;

&lt;p&gt;I would argue that reporting risk based purely on CVSS scores is doing
your organisation a dis-service.&lt;/p&gt;

&lt;p&gt;Are we there yet?  Probably not!  But the new tools I have at my
disposal give me more visibility into my cloud environment than I&amp;rsquo;ve
ever had on-prem!&lt;/p&gt;

&lt;h2 id=&#34;attacks-on-the-csp-itself&#34;&gt;Attacks on the CSP itself&lt;/h2&gt;

&lt;p&gt;Of course this has all been looking at the attack as an attack on the
company.&lt;/p&gt;

&lt;p&gt;We also need to consider attacks on the CSP.  If AWS infrastructure gets
breached then all of the controls I mentioned above don&amp;rsquo;t necessarily
mean a thing.&lt;/p&gt;

&lt;p&gt;This isn&amp;rsquo;t an idle thought, either.  Last year Azure CosmosDB
&lt;a href=&#34;https://www.theverge.com/2021/8/27/22644161/microsoft-azure-database-vulnerabilty-chaosdb&#34;&gt;had a vulnerability&lt;/a&gt; (ChaosDB) which could have exposed data
for years.  Azure container instances &lt;a href=&#34;https://unit42.paloaltonetworks.com/azure-container-instances/&#34;&gt;had a flaw&lt;/a&gt; that could have led to cluster admin
permissions.  And, Azure Functions &lt;a href=&#34;https://www.intezer.com/blog/research/how-we-escaped-docker-in-azure-functions/&#34;&gt;had an exploit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To the best of my knowledge, all potential CSP exploits were responsibly
disclosed and fixed before data had been exposed.&lt;/p&gt;

&lt;p&gt;But what if our Russian friends found an AWS zero-day?  What is our
exposure?&lt;/p&gt;

&lt;p&gt;This isn&amp;rsquo;t easily measurable.  The CSPs, themselves, have cyber teams
to detect actual exploit and infiltration.  What we&amp;rsquo;re doing as the
customer of the CSP, they&amp;rsquo;re also doing on the underlying infrastructure.&lt;/p&gt;

&lt;p&gt;Is it 100% perfect?  Obviously not.&lt;/p&gt;

&lt;p&gt;CSPs are a high value target for attackers; break into that and you
have potential access to thousands of victims.  But they&amp;rsquo;re not the
only people in this privilege position.  Traditional MSPs have,
previously, been used as a route to attack their customers.  Every
VPN you have to a provider, a partner, a client is an attack
vector.  Even traditional on-prem equipment (eg firewalls) have
had vulnerabilities.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In some places cloud is better and new technology solutions can make
security easier and more pervasive than traditional on-prem solutions.
In other places we&amp;rsquo;ve opened new borders, lost traditional protections,
exposed critical interfaces to the internet; these all need solutions
that on-prem didn&amp;rsquo;t need because the risk profile is now different.&lt;/p&gt;

&lt;p&gt;The security controls and processes are &lt;em&gt;different&lt;/em&gt; as a result.&lt;/p&gt;

&lt;p&gt;But the cloud isn&amp;rsquo;t new.  I&amp;rsquo;ve been working with the public cloud for 6
years and I&amp;rsquo;m a relative newbie compared to many.  These are all known
problems and you should have solutions already in place; even if they&amp;rsquo;re
just detective.&lt;/p&gt;

&lt;p&gt;I suspect most breaches will occur at the application layer, and that&amp;rsquo;s
the same on-prem or in the cloud.&lt;/p&gt;

&lt;p&gt;So am I 100% confident our cloud environments are secure from a state
sponsored cyber attack?  No.  But I do have an equivalent level of
confidence as I do for on-prem environments!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The problems with port 80</title>
      <link>https://www.sweharris.org/post/2022-03-02-port80/</link>
      <pubDate>Wed, 02 Mar 2022 20:55:02 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2022-03-02-port80/</guid>
      <description>

&lt;p&gt;I got asked a question&amp;hellip; this gives me a chance to write an opinion.  I have
lots of them!&lt;/p&gt;

&lt;h3 id=&#34;if-i-redirect-my-port-80-traffic-to-another-site-do-i-need-to-get-a-tls-cert&#34;&gt;&lt;em&gt;If I redirect my port 80 traffic to another site, do I need to get a TLS cert?&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;The question here is related to if a bank (or other service) has changed
their name, then do they still need to maintain a TLS site for the old
name?  Can&amp;rsquo;t they just have &lt;code&gt;http://mybank.com&lt;/code&gt; send a redirect to &lt;code&gt;https://newbankname.com&lt;/code&gt; and be done with it?&lt;/p&gt;

&lt;h2 id=&#34;why-do-we-use-tls&#34;&gt;Why do we use TLS?&lt;/h2&gt;

&lt;p&gt;There are a number of reasons that we use TLS connections over the internet (including, but not limited to):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Confidentiality - the data transferred can&amp;rsquo;t be seen by any person in the middle because it&amp;rsquo;s encrypted&lt;/li&gt;
&lt;li&gt;Identity - the TLS certificate tells you that you are talking the website you think you are&lt;/li&gt;
&lt;li&gt;Integrity - the data hasn&amp;rsquo;t changed in transit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these are good security features.  Even supposed
&amp;ldquo;good guys&amp;rdquo; may abuse non-TLS connections.  For example,
in 2015, AT&amp;amp;T inserted adverts into traffic through their
&lt;a href=&#34;http://webpolicy.org/2015/08/25/att-hotspots-now-with-advertising-injection/&#34;&gt;hotspots&lt;/a&gt;.
In 2014 Verizon &lt;a href=&#34;https://www.eff.org/deeplinks/2014/11/verizon-x-uidh&#34;&gt;added tracking
cookies&lt;/a&gt; to their
mobile traffic.  Both of these took advantage of the lack of Integrity
and Confidentiality in the non-TLS connections.&lt;/p&gt;

&lt;h2 id=&#34;stub-server&#34;&gt;Stub server&lt;/h2&gt;

&lt;p&gt;So, typically, we don&amp;rsquo;t serve websites over HTTP on port 80, but use
HTTPS on port 443.  However there is sometimes a &amp;ldquo;stub&amp;rdquo; left on port 80
to redirect.   And this stub isn&amp;rsquo;t always that good.&lt;/p&gt;

&lt;p&gt;For example, the browser might say &amp;ldquo;Hi, I want to go to
&lt;code&gt;http://mybank.com&lt;/code&gt;&amp;rdquo;, and it will make the port 80 connection, and the
server will say &amp;ldquo;OK, really, go to &lt;code&gt;https://www.mybank.com&lt;/code&gt;&amp;rdquo; or sometimes
even &amp;ldquo;Yeah, we&amp;rsquo;ve changed names; go to &lt;code&gt;https://www.newbank.com&lt;/code&gt;&amp;rdquo;.
And now all the traffic is on port 443 and we&amp;rsquo;re good.  Right?  Well,
not so much&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;where-can-this-go-wrong&#34;&gt;Where can this go wrong?&lt;/h2&gt;

&lt;p&gt;An attacker can look at that initial port 80 request, and change it.  Let&amp;rsquo;s look at those three reasons listed above and see how the bad guy can abuse this&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Confidentiality - this isn&amp;rsquo;t so big a deal.  The initial request
your browser sends to the server and the response might be visible to
the attacker, but they can&amp;rsquo;t see anything beyond that.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Identity - now we&amp;rsquo;re getting somewhere.  With HTTP you don&amp;rsquo;t know
the server you&amp;rsquo;re talking to is the server you think you&amp;rsquo;re talking to.
The attacker could have redirected traffic to their own machine.  Now when
you ask for &lt;code&gt;http://mybank.com&lt;/code&gt; your browser may get the response &amp;ldquo;OK, go
to &lt;code&gt;https://mybankk.com&lt;/code&gt;&amp;rdquo;.  Notice the extra k?  If you&amp;rsquo;re not observant
then you may not notice anything different.  It&amp;rsquo;ll even be over TLS
with a nice certificate, for mybankk.com, so your browser happily puts
up the lock icon.   So now you&amp;rsquo;ll enter your bank login details onto a
rogue server&amp;hellip; and the bad guy steals all your money.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Integrity - here&amp;rsquo;s also a fun one.  Your browser sends the initial
request and the server sends the response, but the bad guy changes the
information so that it, again, reads mybankk.  As far as the browser is
concerned that&amp;rsquo;s a good reply and you&amp;rsquo;ll be redirected to the bad site.
(This is basically how AT&amp;amp;T injected their ads, how Verizon added
tracking).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;how-can-these-attacks-happen&#34;&gt;How can these attacks happen?&lt;/h2&gt;

&lt;p&gt;It depends on your situation.  Let&amp;rsquo;s say you&amp;rsquo;re sitting in Starbucks
using their free WiFi&amp;hellip;  well, are you?  Or are you using an attacker&amp;rsquo;s
hotspot that looks like Starbucks, but isn&amp;rsquo;t.  They can steal your
unencrypted traffic and so redirect you to their bad site.   If you&amp;rsquo;re
at home, is your home router secure?  Or has it been broken into?
A number of home routers have known weaknesses (backdoors, default
passwords, etc) which could let an attacker perform that integrity attack.
Or even if your home router is good or you are on a good Starbucks server,
the attack may have been able to steal network routes (BGP attack) or
hijack DNS so that your browser goes to the bad server.  There will be
other attack vectors; I just listed a few.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve previously written some blog posts on this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sweharris.org/post/2016-05-31-secure-webserver/&#34;&gt;Why use SSL/TLS on websites?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sweharris.org/post/2016-07-16-mitm/&#34;&gt;Man in the middle attacks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sweharris.org/post/2017-10-22-threat-vector/&#34;&gt;Know your threats and defend accordingly&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren&amp;rsquo;t attacks on you; they just looking for traffic going to
mybank.com.  You just end up being a victim.&lt;/p&gt;

&lt;h2 id=&#34;so-what-can-we-as-the-website-owner-do-about-this&#34;&gt;So what can we, as the website owner, do about this?&lt;/h2&gt;

&lt;p&gt;Firstly, if you are using a domain (e.g. www.mybank.com) then you &lt;em&gt;MUST&lt;/em&gt;
have a TLS version of the site available.  This TLS version &lt;em&gt;must&lt;/em&gt; set the
&lt;code&gt;Strict-Transport-Security&lt;/code&gt; header on the https connection.  Now, after
the first time a person goes to a website the browser will remember &amp;ldquo;Hey,
I should always go to the HTTPS version&amp;rdquo; and will not try port 80 again.
This really reduces the scope of the attacks listed because if you&amp;rsquo;ve
already visited the bank before then your browser already knows to avoid
port 80.&lt;/p&gt;

&lt;p&gt;BUT: This only works for the same domain name (and potentially
subdomains), so if you have &lt;code&gt;https://newbank.com&lt;/code&gt; set the header then
this will not protect &lt;code&gt;http://mybank.com&lt;/code&gt; because it&amp;rsquo;s a different name.
That means that every name needs to have the https version of the name
also created (with its own &lt;code&gt;Strict-Transport-Security&lt;/code&gt; header), and so
have a TLS certificate.  Without that the browser will always go to the
port 80 version of the site when requested, and be subject to the attack
scenarios listed.&lt;/p&gt;

&lt;p&gt;Even if you, yourself, do not run a port 80 version of your website you
still must have the 443 TLS version with this header, because
the previously discussed bad guy doesn&amp;rsquo;t &lt;em&gt;need&lt;/em&gt; you to have port 80 open;
they can direct traffic to their own server!&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Corporate Application Security standards should require the header to
be in place and check for it with DAST scans.  If you&amp;rsquo;re &lt;em&gt;not&lt;/em&gt; checking
this header as a matter of course then start doing so!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now make sure any redirect you do from http to https stays within
the domain.  So if you want to go from &lt;code&gt;http://www.mybank.com&lt;/code&gt; to
&lt;code&gt;https://www.newbank.com&lt;/code&gt; then you need two steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;http://www.mybank.com&lt;/code&gt; to &lt;code&gt;https://www.mybank.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://www.mybank.com&lt;/code&gt; to &lt;code&gt;https://www.newbank.com&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you miss that middle step then the &lt;code&gt;Strict-Transport-Security&lt;/code&gt; header
won&amp;rsquo;t protect the initial site!&lt;/p&gt;

&lt;p&gt;If you want to get more advanced, once you have the TLS certs in place
then you can request it gets &lt;a href=&#34;https://hstspreload.org/&#34;&gt;preloaded&lt;/a&gt; into
Chrome and other browsers.  Basically your URL gets encoded into the
browser so when you go to a site then the browser will &lt;em&gt;always&lt;/em&gt; try https!&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that some browsers are experimenting with &amp;ldquo;https first&amp;rdquo; designs
to help protect people from these types of problems.  However, as the
website owner you can&amp;rsquo;t rely on this.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;So to cut a long story short (too late!) that simple redirect on port 80
may be causing more headaches than you think.  It definitely opens up
some vulnerabilities which, if exploited, would probably get yourself
into the press.  The mitigation listed (&lt;code&gt;Strict-Transport-Security&lt;/code&gt;)
requires a TLS certificate for each domain.  Even if you close port 80
you&amp;rsquo;ll still need to have a TLS server on 443.&lt;/p&gt;

&lt;p&gt;Yes, keeping &lt;code&gt;www.mybank.com&lt;/code&gt; open to redirect to &lt;code&gt;www.newbank.com&lt;/code&gt; turns
out to be more complicated than just a simple redirect!&lt;/p&gt;

&lt;p&gt;As an aside, from a pure market perspective, if I ever saw my bank do
a redirect on port 80 to another domain then I&amp;rsquo;d close my account ASAP!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Singe cloud or multi cloud?</title>
      <link>https://www.sweharris.org/post/2022-02-15-multi-hybrid-cloud/</link>
      <pubDate>Tue, 15 Feb 2022 17:52:29 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2022-02-15-multi-hybrid-cloud/</guid>
      <description>

&lt;p&gt;I got asked a question&amp;hellip; this gives me a chance to write an opinion.  I have
lots of them!&lt;/p&gt;

&lt;h3 id=&#34;is-it-reasonable-to-just-stick-with-a-single-cloud-provider-or-is-it-better-to-go-multi-cloud&#34;&gt;&lt;em&gt;Is it reasonable to just stick with a single cloud provider, or is it better to go multi-cloud?&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;It think it seems reasonable.  I expect very few places are &lt;em&gt;true&lt;/em&gt; multi-cloud,
as in a given app runs in two clouds.  That becomes challenging if trying
to use cloud native services &amp;lsquo;cos how you access RDS would be different to
how you access Azure SQL, so writing a true multi-cloud application
isn&amp;rsquo;t so simple.  Especially when you start to do Infrastructure as Code
(IaC) where your Terraform templates may be totally different; &amp;ldquo;why does
this work in AWS but not Azure?!&amp;rdquo;&lt;/p&gt;

&lt;p&gt;And if you try to avoid that by basically self-hosting everything (just
using the IaaS) then you avoid many of the benefits of cloud (you&amp;rsquo;re just
outsourcing your datacenter) and might as well stick with a provider
of choice, for simplicity.&lt;/p&gt;

&lt;p&gt;Businesses that are multi-cloud would tend to have App1 in AWS, App2 in
Azure, App3 in GCP&amp;hellip;&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ve made it simple for app teams (they just target a simple cloud) but
this becomes a headache to secure because structures work &lt;em&gt;differently&lt;/em&gt;
between CSPs;  IAM processes are different, auditing and reporting
is different, firewalls/WAFs are different.  Even things which may
seem simple are different.  Even VPC can mean different things between
providers!&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s not to say you can&amp;rsquo;t go multi-cloud for a single app (and handle
data gravity issues and so on), but my feeling is that these are more
the exception than the rule.&lt;/p&gt;

&lt;p&gt;Every cloud provider you use may require a whole new set of
tooling to manage it.&lt;/p&gt;

&lt;p&gt;Note: this ignores SaaS offerings like Microsoft Office 365, or Workday
or and the like.  I suspect everyone is
multi-cloud when you take SaaS into account :-)&lt;/p&gt;

&lt;h3 id=&#34;what-about-a-hybrid-cloud-with-a-solution-that-bridges-into-public-cloud-providers-so-that-they-are-basically-one-cloud-everywhere-even-on-prem-isn-t-that-insecure&#34;&gt;&lt;em&gt;what about a hybrid cloud with a solution that bridges into public cloud providers so that they are basically one cloud everywhere, even on-prem.  Isn&amp;rsquo;t that insecure?&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;Just because there&amp;rsquo;s connectivity, it doesn&amp;rsquo;t mean that there are no
blast radius limitations.  After all, even for pure public cloud hosted
apps you&amp;rsquo;re going to need connectivity back to on-prem (eg via ExpressRoute
or DirectConnect or whatever) just because your cloud-hosted app will
need to talk to on-prem resources to function.  Your core processing and
orchestration systems may be on-prem and your app may have dependencies
on them.  Until you go 100% cloud there will be a requirement for
communication between on-prem and the cloud.&lt;/p&gt;

&lt;p&gt;How you limit your blast radius will depend on how far you want to go.&lt;/p&gt;

&lt;p&gt;For example, in AWS, you could use VPCs as a form of macro-segmentation,
and have an app per VPC.  For traffic to leave a VPC it has to traverse a
firewall where it is inspected and only authorised destinations (whether
that&amp;rsquo;s another VPC or on-prem or even the mainframe).  Azure provides
similar constructs.  You could consider this a &amp;ldquo;hub and spoke&amp;rdquo; model;
all communication between spokes has to go via the hub and this becomes
a good control point.&lt;/p&gt;

&lt;p&gt;This isn&amp;rsquo;t micro-segmentation, but it&amp;rsquo;s probably better than most
traditional datacenters which tend to focus on North-South traffic
(web-&amp;gt;app-&amp;gt;DB) rather than East-West (app-&amp;gt;app).  The IaC nature of
clouds allows for you to programmatically control both types of
traffic!&lt;/p&gt;

&lt;p&gt;With the right type of control plane I can see creating an app environment
on-prem (with VMware) or in AWS or in Azure &lt;em&gt;the same way&lt;/em&gt; and defining
the ingress/egress controls to limit their exposure.  Essentially you can
treat the CSP as a separate availability zone, potentially with custom
resources.  This is what PaaS (eg CloudFoundry) promised.&lt;/p&gt;

&lt;p&gt;So you breach into my b0rken Apache Struts app&amp;hellip; you can&amp;rsquo;t get to Jenkins
to infiltrate my CI/CD pipeline (hi, Solarwinds!) &amp;lsquo;cos you don&amp;rsquo;t have
connectivity!&lt;/p&gt;

&lt;p&gt;Of course you still need your traditional &lt;a href=&#34;https://www.sweharris.org/post/2021-05-06-dlp/&#34;&gt;border controls&lt;/a&gt;, such as WAF, IDS/IPS, DLP between your cloud hosted environment and
the internet.&lt;/p&gt;

&lt;p&gt;A breach at the CSP level gets interesting, but the attacker then has
different challenges.  They might be able to jump into a VM by attacking
the hypervisor, but then they still have the traffic restrictions.  If
they try to bypass the firewalls then they&amp;rsquo;ve got to somehow inject into
the overlay network constructs&amp;hellip; not practical!&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Done correctly (ah, that&amp;rsquo;s the challenge!) a hybrid cloud need not be insecure.  The
risk is equivalent (if not less) than your traditional zoned datacenter.
Especially if you are just single-cloud; again multi-cloud means you have
to build these controls multiple times in different ways!&lt;/p&gt;

&lt;p&gt;Of course I&amp;rsquo;ve just looked at this from an InfoSec perspective.  There are
other business reasons to look at multi-cloud.&lt;/p&gt;

&lt;p&gt;What happens if your cloud
providers decides to compete in your market space (Amazon are looking at
providing financial services; Walmart won&amp;rsquo;t work with AWS)?&lt;/p&gt;

&lt;p&gt;What happens
if your cloud provider decides it&amp;rsquo;s not &lt;a href=&#34;https://www.itpro.com/cloud/cloud-computing/362121/google-cloud-reports-31bn-annual-losses&#34;&gt;financial viable&lt;/a&gt;
to provide a service due to losses?&lt;/p&gt;

&lt;p&gt;What if your
provider has a &lt;a href=&#34;https://msrc-blog.microsoft.com/2021/09/08/coordinated-disclosure-of-vulnerability-in-azure-container-instances-service/&#34;&gt;security issue&lt;/a&gt; and
an attacker exploits it (fortunately didn&amp;rsquo;t happen here)?&lt;/p&gt;

&lt;p&gt;From a security perspective,
I wish I was single-cloud!  Then I could focus on that.  Multi-cloud
makes everything much harder.&lt;/p&gt;

&lt;p&gt;Hey, I said I had opinions!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Using SSH certificates - revisited</title>
      <link>https://www.sweharris.org/post/2022-02-06-ssh-certs-again/</link>
      <pubDate>Sun, 06 Feb 2022 15:14:30 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2022-02-06-ssh-certs-again/</guid>
      <description>

&lt;p&gt;A &lt;a href=&#34;https://www.sweharris.org/post/2016-10-30-ssh-certs/&#34;&gt;while back&lt;/a&gt; I wrote about some basic usage
of SSH certificates as an authentication system.  I only described the
core, but the comments went into some further detail.&lt;/p&gt;

&lt;p&gt;I thought it time to write a follow up post describing some of the more
advanced features.&lt;/p&gt;

&lt;h2 id=&#34;quick-recap&#34;&gt;Quick recap&lt;/h2&gt;

&lt;p&gt;To handle cert based authentication you need a CA certificate.  This is
created with the &lt;code&gt;ssh-keygen&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;e.g.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ mkdir ssh-ca
$ cd ssh-ca
$ ssh-keygen -f server_ca
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Server certificates are similarly signed with the same command.&lt;/p&gt;

&lt;p&gt;e.g.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo ssh-keygen -s server_ca -I key_for_test1 -h -n test1.spuddy.org -V +52w /etc/ssh/ssh_host_rsa_key.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;More details on this are available at the original post.&lt;/p&gt;

&lt;h2 id=&#34;checking-the-certificate-details&#34;&gt;Checking the certificate details.&lt;/h2&gt;

&lt;p&gt;We can look at the certificate, again with &lt;code&gt;ssh-keygen&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh-keygen -L -f /etc/ssh/ssh_host_rsa_key-cert.pub
/etc/ssh/ssh_host_rsa_key-cert.pub:
        Type: ssh-rsa-cert-v01@openssh.com host certificate
        Public key: RSA-CERT SHA256:ggTP5Bg7d74kmK+g+g8KVNizhmEz7ilCmO41GPRRVag
        Signing CA: RSA SHA256:9Uu2dQc6N4hgwv5Yz/UVU+fJfUTJzShQ0i4LdU7owEU
        Key ID: &amp;quot;key_for_test1&amp;quot;
        Serial: 0
        Valid: from 2022-02-06T15:08:00 to 2023-02-05T15:09:50
        Principals: 
                test1.spuddy.org
        Critical Options: (none)
        Extensions: (none)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can see the &lt;code&gt;Key ID&lt;/code&gt; values matches the &lt;code&gt;-I&lt;/code&gt; parameter used on the
signing command, the principal name is the hostname, and the validity
period is 52 weeks.&lt;/p&gt;

&lt;h2 id=&#34;user-certificates&#34;&gt;User certificates&lt;/h2&gt;

&lt;p&gt;This is where we start to go deeper.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s sign a user key the same way as we did before, and then look at
it.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh-keygen -s ssh-ca/server_ca -I user_sweh -n sweh -V +52w .ssh/id_rsa.pub
Signed user key .ssh/id_rsa-cert.pub: id &amp;quot;user_sweh&amp;quot; serial 0 for sweh valid from 2022-02-06T15:37:00 to 2023-02-05T15:38:31

$ ssh-keygen -L -f .ssh/id_rsa-cert.pub
.ssh/id_rsa-cert.pub:
        Type: ssh-rsa-cert-v01@openssh.com user certificate
        Public key: RSA-CERT SHA256:W+cq9v38nF6h1Wlse45h0qizmybkkj0J4Yh820ihG7A
        Signing CA: RSA SHA256:9Uu2dQc6N4hgwv5Yz/UVU+fJfUTJzShQ0i4LdU7owEU
        Key ID: &amp;quot;user_sweh&amp;quot;
        Serial: 0
        Valid: from 2022-02-06T15:37:00 to 2023-02-05T15:38:31
        Principals: 
                sweh
        Critical Options: (none)
        Extensions: 
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;rsquo;s interesting to note that &amp;ldquo;Principals&amp;rdquo; implies we can list more than
one principal (the &lt;code&gt;-n&lt;/code&gt; option).  &amp;ldquo;Extensions&amp;rdquo; is also interesting.&lt;/p&gt;

&lt;h2 id=&#34;principals&#34;&gt;Principals&lt;/h2&gt;

&lt;h3 id=&#34;generating-a-certificate-with-multiple-principals&#34;&gt;Generating a certificate with multiple principals.&lt;/h3&gt;

&lt;p&gt;This is done by specifying each principal separated by a comma.  In a general
corporate environment, with Active Directory, it might be worth generating
certificates with the &lt;code&gt;sAMAccountName&lt;/code&gt; and &lt;code&gt;UserPrincipalName&lt;/code&gt; values.
Typically that&amp;rsquo;ll be a short name and an email address.  So, for example,&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh-keygen -s ssh-ca/server_ca -I user_sweh -n sweh,sweh@sweharris.org -V +52w .ssh/id_rsa.pub
Signed user key .ssh/id_rsa-cert.pub: id &amp;quot;user_sweh&amp;quot; serial 0 for sweh,sweh@sweharris.org valid from 2022-02-06T15:46:00 to 2023-02-05T15:47:10

$ ssh-keygen -L -f .ssh/id_rsa-cert.pub
.ssh/id_rsa-cert.pub:
        Type: ssh-rsa-cert-v01@openssh.com user certificate
        Public key: RSA-CERT SHA256:W+cq9v38nF6h1Wlse45h0qizmybkkj0J4Yh820ihG7A
        Signing CA: RSA SHA256:9Uu2dQc6N4hgwv5Yz/UVU+fJfUTJzShQ0i4LdU7owEU
        Key ID: &amp;quot;user_sweh&amp;quot;
        Serial: 0
        Valid: from 2022-02-06T15:46:00 to 2023-02-05T15:47:10
        Principals: 
                sweh
                sweh@sweharris.org
        Critical Options: (none)
        Extensions: 
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;using-principals&#34;&gt;Using principals&lt;/h3&gt;

&lt;p&gt;In the default case, sshd tries to match the principal name to the
username being logged into.  This really works well most of the time;
if I want to login as &lt;code&gt;sweh&lt;/code&gt; and my certificate has &lt;code&gt;sweh&lt;/code&gt; as the
principal then it&amp;rsquo;ll let me in.&lt;/p&gt;

&lt;p&gt;This is not so good if you&amp;rsquo;re trying to access a system, service, or
shared account.  e.g. &lt;code&gt;root&lt;/code&gt; or (on AWS) &lt;code&gt;ec2-user&lt;/code&gt;, or &lt;code&gt;oracle&lt;/code&gt; or&amp;hellip;&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Side note: I don&amp;rsquo;t generally recommend logging in as these types of
account directly.  I prefer people to login as themselves and then use
privilege escalation tools such as &lt;code&gt;sudo&lt;/code&gt; to provide a stronger audit trail
of &lt;em&gt;who&lt;/em&gt; has done &lt;em&gt;what&lt;/em&gt;.  If 3 people have all logged in as &lt;code&gt;root&lt;/code&gt; and
the server gets rebooted, how do you know who did it?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is where we can use an option in &lt;code&gt;sshd_config&lt;/code&gt; that&amp;rsquo;s normally
disabled; &lt;code&gt;AuthorizedPrincipalsFile&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;e.g.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here we can list the principals allow to access an account:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo cat /etc/ssh/auth_principals/ec2-user
testuser@sweharris.org
sweh@sweharris.org
$ ssh ec2-user@test1.spuddy.org id
uid=1000(ec2-user) gid=1000(ec2-user) groups=1000(ec2-user)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and looking at the logs&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Feb  6 16:09:23 test1 sshd[8160]: Accepted publickey for ec2-user from 10.0.0.158 port 34974 ssh2: RSA-CERT ID user_sweh (serial 0) CA RSA SHA256:9Uu2dQc6N4hgwv5Yz/UVU+fJfUTJzShQ0i4LdU7owEU
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;roles-as-principals&#34;&gt;Roles as principals&lt;/h3&gt;

&lt;p&gt;This gets hard to manage at scale.  If you have thousands of machines then
you may not want to list every possible sysadmin on every machine.  Instead
you could create a &lt;em&gt;role&lt;/em&gt; name, such as &lt;code&gt;sysadmin&lt;/code&gt; and your signing tool can
add this to the to user certificate.  eg sweh,sweh@sweharris.org,sysadmin.
Now the &lt;code&gt;AuthorizedPrincipalsFile&lt;/code&gt; only needs to list &lt;code&gt;sysadmin&lt;/code&gt; and
anyone who has that listed will be able to have access.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s recommended that if you use role based principals then the validity
is reduced (eg 90 days) to help enforce that when someone transfers to
a new department then their roles will be removed within a reasonable
period.  Using &lt;code&gt;@revoked&lt;/code&gt; and maintaining a CRL may also be useful to
ensure certificates can no longer be used.&lt;/p&gt;

&lt;h3 id=&#34;more-dynamic&#34;&gt;More dynamic&lt;/h3&gt;

&lt;p&gt;A larger enterprise may wish to use &lt;code&gt;AuthorizedPrincipalsCommand&lt;/code&gt; instead
of a fixed file.  This could do a dynamic lookup (e.g. in LDAP or an
API call) to generate a list of acceptable principals.  This could allow
for real-time evaluation (&amp;ldquo;Who is allowed to login as ec2-user on host
test1?&amp;ldquo;).  Such a process would handle leaver/transfer handling (&amp;ldquo;Stephen
is no longer a sysadmin; Fred left the company; John has become a DBA&amp;rdquo;)
without needing to revoke certificates or require re-signed certificates.&lt;/p&gt;

&lt;h2 id=&#34;extensions&#34;&gt;Extensions&lt;/h2&gt;

&lt;p&gt;Thus far we&amp;rsquo;ve just talked about who can login to a server as a specific
user (&amp;ldquo;Stephen can login as ec2-user&amp;rdquo;).  With extensions we can be a
little more fine grained.&lt;/p&gt;

&lt;p&gt;By default the following are permitted:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        Extensions: 
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This can be changed on the &lt;code&gt;ssh-keygen&lt;/code&gt; line with the &lt;code&gt;-O&lt;/code&gt; option.  e.g. to
remove all the &amp;ldquo;permit&amp;rdquo; options can we can use the &lt;code&gt;clear&lt;/code&gt; value&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh-keygen -s ssh-ca/server_ca -O clear -I user_sweh -n sweh,sweh@sweharris.org -V +52w .ssh/id_rsa.pub
Signed user key .ssh/id_rsa-cert.pub: id &amp;quot;user_sweh&amp;quot; serial 0 for sweh,sweh@sweharris.org valid from 2022-02-06T16:44:00 to 2023-02-05T16:45:52
$ ssh-keygen -L -f .ssh/id_rsa-cert.pub
.ssh/id_rsa-cert.pub:
        Type: ssh-rsa-cert-v01@openssh.com user certificate
        Public key: RSA-CERT SHA256:W+cq9v38nF6h1Wlse45h0qizmybkkj0J4Yh820ihG7A
        Signing CA: RSA SHA256:9Uu2dQc6N4hgwv5Yz/UVU+fJfUTJzShQ0i4LdU7owEU
        Key ID: &amp;quot;user_sweh&amp;quot;
        Serial: 0
        Valid: from 2022-02-06T16:44:00 to 2023-02-05T16:45:52
        Principals: 
                sweh
                sweh@sweharris.org
        Critical Options: (none)
        Extensions: (none)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can also specify things like &lt;code&gt;force-command&lt;/code&gt; (matching what we can put
into &lt;code&gt;authorized_keys&lt;/code&gt;).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh-keygen -s ssh-ca/server_ca -O clear -O force-command=&amp;quot;/usr/bin/id&amp;quot; -I user_sweh -n sweh,sweh@sweharris.org -V +52w .ssh/id_rsa.pub
Signed user key .ssh/id_rsa-cert.pub: id &amp;quot;user_sweh&amp;quot; serial 0 for sweh,sweh@sweharris.org valid from 2022-02-06T16:47:00 to 2023-02-05T16:48:06
$ ssh-keygen -L -f .ssh/id_rsa-cert.pub                                       
.ssh/id_rsa-cert.pub:
        Type: ssh-rsa-cert-v01@openssh.com user certificate
        Public key: RSA-CERT SHA256:W+cq9v38nF6h1Wlse45h0qizmybkkj0J4Yh820ihG7A
        Signing CA: RSA SHA256:9Uu2dQc6N4hgwv5Yz/UVU+fJfUTJzShQ0i4LdU7owEU
        Key ID: &amp;quot;user_sweh&amp;quot;
        Serial: 0
        Valid: from 2022-02-06T16:47:00 to 2023-02-05T16:48:06
        Principals: 
                sweh
                sweh@sweharris.org
        Critical Options: 
                force-command /usr/bin/id
        Extensions: (none)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now if I try to use this certificate I can only run the one command&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh ec2-user@test1.spuddy.org cat /etc/passwd
uid=1000(ec2-user) gid=1000(ec2-user) groups=1000(ec2-user)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These extensions can let us lock down certificates pretty much as
tightly as the older private keys (&lt;code&gt;command&lt;/code&gt; and &lt;code&gt;from&lt;/code&gt; restrictions in
&lt;code&gt;authorized_keys&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;force-command&lt;/code&gt; and &lt;code&gt;source-address&lt;/code&gt; options are particularly useful
when performing app-to-app type communication.  These keys generally don&amp;rsquo;t
have a passphrase on them (since it&amp;rsquo;s automated) so have the ability
to let one server &lt;code&gt;scp&lt;/code&gt; a file to another without granting full shell
access and enforcing the server the connection came from is important.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;In a firewalled environment it&amp;rsquo;s worth thinking about always using
&lt;code&gt;-O clear&lt;/code&gt; to start with to prevent tunneling through firewalls.  I would
also add &lt;code&gt;-O no-user-rc&lt;/code&gt; since &lt;code&gt;~/.ssh/rc&lt;/code&gt; can be used to bypass restrictions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;SSH certificates have a lot of power to them.&lt;/p&gt;

&lt;p&gt;However they do require a good admin tool to manage them; to do the
signing, to add roles (if used), to add restrictions, remove permissions,
revoke keys and so on.  I try not to recommend tools in this blog (so
don&amp;rsquo;t ask!) but if you search the internet you&amp;rsquo;ll find a number of them,
both commercial and open-source.&lt;/p&gt;

&lt;p&gt;There are limitations with certificates (as with keys).  In particular,
we can&amp;rsquo;t enforce passphrase complexity (or indeed any passphrase at all!)
and we can&amp;rsquo;t &lt;em&gt;stop&lt;/em&gt; users from sharing keys.  Just because a key has an
identity &lt;code&gt;user_sweh&lt;/code&gt; doesn&amp;rsquo;t mean it was me who used it; I could have
shared it with Fred and John!  Some of this is education (we teach people
not to share passwords; we need to start teaching them not to share keys).
Some of this can also be mitigated by shorter durations for human owned
keys (if I need to get it re-signed every 90 days then it&amp;rsquo;s less likely
that a shared cert will be usable).&lt;/p&gt;

&lt;p&gt;But the ability to &lt;em&gt;centrally&lt;/em&gt; control the options on a key as part
of the signature (as opposed to relying on the correct settings in
&lt;code&gt;authorized_keys&lt;/code&gt;) is big, and allows for better auditing.&lt;/p&gt;

&lt;h2 id=&#34;special-thanks&#34;&gt;Special Thanks&lt;/h2&gt;

&lt;p&gt;I want to thank everyone who commented or emailed on the original post.
I learned from them and they got me digging deeper into certificate
capabilities.  Thank you!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>X-Forwarded-For and IP Allow-List</title>
      <link>https://www.sweharris.org/post/2021-10-13-x-forwarded-for/</link>
      <pubDate>Wed, 13 Oct 2021 16:45:31 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2021-10-13-x-forwarded-for/</guid>
      <description>

&lt;h2 id=&#34;what-is-ip-allow-listing&#34;&gt;What is IP Allow-Listing&lt;/h2&gt;

&lt;p&gt;Typically when you want to access a remote resource (e.g. login to
a server) you need to provide credentials.  It might be a simple
username/password, it could be via SSH keys, it could use Mutual TLS
with client-side certificates&amp;hellip; doesn&amp;rsquo;t really matter.&lt;/p&gt;

&lt;p&gt;One concern is &amp;ldquo;what happens if the credential is stolen&amp;rdquo;.  IP allow-listing
is a way of restricting where you can use that credential &lt;em&gt;from&lt;/em&gt;.  &amp;ldquo;You must
be coming from 66.228.55.57 in order to login as Stephen&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;This works quite well when restricting server-to-server communication, because
servers tend to have fixed addresses (human-to-server wasn&amp;rsquo;t so useful because
desktops or home ISP connection IP addresses may change frequently).  Well&amp;hellip;
servers &lt;em&gt;used&lt;/em&gt; to have static addresses, but in the modern cloudy world this
isn&amp;rsquo;t always true any more.  I jokingly call IP allow-listing a 20th Century
solution because of this.  However sometimes you still want to use it.&lt;/p&gt;

&lt;h2 id=&#34;it-s-simple-right&#34;&gt;It&amp;rsquo;s simple, right?&lt;/h2&gt;

&lt;p&gt;In the early days, servers would communicate directly with each other,
perhaps with a firewall in the middle&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/xff-client-fw-server.jpg&#34; alt=&#34;client server&#34;&gt;
&lt;/div&gt;


&lt;p&gt;In this model your server can see exactly the IP address of the client
machine (&amp;ldquo;Oh, you are 66.228.55.57; OK, I&amp;rsquo;ll let you login as Stephen&amp;rdquo;).&lt;/p&gt;

&lt;h2 id=&#34;nope&#34;&gt;Nope!&lt;/h2&gt;

&lt;p&gt;Unfortunately this type of design is not really secure or performant.  You
may have load balancers in the path; you may (should!) have WAFs in the path;
there may be proxy servers (on both the client and server side!).&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/xff-client-fw-waf-lb-server.jpg&#34; alt=&#34;client waf lb server&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Now your server only sees the IP address of the load balancer!  So we need
a solution for this.&lt;/p&gt;

&lt;h2 id=&#34;x-forwarded-for&#34;&gt;X-Forwarded-For&lt;/h2&gt;

&lt;p&gt;This is a de-facto header for https communications that can be added to the
request header.  So in the above diagram the WAF would add a header&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    X-Forwarded-For: 66.228.55.57
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The load balancer would then add an extra entry for the WAFs IP address&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    X-Forwarded-For: 66.228.55.57, 10.10.10.100
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So now your server can look at this header and determine the original
connection address.&lt;/p&gt;

&lt;h2 id=&#34;so-we-can-trust-the-left-most-entry&#34;&gt;So we can trust the left-most entry?&lt;/h2&gt;

&lt;p&gt;Unfortunately not.  If the client had their own &lt;code&gt;X-Forward-For&lt;/code&gt; header then
this would appear first&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    X-Forwarded-For: &amp;lt;client_values&amp;gt;, 66.228.55.57, 10.10.10.100
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This might legitimately happen if the client was sitting behind a proxy server&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/xff-client-proxy-fw-waf-lb-server.jpg&#34; alt=&#34;client proxy waf lb server&#34;&gt;
&lt;/div&gt;


&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    X-Forwarded-For: 192.168.100.42, 66.228.55.57, 10.10.10.100
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Worse, an &lt;em&gt;attacker&lt;/em&gt; could present their own values&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    X-Forwarded-For: &amp;lt;attacker_provided&amp;gt;, 66.228.55.57, 10.10.10.100
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And these fields may not be well-formatted resulting in a real mess.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    X-Forwarded-For: &amp;quot;ha ha I&#39;m, attacking, you, 66.228.55.57, 10.10.10.100
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;so-how-do-i-use-this-header&#34;&gt;So how do I use this header?&lt;/h2&gt;

&lt;p&gt;The first step is to &lt;em&gt;not&lt;/em&gt; use it, unless you need it.  If you&amp;rsquo;re in the
first scenario (server to server, e.g. inside your company, or via trusted
VPNs or fixed links to partner companies) where there is no WAF/LB in the
path then you &lt;em&gt;must not&lt;/em&gt; use the &lt;code&gt;X-Forward-For&lt;/code&gt; header; it&amp;rsquo;s not trustworthy.&lt;/p&gt;

&lt;p&gt;The next step is to start working from the right.  So we start with knowing
the load balancer is talking to us, and has presented the string&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    X-Forwarded-For: 192.168.100.42, 66.228.55.57, 10.10.10.100
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Hmm, we know &amp;ldquo;10.10.10.100&amp;rdquo; is the internal address of the WAF.  So we
ignore that.  Hmm, &amp;ldquo;66.228.55.57&amp;rdquo;?  Nope, that&amp;rsquo;s not one we know so we&amp;rsquo;ll
use that.  That&amp;rsquo;s the IP address we can use for allow-listing.&lt;/p&gt;

&lt;p&gt;This process works for a longer chain of trusted services; you might have
a kubernettes environment with Istio; the Istio gateway proxy may add
its own &lt;code&gt;X-Forward-For&lt;/code&gt; header.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    X-Forwarded-For: 192.168.100.42, 66.228.55.57, 10.10.10.100, 10.10.20.53
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we see the Load Balancer address, but the same parsing process still
works; start at the right and remove the addresses we know are ours.&lt;/p&gt;

&lt;p&gt;Remember, this string may be badly formatted so ensure whatever you&amp;rsquo;re using
to parse this line is robust!&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;IP Allow-listing may be considered a mitigating control for credential theft.
You can&amp;rsquo;t always use it because of cloudy infrastructure and dynamic
addresses.  And intermediate infrastructure such as WAFs and load balancers
make it harder to know the client IP address.  The &lt;code&gt;X-Forward-For&lt;/code&gt; header
is a solution to pass this information on, but you have to be careful how
you trust it!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Explaining technology as a story - TLS Certificates</title>
      <link>https://www.sweharris.org/post/2021-09-26-story-certificate/</link>
      <pubDate>Sun, 26 Sep 2021 16:11:30 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2021-09-26-story-certificate/</guid>
      <description>

&lt;p&gt;When people ask me something technical, I frequently find it useful to
tell the basics as a story or an analogy.  Obviously all these stories
have limitations to how accurate they can get, but it&amp;rsquo;s surprising how
well it gets people to understand what you mean.  So this post is part
of a series of &amp;ldquo;explaining technology as a story&amp;rdquo;&lt;/p&gt;

&lt;h2 id=&#34;tls-certificates&#34;&gt;TLS Certificates&lt;/h2&gt;

&lt;p&gt;One of the challenges, on the internet, is to know who you are talking
to.  If you&amp;rsquo;re about to enter your credit card details to Amazon then you
want to be sure you&amp;rsquo;re talking &lt;em&gt;to&lt;/em&gt; Amazon, and not someone pretending
to be.  Similarly if you want to login to your bank you need to be sure
you&amp;rsquo;re really talking to your bank.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;We also want to be sure no one is listening in; TLS handles both of this
but I&amp;rsquo;m only concerned around the &lt;em&gt;identity&lt;/em&gt; aspects.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;This isn&amp;rsquo;t a new problem and different solutions have been used over the
years.  Letters would be sealed with molten wax and stamped with a signet
ring.  As long as the letter was still sealed and the recipient recognized
the impression in the wax then there was a level of confidence that the
letter was authenticate.  Well&amp;hellip; unless the ring was stolen, or had been
duplicated, or some real clever person was able to open and reseal
the letter with no evidence of tampering.&lt;/p&gt;

&lt;p&gt;On the Internet, a TLS certificate does the same thing.  Instead of a
wax seal impressed with a signet ring we have a cryptographic &lt;em&gt;signature&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&#34;what-is-identity&#34;&gt;What is identity?&lt;/h2&gt;

&lt;p&gt;Identity means different things to different people&amp;hellip;or computers.&lt;/p&gt;

&lt;p&gt;At one level it could be &amp;ldquo;I have gone to sweharris.org&amp;hellip; am I looking
at that site?&amp;ldquo;.  This is the lowest level of identity.  It doesn&amp;rsquo;t
tell you anything about &lt;em&gt;who&lt;/em&gt; is operating the web site.  It&amp;rsquo;s really
meant for the assurance that the site that came back was the site you
requested.  It won&amp;rsquo;t help you if you typed the wrong name, or clicked
on a link that &lt;em&gt;looked&lt;/em&gt; right but isn&amp;rsquo;t.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Hi, I&amp;rsquo;m sweharris.org and here&amp;rsquo;s my signature that proves it&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If this part doesn&amp;rsquo;t match then the browser will throw up a nasty
warning message to try and protect you.&lt;/p&gt;

&lt;p&gt;At another layer it could help identity the person or company or
runs the website.  This is meant to be for the human using the
web browser to be sure that when you go to a site you have a level of
trust that you know who is running it&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Hi, I&amp;rsquo;m sweharris.org, which is run by Stephen Harris and here&amp;rsquo;s my signature that proves it&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The browser can&amp;rsquo;t help so much with the &amp;ldquo;organisation&amp;rdquo; part of this;
that&amp;rsquo;s for the human to verify.  It&amp;rsquo;s not clear this is a big win
because of how it&amp;rsquo;s normally presented to the end-user.  Indeed some
browsers have stopped showing this &amp;ldquo;extended&amp;rdquo; identity at all.&lt;/p&gt;

&lt;p&gt;Both of these identities can be stored in a certificate.&lt;/p&gt;

&lt;h2 id=&#34;certificate-authorities&#34;&gt;Certificate Authorities&lt;/h2&gt;

&lt;p&gt;Now there&amp;rsquo;s no way you can recognise all the millions of &amp;ldquo;signet rings&amp;rdquo;
that would be needed.  Especially when they change yearly!  So, instead,
we have a smaller number of people we trust, and we get &lt;em&gt;them&lt;/em&gt; to sign it.
So really what the web site sends is something closer to&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Hi, I&amp;rsquo;m sweharris.org and here&amp;rsquo;s &lt;em&gt;Harry&amp;rsquo;s&lt;/em&gt; signature that proves it&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We call these trusted signers &amp;ldquo;Certificate Authorities&amp;rdquo;, frequently
abbreviated to CA.&lt;/p&gt;

&lt;h2 id=&#34;certificate-store&#34;&gt;Certificate Store&lt;/h2&gt;

&lt;p&gt;That all sounds well and good, but how do you know the CA is one that
can be trusted?&lt;/p&gt;

&lt;p&gt;This is one of the harder parts.  We still have hundreds of &amp;ldquo;signet rings&amp;rdquo;
that can be used to create signatures.   Fortunately your operating system
and browser handle most of this for you.  e.g. in Chrome on Linux I can
go to settings/Privacy and Security/Security/Manage Certificates
(chrome://settings/certificates) and then click on the &amp;ldquo;Authorities&amp;rdquo; tab).
There are over 70 organisations listed there, and many of those have
multiple &amp;ldquo;Root&amp;rdquo; certificates.&lt;/p&gt;

&lt;p&gt;So now it&amp;rsquo;s something like&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Hi, I&amp;rsquo;m sweharris.org and here&amp;rsquo;s Harry&amp;rsquo;s signature that proves it, and
you can check it&amp;rsquo;s a trusted signature in your CA Store&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can think of this CA store as a book of trusted people.  And you
can add your own CA Roots (it&amp;rsquo;s not uncommon for enterprises to have their
own internal CAs).  These will work the same as a public CA for trust
purposes.&lt;/p&gt;

&lt;p&gt;And you can even add a specific certificate, so now we have&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Hi, I&amp;rsquo;m YourServer.example.org and you can trust that because you &lt;em&gt;know&lt;/em&gt; me&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;intermediate-certs&#34;&gt;Intermediate Certs&lt;/h2&gt;

&lt;p&gt;Of course it&amp;rsquo;s never that simple.  For security reasons the CA Root
certs are rarely used to directly sign end certificates.  What really
happens is that the CA creates an &lt;em&gt;Intermediate&lt;/em&gt; certificate and this
is what is used to sign the end certificate.&lt;/p&gt;

&lt;p&gt;So now the conversation is really something like&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Hi, I&amp;rsquo;m sweharris.org and here&amp;rsquo;s &lt;em&gt;Fred&amp;rsquo;s&lt;/em&gt; signature that proves it, and
also here&amp;rsquo;s Fred&amp;rsquo;s proof of authenticity and &lt;em&gt;that&lt;/em&gt; has been signed by
Harry, and you can check Harry&amp;rsquo;s signature in your CA Store&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;This chain of trust can extend to multiple layers if necessary.  It&amp;rsquo;s
important that the server sends all these intermediates as a &amp;ldquo;chain&amp;rdquo;
so the client can follow the chain to a trusted root.&lt;/p&gt;

&lt;h2 id=&#34;that-s-a-lot-of-trust-can-we-trust-this-is-trustworthy&#34;&gt;That&amp;rsquo;s a lot of trust!  Can we trust this is trustworthy?&lt;/h2&gt;

&lt;p&gt;This is where it gets a little bit messy.  The main browser and CAs got
together and formed the &lt;a href=&#34;https://cabforum.org&#34;&gt;CAB Forum&lt;/a&gt;.  This is a
self-regulatory group that defined a set of rules that the CAs have to
follow.  If they don&amp;rsquo;t then the browsers will remove the Root CA and now
the CA customers certs won&amp;rsquo;t be trusted.&lt;/p&gt;

&lt;p&gt;Some of those rules are around how the CA verifies the customer is who
they say they are.  If I asked a CA for a signature claiming I was
www.google.com then they &lt;em&gt;should&lt;/em&gt; reject it because I can&amp;rsquo;t prove I
own that domain.&lt;/p&gt;

&lt;p&gt;Unfortunately with over 70 public Roots there&amp;rsquo;s a fair sized footprint
for an attacker to try and get one of them to mis-sign a certificate,
and some of the verification processes themselves depend on weak controls
such as DNS  (e.g. if I could compromise your DNS then I could create
a certificate and request a signature from a CA that trusts DNS).&lt;/p&gt;

&lt;p&gt;Since this is an &amp;ldquo;all or nothing&amp;rdquo; type scenario (&amp;ldquo;is there a chain of
trust back to &lt;em&gt;any&lt;/em&gt; Root in my CA Store?&amp;ldquo;) a compromise of one CA is
pretty bad.&lt;/p&gt;

&lt;p&gt;This is a recognized weakness of the current trust model, where
ultimate trust is out of the end-user control (basically concentrated
in the CABforum) and with weak processes.  But it works pretty well and
protects trillions of dollars per year in ecommerce globally.  I think
it&amp;rsquo;s good enough!&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s a lot more to certs than just identity assertion (a lot of
maths for one, along with public/private keys, renewal, multiple names,
wildcards, client side certs&amp;hellip;)  but I&amp;rsquo;m mostly focusing on the story
around verifying the identity of a server and how a typical browser does
the job.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Explaining technology as a story - DHCP</title>
      <link>https://www.sweharris.org/post/2021-08-29-story-dhcp/</link>
      <pubDate>Sun, 29 Aug 2021 08:38:21 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2021-08-29-story-dhcp/</guid>
      <description>

&lt;p&gt;When people ask me something technical, I frequently find it useful to
tell the basics as a story or an analogy.  Obviously all these stories
have limitations to how accurate they can get, but it&amp;rsquo;s surprising how
well it gets people to understand what you mean.  So this post is part
of a series of &amp;ldquo;explaining technology as a story&amp;rdquo;&lt;/p&gt;

&lt;h2 id=&#34;dhcp&#34;&gt;DHCP&lt;/h2&gt;

&lt;p&gt;For a machine to be able to talk over IP it, naturally, needs an IP address.
And that address needs to be unique on the local network.&lt;/p&gt;

&lt;p&gt;Now for small networks you might be able to do this by manually
configuring the address on each machine (e.g. on a home network you
might do something like &amp;ldquo;my desktop is 192.168.0.10; the printer is
192.168.0.11; the laptop is 192.168.0.11; the X-box is&amp;hellip;&amp;ldquo;).  You might
also want to do that if you have a bunch of servers where you need to
know the address.&lt;/p&gt;

&lt;p&gt;But this can be a pain, and it&amp;rsquo;s a lot of work to keep up.  Even in a
home environment do you really want to have to allocate everything?  Your
desktop, your laptop, your phone, your smart-TV, your DVR, your X-box,
your IoT light-switch, IoT bulbs&amp;hellip;  I look at stuff in my house with an
IP address and there&amp;rsquo;s a &lt;em&gt;lot&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So what we do is use DHCP (&amp;ldquo;Dynamic Host Configuration Protocol&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;When a machine is added to the network (e.g. plugged into to an ethernet
port, or connected to WiFi) the machine will send out a message, asking
for what IP address to use (&amp;ldquo;Who am I, on this network?&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;The process has been given the name DORA, after the four steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DISCOVER - the client calls out to the local network &amp;ldquo;Hey, can anyone tell
me what my address is?&amp;rdquo;&lt;/li&gt;
&lt;li&gt;OFFER - A DHCP server on the network sends a reply &amp;ldquo;Oh, hi!  If you like you can have address 192.168.0.100&amp;rdquo;&lt;/li&gt;
&lt;li&gt;REQUEST - The client tries to confirm this &amp;ldquo;Hey, server, is it OK if I use address 192.168.0.100?&amp;rdquo;&lt;/li&gt;
&lt;li&gt;ACKNOWLEDGE - The server responds. &amp;ldquo;Yep, that&amp;rsquo;s fine.  Oh, you might also want to know these are the details default route, and the DNS servers, and the time server and so on.  BTW, check back in no later than 3 hours later just in case this has changed&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this fails for any reason (maybe the DHCP server isn&amp;rsquo;t working, or
it doesn&amp;rsquo;t think there&amp;rsquo;s any free addresses) then the client will try
a few times and then give up.  At that point you might notice you get
no address or you might get an address in the 169.254.&lt;em&gt;.&lt;/em&gt; range (Windows,
for example, will use the 169.254 range).&lt;/p&gt;

&lt;p&gt;At roughly the &lt;em&gt;half&lt;/em&gt; the check back time the client will try to refresh
the values.  It does that by jumping straight to the REQUEST part; &amp;ldquo;Hey,
server, can I keep using this address?&amp;rdquo;  If everything is OK the server
will respond with its normal &amp;ldquo;That&amp;rsquo;s fine&amp;rdquo; response.  If the server
doesn&amp;rsquo;t like it then it might respond with a NAK (&amp;ldquo;No, that&amp;rsquo;s not good,
ask for a new address&amp;rdquo;) and the client will go back to the DISCOVER part.&lt;/p&gt;

&lt;p&gt;This refresh process is useful.  It allows the server to update the client
(eg if you changed your DNS servers, for example, the clients will eventually
pick up the change).  It also allows for the server to know if a client has
left the network, so it can re-use the address elsewhere.&lt;/p&gt;

&lt;h3 id=&#34;static-configuration-and-dynamic-dns&#34;&gt;Static configuration and Dynamic DNS&lt;/h3&gt;

&lt;p&gt;Many DHCP servers, including the one built into many home routers, allows
you to reserve addresses.  For example, in an office you might have a
printer on the same network as workstations.  While the workstations
can change address, the printer should always get the same one.  To do
this you would use the printer&amp;rsquo;s MAC address (this is the low level
address built into the ethernet or WiFi card) and associate it with a
fixed address.  Now at the OFFER state the DHCP server will always
respond with that address.&lt;/p&gt;

&lt;p&gt;Now the REQUEST phase can be a little more complicated.  When the client
is requesting an address it can include additional information, such as
&amp;ldquo;BTW, my name is &amp;lsquo;Stephens_Desktop&amp;rsquo;&amp;ldquo;.  The server can use this information
to update the DNS server&amp;rsquo;s configuration, so other machines can use the
name.  You don&amp;rsquo;t need to know what IP address a client received if the DNS
is automatically updated.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;In many offices desktop segments may have a Windows based DHCP and DNS
server, which are also hooked into Active Directory.  When a desktop
is rebooted or a laptop connected it will use the DHCP server to get
all the necessary details to talk on the network.&lt;/p&gt;

&lt;p&gt;This process is fundamentally the same as when you turn on your X-Box
at home, getting an address from your home router which typically has
DHCP and DNS servers built into it.&lt;/p&gt;

&lt;p&gt;Large or small deployments; DHCP is very common!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Explaining technology as a story - DNS</title>
      <link>https://www.sweharris.org/post/2021-08-21-story-dns/</link>
      <pubDate>Sat, 21 Aug 2021 08:35:52 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2021-08-21-story-dns/</guid>
      <description>

&lt;p&gt;When people ask me something technical, I frequently find it useful to
tell the basics as a story or an analogy.  Obviously all these stories
have limitations to how accurate they can get, but it&amp;rsquo;s surprising how
well it gets people to understand what you mean.  So this post is part
of a series of &amp;ldquo;explaining technology as a story&amp;rdquo;&lt;/p&gt;

&lt;h2 id=&#34;dns&#34;&gt;DNS&lt;/h2&gt;

&lt;p&gt;The internet basically runs on numbers (either IPv4 or IPv6).  When your
desktop connects to a server, or a web site, or pretty much anything then
it uses the IP address.  But humans prefer names; what is easier to
remember, &lt;code&gt;www.google.com&lt;/code&gt; or &lt;code&gt;2607:f8b0:4004:82f::2004&lt;/code&gt;?  DNS is
typically used to convert from the name to the number.&lt;/p&gt;

&lt;p&gt;In a way you can think of this like a phone book.  In the old days the
phone company would ship you a large book (or two; &amp;ldquo;white pages&amp;rdquo; and
&amp;ldquo;yellow pages&amp;rdquo;).  If you wanted to phone someone and didn&amp;rsquo;t know the
number then you&amp;rsquo;d look it up in the book and then dial the number.
You might even have your own personal phone book with entries like
&amp;ldquo;Mum and Dad&amp;rdquo;.  With a modern smart phones you can search your address book
for a name and the phone will be able to call them without you entering
the number.  This is what DNS does for the internet.&lt;/p&gt;

&lt;p&gt;But the internet is massive; you can&amp;rsquo;t ship a &amp;ldquo;white pages&amp;rdquo; equivalent
to every computer in the world.  So it needs some clever lookups.  So
we need something similar to a telephone operator (&amp;ldquo;Goose Island, Oregon,
please.  The number for Dr Robert Humes&amp;rdquo;).  We call these operators
a &amp;ldquo;DNS Server&amp;rdquo; or &amp;ldquo;DNS Recursive resolver&amp;rdquo;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Side note: In the early early days we &lt;em&gt;did&lt;/em&gt; have a white pages equivalent
called HOSTS.TXT.  But eventually the scale of the internet made it unfeasible.
It went away (much like the old phone books; I don&amp;rsquo;t think I&amp;rsquo;ve seen one for
a decade!) but remnants survive in &lt;code&gt;/etc/hosts&lt;/code&gt; or &lt;code&gt;c:\windows\system32\drivers\etc\hosts.txt&lt;/code&gt; and similar places.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now these DNS servers still don&amp;rsquo;t have a complete list of every address,
so they have to ask other people.&lt;/p&gt;

&lt;p&gt;Basically the server story goes like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I need to look up www.google.com.  Hmm, I don&amp;rsquo;t know that.&lt;/li&gt;
&lt;li&gt;Let&amp;rsquo;s see.  Do I know who to ask about google.com?  Nope!&lt;/li&gt;
&lt;li&gt;OK, what about com?  Can I ask someone there?  I don&amp;rsquo;t no!&lt;/li&gt;
&lt;li&gt;Hey, &amp;ldquo;DNS root&amp;rdquo;!  I know about you&amp;hellip; can you tell me who to ask about com?&lt;/li&gt;
&lt;li&gt;&amp;lt;gets answer back; writes it in a book&amp;gt;&lt;/li&gt;
&lt;li&gt;Hey, com server?  Can you tell me where google.com information can be found?&lt;/li&gt;
&lt;li&gt;&amp;lt;gets answer back; writes it in the book&amp;gt;&lt;/li&gt;
&lt;li&gt;Hey, google.com server?  Can you tell me about www.google.com?&lt;/li&gt;
&lt;li&gt;&amp;lt;gets answer; also writes &lt;em&gt;that&lt;/em&gt; in the book&amp;gt;&lt;/li&gt;
&lt;li&gt;Great!  I know the answer now.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is quite clever.  It means that each operator only needs to know
about things one level below it in the tree.  It doesn&amp;rsquo;t need to
know about everything.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/Simple-DNS.png&#34; alt=&#34;DNS tree&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Now each time something is written in the book the server also writes down
other information (e.g. when the entry was written, and how long to trust
it for).&lt;/p&gt;

&lt;p&gt;Next time someone asks the server for www.google.com it will look in the
book and see &amp;ldquo;hey, I just found that out 2 minutes ago; I still trust it,
and will return the same result&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;But what if someone then asks for maps.google.com?  The process gets
shortcutted&amp;hellip;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I need to look up maps.google.com.  Hmm, I don&amp;rsquo;t know that.&lt;/li&gt;
&lt;li&gt;Let&amp;rsquo;s see.  Do I know who to ask about google.com?  Yes!  I just looked that up a minute ago!&lt;/li&gt;
&lt;li&gt;Hey, google.com server?  Can you tell me about maps.google.com?&lt;/li&gt;
&lt;li&gt;&amp;lt;gets answer; puts that in the book&amp;gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To make things more efficient, your local machine may also keep a small
copy of the address book.  So when you lookup up www.google.com it will
remember it, and next time you want to go to www.google.com it will use
its local copy and not even ask the operator.  The &lt;em&gt;web browser&lt;/em&gt; itself
may even have an address book it keeps track of!&lt;/p&gt;

&lt;p&gt;All these address books have to know how old the entry is and how long
to trust it for.  This is called the &amp;ldquo;Time To Live&amp;rdquo; (TTL).  After an
entry is older than the TTL then we should basically forget what we
knew and ask for new data.  This is how changes eventually make it
across the internet so if a server moves to a new address &lt;em&gt;eventually&lt;/em&gt;
everyone should get the new data.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;This story only reflects the barest basics of how DNS works (I haven&amp;rsquo;t
gone into resource types, signing, delegation, glue records, and so on)
and even this simplified version isn&amp;rsquo;t really accurate.  There&amp;rsquo;s lots of
edge cases in DNS; it&amp;rsquo;s really complicated!&lt;/p&gt;

&lt;p&gt;But I find this story acts as a starting point.&lt;/p&gt;

&lt;p&gt;Although I wonder how many people have even seen white/yellow pages
outside of a movie? :-)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Explaining technology as a story - Routing</title>
      <link>https://www.sweharris.org/post/2021-08-15-story-routing/</link>
      <pubDate>Sun, 15 Aug 2021 20:51:05 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2021-08-15-story-routing/</guid>
      <description>

&lt;p&gt;When people ask me something technical, I frequently find it useful to
tell the basics as a story or an analogy.  Obviously all these stories
have limitations to how accurate they can get, but it&amp;rsquo;s surprising how
well it gets people to understand what you mean.  So this post is part
of a series of &amp;ldquo;explaining technology as a story&amp;rdquo;&lt;/p&gt;

&lt;h2 id=&#34;routing&#34;&gt;Routing&lt;/h2&gt;

&lt;p&gt;Far too frequently there are internet routing issues.  Sometimes it gets
bad that a large fraction of people can&amp;rsquo;t work (e.g. can&amp;rsquo;t see the corporate
VPN gateways).  In a recent occurrence some of the people I
was chatting with didn&amp;rsquo;t understand what that really meant and why it
impacted some users, but not others.&lt;/p&gt;

&lt;p&gt;So I came up with a story about getting around town.&lt;/p&gt;

&lt;p&gt;Imagine you don&amp;rsquo;t know how to get to where you want to go.  All you
really know is your local street, and how to get to the end of it.
So what you do is go to that intersection, where you find a nice person.
They ask you where you want to go, and then tells you to turn left, or to
turn right, or to go straight on.  You go down that street until you get
to the next intersection and the same thing happens.  Eventually you&amp;rsquo;ll
get to your destination.&lt;/p&gt;

&lt;p&gt;Now some of these people directing you are pretty dumb; they just say &amp;ldquo;I
dunno, go that way and someone else will help you.&amp;rdquo;  But others have a lot
of information; they&amp;rsquo;ve got a big book of shortcuts and know a quick way.&lt;/p&gt;

&lt;p&gt;These books aren&amp;rsquo;t fixed; they get updated all the time.&lt;/p&gt;

&lt;p&gt;When there is a routing problem on the internet what has happened is that
some of these kind people have had instructions crossed out in their book.
Or worse, they may have received bad instructions and are sending you
the wrong way.&lt;/p&gt;

&lt;p&gt;Eventually the problem will be fixed and all these helpers will get their
books up to date.  But until then some people might be directed correctly,
other people might be sent the wrong way, and yet others might just be
told to give up; &amp;ldquo;you can&amp;rsquo;t get there from here!&amp;rdquo;&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Obviously in this story we&amp;rsquo;re talking about packets and routers,
and dynamic route updates (eg BGP).  And I haven&amp;rsquo;t gone into any of
the details.&lt;/p&gt;

&lt;p&gt;But I think this gets across the basics of routing!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Summary of my current Home Automation Setup</title>
      <link>https://www.sweharris.org/post/2021-08-08-home-automation/</link>
      <pubDate>Sun, 08 Aug 2021 18:52:08 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2021-08-08-home-automation/</guid>
      <description>

&lt;p&gt;I was asked to describe the stuff I use for my not-so-smart home and
how it fits together.  This was originally an email, but I figure other
people might find it interesting&lt;/p&gt;

&lt;p&gt;This is as complete as I can think!&lt;/p&gt;

&lt;p&gt;The goal, where possible, is to have everything under local control and
not dependent on the cloud.  Setup may require cloud&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;lights&#34;&gt;Lights&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Philips hue bulbs where possible (including the mirror light)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hue hub has a local API&lt;/li&gt;
&lt;li&gt;Mostly Hue White bulbs (LWB014), a couple of Hue White Ambience (LTA003)
and a mirror light (LWT018)&lt;/li&gt;
&lt;li&gt;Hue dimmer switches (RWL020) for normal &amp;ldquo;light switch&amp;rdquo; type control.&lt;/li&gt;
&lt;li&gt;Hue Motion Sensors (SML001) downstairs bathroom, laundry, attic&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Lutron Caseta switches elsewhere (eg for outside garden lights, fluorescent bulbs)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Really a cloudy service, but people have reverse engineered the
protocol to allow for local communications, at least for monitoring
and control.  Requires cloud to add new switches&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Smart switches (&lt;a href=&#34;https://www.amazon.com/gp/product/B079FDTG7T/&#34;&gt;https://www.amazon.com/gp/product/B079FDTG7T/&lt;/a&gt;)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;flashed with Tasmota firmware for local control&lt;/li&gt;
&lt;li&gt;The original firmware is chinese cloudy but Tasmota firmware replaces
this and provides local control via API or MQTT&lt;/li&gt;
&lt;li&gt;NOTE: Tasmota is not a supported firmware and newer revisions of the
switch may not be flashable!  Do research.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Ikea TRADFRI bulb 950lm&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is a Zigbee bulb and &lt;em&gt;can&lt;/em&gt; be added to the Hue Bridge.  It&amp;rsquo;s
a lot cheaper than Hue bulbs, but can&amp;rsquo;t be upgraded from the Hue
Bridge.&lt;/li&gt;
&lt;li&gt;Pairing isn&amp;rsquo;t always easy (it took me many attempts) and it
sometimes falls off the bridge and needs a power cycle.&lt;/li&gt;
&lt;li&gt;Doesn&amp;rsquo;t support the &amp;ldquo;on power failure/restore return the previous state&amp;rdquo;
function of Hue Bulbs.&lt;/li&gt;
&lt;li&gt;I wouldn&amp;rsquo;t consider these for bedrooms because of that.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;plugs&#34;&gt;Plugs:&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;TP-Link HS105&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Really cloudy (Kasa) but people have reverse engineered the protocol
for local control&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Generic (&lt;a href=&#34;https://www.amazon.com/gp/product/B07N1JPPXK/&#34;&gt;https://www.amazon.com/gp/product/B07N1JPPXK/&lt;/a&gt;)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flashed with Tasmota.  See previous warning!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Power sensing (&lt;a href=&#34;https://www.amazon.com/gp/product/B07LGSBFNJ/&#34;&gt;https://www.amazon.com/gp/product/B07LGSBFNJ/&lt;/a&gt;)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flashed with Tasmota.  See previous warning!&lt;/li&gt;
&lt;li&gt;I&amp;rsquo;m not sure these are accurate in what they report, but they&amp;rsquo;re
good enough to let me know when the washing machine or drier has
finished&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;thermostat&#34;&gt;Thermostat&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Radio Thermostat CT50 with Wireless module

&lt;ul&gt;
&lt;li&gt;I got this &amp;lsquo;cos it has full local control API&amp;hellip; but it&amp;rsquo;s not very
good; it seems like it only has a single-threaded CPU/OS so when it&amp;rsquo;s
busy doing one thing then it can&amp;rsquo;t handle another, so API calls
frequently get dropped.  It works, but I don&amp;rsquo;t recommend it.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;garage-door&#34;&gt;Garage Door&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Shelly-1 with magnetic reed switch.

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sweharris.org/post/2019-05-19-garage/&#34;&gt;https://www.sweharris.org/post/2019-05-19-garage/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;other&#34;&gt;Other&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Frigidaire Air Conditioner FGRC0644U1&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This isn&amp;rsquo;t a &lt;em&gt;bad&lt;/em&gt; aircon, but the mobile app isn&amp;rsquo;t the best.  It&amp;rsquo;s
totally cloudy with no local API.&lt;/li&gt;
&lt;li&gt;Has Alexa integration&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Toshiba Microwave ML-EM34P&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As a microwave it&amp;rsquo;s OK.  As a &lt;em&gt;smart&lt;/em&gt; microwave it&amp;rsquo;s pretty bad.&lt;/li&gt;
&lt;li&gt;Totally cloudy&lt;/li&gt;
&lt;li&gt;Alexa integration frequently breaks (so much so, I stopped using it)&lt;/li&gt;
&lt;li&gt;The MSSmartLife app on mobile device isn&amp;rsquo;t even working properly!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;home-grown-stuff&#34;&gt;Home Grown Stuff&lt;/h2&gt;

&lt;p&gt;Lots of things based around ESP8266/ESP32 with sketches I&amp;rsquo;ve written, to
either report information or try to turn dumb devices semi-smart&lt;br&gt;
eg&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sweharris/esp32-doorbell&#34;&gt;https://github.com/sweharris/esp32-doorbell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sweharris/esp8266-temperature&#34;&gt;https://github.com/sweharris/esp8266-temperature&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sweharris/esp8266-indicator&#34;&gt;https://github.com/sweharris/esp8266-indicator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sweharris/esp8266-bme280&#34;&gt;https://github.com/sweharris/esp8266-bme280&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sweharris/esp8266-aircon&#34;&gt;https://github.com/sweharris/esp8266-aircon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More complicated stuff:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/sweharris/huebridge-shell&#34;&gt;https://github.com/sweharris/huebridge-shell&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It presents a &amp;ldquo;fake Hue Bridge&amp;rdquo; which is good enough for Alexa to
discover.  The lights it presents are handled by scripts.  So if I
say &amp;ldquo;Alexa turn bluray on&amp;rdquo; then it will turn on the fake light called
&amp;ldquo;bluray&amp;rdquo; and my script will turn on the TV, turn on the BluRay player,
turn on the Denon receiver and switch it to BluRay input.  This is
also how I can control the Tasmota switches by voice.&lt;/li&gt;
&lt;li&gt;I run 3 copies of this!  One on my Mac for media player stuff, since
it also can control itunes; one on the Home Automation (HA) VM for
thermostat, aircon, tasmota devices, Garage Door; one on my desktop
Linux machine so I can turn the screen off.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/sweharris/Alexa-Smart-Home-VirtualButtons&#34;&gt;https://github.com/sweharris/Alexa-Smart-Home-VirtualButtons&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using Lambda functions to present fake &amp;ldquo;door sensors&amp;rdquo; to Alexa
which can be triggered via HTTP calls.  When these sensors trip
an Alexa routine can be triggered (eg say &amp;ldquo;Garage door is open&amp;rdquo;).&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;(unplublished) Media-API Alexa Skill&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&amp;ldquo;Alexa tell the robot &amp;hellip;&amp;rdquo;&lt;/li&gt;
&lt;li&gt;This is written in GoLang and runs on my Mac Mini media player and is mostly for
media control (&amp;ldquo;tell the robot to pause&amp;rdquo;).  It&amp;rsquo;ll work out the
current device (eg BluRay, or iTunes, or DVD Player App, etc) and send
the appropriate commands.  Also can be used for reporting (&amp;ldquo;ask the
robot what for temperature&amp;rdquo;) where it will query MQTT for current
values.  This is kinda parallel to all the home automation stuff.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;putting-it-all-together&#34;&gt;Putting it all together&lt;/h2&gt;

&lt;p&gt;A lot of this stuff communicates via MQTT, so I run Mosquitto MQTT
  server (&lt;a href=&#34;https://mosquitto.org/&#34;&gt;https://mosquitto.org/&lt;/a&gt;) on the HA VM.  Since I use CentOS 7
  for the VM, I just use the version in EPEL&lt;/p&gt;

&lt;p&gt;And then I run Home Assistant (&lt;a href=&#34;https://www.home-assistant.io/&#34;&gt;https://www.home-assistant.io/&lt;/a&gt;) in a Docker container on the
  HA VM.  This is what handles the coordination and triggers, as well as
  providing a dashboard.  It also provides a mobile app so I can control
  things from out of home, as well as receive notifications (eg my
  phone plays a noise when the garage door opens).  Talks to Hue, Caseta,
  TP-Link, MQTT directly without cloud requirements.  Can talk to the
  Frigidaire cloud via a third party integration.&lt;/p&gt;

&lt;p&gt;The Alexa Skill requires access from the internet so a firewall hole needs
  to be opened (in my case I had a webserver exposed, so I made it also act
  as a reverse proxy to send the request from external to internal).&lt;/p&gt;

&lt;p&gt;Home Assistant requires access from the internet if you want to use it
  out of home, so needs a firewall hole as well.  OR you can sign up for
  a cloud account and have them proxy the data.  I didn&amp;rsquo;t want cloud
  dependency.&lt;/p&gt;

&lt;h2 id=&#34;examples&#34;&gt;Examples:&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&amp;ldquo;Alexa open the garage doors&amp;rdquo;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alexa -&amp;gt; HueBridge-Shell -&amp;gt; Shelly 1&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Alexa announcing &amp;ldquo;Garage Door is open&amp;rdquo;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shelly 1 (reed switch) -&amp;gt; MQTT -&amp;gt; HA Automation -&amp;gt; VirtualButton -&amp;gt; Alexa Routine&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Walk into downstairs bathroom, light turns on&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Motion Sensor -&amp;gt; Philips Hue Bridge -&amp;gt; Light&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Turn on basement main light, second light over computers turn on&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Caseta -&amp;gt; HA Automation -&amp;gt; Caseta&lt;/li&gt;
&lt;li&gt;(this is how two unrelated switches can be put together to act as if
they are one)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Walk into laundry, Hue Bulbs turn on, fluorescent bulbs turn on&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Motion Sensor -&amp;gt; Philips Hue Bridge -&amp;gt; Light -&amp;gt;
HA Automation -&amp;gt; Lutron Caseta&lt;/li&gt;
&lt;li&gt;(an example how two different ecosystems can be put together)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Turn off Laundry lights with switch, Hue bulbs turn off&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Caseta -&amp;gt; HA Automation -&amp;gt; Philips Hue Bridge&lt;/li&gt;
&lt;li&gt;(another example of two different ecosystems)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&amp;ldquo;Alexa what&amp;rsquo;s the temperature&amp;rdquo;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alexa routine -&amp;gt; &amp;ldquo;ask the robot for temperature&amp;rdquo; -&amp;gt; Media-API&lt;/li&gt;
&lt;li&gt;(an example of how Alexa routines can now call skills)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&amp;ldquo;Alexa bedtime&amp;rdquo;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Turns off the media center, nearly all the lights, my Linux machine
monitor, the ground floor air-con; turns on the bedroom lights,
starts the bedroom Echo playing music&lt;/li&gt;
&lt;li&gt;Alexa routine -&amp;gt; Philips Hue Brige + Caseta + HueBridge Shell (all 3 copies) + &amp;hellip;&lt;/li&gt;
&lt;li&gt;(basically uses a lot of the stuff, all together in one routine!)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The current state of home automation involves a lot of patchwork and
kludges.  At least if you&amp;rsquo;re doing it on a budget!&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve got it working, and it&amp;rsquo;s pretty reliable.  But it&amp;rsquo;s not
totally hands free (I&amp;rsquo;d estimate maybe once a month I have to poke at
HA; less so once I got rid of the Alexa integration and wrote my own
VirtualButton skill).&lt;/p&gt;

&lt;p&gt;What I&amp;rsquo;ve done works for me.  And somehow the HA VM has gone from being
a test (&amp;ldquo;how does this work&amp;rdquo;) to part of my daily home experience.  It
does stuff in the background that I only realise if it breaks!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Making a doorbell semi-smart</title>
      <link>https://www.sweharris.org/post/2021-07-08-smart-doorbell/</link>
      <pubDate>Thu, 08 Jul 2021 20:04:31 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2021-07-08-smart-doorbell/</guid>
      <description>

&lt;p&gt;If you&amp;rsquo;re anything like me then you sometimes miss the doorbell ringing.&lt;/p&gt;

&lt;p&gt;It may be because you&amp;rsquo;re engrossed in a movie and the doorbell sound
doesn&amp;rsquo;t register.  Or you might be (in these COVID times) in a make shift
home-office with the door closed and an air-con blasting out.  Or you
may even be out of home.&lt;/p&gt;

&lt;p&gt;Can we add some home-automation smarts to a dumb doorbell?&lt;/p&gt;

&lt;h2 id=&#34;how-does-a-doorbell-work&#34;&gt;How does a doorbell work?&lt;/h2&gt;

&lt;p&gt;Your typical doorbell is powered by a transformer; maybe 16V AC.  Yes,
it&amp;rsquo;s an AC circuit.  This causes many complications for smart devices,
and even lighted doorbell switches (which need a diode to cause the light
to work!)&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Side note: A smart doorbell like a Ring needs to draw enough current to power the
smart electronics, but not enough to cause the doorbell to actually ring.
This is sometimes an art, given the sheer variety of doorbell chimes, so
it&amp;rsquo;s not uncommon to hear complaints of &amp;ldquo;buzzing&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is my transformer:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/doorbell_transformer.jpg&#34; alt=&#34;Transformer&#34;&gt;
&lt;/div&gt;


&lt;p&gt;But the doorbell circuit itself is pretty simple.  It&amp;rsquo;s a a simple
loop between the transformer and the chime with a button in the middle.
When you press the button the circuit is complete and the chime rings!&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/onebutton.png&#34; alt=&#34;One Button&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Now a number of houses have two doorbells.  They&amp;rsquo;re effectively two
independent circuits.  They share a common line to the transformer
but have different connections to the door chime.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/twobuttons.png&#34; alt=&#34;One Button&#34;&gt;
&lt;/div&gt;


&lt;p&gt;And at the door chime itself we can see how the three wires all
get together:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/doorchime_internal.jpg&#34; alt=&#34;Internals&#34;&gt;
&lt;/div&gt;


&lt;h2 id=&#34;measuring-this&#34;&gt;Measuring this&lt;/h2&gt;

&lt;p&gt;Now if this was a simple DC circuit then we could (with suitable
resistor dividers) just measure the voltage on the wire going from
the doorbell to the chime.  But it isn&amp;rsquo;t; it&amp;rsquo;s AC.  So we&amp;rsquo;re going
to have to be a little more clever.&lt;/p&gt;

&lt;p&gt;Fortunately there exist sensors that can measure &lt;em&gt;current&lt;/em&gt;.  There are
some that sit in the circuit, and there are some that can wrap around
a cable and use a &lt;a href=&#34;https://en.wikipedia.org/wiki/Hall_effect_sensor&#34;&gt;&amp;ldquo;hall effect&amp;rdquo;&lt;/a&gt; sensor to detect current flow.&lt;/p&gt;

&lt;p&gt;This latter is what I used.  The one I used looks a lot like this and
uses a &amp;ldquo;CT103C&amp;rdquo; sensor:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/ct103c.png&#34; alt=&#34;CT103C&#34;&gt;
&lt;/div&gt;


&lt;p&gt;This provides a small analogue signal that can be measured by a simple
sketch on an Arduino or similar.  Because I have two doorbells and wanted
WiFi this meant I needed an ESP32 (the ESP8266 I normally use only has
one ADC channel).&lt;/p&gt;

&lt;p&gt;The idea is that you put the wire from the doorbell to the chime through
the center hole and reconnect it to the chime.  Don&amp;rsquo;t put it on the common
wire to the transformer &amp;lsquo;cos then you won&amp;rsquo;t know what button was pressed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;In practice I found there wasn&amp;rsquo;t enough space inside the chime cover
to hold both sensors, so I used a simple extension wire to let it go
outside of the chime case.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can now do an &lt;code&gt;analogRead()&lt;/code&gt; on the pin.  Typically when the button
isn&amp;rsquo;t pressed you&amp;rsquo;ll see a value close to zero (it may be a little higher
if you have a lighted doorbell button).  But when you press the button
the value jumps a lot.  In my case it went to over 400.  This makes it
easy to detect a button push.&lt;/p&gt;

&lt;h2 id=&#34;other-considerations&#34;&gt;Other considerations&lt;/h2&gt;

&lt;p&gt;We also want to add a short &amp;ldquo;debounce&amp;rdquo; delay; this will stop &amp;ldquo;unclean&amp;rdquo;
press/release from triggering the event too quickly.  And, hey, we&amp;rsquo;ve all
seen that impatient person ringing the doorbell multiple times per second&amp;hellip;
we can stop that as well!&lt;/p&gt;

&lt;p&gt;Because of my home automation setup, I just made the ESP32 send a message
to my MQTT server.  The exact topic that will be used will depend on
the MAC address of the ESP32 used, but in general it will send a &amp;ldquo;pressed&amp;rdquo;
message&lt;/p&gt;

&lt;p&gt;The resulting sketch is &lt;a href=&#34;https://github.com/sweharris/esp32-doorbell&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;what-can-we-use-this-for&#34;&gt;What can we use this for?&lt;/h2&gt;

&lt;p&gt;In &lt;a href=&#34;https://www.home-assistant.io/&#34;&gt;Home Assistant&lt;/a&gt; we can set up
&lt;em&gt;automation&lt;/em&gt; tasks.   In the automation section, a setup such as&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;- alias: Back Doorbell
  initial_state: true
  trigger:
    - platform: mqtt
      topic: doorbell/123456/back_doorbell
      payload: &#39;pressed&#39;
  action:
    ....

- alias: Front Doorbell
  initial_state: true
  trigger:
    - platform: mqtt
      topic: doorbell/123456/front_doorbell
      payload: &#39;pressed&#39;
  action:
    ....
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;is sufficient.  We don&amp;rsquo;t need to create sensors, just have the automation
triggered directly.&lt;/p&gt;

&lt;p&gt;Now we can do anything that Home Assistant is configured for.&lt;/p&gt;

&lt;p&gt;If you use my &lt;a href=&#34;https://github.com/sweharris/Alexa-Smart-Home-VirtualButtons&#34;&gt;Alexa Virtual Buttons skill&lt;/a&gt; then you can have Alexa trigger anything it
controls (even speak &amp;ldquo;Back door bell pressed&amp;rdquo;).  Or you could have flash
lights (useful for deaf people).  Or if you have a smart TV then you
could pop up a message; e.g. with an LG OLED TV and my &lt;a href=&#34;https://github.com/sweharris/go-lgtv&#34;&gt;code fork&lt;/a&gt; you can do something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  action:
    - service: rest_command.alexa
      data:
        command: &amp;quot;pushcontactbyname&amp;quot;
        param1: &amp;quot;Front Door&amp;quot;
        param2: 0
    - service: shell_command.tv_toast
      data:
        message: &amp;quot;Front doorbell&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;as the action.  If you&amp;rsquo;re out of home you could have it send a text
message, or use the Home Assistant application to create a notification
(although they&amp;rsquo;re not so quick, sometimes!)&lt;/p&gt;

&lt;h3 id=&#34;logging&#34;&gt;Logging&lt;/h3&gt;

&lt;p&gt;Home Assistant also logs activity.  In the logbook you may see entries
such as&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Back Doorbell has been triggered by mqtt topic doorbell/123456/back_doorbell
6:59:19 PM - 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or if you&amp;rsquo;re into SQL&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;MariaDB [hass]&amp;gt; select time_fired,event_data from events where event_type=&#39;automation_triggered&#39; and event_data like &#39;%doorbell%mqtt topic%&#39;;
+----------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| time_fired                 | event_data                                                                                                                  |
+----------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| 2021-07-08 22:59:19.544307 | {&amp;quot;name&amp;quot;: &amp;quot;Back Doorbell&amp;quot;, &amp;quot;entity_id&amp;quot;: &amp;quot;automation.back_doorbell&amp;quot;, &amp;quot;source&amp;quot;: &amp;quot;mqtt topic doorbell/47C708/back_doorbell&amp;quot;}    |
| 2021-07-08 23:00:08.090737 | {&amp;quot;name&amp;quot;: &amp;quot;Front Doorbell&amp;quot;, &amp;quot;entity_id&amp;quot;: &amp;quot;automation.front_doorbell&amp;quot;, &amp;quot;source&amp;quot;: &amp;quot;mqtt topic doorbell/47C708/front_doorbell&amp;quot;} |
+----------------------------+-----------------------------------------------------------------------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You now have a record of every time your doorbell was pressed!&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;This isn&amp;rsquo;t a fully smart doorbell&amp;hellip; but it gets part way there, and isn&amp;rsquo;t
dependent on any cloud provider.  Local control!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Digital Safe version 2</title>
      <link>https://www.sweharris.org/post/2021-05-18-digital_safe_2/</link>
      <pubDate>Tue, 18 May 2021 16:12:56 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2021-05-18-digital_safe_2/</guid>
      <description>

&lt;p&gt;&lt;a href=&#34;https://www.sweharris.org/post/2017-10-09-digital_safe&#34;&gt;Previously&lt;/a&gt; I modified a cheap electric
safe to work with an Arduino, because the original controller board had
failed.&lt;/p&gt;

&lt;p&gt;But because my build skills aren&amp;rsquo;t the best, I kept getting serial port
issues, and more than once needed to get to the emergency key to open
the safe.&lt;/p&gt;

&lt;p&gt;At the same time someone asked me if the same design would work with
one of the real cheap ($30) safes on Amazon.&lt;/p&gt;

&lt;p&gt;So I wondered if I could do better.  This time using an ESP8266 board,
which provides WiFi access.  No serial ports, and the board can host
all the software.  A quick test of putting one inside the safe (powered
by a battery pack) showed only a small attenuation in the WiFi signal;
it was still strong enough to talk to the network.&lt;/p&gt;

&lt;p&gt;I had also been asked if some of the cheaper safes might be convertable.&lt;/p&gt;

&lt;h2 id=&#34;requirements&#34;&gt;Requirements&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.amazon.com/gp/product/B078MRD3RB/&#34;&gt;A cheap Safe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.amazon.com/gp/product/B07LCMNXTN&#34;&gt;An ESP-12E&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.amazon.com/gp/product/B07CTF1JVD&#34;&gt;RFP30N06LE&lt;/a&gt; MOSFET&lt;/li&gt;
&lt;li&gt;A 4.7kOhm resistor&lt;/li&gt;
&lt;li&gt;A N4004 Diode&lt;/li&gt;
&lt;li&gt;A board to solder it to&lt;/li&gt;
&lt;li&gt;Some wires and connectors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The MOSFET, diode and resistor aren&amp;rsquo;t size sensitive.  I just picked these ones &amp;lsquo;cos they felt right.  The important part is the MOSFET needs to trigger at
2V and be of N-channel type (to switch the -ve side of the circuit).&lt;/p&gt;

&lt;h2 id=&#34;the-safe&#34;&gt;The Safe&lt;/h2&gt;

&lt;p&gt;This is the safe I got.
It&amp;rsquo;s about $30 from Amazon.  The model I bought was &amp;lsquo;cos it was $2
cheaper, but there&amp;rsquo;s a lot of identical models on Amazon.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/original_safe.jpg&#34; alt=&#34;Original Safe&#34;&gt;
&lt;/div&gt;


&lt;p&gt;This is the inside of the safe.  The red button on the left is what you
would press to reset the combination.  But we&amp;rsquo;re interested in the
two screw holes.  A standard phillips head will let you remove these
two screws.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/inside_safe.jpg&#34; alt=&#34;Inside Safe&#34;&gt;
&lt;/div&gt;


&lt;p&gt;You also need to remove this screw.  At this point the cover can be
removed.  It&amp;rsquo;s a bit tight because of the rubber plug that&amp;rsquo;s there to
stop the door rattling, but a bit of brute force will get it out.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/door_screw.jpg&#34; alt=&#34;Door Screw&#34;&gt;
&lt;/div&gt;


&lt;p&gt;And this is what the internals look like.  The magic is the blue
solenoid.  In the &amp;ldquo;down&amp;rdquo; state it lets the locking gate slide sideways.
And that&amp;rsquo;s how this type of safe works; the key (as shown in this picture)
pushes down on the solenoid.  The electronic part activates the solenoid
and that lets the gate slide.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/internals.jpg&#34; alt=&#34;Internals&#34;&gt;
&lt;/div&gt;


&lt;p&gt;This is what it looks like in the locked position.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/solenoid_locked.jpg&#34; alt=&#34;Solenoid Locked&#34;&gt;
&lt;/div&gt;


&lt;p&gt;The only cable we care about is the two wired to the solenoid.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/original_wiring.jpg&#34; alt=&#34;Original Wiring&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Disconnect those from the board.  FWIW the other 4 wires handle the
power (red/black) and the reset button (white).  We don&amp;rsquo;t care about
these, though; we only want the two wires to the solenoid.  So carefully
unplug that cable.  That&amp;rsquo;s it!&lt;/p&gt;

&lt;p&gt;At this point we &lt;em&gt;could&lt;/em&gt; remove the circuit board, but let&amp;rsquo;s leave it
in place.  We can always revert the changes and switch the safe back to
normal operation just by plugging the cable back in again.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE:  This solenoid is especially easy to &amp;ldquo;bounce&amp;rdquo; by banging on the
safe; the spring is very weak. That means that the right timing of
banging on the top and turning the handle might open the safe.  This
isn&amp;rsquo;t high security!  (The key lock also isn&amp;rsquo;t high quality).  Increasing
the security of the safe isn&amp;rsquo;t part of this instruction!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Annoyingly it&amp;rsquo;s not clear what the solenoid is.  The blue wrapper blocks
all data.  So how much power does it need?  We know it can work on 6V
(&amp;lsquo;cos of the 4 batteries) but how much current does it need?  I measured
the resistance (15ohms).  At 6V that&amp;rsquo;d be around 400mA which made me
wonder if the Vin line of the NodeMCU would be sufficient.  And&amp;hellip;
it wasn&amp;rsquo;t.  It was enough to &lt;em&gt;hold&lt;/em&gt; the lock open but it wasn&amp;rsquo;t enough
to cause the solenoid to activate.  So we&amp;rsquo;re gonna need to be more
innovative about powering the system.&lt;/p&gt;

&lt;h2 id=&#34;designing-the-replacement-board&#34;&gt;Designing the replacement board&lt;/h2&gt;

&lt;p&gt;So let&amp;rsquo;s look at designing the replacement.&lt;/p&gt;

&lt;p&gt;For power, let&amp;rsquo;s use a MOSFET as a relay.  I used a RFP30N06LE because
this can be triggered at 2V and so the 3.3V output from the NodeMCU
should work.&lt;/p&gt;

&lt;p&gt;To make sure we have the order of the pins on the MOSFET right, looking
at the front (with the writing facing you and the pins downwards) the
3 pins are:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    Gate   Drain   Source
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Source will be connected to ground, drain will connect to the solenoid,
and gate will connect to the NodeMCU pin we use to trigger this.  The
other pin of the solenoid will connect to the power.  Now when the gate
line goes high the solenoid will trigger.&lt;/p&gt;

&lt;p&gt;Finally there&amp;rsquo;s a 4k7 resistor between gate and ground.  This is a
pull-down resistor just in case the ESP-12E pin floats.  It&amp;rsquo;s
possibly not needed, because the software drives the pin high or low
and if the software crashes then the watchdog timer will reboot it
pretty quickly, but I put it there just in case.&lt;/p&gt;

&lt;p&gt;That all sounds complicated!  Now to work out the best placement for a
veroboard so I can solder it all together.  Which appears to be:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/DigiSafe.png&#34; alt=&#34;Circuit Diagram&#34;&gt;
&lt;/div&gt;


&lt;p&gt;That doesn&amp;rsquo;t look &lt;em&gt;too&lt;/em&gt; complicated.  One diode, one resistor, one
MOSFET, a few cables, and some pins.&lt;/p&gt;

&lt;h2 id=&#34;prototype&#34;&gt;Prototype&lt;/h2&gt;

&lt;p&gt;So I prototyped this on protoboard.  This is powered by a 9V battery, which
won&amp;rsquo;t be the final solution!  I removed the solenoid from the safe to
make it easier to test.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/proof_of_concept.jpg&#34; alt=&#34;Proof Of Concept&#34;&gt;
&lt;/div&gt;


&lt;p&gt;(Note: there&amp;rsquo;s no diode here; I added it later!  And if you&amp;rsquo;re looking
carefully the resistor is in the wrong place.  Apparently I got lucky
and didn&amp;rsquo;t destroy the MOSFET&amp;hellip;  Also &lt;em&gt;shush&lt;/em&gt; spot the cable from D7
when the diagram says D6.  You didn&amp;rsquo;t see that!  How this prototype ever
worked&amp;hellip; I dunno!)&lt;/p&gt;

&lt;p&gt;In this setup I can do&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    curl http://safe.local/safe/?open=1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and the solenoid will open for 5 seconds.  And&amp;hellip; it worked!&lt;/p&gt;

&lt;p&gt;In this case I used a NodeMCU ESP-12E even though it&amp;rsquo;s overkill and
oversized.  You could use a WeMos D1 Mini or clone and it would work
just a well.  However the D1 Mini will only take 4-&amp;gt;6V input, whereas
the NodeMCU ESP-12E can take up to 10V (maybe even 12V).  That gives us
more flexibility in the power supply we use.  I did my testing with a
9V battery, which wouldn&amp;rsquo;t have been possible with the D1 Mini.&lt;/p&gt;

&lt;p&gt;Note that D6 on the ESP-12E &amp;ldquo;conveniently&amp;rdquo; lines up with the Gate on the
MOSFET.  Not like I planned that or anything, honest!  (Confession I had
planned on D7 being the pin but I counted wrong and D6 it is.  Which is why
the proof of concept used the wrong pin.  Oops!).&lt;/p&gt;

&lt;p&gt;Now I wanted to use a &amp;ldquo;socket&amp;rdquo; like approach for the ESP-12E so I could
remove it for software upgrades.  This just required 3 pins (GND, Vin, D6)
but I used 4 (the second GND) to add a bit of stability.  This turned out
to be one of the harder parts because I couldn&amp;rsquo;t find any single-pin
sockets that are big enough to handle the standard pins.  I ended up
cutting up a 40pin strip, and that&amp;rsquo;s not very tidy&amp;hellip; but it worked.&lt;/p&gt;

&lt;p&gt;(In the second of these boards that I made I used a couple of 8 pin strips
and cut the pins off and covered the gaps with insulation tape; that
also worked and was easier to handle).&lt;/p&gt;

&lt;p&gt;I also put a couple of normal pins on the board to make it easy to
connect to the solenoid via normal male-&amp;gt;female connector cables, and
I soldered relatively thick power cables that can be connected to the
power supply.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/the_board.jpg&#34; alt=&#34;The Board&#34;&gt;
&lt;/div&gt;


&lt;p&gt;(and yes the resistor is still in the wrong place!  but at least the
diode is there, now)&lt;/p&gt;

&lt;p&gt;And this is how it looks with the solenoid connected and the ESP-12E
inserted.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/the_board_with_esp.jpg&#34; alt=&#34;Board with ESP&#34;&gt;
&lt;/div&gt;


&lt;p&gt;My soldering skills still aren&amp;rsquo;t the best&amp;hellip; but, at least it works!&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/soldering.jpg&#34; alt=&#34;Bad Soldering&#34;&gt;
&lt;/div&gt;


&lt;h2 id=&#34;mounting&#34;&gt;Mounting&lt;/h2&gt;

&lt;p&gt;Unfortunately there&amp;rsquo;s not enough space inside the safe cover on this
small safe (the old large safe had plenty of free space) so now we get
to the mounting part.&lt;/p&gt;

&lt;p&gt;To run the solenoid cables from inside the safe cover to outside it I
cut a small hole near the top of the battery door.  Just big enough to
slide the two wires through.  This is the only real change to the safe.&lt;/p&gt;

&lt;p&gt;I connected two &amp;ldquo;dupont compatible&amp;rdquo; male-female cables to this connector.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/hole_for_solenoid.jpg&#34; alt=&#34;Hole for Solenoid Cable&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Mounting of the whole thing was&amp;hellip; done by duct tape.  Yeah not very
professional but it seems to work.&lt;/p&gt;

&lt;p&gt;Importantly I taped down the power wire so that it didn&amp;rsquo;t flex whenever
the door was opened/closed.  This means the wires shouldn&amp;rsquo;t snap off
the board.  Whenever movement happens it can stress solder joints, so
we want to prevent that as much as possible.  Let the tape take the
strain!&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/duct_tape_mount.jpg&#34; alt=&#34;Duct Tape&#34;&gt;
&lt;/div&gt;


&lt;p&gt;And the ESP-12E just slots in, nicely.  It&amp;rsquo;s easy to remove if software
updates are needed.  Just be careful to align the pins correctly when
you plug it in.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/mount_with_esp.jpg&#34; alt=&#34;Mounted Result&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Now the power cables can feed out of the back of the case.  I was worried
that the relatively thin metal could rub and end up damaging the cables
so I protected them with some more tape.  And I taped the wire to the top
edge of the box.  I didn&amp;rsquo;t do a very good job, really.  Not pretty&amp;hellip; but
it works!&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/power_cable_inside.jpg&#34; alt=&#34;Power Cable Inside&#34;&gt;
&lt;/div&gt;


&lt;p&gt;And then out of the back I added more tape to try and keep it in place.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/back_of_safe.jpg&#34; alt=&#34;Back Of Safe&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Powering this safe can be done pretty much from any DC power supply from
5V to 10V (maybe up to 12V).  I had a really old Blackberry power supply
(I never had a Blackberry, so not sure where I got it?  Maybe from a &amp;ldquo;junk&amp;rdquo;
bin at work).  This is 5V 700mA.  Plenty.  I cut the tip off and connected
the wires up.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s &lt;em&gt;very&lt;/em&gt; important to ensure you get the +ve side connected to the +ve
input to the board, because the ESP-12E may not like reverse voltages.  This
power supply didn&amp;rsquo;t make it obvious which wire was +ve so I had to use a
multi-meter.  But once I knew which was which it was simple to connect.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/power_supply.jpg&#34; alt=&#34;Power Supply&#34;&gt;
&lt;/div&gt;


&lt;p&gt;And to protect this also from movement I stuck it to the back.  Lots of
duct tape used in this build!&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/more_duct_tape.jpg&#34; alt=&#34;More Duct Tape&#34;&gt;
&lt;/div&gt;


&lt;p&gt;And that&amp;rsquo;s it!  The safe is built.&lt;/p&gt;

&lt;h2 id=&#34;software&#34;&gt;Software&lt;/h2&gt;

&lt;p&gt;Now we come to the &lt;a href=&#34;https://github.com/sweharris/digi-safe-v2&#34;&gt;software&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This software can be built with the standard Arduino tool set with the
esp8266 libraries loaded.  To make it simpler I embed the HTML inside the
code (as an include file) rather than using SPIFFS.  That way there&amp;rsquo;s just
one image to flash and not two.  The code is small enough that it still fits.&lt;/p&gt;

&lt;p&gt;The safe is modeled with some simple states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unlocked (no password set; safe can be opened any number of times)&lt;/li&gt;
&lt;li&gt;Unlocked once (safe can be opened once, then goes back to being locked)&lt;/li&gt;
&lt;li&gt;Locked (password is needed).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The solenoid lock is always kept in the locked position unless the &amp;ldquo;open&amp;rdquo;
function is selected.  Open can not be selected if the safe is Locked.&lt;/p&gt;

&lt;p&gt;When the safe software is first loaded it will create a WiFi Access Point
called something like &amp;ldquo;Safe-123456&amp;rdquo; (the exact name will depend on the
MAC address of your board).  You should connect your phone or
laptop to that access point.&lt;/p&gt;

&lt;p&gt;This will let you go to &lt;code&gt;http://192.168.4.1&lt;/code&gt; or (if you&amp;rsquo;re lucky)
&lt;code&gt;http://safe.local&lt;/code&gt; and that will display the WiFi configuration
screen.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/change_ap.png&#34; alt=&#34;Change AP&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Enter your WiFi SSID and password.  In 5 seconds the software will reboot
and the safe will connect to your local network.  It will attempt to get
an address by DHCP.&lt;/p&gt;

&lt;p&gt;If it is unable to connect to the network after 60 seconds then it will
give up and start up the Safe-123456 access point again and allow you to
change the network details and try again.&lt;/p&gt;

&lt;p&gt;Once the safe is on your network it will broadcast the name &amp;ldquo;safe.local&amp;rdquo;
via mDNS (aka zeroconf, Bonjour, Rendezvous).  If your machine supports
this then you should be able to go to &lt;a href=&#34;http://safe.local&#34;&gt;http://safe.local&lt;/a&gt; otherwise you may
need to check your router to find the IP address that was assigned to it.&lt;/p&gt;

&lt;p&gt;Opening the web page in a browser should give you a menu on the left and
a larger status box on the right.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/menu.png&#34; alt=&#34;Main Menu&#34;&gt;
&lt;/div&gt;


&lt;p&gt;The first thing you should do is go to the &amp;ldquo;Change Safe Authentication
Details&amp;rdquo; link at the bottom of the menu.  Here you can set a username
and password for your safe.  It&amp;rsquo;s recommended you do this so that only
authorised people on your network can reach this interface.  After setting
the password you should be prompted to login before doing any more work.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/set_auth.png&#34; alt=&#34;Set Authentication&#34;&gt;
&lt;/div&gt;


&lt;p&gt;On the main menu you will see various options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Status&amp;rdquo; will tell you if the safe is unlocked, locked, or one-time unlocked.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Open safe&amp;rdquo; lets you open the solenoid so the door can be opened.  This will
not work if the safe is locked.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Unlock pswd&amp;rdquo; has 3 options.  If you get the password wrong for any of
these then there is a 2 second delay before the safe will respond again.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&amp;ldquo;Test&amp;rdquo; - this will let you test the password but leave the safe locked.
This may be useful to use after setting a password so you can be sure you
can unlock it again, but before closing the door.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Unlock Once&amp;rdquo; - this will let you select the &amp;ldquo;Open Safe&amp;rdquo; function once.
After that the safe will go back to locked mode and you&amp;rsquo;ll need to re-enter
the password to unlock it again.  This is the normal function to emulate
the original safe.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Unlock Permanent&amp;rdquo; - this will remove the password totally and let you
use the &amp;ldquo;Open Safe&amp;rdquo; function as many times as you like.  This is similar
to pressing the &amp;ldquo;red button&amp;rdquo; inside the safe that lets you change the
combination.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Finally the &amp;ldquo;Lock Safe&amp;rdquo; function lets you set a new password for the safe.
This can only be done if the safe is unlocked.  If the safe is locked or
&amp;ldquo;unlock once&amp;rdquo; then it will be rejected.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note I&amp;rsquo;ve been saying &amp;ldquo;Password&amp;rdquo; and not combination.  That&amp;rsquo;s because
we&amp;rsquo;re not limited to numbers and we&amp;rsquo;re not limited to 8 digits.&lt;/p&gt;

&lt;p&gt;Passwords can be up to 100 characters long.  Although I&amp;rsquo;ve tested with a
few special characters (eg. % and &amp;amp;) you should verify the password with
the &amp;ldquo;Test password&amp;rdquo; function before closing the safe door!&lt;/p&gt;

&lt;h2 id=&#34;talking-to-the-safe-programmatically&#34;&gt;Talking to the safe programmatically&lt;/h2&gt;

&lt;p&gt;Although the software wasn&amp;rsquo;t designed to provide an API, all the access
is via HTTP requests and so can be performed from the command line
(eg curl).&lt;/p&gt;

&lt;p&gt;The format is&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    http://safe.local/safe/?command=1&amp;amp;amp;parameters...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;/?&lt;/code&gt; are important.&lt;/p&gt;

&lt;p&gt;Of course you need to provide the username and password.&lt;/p&gt;

&lt;p&gt;So, for example, to get the status:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    curl -u user:pass http://safe.local/safe/?status=1
    Safe is unlocked
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Commands you might use:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    ?open=1&amp;amp;duration=&amp;lt;time_in_seconds&amp;gt;
    ?lock=1&amp;amp;lock1=&amp;lt;pswd&amp;gt;&amp;amp;lock2=&amp;lt;pswd&amp;gt;
    ?pwtest=1&amp;amp;unlock=&amp;lt;pswd&amp;gt;
    ?unlock_1=1&amp;amp;unlock=&amp;lt;pswd&amp;gt;
    ?unlock_all=1&amp;amp;unlock=&amp;lt;pswd&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that &amp;ldquo;lock&amp;rdquo; needs the password sent twice &amp;lsquo;cos it checks the two
match.&lt;/p&gt;

&lt;p&gt;Now you might think &amp;ldquo;if I can send unlock_all requests in a program then
I can write a loop to test them all&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Yes&amp;hellip; but, good luck!  An 8 digit numeric password has 100,000,000
combinations.  Let&amp;rsquo;s assume you get it right half way through.  50,000,000
attempts.  Each attempt takes 2 seconds &amp;lsquo;cos the safe code enforces that.
That&amp;rsquo;s around 3 years.  And the password can be digits and letters and
more.  You might get lucky!  But don&amp;rsquo;t bet on it&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;And that&amp;rsquo;s it!&lt;/p&gt;

&lt;p&gt;These cheap safes can be converted in pretty much the same way as the
larger one.  I&amp;rsquo;m not sure what use these safes are, though, because
they&amp;rsquo;re not very secure.&lt;/p&gt;

&lt;p&gt;I think I&amp;rsquo;m gonna replace the Arduino/Relay board in my other safe with
another one of these ESP8266 based boards, though.  Should be a lot more
reliable than the old design, has less cables and isn&amp;rsquo;t chained to the
computer by a serial port!&lt;/p&gt;

&lt;h2 id=&#34;update-with-a-different-board&#34;&gt;Update with a different board&lt;/h2&gt;

&lt;p&gt;It&amp;rsquo;s been pointed out to me that &lt;a href=&#34;https://www.amazon.com/Ximimark-ESP8266-Network-Automatic-Protection/dp/B07KVSLMBN/&#34;&gt;ESP8266/Relay&lt;/a&gt; boards exist.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Safe_v2/esp8266-relay.jpg&#34; alt=&#34;Relay&#34;&gt;
&lt;/div&gt;


&lt;p&gt;On these boards the relay is typically connected to D4.  You&amp;rsquo;ll obviously
need a USB-&amp;gt;Serial (3.3V!) programmer to program this type of board since
they don&amp;rsquo;t come with their own serial interface.  But the sketches I
provide &lt;em&gt;should&lt;/em&gt; work with it with just the pin change.&lt;/p&gt;

&lt;p&gt;This is probably a easier option; no soldering necessary.  A little bit
more hassle to program the device, but a lot cleaner!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Using RSA and ECDSA on Apache with CentOS / RedHat</title>
      <link>https://www.sweharris.org/post/2021-05-08-ecdsa-certs/</link>
      <pubDate>Sat, 08 May 2021 17:25:57 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2021-05-08-ecdsa-certs/</guid>
      <description>

&lt;p&gt;&lt;a href=&#34;https://www.sweharris.org/post/2020-09-23-update-ssl/&#34;&gt;Previously&lt;/a&gt; I described a relatively modern
set of TLS settings that would give an A+ score on &lt;a href=&#34;https://ssllabs.com/ssltest/&#34;&gt;SSLtest&lt;/a&gt;.  This was based purely on an RSA certificate.&lt;/p&gt;

&lt;p&gt;There exist another type of certificate, based on Elliptical Curve cryptography.
You may see this referenced as ECC or, for web sites, ECDSA.  An ECDSA
certificate is smaller than an RSA cert (eg a 256bit ECDSA cert is roughly
the equivalent of a 3072bit RSA one).  This makes it quicker to send,
although at present RSA signatures are quicker to verify than ECDSA.&lt;/p&gt;

&lt;h2 id=&#34;my-setup&#34;&gt;My setup&lt;/h2&gt;

&lt;p&gt;I use &lt;a href=&#34;https://letsencrypt.org&#34;&gt;LetsEncrypt&lt;/a&gt; for my certificates, although
(for complicated reasons) I don&amp;rsquo;t use their standard &lt;code&gt;certbot&lt;/code&gt; client.
Instead I use &lt;a href=&#34;https://github.com/dehydrated-io/dehydrated&#34;&gt;Dehydrated&lt;/a&gt;.
I like this client because it just puts the certs into a directory and
then you can do whatever you like with them (in my case I use &lt;code&gt;ansible&lt;/code&gt;
to distribute to lots of different endpoints).&lt;/p&gt;

&lt;p&gt;The Dehydrated client also supports ECDSA certificates (indeed, in the
current version it defaults to &lt;code&gt;secp384r1&lt;/code&gt; to generate 384bit certs).&lt;/p&gt;

&lt;h2 id=&#34;configuring-dehydrated-for-both-cert-types&#34;&gt;Configuring Dehydrated for both cert types&lt;/h2&gt;

&lt;p&gt;I want to use both RSA and ECDSA certificates on this site but Dehydrated
can only handle one type at a time.  Fortunately it has a work around;
you can create a second certificate directory and have that override
the cert type.&lt;/p&gt;

&lt;p&gt;So in my case I configured the app to default to &lt;code&gt;rsa&lt;/code&gt; and then created
an override.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;   % cat domains.txt
   *.sweharris.org sweharris.org &amp;gt; sweharris
   *.sweharris.org sweharris.org &amp;gt; sweharris_ecdsa

   % grep KEY_ALGO config 
   KEY_ALGO=rsa

   % cat certs/sweharris_ecdsa/config 
   KEY_ALGO=&amp;quot;secp384r1&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this setup when I run the &amp;ldquo;refresh&amp;rdquo; command (&lt;code&gt;dehydrated -c&lt;/code&gt;) it
will place the RSA cert in the &lt;code&gt;sweharris&lt;/code&gt; directory and ECDSA cert in
the &lt;code&gt;sweharris_ecdsa&lt;/code&gt; directory:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;   % openssl x509 -noout -text -in certs/sweharris/cert.pem | grep Public.Key.Algo
               Public Key Algorithm: rsaEncryption

   % openssl x509 -noout -text -in certs/sweharris_ecdsa/cert.pem | grep Public.Key.Algo
               Public Key Algorithm: id-ecPublicKey
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Inside the &lt;code&gt;certs&lt;/code&gt; directory we will find four files of interest.  These
are always symbolic links to the latest version, so that provides a
consistent name for us to use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cert.pem&lt;br&gt;
This is the public key for the server certificate&lt;/li&gt;
&lt;li&gt;privkey.pem&lt;br&gt;
This is the private key for the server.&lt;/li&gt;
&lt;li&gt;chain.pem&lt;br&gt;
This file contains the &amp;ldquo;chaining&amp;rdquo; certificates needed to generate a chain
of trust to the root.&lt;/li&gt;
&lt;li&gt;fullchain.pem&lt;br&gt;
This file contains the chaining certificates &lt;em&gt;and&lt;/em&gt; the server public key.
Sometimes this can be easier to use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We&amp;rsquo;ll see, next, how these files are used.&lt;/p&gt;

&lt;h2 id=&#34;configuring-apache&#34;&gt;Configuring Apache&lt;/h2&gt;

&lt;p&gt;I have two primary server types in my environment.  They&amp;rsquo;re either based
on CentOS 7 or CentOS 8.  The configuration is &lt;em&gt;slightly&lt;/em&gt; different.&lt;/p&gt;

&lt;h3 id=&#34;the-certificates&#34;&gt;The certificates&lt;/h3&gt;

&lt;p&gt;For CentOS 8 it&amp;rsquo;s pretty simple, we can use the full chain file:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;   SSLCertificateFile    /etc/httpd/conf/sweharris/fullchain.pem
   SSLCertificateKeyFile /etc/httpd/conf/sweharris/privkey.pem

   SSLCertificateFile    /etc/httpd/conf/sweharris_ecdsa/fullchain.pem
   SSLCertificateKeyFile /etc/httpd/conf/sweharris_ecdsa/privkey.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now if you try that on CentOS 7 it &lt;em&gt;seems&lt;/em&gt; to work, but SSLtest complains
about missing chain certificates and small DH key sizes.  Not sure why
that happens.  But fortunately we can use a slightly different path&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;   SSLCertificateFile /etc/httpd/conf/sweharris/cert.pem
   SSLCertificateKeyFile /etc/httpd/conf/sweharris/privkey.pem

   SSLCertificateFile /etc/httpd/conf/sweharris_ecdsa/cert.pem
   SSLCertificateKeyFile /etc/httpd/conf/sweharris_ecdsa/privkey.pem

   SSLCertificateChainFile /etc/httpd/conf/sweharris/chain.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This works because both certs are signed by LetsEncrypt via the same chain
(same intermediate, same root).  If that wasn&amp;rsquo;t the case then we&amp;rsquo;d need
to work a little harder to ensure the chain file had everything that was
necessary.&lt;/p&gt;

&lt;h3 id=&#34;the-ciphers&#34;&gt;The ciphers&lt;/h3&gt;

&lt;p&gt;The previous cipher list I provided only selected RSA options; after all,
why bother with ECDSA options if you don&amp;rsquo;t have the right certificate?
But now we do.  As with the RSA certificates there&amp;rsquo;s a small number
that can be considered &amp;ldquo;strong&amp;rdquo;.  Indeed, we&amp;rsquo;ll stick with two&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;   ECDHE-ECDSA-AES256-GCM-SHA384
   ECDHE-ECDSA-AES128-GCM-SHA256
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There &lt;em&gt;are&lt;/em&gt; others which maybe considered (e.g. CHACHA-POLY based),
but I don&amp;rsquo;t believe the oldish versions of openssl on CentOS currently
support them.&lt;/p&gt;

&lt;p&gt;This results in a cipher suite configuration of:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;   SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You may notice that i no longer have &lt;code&gt;DHE-RSA-AES256-GCM-SHA384&lt;/code&gt; listed as
a cipher, but I &lt;em&gt;still&lt;/em&gt; have a couple of CBC based ones there.&lt;/p&gt;

&lt;p&gt;The CBC ciphers are still needed because, as we previously saw, older
versions of Safari need them, and these old versions don&amp;rsquo;t work with
ECDSA&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;   Safari 6 / iOS 6.0.1
   Safari 7 / iOS 7.1
   Safari 7 / OS X 10.9
   Safari 8 / iOS 8.4
   Safari 8 / OS X 10.10
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;the-result&#34;&gt;The result&lt;/h2&gt;

&lt;p&gt;The good news is that we still get an A+ rating!  The report also shows
the two options for the certificates.&lt;/p&gt;

&lt;p&gt;It correctly reports the 6 ciphers as being available&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;   TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c) ECDH secp256r1 (eq. 3072 bits RSA)  FS	  256
   TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)   ECDH secp256r1 (eq. 3072 bits RSA)  FS	  256
   TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b) ECDH secp256r1 (eq. 3072 bits RSA)  FS	  128
   TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)   ECDH secp256r1 (eq. 3072 bits RSA)  FS 	  128
   TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)   ECDH secp256r1 (eq. 3072 bits RSA)  FS  WEAK  256
   TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)   ECDH secp256r1 (eq. 3072 bits RSA)  FS  WEAK  128
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course the two CBC ciphers are still flagged as weak, but we&amp;rsquo;re aware of
this and they&amp;rsquo;re needed for Safari compatibility.&lt;/p&gt;

&lt;p&gt;Digging further into the report I noticed that most of the clients
negotiated ECDSA mode.  Only a handful did RSA mode!&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;  Chrome 49 / XP SP3	TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  Safari 6 / iOS 6.0.1	TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
  Safari 7 / iOS 7.1 	TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
  Safari 7 / OS X 10.9 	TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
  Safari 8 / iOS 8.4  	TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
  Safari 8 / OS X 10.10	TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Literally everything else that SSLtest emulates that can work with with TLS1.2
all negotiated ECDSA.  Interestingly &amp;ldquo;IE 11 / Win Phone 8.1&amp;rdquo; previously
needed a CBC cipher but it can do ECDSA in GCM mode!&lt;/p&gt;

&lt;h2 id=&#34;complication&#34;&gt;Complication&lt;/h2&gt;

&lt;p&gt;Although this doesn&amp;rsquo;t impact me, in an enterprise environment the support
for multiple certificate types may be impacted by middleware boxes such
as load balancers that do TLS termination (so they can inspect the
traffic and do sticky sessions or similar).  It&amp;rsquo;s not much point in
doing ECDSA if other devices can&amp;rsquo;t support it!  Similarly you may need
the DHE based ciphers to handle limitations of those devices.  But
the list provided here should be a good starting point.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;This didn&amp;rsquo;t take too long to figure out, once I stopped fighting the
CentOS 7 build and attempting to use the &lt;code&gt;fullchain.pem&lt;/code&gt; file there.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s now possible, even for the relatively old CentOS 7, to support
modern ciphers and modern public key cryptography.  Every cipher used
supports forward secrecy and large key sizes.  We just need to be
careful about any future CBC Oracle attacks!&lt;/p&gt;

&lt;p&gt;Of course ECDSA isn&amp;rsquo;t resilient against quantum computing attacks, but
I really don&amp;rsquo;t think that&amp;rsquo;s going to be a practical concern for a long
time.&lt;/p&gt;

&lt;p&gt;Note the &lt;a href=&#34;https://www.sweharris.org/SSL_Server_Test_www.sweharris_ecdsa.pdf&#34;&gt;full report&lt;/a&gt; includes a
secondary domain (&lt;code&gt;*.spuddy.org&lt;/code&gt;) so doesn&amp;rsquo;t quite match what I&amp;rsquo;ve
written.  I didn&amp;rsquo;t include a description of that because it&amp;rsquo;s unnecessary
complication.  In this case a client without SNI (are there any that
also support TLS1.2?) would get a cert for a different virtual host and
so get an error.  That&amp;rsquo;s also not relevant to this post :-)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Data Loss Prevention (DLP)</title>
      <link>https://www.sweharris.org/post/2021-05-06-dlp/</link>
      <pubDate>Thu, 06 May 2021 09:11:41 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2021-05-06-dlp/</guid>
      <description>

&lt;p&gt;Working in Cyber Security I&amp;rsquo;m frequently reminded that the reason we do
all the things we do is, ultimately, to protect the data.  After all, apps
are there to process data, servers (and clouds) are there to run apps and
store data.  So the whole of cyber security is there to protect the data.
It may be Identity and Access Management (restrict access to data to those
people who should have access to it).  It may be anti-virus or endpoint
malware detection (prevent ransomware from destroying data).  It may be
encryption (prevent attackers from bypassing other controls and reading
data directly).  We have secure software development processes to prevent
attacker getting access to data via application bugs.  We have WAFs to
detect and block common patterns (eg SQL injection).  And so on.&lt;/p&gt;

&lt;h2 id=&#34;traditional-dlp&#34;&gt;Traditional DLP&lt;/h2&gt;

&lt;p&gt;Each of these &amp;ldquo;pillars&amp;rdquo; of cyber security are critical and all form part
of a DLP posture.  But in this blog post I&amp;rsquo;m going to focus on the area
most traditionally associated with the moniker &amp;ldquo;DLP&amp;rdquo;; preventing data
&amp;ldquo;theft&amp;rdquo; and how the cloud makes this a lot more challenging.&lt;/p&gt;

&lt;p&gt;In this realm we&amp;rsquo;ve traditionally focused on protecting the data
at rest and in preventing unauthorized data from leaving the company
(the challenge, of course, being to permit &lt;em&gt;authorized&lt;/em&gt; data transfers;
don&amp;rsquo;t block the business from working!).&lt;/p&gt;

&lt;p&gt;Our threat actors are staff making mistakes (&amp;ldquo;oops; I sent this
confidential email to the wrong address&amp;rdquo;), malicious insiders (e.g. a
salesman planning on getting a new job trying to take confidential
documents with him) through attackers who have a footprint in your
environment and want to use that to exfiltrate your data.&lt;/p&gt;

&lt;h2 id=&#34;border&#34;&gt;Border&lt;/h2&gt;

&lt;p&gt;A standard way to assist in DLP is to create a strong border around
your assets.  There&amp;rsquo;s firewalls between you and the internet, between
you and any partners you may have connections to, potentially even
between parts of your company (why should HR staff have connectivity to
trading systems?), and definitely between desktops and the internet.
Of course you &lt;em&gt;need&lt;/em&gt; internet access so you create bridges across the
border between the internal and external networks, such as web proxies.
Traffic is funneled through these proxies and can be inspected.
Bad traffic can be blocked.&lt;/p&gt;

&lt;p&gt;The challenge, here, is that these controls are relatively easily
bypassed.&lt;/p&gt;

&lt;p&gt;Those that work on traffic inspection (&amp;ldquo;Hmm, this looks like a bunch
of credit card numbers; we shouldn&amp;rsquo;t let that out&amp;rdquo;) can be defeated
by a simple obfuscation (map &lt;code&gt;1&lt;/code&gt; to &lt;code&gt;!&lt;/code&gt;; map &lt;code&gt;2&lt;/code&gt; to &lt;code&gt;&amp;quot;&lt;/code&gt; and so on).
Encrypted files are yet another challenge for traffic inspection.
There are some clever tricks that can increase coverage (require encrypted
files to use a managed solution with keys the DLP agent can access) but in
general they&amp;rsquo;re a &amp;ldquo;best efforts&amp;rdquo; type solution.  They&amp;rsquo;ll definitely help
in catching mistakes but a competent malicious person can bypass them.
The stricter you make the rules the harder you make it for the company
to do business.&lt;/p&gt;

&lt;p&gt;Similarly controls that work on volumetric patterns (&amp;ldquo;Huh, this machine is
consistently sending 10Mbit/s of traffic for the past day&amp;rdquo;) are defeated
by slow exfiltration techniques.&lt;/p&gt;

&lt;p&gt;And to make things even worse, not all traffic can be proxied so the
firewall, itself, may need to inspect traffic.  TLS1.3 (and good TLS1.2
settings) is designed for Perfect Forward Secrecy (PFS) and so the
firewall can not just decrypt the traffic as it flows through.&lt;/p&gt;

&lt;h2 id=&#34;where-is-your-border&#34;&gt;Where is your border?&lt;/h2&gt;

&lt;p&gt;But all this presumes you know where your border is.  Do you?  The cloud
changes all this.  If you spin up an AWS VPC and create an Internet
Gateway to that VPC then you&amp;rsquo;ve added a new border to your environment.
Every vNet in Azure automatically has a gateway and so a border.
If you use an S3 bucket then that&amp;rsquo;s potentially exposed to the internet;
a border!  Other cloud native services?  Borders!&lt;/p&gt;

&lt;p&gt;Even if you think you know all your borders then the posture may
change without you knowing.  In March 2021 Amazon introduced &lt;a href=&#34;https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-serial-console.html&#34;&gt;EC2 Serial
consoles&lt;/a&gt;
which let you access the console of your EC2 instance.  This is really
useful if you have broken your network config; it lets you get in and
fix things.  The problem is that this serial connection can be exposed to
the internet via SSH.  It requires a malicious person to do this (since
the config needs to be refreshed every minute to persist the gateway)
but this connection is direct to your VM bypassing all your firewalls,
your processes.  It&amp;rsquo;s a new border!  Oops!  (At time of writing there&amp;rsquo;s
no way to disable this SSH gateway without blocking serial console access
totally because of how AWS has implemented the technology; there&amp;rsquo;s an
enhancement request in!)&lt;/p&gt;

&lt;p&gt;Other borders may be hidden.  If you use Lambda functions (pretty common!)
then additional triggers may be added.  In particular, HTTP API gateways
provide a way for the function to be called from the internet.  Again it
bypasses your firewalls and WAFs; it&amp;rsquo;s a new border.  Amusingly, &lt;em&gt;Alexa&lt;/em&gt;
triggers can be added to Lambda functions.  An intruder could potentially
persist a foothold in your environment as an Alexa call (&amp;ldquo;Alexa, open
the backdoor to megacorp&amp;rdquo;;  &amp;ldquo;Alexa read out all the stolen credit card
numbers&amp;rdquo;).  Are you monitoring for Alexa triggers attached to your lambda
functions?  You should be; it&amp;rsquo;s a border that needs to be controlled!&lt;/p&gt;

&lt;p&gt;So we can see that controlling the border is a lot more complicated in
the world of cloud.  All of these new borders need new technologies to
detect, block and control.  Your traditional firewall/web-proxy solution
won&amp;rsquo;t work.&lt;/p&gt;

&lt;h2 id=&#34;zero-trust&#34;&gt;Zero Trust&lt;/h2&gt;

&lt;p&gt;You may look at Zero Trust Networking as the solution to this; if every
endpoint is doing the inspection and validation of traffic then do we need
a border?  In my view the answer is &amp;ldquo;yes&amp;rdquo;.  For example, developers make
mistakes.  Also not all technologies can be fully controlled (e.g. BMC
ports, out of band consoles) to the same level as a VM (which can have
agents installed).&lt;/p&gt;

&lt;p&gt;We also have a much bigger configuration management problem to deal
with, including how to be sure you&amp;rsquo;ve got 100% coverage (which in turns
requires an accurate inventory of all assets, which is a hard problem!),
activity logging and so on.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ve moved from needing to control a small number of border crossing
points to controlling tens of thousands of endpoints; every server, every
database, memcached, key/value stores&amp;hellip; a green-field environment may
be able to create an architecture that would work, but for the rest of
us in brownfield waste dumps&amp;hellip; nope!  A lot of enterprise technology
of the past 2 decades was designed with the assumption that it would
be protected from the outside world (single factor LDAP authn?  Ugh)
and can&amp;rsquo;t easily be fixed.&lt;/p&gt;

&lt;h2 id=&#34;configuration-management&#34;&gt;Configuration management&lt;/h2&gt;

&lt;p&gt;Configuration management also applies to cloud environments.  So many
cloud providers allow changes to be performed from web consoles.
Indeed many changes are easier from the console because they call dozens
of backend APIs to get the job done.  Where possible you want to deploy
and manage your cloud environments programmatically (e.g. using Terraform)
but even there you must validate the deployed configuration hasn&amp;rsquo;t drifted
because of a mistake by an admin.  This is critical for environments such
as &amp;ldquo;Microsoft 365&amp;rdquo;; even if you use Powershell to manage the environment
it&amp;rsquo;s possible for an admin on the console to accidentally click the
wrong button.  Monitor your configurations and alert if they change!&lt;/p&gt;

&lt;h2 id=&#34;encryption&#34;&gt;Encryption&lt;/h2&gt;

&lt;p&gt;But what about encryption?  Can this help with DLP?  Yes&amp;hellip; and no!&lt;/p&gt;

&lt;p&gt;As I wrote in &lt;a href=&#34;https://www.sweharris.org/post/2017-06-04-encryption-rest/&#34;&gt;Data At Rest Encryption&lt;/a&gt;
encryption can be deployed at different layers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Block Level.  This is useful for laptops (&amp;ldquo;oh no, I left my laptop in
the taxi&amp;rdquo;) or mobile devices where the risk of physical loss of a device
is something to be mitigated, but it doesn&amp;rsquo;t really help in a datacenter
environment where the loss of a disk isn&amp;rsquo;t that high a risk.&lt;/li&gt;
&lt;li&gt;Database level.  This can help against an attacker getting access to the
server, but isn&amp;rsquo;t a strong defense against someone with database credentials&lt;/li&gt;
&lt;li&gt;Application level.  This now requires the application itself to be compromised
(so you need credentials and encryption keys to get the data) but has some
downsides (e.g. full text searching may not be possible) so isn&amp;rsquo;t a good
solution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember that everywhere you store your data you need to protect it; that
includes backups!  Depending on how the backup is done and the encryption
used, you may need to ensure your backups are fully protected.  There has
been more than one data leak from badly protected backups.&lt;/p&gt;

&lt;p&gt;Cloud services complicate the encryption world even more.  Many services
have &amp;ldquo;server side encryption&amp;rdquo; options; e.g. S3, RDS, EBS in Amazon
can all be encrypted.  The problem with this encryption is that it&amp;rsquo;s
closely aligned to &amp;ldquo;block level&amp;rdquo; or &amp;ldquo;database level&amp;rdquo; encryption; if
you get valid credentials then the data is transparently decrypted.
The Capital One breach in 2019 had data stored encrypted this way but
because the attacker was able to get credentials they were able to get
access to the unencrypted text.&lt;/p&gt;

&lt;p&gt;I, personally, don&amp;rsquo;t consider cloud server side encryption to be
sufficient protection for data at rest.  Wherever possible use application
level encryption.&lt;/p&gt;

&lt;h2 id=&#34;scan-on-upload&#34;&gt;Scan on upload&lt;/h2&gt;

&lt;p&gt;You should also try and scan data when it&amp;rsquo;s been placed in storage;
e.g. putting data in an S3 bucket or in OneDrive/Sharepoint can raise an
event that can trigger a scan of the object.  If it&amp;rsquo;s been determined to
be &amp;ldquo;bad&amp;rdquo; then remedial action (&amp;ldquo;delete!!&amp;rdquo;) can be taken programmatically.
Of course this scanning still has the same problems previously discussed,
but it will (again) detect mistakes.&lt;/p&gt;

&lt;h2 id=&#34;data-destruction&#34;&gt;Data Destruction&lt;/h2&gt;

&lt;p&gt;That&amp;rsquo;s not to say that cloud level encryption is useless.  If you can
encrypt it with a customer managed key (CMK) that you can delete then you
have the ability to delete data (by cryptoshredding) when you no longer
need it (e.g. exiting a cloud provider).  Remember that data needs to
be protected wherever it is; when you leave an environment you should
ensure all traces are destroyed, and deleting the encryption key so any
data remnants that may remain are unreadable.&lt;/p&gt;

&lt;p&gt;This CMK requirement can rule out some services.  For example some part
of the Azure DevOps suite use shared services at the backend that are
controlled and managed by Microsoft and so use Microsoft managed keys.
Your source code may be confidential data and a corporate asset; do you
want to trust it to an environment where you can&amp;rsquo;t be sure of deletion?&lt;/p&gt;

&lt;h2 id=&#34;saas-and-dlp&#34;&gt;SaaS and DLP&lt;/h2&gt;

&lt;p&gt;And then we get to SaaS offerings.  These providers &lt;em&gt;need&lt;/em&gt; access to
your data so they can process it.  If you just sent them encrypted blobs
then they won&amp;rsquo;t be able to do much work.  So, remembering that data
needs to be protected &lt;em&gt;everywhere&lt;/em&gt;, you need to look at how the SaaS
provider protects it.  Do they let you use a CMK?  Are you comfortable
with their encryption processes?  How is access to the SaaS offering
managed?  This is effectively a new border!  How can you control this one!&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;As we can see, DLP is not an easy topic.  There&amp;rsquo;s no good answer here,
just various levels of &amp;ldquo;not so good&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;And this is where risk management comes in.  What is the impact to
the company if &lt;em&gt;this&lt;/em&gt; set of data is exposed (including reputational
impact, which still applies even if the data was encrypted) versus the
benefit to the company of processing data in this way.  Because of the
limited border crossings in the traditional world we had a pretty good
idea of the size of the risk and we knew how to mitigate many of them
(e.g. endpoint security controls and agents; remember all the cyber
pillars are involved!).&lt;/p&gt;

&lt;p&gt;But in this new world where data is everywhere and every location has
unique controls and traditional solutions can&amp;rsquo;t be deployed, we need to
look at alternate mitigations and controls and evaluate the risk on a
case by case basis.&lt;/p&gt;

&lt;p&gt;DLP is hard!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>More modern TLS settings</title>
      <link>https://www.sweharris.org/post/2020-09-23-update-ssl/</link>
      <pubDate>Wed, 23 Sep 2020 19:30:16 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2020-09-23-update-ssl/</guid>
      <description>

&lt;p&gt;Back in 2016 I documented &lt;a href=&#34;https://www.sweharris.org/post/2016-10-16-ssl-score/&#34;&gt;how to get an A+ TLS score&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With minor changes this still works.&lt;/p&gt;

&lt;p&gt;But times have changed.  In particular older versions of TLS aren&amp;rsquo;t good;
at a very least you must support nothing less than TLS1.2.&lt;/p&gt;

&lt;h2 id=&#34;consequences-of-limiting-to-tls-1-2-or-better&#34;&gt;Consequences of limiting to TLS 1.2 or better&lt;/h2&gt;

&lt;p&gt;If you set your server to deny anything less than TLS 1.2 then sites like &lt;a href=&#34;https://ssllabs.com/ssltest&#34;&gt;SSLlab&lt;/a&gt; tell us that older clients can no longer connect.&lt;/p&gt;

&lt;p&gt;In particular:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    Android 2.3.7
    Android 4.0.4, 4.1.1, 4.2.2, 4.3
    Baidu Jan 2015
    IE 6 / XP
    IE 7 / Vista
    IE 8 / XP
    IE 8-10 / Win 7
    IE 10 / Win Phone 8.0
    Java 6u45, 7u25
    OpenSSL 0.9.8y
    Safari 5.1.9 / OS X 10.6.8
    Safari 6.0.4 / OS X 10.8.4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now these are very old.  We know that Win7 is still popular, so should
we worry?  Not so much; IE 11 on Win7 &lt;em&gt;can&lt;/em&gt; support TLS1.2.&lt;/p&gt;

&lt;p&gt;So I think it&amp;rsquo;s reasonable to disable anything lower.&lt;/p&gt;

&lt;h2 id=&#34;stronger-ciphers&#34;&gt;Stronger ciphers&lt;/h2&gt;

&lt;p&gt;We also see that SSLlabs flag CBC ciphers as weak.  Now this is
debatable.  CBC isn&amp;rsquo;t &lt;em&gt;necessarily&lt;/em&gt; weak.  But it&amp;rsquo;s historically had
a lot of bad implementations, leading to variations of POODLE attacks
(amongst others).  It&amp;rsquo;s kinda expected that there will be yet another
variation of POODLE on CBC.  So SSLlabs flag these ciphers as weak,
as an encouragement to move people off and onto stronger ciphers.&lt;/p&gt;

&lt;p&gt;Unfortunately, it turns out there aren&amp;rsquo;t that many!  At least not if you&amp;rsquo;re
using RSA certs (which most people do).&lt;/p&gt;

&lt;p&gt;In Apache/OpenSSL terms these ciphers are pretty much the only good ones:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;     ECDHE-RSA-AES128-GCM-SHA256
     ECDHE-RSA-AES256-GCM-SHA384
     DHE-RSA-AES128-GCM-SHA256
     DHE-RSA-AES256-GCM-SHA384
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yes, that&amp;rsquo;s it.  4 of them.&lt;/p&gt;

&lt;p&gt;If you run this through SSLlabs then it&amp;rsquo;ll be strong, but a number of
clients won&amp;rsquo;t be able to connect.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    IE 11 / Win Phone 8.1
    Safari 6 / iOS 6.0.1
    Safari 7 / iOS 7.1
    Safari 7 / OS X 10.9
    Safari 8 / iOS 8.4
    Safari 8 / OS X 10.10
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(Notice IE11/Win7 isn&amp;rsquo;t on that list; it&amp;rsquo;ll happily do secure ciphers).&lt;/p&gt;

&lt;p&gt;You need to decide if you want to support these older clients.  If you
do then these two CBC ciphers will make everything work:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    ECDHE-RSA-AES256-SHA384
    ECDHE-RSA-AES128-SHA256
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yes, these get flagged as weak, but now every client that supports TLS1.2
&lt;em&gt;should&lt;/em&gt; work.&lt;/p&gt;

&lt;h2 id=&#34;complications&#34;&gt;Complications&lt;/h2&gt;

&lt;p&gt;In an enterprise environment the client rarely talks directly to the server,
especially not over the internet.  There may be load balancers or WAFs in
the path and these may be the ones that terminate the TLS connection.  So
&lt;em&gt;their&lt;/em&gt; configuration is important.&lt;/p&gt;

&lt;p&gt;In particular, F5&amp;rsquo;s BigIP servers can only do DH key exchange on 1024 bit
keys.  Which is considered weak.  2048bit is the minimum.  Their
&lt;a href=&#34;https://support.f5.com/csp/article/K82014843&#34;&gt;rationale&lt;/a&gt; is that 2048bit
keys require 5 times the computation than 1024bit keys.  Which makes me
wonder if the &amp;ldquo;big&amp;rdquo; in &amp;ldquo;BigIP&amp;rdquo; is now valid!&lt;/p&gt;

&lt;p&gt;This is a problem.  We have to choose between weak key sizes or &lt;em&gt;potentially&lt;/em&gt;
weak ciphers.  In this scenario I recommend enabling CBC mode and ensuring
you&amp;rsquo;re always on top of all patches; if a new POODLE variant is discovered,
patch ASAP!&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;For my CentOS 7 Apache servers I now have the following configuration:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    SSLProtocol TLSv1.2
    SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;SSLlabs tells me this results in:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)   ECDH secp256r1 (eq. 3072 bits RSA)   FS            128
    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)   ECDH secp256r1 (eq. 3072 bits RSA)   FS            256
    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x9e)       DH 4096 bits                         FS            128
    TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x9f)       DH 4096 bits                         FS            256
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)   ECDH secp256r1 (eq. 3072 bits RSA)   FS   WEAK     256
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)   ECDH secp256r1 (eq. 3072 bits RSA)   FS   WEAK     128
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All the ciphers have forward secrecy, all are at least 128bit in strength,
and all the clients that support TLS1.2 will connect.&lt;/p&gt;

&lt;p&gt;Note the DH key is 4096bits in size.  Why can&amp;rsquo;t BigIP support that?!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>It was OK before; why is it broke now?</title>
      <link>https://www.sweharris.org/post/2020-08-09-recheck/</link>
      <pubDate>Sun, 09 Aug 2020 12:07:30 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2020-08-09-recheck/</guid>
      <description>

&lt;p&gt;As I was &lt;a href=&#34;https://www.sweharris.org/post/2020-07-25-extending_router/&#34;&gt;rebuilding my network&lt;/a&gt;
I came across a problem.&lt;/p&gt;

&lt;p&gt;In my basement I had previous run a cable from my core switch around the room
to the other side, where I had a small 100baseT switch to handle the equipment
on that table.  I&amp;rsquo;d also run another cable across the ceiling to the back
of the house, where I had the Powerline network.&lt;/p&gt;

&lt;p&gt;Everything seemed to be working fine, and it had been doing so for years.&lt;/p&gt;

&lt;p&gt;But when I upgraded the equipment to handle gigabit I was annoyed to see
both of these links only connected at 100Mbit speeds.  WTF?  I checked
the cable itself.  That&amp;rsquo;s fine; it&amp;rsquo;s cat5e.  I did a pin test.  That&amp;rsquo;s
fine; all 8 pins had proper continuity, no breaks.&lt;/p&gt;

&lt;p&gt;So then I looked closer.  WTF?  I had wired the &lt;em&gt;pairs&lt;/em&gt; wrong.&lt;/p&gt;

&lt;p&gt;A normal UTP cable (defined as &lt;a href=&#34;https://en.wikipedia.org/wiki/TIA/EIA-568&#34;&gt;T568&lt;/a&gt;) has the pin pairs as 12 36 45 78.  Somehow I had wired them 12 34 56 78.
So this meant the original RX pair were not across a single twisted pair,
but across two separate wires.&lt;/p&gt;

&lt;p&gt;At 100Mbit speeds this didn&amp;rsquo;t seem to matter.  But at Gigabit speeds it
just didn&amp;rsquo;t work.  Cutting off the bad ends and crimping new ones on
solved the problem.&lt;/p&gt;

&lt;h2 id=&#34;vendor-risk-management&#34;&gt;Vendor Risk Management&lt;/h2&gt;

&lt;p&gt;The next day, at work, I had to have a similar discussion, but around
vendor risk.&lt;/p&gt;

&lt;p&gt;Normally when we look at a vendor (say, we&amp;rsquo;re outsourcing data processing,
or selecting a SaaS provider) we look at the type of data we will be
using with that vendor, and look at their controls and determine if they&amp;rsquo;re
good enough.  After all, we don&amp;rsquo;t need as much control around a site that
just has pictures of the CEO&amp;rsquo;s cat doing funny things as we would around a
processor of credit card information.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ll document what we found out about the vendor, the risk management team
will do their due diligence and give an approval.&lt;/p&gt;

&lt;p&gt;Then a year later someone decides &amp;ldquo;Hey, these guys are cheap, let&amp;rsquo;s move
all our HR ID photos into their system&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;At this point alarms should start ringing.&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;new&lt;/em&gt; evaluation of the vendor is now required.  You&amp;rsquo;ve changed the scope
of the engagement, the riskiness of the data they&amp;rsquo;ll be processing.  What was
OK for the cat pictures may not be OK for HR data.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s not just data; it could also be access.  A site that was accessed
by two people&amp;hellip; we could get away with local admin control.  But if
we then open up that site to a thousand people (&amp;ldquo;let&amp;rsquo;s allow all staff
members to upload cat pics&amp;rdquo;), we&amp;rsquo;re going to need to look at access admin
and controls.  We might even need an approvals workflow, to prevent staff
from uploading inappropriate photos.&lt;/p&gt;

&lt;p&gt;So &lt;em&gt;quantity&lt;/em&gt; can also impact control requirements.&lt;/p&gt;

&lt;p&gt;But not all changes do; if the CEO got a dog and wanted to make it &amp;ldquo;cat and
dog pictures&amp;rdquo; we haven&amp;rsquo;t appreciably changed the scope, and a new risk
evaluation wouldn&amp;rsquo;t be needed.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Don&amp;rsquo;t assume that what was good in the past will be good after a change
has been made.  In my case the cable that worked fine for years was no
longer suitable.&lt;/p&gt;

&lt;p&gt;Similarly, engagement changes may require a re-evaluation of the current
service to determine if it&amp;rsquo;s good enough.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Extending the wireless on my router</title>
      <link>https://www.sweharris.org/post/2020-07-25-extending_router/</link>
      <pubDate>Sat, 25 Jul 2020 18:34:00 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2020-07-25-extending_router/</guid>
      <description>

&lt;p&gt;3 years ago I replaced OpenWRT with a &lt;a href=&#34;https://www.sweharris.org/post/2017-05-07-home-grown-router/&#34;&gt;home grown router&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s worked pretty well, but I wanted to take advantage of improvements
in networking (5Ghz!) and also improve coverage.  This kinda became important
due to COVID lockdown and Work From Home.  My library, where I was working
from, had very weak network signal.  I needed to do better.&lt;/p&gt;

&lt;p&gt;So I decided to look at turning off in the inbuilt WiFi and use an
external WAP (Wireless Access Point, or just AP).  However I wanted to
keep using the Multi-SSID setup I had, to allow for LAN and Guestnet
access (and since that post I also added an IoT network, although I&amp;rsquo;m
not sure I&amp;rsquo;m gonna keep it).&lt;/p&gt;

&lt;p&gt;The obvious way of doing this, on Linux, is to use 802.1q VLANs and then
have the AP map the SSID to the VLAN.  In that way traffic from the LAN
network would still appear on the &lt;code&gt;br-lan&lt;/code&gt; bridge on the router and
everything would work the same way.&lt;/p&gt;

&lt;p&gt;I might write another post, later, explaining 802.1q but for now you
can imagine it&amp;rsquo;s a way of having multiple virtual LANs all running over
the same cable.  Each virtual LAN gets a number between 1 and 4095, and
the switches can decide what ports get to see the traffic.  This allows
you to create a backbone network, but still only pass relevant traffic to
different network segements.  What I&amp;rsquo;m doing, in this post, is defining
a network backbone of 3 VLANS, but endpoints (eg my desktop, or a
phone on the guest wifi network) acts is if it was on a dedicated network.&lt;/p&gt;

&lt;h2 id=&#34;switches&#34;&gt;Switches&lt;/h2&gt;

&lt;p&gt;Now this requires switching equipment to also be able to understand 802.1q
tagging and be able to make some ports dedicated to various networks, and
make other ports &amp;ldquo;trunk&amp;rdquo; networks, able to pass traffic for multiple
networks.&lt;/p&gt;

&lt;p&gt;I picked the TP-Link SG116E switch for this.  It&amp;rsquo;s a 16 port Gigabit
switch and can handle 802.1q VLANs.  I got two of these; one for my
basement (where the existing switch is) and one to replace the living
room switch.&lt;/p&gt;

&lt;p&gt;Now, arbitrarily, I chose VLAN 10 to be my main LAN, VLAN 11 to be
for Guestnet and VLAN 12 to be for IoT.&lt;/p&gt;

&lt;h2 id=&#34;router-config&#34;&gt;Router config&lt;/h2&gt;

&lt;p&gt;On the Linux router this is done by configuring &amp;ldquo;sub-interfaces&amp;rdquo;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat ifcfg-enp3s0.10 
DEVICE=enp3s0.10
TYPE=Ethernet
ONBOOT=yes
BRIDGE=&amp;quot;br-lan&amp;quot;
NM_CONTROLLED=&amp;quot;no&amp;quot;
VLAN=yes
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This simple configuration will add the &amp;ldquo;enp3s0&amp;rdquo; sub-interface 10 to the
&lt;code&gt;br-lan&lt;/code&gt; and any traffic sent out of it will have an 802.1q tag value of
10.&lt;/p&gt;

&lt;p&gt;Interfaces &amp;ldquo;.11&amp;rdquo; and &amp;ldquo;.12&amp;rdquo; are similarly configured.&lt;/p&gt;

&lt;p&gt;So now the bridging table would look something like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;bridge name     bridge id               STP enabled     interfaces
br-guest        8000.000db9439cce       no              enp3s0.11
br-iot          8000.000db9439cce       no              enp3s0.12
br-lan          8000.000db9439ccc       no              enp3s0.10
br-wan          8000.000db9439ccd       no              enp2s0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(I&amp;rsquo;ve hidden the &lt;code&gt;hostapd&lt;/code&gt; entries for WiFi since I&amp;rsquo;m gonna turn that
off in a little while, and it&amp;rsquo;ll just confuse things)&lt;/p&gt;

&lt;p&gt;The wisdom of building these bridges, earlier, is now paying dividends.
I can add new networking constructs to the bridges and it &amp;ldquo;just works&amp;rdquo;.&lt;/p&gt;

&lt;h2 id=&#34;back-to-the-switch&#34;&gt;Back to the switch&lt;/h2&gt;

&lt;p&gt;I now need to configure the switch to understand this.  I plug the router
port 3 (&amp;ldquo;enp3s0&amp;rdquo;) to the switch port 1.  And I configured the switch so
that port 1 is &lt;em&gt;tagged&lt;/em&gt; VLANs 10, 11, 12 and every other port is &lt;em&gt;untagged&lt;/em&gt;
VLAN 10.&lt;/p&gt;

&lt;p&gt;At this point we haven&amp;rsquo;t gained anything; everything on the wired
network is still all LAN traffic.  But we&amp;rsquo;ve got VLAN tagging between
the router and the switch.  So we&amp;rsquo;ve now got potential.&lt;/p&gt;

&lt;p&gt;Next step is to do similar for the switch in the living room, behind
the TV.  I similarly configure that switch so port 1 is tagged 10,11,12
and the rest are untagged 10.  I can now configure basement port 7 (don&amp;rsquo;t
ask!) to be tagged VLANs as well.&lt;/p&gt;

&lt;p&gt;So now all the VLANs exist in both the main switches, even though all
the client machines are on VLAN10 (LAN) only.&lt;/p&gt;

&lt;h2 id=&#34;access-points&#34;&gt;Access Points.&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;m now ready to start putting APs on the network.&lt;/p&gt;

&lt;p&gt;I looked at mesh networks, but most of the kit wasn&amp;rsquo;t able to do
multi-SSID to VLAN mappings.  They&amp;rsquo;re great at coverage, but if I
can&amp;rsquo;t do the networking constructs I want then they&amp;rsquo;re useless to me.
It&amp;rsquo;s possible the Ubiquiti products &lt;em&gt;can&lt;/em&gt; do this, but they&amp;rsquo;re very
expensive.  If you want prosumer, go that path.  I decided to go down
the DIY path.&lt;/p&gt;

&lt;p&gt;Which meant delving back into the OpenWRT world.  Some research (and a
sale at Amazon) lead to buying 3 TP-Link Archer A7 routers.  These can
very easily be flashed with OpenWRT.  They can then be configured to
act as APs and not routers.  It took a few trial and errors to understand
what the document and examples &lt;em&gt;meant&lt;/em&gt; when it came to multiple VLANs and
multiple SSIDs, but eventually I got it.&lt;/p&gt;

&lt;p&gt;I avoided re-using constructs the base software uses (eg the WAN port,
or the network names WAN and LAN, and VLANs 1 and 2).  So I&amp;rsquo;m just going
to use the 4 LAN ports and build three networks Main, Guest, IoT&lt;/p&gt;

&lt;p&gt;Only the Main network needs to have an address &amp;lsquo;cos that&amp;rsquo;s how you&amp;rsquo;ll
talk to the AP later.&lt;/p&gt;

&lt;h2 id=&#34;defining-ap-vlan-ports&#34;&gt;Defining AP VLAN ports&lt;/h2&gt;

&lt;p&gt;OpenWRT being Linux, you have similar sub-interface addressing
for VLANS.&lt;/p&gt;

&lt;p&gt;We also need to tell the switch what ports are on what networks.&lt;/p&gt;

&lt;p&gt;BE VERY CAREFUL HERE.  If you get the setup wrong you can lose network
connectivity to your AP and then have to fight to get it back.  I&amp;rsquo;m
going to describe the &lt;em&gt;target&lt;/em&gt; state but not how to get there in each
step.  It&amp;rsquo;s worth leaving at least one port on LAN and keeping that
configured so the original 192.168.1.1 address is still visible on
that port&amp;hellip; just in case :-)&lt;/p&gt;

&lt;p&gt;But at the end of the day, in the main main network/switch menu you will
end up with a config similar to:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/a7-vlan-switch.png&#34; alt=&#34;OpenWRT VLAN switches&#34;&gt;
&lt;/div&gt;


&lt;p&gt;This tells the AP to configure all 4 LAN ports as tagged for 10, 11, 12.
In this case I have port 4 plugged into the main switch, which is &lt;em&gt;also&lt;/em&gt;
set for tagged VLANS.  VLAN1 was the original VLAN used by the software
to manage the LAN, and VLAN2 is for the WAN.  It&amp;rsquo;s possible (but I haven&amp;rsquo;t
tested) to remove VLAN2 from the WAN port and add that to 10,11,12.&lt;/p&gt;

&lt;p&gt;The equivalent in &lt;code&gt;/etc/config/switch&lt;/code&gt; is&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;config switch
        option name &#39;switch0&#39;
        option reset &#39;1&#39;
        option enable_vlan &#39;1&#39;

config switch_vlan
        option device &#39;switch0&#39;
        option vlan &#39;1&#39;
        option vid &#39;1&#39;
        option ports &#39;0t&#39;

config switch_vlan
        option device &#39;switch0&#39;
        option vlan &#39;2&#39;
        option vid &#39;2&#39;
        option ports &#39;0t 1&#39;

config switch_vlan
        option device &#39;switch0&#39;
        option vlan &#39;3&#39;
        option vid &#39;10&#39;
        option ports &#39;0t 2t 3t 4t 5t&#39;

config switch_vlan
        option device &#39;switch0&#39;
        option vlan &#39;4&#39;
        option vid &#39;11&#39;
        option ports &#39;0t 2t 3t 4t 5t&#39;

config switch_vlan
        option device &#39;switch0&#39;
        option vlan &#39;5&#39;
        option vid &#39;12&#39;
        option ports &#39;0t 2t 3t 4t 5t&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The numbers &amp;ldquo;0 1 2 3 4 5&amp;rdquo; on the &lt;code&gt;option ports&lt;/code&gt; line refer to ports
seen in the diagram, but the &lt;em&gt;ordering&lt;/em&gt; can change on different equipment.
On the A7, 0 is CPU, 1 is WAN, 2-&amp;gt;5 are the LAN ports.  This is common,
but not always true!  That&amp;rsquo;s why it&amp;rsquo;s worth doing that bit in the GUI,
to let it pick the port numbers.&lt;/p&gt;

&lt;p&gt;We can then define the 3 bridges (&amp;ldquo;interfaces&amp;rdquo; in OpenWRT speak) and
associate them with the VLANs (also in the same config file).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;config interface &#39;Main&#39;
        option ifname &#39;eth0.10&#39;
        option type &#39;bridge&#39;
        option delegate &#39;0&#39;
        option proto &#39;static&#39;
        option netmask &#39;255.255.255.0&#39;
        option ipaddr &#39;10.0.0.249&#39;

config interface &#39;Guest&#39;
        option proto &#39;none&#39;
        option type &#39;bridge&#39;
        option delegate &#39;0&#39;
        option ifname &#39;eth0&#39;

config interface &#39;Iot&#39;
        option ifname &#39;eth0.12&#39;
        option proto &#39;none&#39;
        option type &#39;bridge&#39;
        option delegate &#39;0&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So now we have the AP configured on the ethernet site and can be plugged
into a trunk port on the switch.&lt;/p&gt;

&lt;h2 id=&#34;defining-ap-wifi&#34;&gt;Defining AP WiFi&lt;/h2&gt;

&lt;p&gt;Onto WiFi!&lt;/p&gt;

&lt;p&gt;From the Network/Wireless menu you can simply add new networks to each
Radio (2.4Ghz and 5GHz).  The setup would look similar to:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/a7-define-wifi.png&#34; alt=&#34;OpenWRT WiFi&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Remember to set a WPA2 key on the security TAB.  For me that meant
adding entries for the Lan/Guest/IoT networks and selecting the relevant
interface.  It&amp;rsquo;s boring, but works.&lt;/p&gt;

&lt;p&gt;At the end, in &lt;code&gt;/etc/config/wireless&lt;/code&gt; you&amp;rsquo;ll see entries similar to:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;config wifi-iface &#39;wifinet1&#39;
        option device &#39;radio1&#39;
        option mode &#39;ap&#39;
        option network &#39;Main&#39;
        option encryption &#39;psk2&#39;
        option key &#39;MYPASSWORD&#39;
        option ssid &#39;MYSSID&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You should see entries for each of the SSIDs and for both &lt;code&gt;radio1&lt;/code&gt; and
&lt;code&gt;radio0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can see the OpenWRT eventually built network structures very similar
to what my original router config had:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# brctl show
bridge name     bridge id               STP enabled     interfaces
br-Guest        7fff.74da88a9a43b       no              eth0.11
                                                        wlan1-1
                                                        wlan0-1
br-Main         7fff.74da88a9a43b       no              eth0.10
                                                        wlan1
                                                        wlan0
br-Iot          7fff.74da88a9a43b       no              eth0.12
                                                        wlan1-2
                                                        wlan0-2
br-lan          7fff.74da88a9a43b       no              eth0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After &lt;em&gt;all&lt;/em&gt; of this hard work, we&amp;rsquo;re kinda back where we started.&lt;/p&gt;

&lt;p&gt;We have an AP presenting the same 3 wireless networks as before and they&amp;rsquo;re
on the same router bridges as before, and so the same firewall and routing
rules work.&lt;/p&gt;

&lt;h2 id=&#34;replication&#34;&gt;Replication&lt;/h2&gt;

&lt;p&gt;So why go to all this hard work?&lt;/p&gt;

&lt;p&gt;Well, now we can &lt;em&gt;replicate&lt;/em&gt; this.  I can put one of these A7s behind the
TV in my living room (pretty much central to the house).  I can put one
in the laundry area of the basement at the back of my house.  And I can put
a third one in my library, with an ethernet cable running to the living room
TV switch.  I chose different frequencies for each one, so they don&amp;rsquo;t
fight for airwave bandwidth!&lt;/p&gt;

&lt;p&gt;Which is what I did.  And it works&amp;hellip; adequately.   OpenWRT doesn&amp;rsquo;t
currently have &amp;ldquo;beam steering&amp;rdquo; available, so when I walk from one room
to another then my phone might decide to fall back to the slower 2.4Ghz,
rather than stay on 5Ghz.  And, oddly, machines don&amp;rsquo;t always connect to
the closest AP (why would a smart plug in the laundry, literally 4ft away
from the AP, decide to connect to the one in the library, 2 floors away?)&lt;/p&gt;

&lt;p&gt;But despite this, it works well.  I have strong signal everywhere.&lt;/p&gt;

&lt;h2 id=&#34;garage&#34;&gt;Garage&lt;/h2&gt;

&lt;p&gt;With one caveat.  My &lt;em&gt;garage&lt;/em&gt;.  When the metal door is closed it seems
to reduce the signal strength just enough to cause my
&lt;a href=&#34;https://www.sweharris.org/post/2019-05-19-garage/&#34;&gt;smart dumb opener&lt;/a&gt; to lose network signal.&lt;/p&gt;

&lt;p&gt;So for that I used a TP-Link AC750 Powerline adapter.  I found a plug in
the basement (conveniently close to the basement A7) that was on the
same circuit as the garage electrics.  So I was able to use one port
of the A7 to be &lt;em&gt;untagged&lt;/em&gt; Guestnet and plugged the Powerline adapter
into that.  It works.&lt;/p&gt;

&lt;p&gt;The power of 802.1q aware switches (which my core switches and the A7s are)
is that they can extend and expose any of the networks, so I could even
expose a hardwired Guestnet port from any of these switches.&lt;/p&gt;

&lt;h2 id=&#34;port-summary&#34;&gt;Port Summary&lt;/h2&gt;

&lt;p&gt;Basement:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; VLAN  VLAN Name      Member Ports   Tagged Ports   Untagged Ports
 1     Default_VLAN 
 10    lan            1-16           1-3,7          4-6,8-16
 11    guest          1-3,7          1-3,7
 12    iot            1-3,7          1-3,7
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Port 1 goes to the router; 2 is my &amp;ldquo;test&amp;rdquo; port and is currently unused,
3 connects to the basement A7 and 7 connects to the Living Room switch.
All other ports are on the main LAN&lt;/p&gt;

&lt;p&gt;Living Room:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; VLAN  VLAN Name      Member Ports   Tagged Ports   Untagged Ports
 1     Default_VLAN
 10    lan            1-16           1-2,12          3-11,13-16
 11    guest          1-2,12         1-2,12            
 12    iot            1-2,12         1-2,12
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;1 goes to the basement switch, 2 goes to the living room A7, 12 goes to
the library A7.  All other ports are on the main LAN.&lt;/p&gt;

&lt;h2 id=&#34;finally&#34;&gt;Finally&lt;/h2&gt;

&lt;p&gt;And just for completeness, I have a dumb Gigabit switch in the basement
on the far side from the router and core switch.  This is used for my
&amp;ldquo;exercise entertainment&amp;rdquo; center; I have an old old TV, an old Mac Mini,
a TiVo Mini, a Pioneer Amp and a FireTV stick there.  These need networks,
so I ran a cable around the room and put a dumb switch (my original
gigabit switch before I went VLAN aware) there.&lt;/p&gt;

&lt;p&gt;So my final network looks like:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/Network_Diagram.png&#34; alt=&#34;Network Diagram&#34;&gt;
&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title>Firewall Basics</title>
      <link>https://www.sweharris.org/post/2020-03-01-firewall_basics/</link>
      <pubDate>Sun, 01 Mar 2020 19:10:30 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2020-03-01-firewall_basics/</guid>
      <description>

&lt;h1 id=&#34;what-is-a-firewall&#34;&gt;What is a firewall?&lt;/h1&gt;

&lt;p&gt;Think of an office building with a keycard entry system.  To get into the
building you need to put your card to the reader.  If it think you&amp;rsquo;re
authorized then the gate will open and you can enter.  Similarly, a number
of offices require you to &amp;ldquo;badge out&amp;rdquo; as well.  This badge/gate system is a
simple analogy for a firewall.&lt;/p&gt;

&lt;p&gt;A network firewall may be considered to be a security gate to separate
the network up into &amp;ldquo;inside&amp;rdquo; and &amp;ldquo;outside&amp;rdquo; and you define rules to allow
traffic to pass through the gate.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;outside&lt;/em&gt; of a firewall is generally considered the less &amp;ldquo;trusted&amp;rdquo;
environment.  The &lt;em&gt;inside&lt;/em&gt; is the more trusted.  An obvious example is
a firewall between your internal network and the internet.  The internet
is &amp;ldquo;outside&amp;rdquo; and the internal network is &amp;ldquo;inside&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Traffic that flows from the outside to the inside is called &lt;em&gt;ingress&lt;/em&gt; traffic.
Traffic flowing in the opposite direction is called &lt;em&gt;egress&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;We also call the traffic that flows through a firewall to be &amp;ldquo;North-South&amp;rdquo;
traffic.&lt;/p&gt;

&lt;p&gt;Typically, in an enterprise, we control ingress traffic to restrict what
an outside attacker can see.  Similarly we control egress traffic to
restrict what can be reached.  Why would your database server even need
to connect to the bitcoin network?&lt;/p&gt;

&lt;h1 id=&#34;internal-firewalls-on-a-network&#34;&gt;Internal firewalls on a network&lt;/h1&gt;

&lt;p&gt;Above I mentioned an obvious firewall location; between the internal
network and the internet.  However there&amp;rsquo;s also a benefit to splitting
up your internal network.&lt;/p&gt;

&lt;p&gt;A common design is the &amp;ldquo;3 tier network&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.sweharris.org/images/3tier.png&#34; alt=&#34;3tier diagram&#34; /&gt;&lt;/p&gt;

&lt;p&gt;The firewall between the internet and Tier 1 is commonly called a &amp;ldquo;border
firewall&amp;rdquo;.  The others are &amp;ldquo;internal firewalls&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;This doesn&amp;rsquo;t look like much.  What&amp;rsquo;s the advantage of all these
internal firewalls?&lt;/p&gt;

&lt;p&gt;The advantage comes in when you have multiple applications on your network
(which is common to enterprises).  The webserver for &amp;ldquo;application A&amp;rdquo;
sitting in tier 1 (DMZ) can have permission to &lt;em&gt;only&lt;/em&gt; talk to the
application servers in tier 2 (App) that run application A.  In that
way if the web server is compromised it can&amp;rsquo;t even &lt;em&gt;see&lt;/em&gt; the app servers
for &amp;ldquo;application B&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Similarly if an application server is breached (e.g. an attacker manages
to jump from the web to the app tier) then the only databases they can
see are those that are used by the application.  Application B&amp;rsquo;s databases
can&amp;rsquo;t be reached.&lt;/p&gt;

&lt;p&gt;Now this sort of design has some limitations.  &amp;ldquo;East-West&amp;rdquo; traffic (traffic
between servers sitting in the same tier) isn&amp;rsquo;t restricted.  This leads to
a more fine grained designed, sometimes called &amp;ldquo;micro-segmentation&amp;rdquo;, but
that&amp;rsquo;s beyond the scope of this blog entry!&lt;/p&gt;

&lt;h1 id=&#34;types-of-firewall&#34;&gt;Types of Firewall&lt;/h1&gt;

&lt;p&gt;Firewalls typically operate at 2 layers of the network stack.&lt;/p&gt;

&lt;h2 id=&#34;ip-layer&#34;&gt;IP layer&lt;/h2&gt;

&lt;p&gt;The first operates at the IP layer, and looks at packets.  When a client
wants to make a connection it (typically) generates a local port and then
does the equivalent of &amp;ldquo;I am 10.20.30.40 port 12345 and I want to connect to
192.168.100.200 port 443&amp;rdquo;.  The firewall can see this and decide whether to
allow the traffic through or not.&lt;/p&gt;

&lt;p&gt;Things get slightly more complicated because a &amp;ldquo;session&amp;rdquo; consists of
multiple packets and not all of them say &amp;ldquo;I want to connect&amp;rdquo;; some of them
say &amp;ldquo;and I&amp;rsquo;m part of the conversation I&amp;rsquo;m already having&amp;rdquo;.   A large packet
may also be split up; if you send 64K worth of data then it&amp;rsquo;s normally
split up into 1500 byte or smaller &lt;em&gt;fragments&lt;/em&gt; and then reassembled.&lt;/p&gt;

&lt;p&gt;This leads to three types of IP firewalls:&lt;/p&gt;

&lt;h4 id=&#34;packet-filtering&#34;&gt;Packet filtering&lt;/h4&gt;

&lt;p&gt;This is the original design of a firewall.  Basically it would have rules
that say &amp;ldquo;ingress traffic to my webserver on port 443 is allowed; the
webserver can talk out&amp;rdquo;.  It&amp;rsquo;s how I did Cisco ACLs back in the 90s.  It
works to protect against ingress traffic against unapproved services (&amp;ldquo;no,
you can&amp;rsquo;t reach my ssh port!&amp;ldquo;) but some protocols may be open to abuse
from an attacker sending malformed packets.&lt;/p&gt;

&lt;h4 id=&#34;stateful-packet-inspection-spi&#34;&gt;Stateful packet inspection (SPI)&lt;/h4&gt;

&lt;p&gt;This is probably the most common form of IP firewall.  Now the firewall
keeps track of traffic previously approved, and allows related traffic
to pass through.&lt;/p&gt;

&lt;p&gt;In my &lt;a href=&#34;https://www.sweharris.org/post/2017-05-07-home-grown-router/&#34;&gt;home grown router&lt;/a&gt; config
my &lt;code&gt;iptables&lt;/code&gt; rules had:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate INVALID -j DROP
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These use a &amp;ldquo;connection tracker&amp;rdquo; (&lt;code&gt;conntrack&lt;/code&gt;) to keep track of traffic
and only permit relevant traffic through.  Now my web server doesn&amp;rsquo;t
need to have a specific &amp;ldquo;allow to talk to the internet&amp;rdquo; rule; it can
&lt;em&gt;magically&lt;/em&gt; respond to incoming requests.  This is clearly stronger.&lt;/p&gt;

&lt;p&gt;We also drop traffic that claims it&amp;rsquo;s related to a session, but isn&amp;rsquo;t
(eg attackers sending fragments, or trying to hijack sessions with the
wrong values).&lt;/p&gt;

&lt;h4 id=&#34;deep-packet-inspection-dpi&#34;&gt;Deep packet inspection (DPI)&lt;/h4&gt;

&lt;p&gt;Now we start to look inside the traffic itself and reject stuff that
looks bad.  At the IP layer, itself, we can block malicious traffic
from hitting the web server.  Both filtering and SPI are done on the
headers; DPI (as the name suggests) goes deep into the packet contents.
It will collect together fragments and try to understand the &lt;em&gt;content&lt;/em&gt;
of a message.  Does it look bad?  &amp;ldquo;Why is there HTTP traffic on the
SMTP port?&amp;rdquo;  Block!&lt;/p&gt;

&lt;p&gt;In a world that is trending towards &amp;ldquo;encrypt everything&amp;rdquo;, DPI is becoming
less useful.  But there&amp;rsquo;s still enough unencrypted traffic that it&amp;rsquo;s not
without value.&lt;/p&gt;

&lt;h2 id=&#34;application-layer&#34;&gt;Application layer&lt;/h2&gt;

&lt;p&gt;The most common use of firewalls at the application layer are the Web
Application Firewall (WAF).  These are protocol specific (in this case,
http traffic) and know a &lt;em&gt;lot&lt;/em&gt; about the types of attack that can happen
at that layer (&amp;ldquo;SQL injection, buffer overflow, invalid headers&amp;rdquo; for
example) and can block and reject the traffic before it even hits the
webserver.  An enterprise with thousands of webservers may take time to
patch against the latest Apache Struts vulnerability (not to pick a product
at random)&amp;hellip; but your WAF can be programmed to detect a potential attack
against Struts and block it.  (But still patch your servers! Don&amp;rsquo;t rely
on a single defense!)&lt;/p&gt;

&lt;p&gt;WAFs are expensive to run, both in terms of compute and in terms of
operation because they are prone to false positives, but they are a
critical component in a firewall posture.&lt;/p&gt;

&lt;p&gt;For the rest of this blog I&amp;rsquo;m going to focus more on the network layer
because that&amp;rsquo;s where most people run into trouble.&lt;/p&gt;

&lt;h1 id=&#34;ipv6&#34;&gt;IPv6&lt;/h1&gt;

&lt;p&gt;At this point I should point out that IPv6 is a &lt;em&gt;different&lt;/em&gt; protocol
to IPv4.  Your network firewall rules written for IPv4 will &lt;em&gt;not&lt;/em&gt;
automatically protect against IPv6 unless you have a management stack
that handles both.&lt;/p&gt;

&lt;p&gt;This has some pro&amp;rsquo;s and con&amp;rsquo;s.&lt;/p&gt;

&lt;p&gt;For my personal home network the IPv6
rules were pretty simple; &amp;ldquo;allow access from trusted IPv6 servers; reject
everything else&amp;rdquo;.  But the IPv4 rules had dozens of entries to handle
all the ingress rules I permitted.&lt;/p&gt;

&lt;p&gt;For an enterprise they need to be aware that migrating from an IPv4 only
environment to a (normally dual-stacked) IPv6 environment will require
ensuring their firewalls &lt;em&gt;also&lt;/em&gt; cover the new stack.&lt;/p&gt;

&lt;h1 id=&#34;what-direction&#34;&gt;What direction?&lt;/h1&gt;

&lt;p&gt;This is where I see a lot of developers get confused.  They look at
traffic as to &amp;ldquo;where the data flows&amp;rdquo;.  For a lot of developers &amp;ldquo;I pull
data from &lt;a href=&#34;https://api.example.com&amp;quot;&#34;&gt;https://api.example.com&amp;quot;&lt;/a&gt; is considered an ingress.  And
from a dataflow perspective it is.  But from a &lt;em&gt;network&lt;/em&gt; perspective
what matters is &amp;ldquo;who initiates the connection&amp;rdquo;.  If my server is making
the connection then it&amp;rsquo;s an &lt;em&gt;egress&lt;/em&gt; rule that needs to be created;
&amp;ldquo;my server 10.20.30.40 needs an egress rule to talk to 192.168.100.200
on port 443&amp;rdquo;&lt;/p&gt;

&lt;p&gt;When creating network firewall rules you need to think at layer 4 of the
OSI stack (TCP, normally) and not at layer 7 (the application layer).&lt;/p&gt;

&lt;h1 id=&#34;is-a-nat-router-a-firewall&#34;&gt;Is a NAT router a firewall?&lt;/h1&gt;

&lt;p&gt;No.  But kinda?&lt;/p&gt;

&lt;p&gt;NAT is nasty.  It breaks a lot of rules.  But, in some respects, it
provides a useful ingress firewall.  That&amp;rsquo;s because the machines behind
the NAT gateway can&amp;rsquo;t directly be reached from the outside; they&amp;rsquo;re not
routable.  No one on the internet can reach 192.168.1.100.  But if I
add &amp;ldquo;port forward&amp;rdquo; on the router so that 443 -&amp;gt; 192.168.1.100:443 now
the web server on that machine &lt;em&gt;can&lt;/em&gt; be reached.&lt;/p&gt;

&lt;p&gt;So this has some of the benefits of an ingress firewall.  Nothing can
be reached unless you specifically permit it!  So the SPI rules kinda
apply.  It&amp;rsquo;s not really a firewall but kinda acts as one.&lt;/p&gt;

&lt;p&gt;Note that has home networks start to move to IPv6 then NAT may (should!)
disappear.  So some of the protections home networks have had due to NAT
may disappear.&lt;/p&gt;

&lt;h1 id=&#34;is-a-proxy-server-a-firewall&#34;&gt;Is a proxy server a firewall?&lt;/h1&gt;

&lt;p&gt;Kinda, yes?&lt;/p&gt;

&lt;p&gt;An enterprise typically uses a proxy server to permit egress traffic to
&amp;ldquo;trusted&amp;rdquo; sources.  The proxy can do content inspection and reject malware
and traffic to known bad hosts.  In some respects we can think of the proxy
as the &amp;ldquo;other side&amp;rdquo; to a WAF; WAF protects ingress traffic, a proxy protects
against egress.&lt;/p&gt;

&lt;p&gt;In a strongly controlled enterprise, firewalls should block all egress
traffic by default.  Only specifically opened firewall rules should
be allowed.  And proxies form a strong part of this.  There could be
a set of rules for desktops, and each server could be specifically
permissioned to only see the https endpoints it&amp;rsquo;s meant to see.&lt;/p&gt;

&lt;p&gt;Proxies have a great advantage over network layer firewalls because they
work at the URL level.  A web service hosted in AWS could have a gazillion
of IP address and you &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; want to allow your network firewall to open
all those addresses &amp;lsquo;cos other AWS customers also use them.  But the URL?
That&amp;rsquo;s easier.&lt;/p&gt;

&lt;p&gt;I consider egress proxy rules to be far superior in these days of modern
elastic compute, and so proxies form a critical component in allowing the
enterprise to consume external resources.&lt;/p&gt;

&lt;h1 id=&#34;is-a-reverse-proxy-server-a-firewall&#34;&gt;Is a reverse proxy server a firewall?&lt;/h1&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;A reverse proxy, typically, just takes incoming requests from the internet
and directs them to a second server.  It &lt;em&gt;may&lt;/em&gt; look at the request and
forward the request to different servers; it &lt;em&gt;may&lt;/em&gt; load balance requests.
But, in essence, a reverse proxy is just a &amp;ldquo;layer 7 router&amp;rdquo;.  It doesn&amp;rsquo;t
add any real security and, indeed, can &lt;em&gt;reduce&lt;/em&gt; security by exposing backend
servers that wouldn&amp;rsquo;t otherwise be reachable (because the firewall has
blocked it).&lt;/p&gt;

&lt;p&gt;There are some good functional reasons to have reverse proxies in your
environment (e.g. to allow the creation of unreachable networks, and have
this bridge the gap) but this doesn&amp;rsquo;t replace a firewall.  Indeed it&amp;rsquo;s
almost an anti-firewall!&lt;/p&gt;

&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;A firewall segregates network traffic.  It may operate at different layers
of the network stack.  It&amp;rsquo;s a critical component for any network security
model.&lt;/p&gt;

&lt;p&gt;Understanding the underlying network layers (e.g. TCP, UDP) &lt;em&gt;and&lt;/em&gt; the
application layer is important to building a strong firewall posture.&lt;/p&gt;

&lt;p&gt;If you&amp;rsquo;re in an enterprise and need to create a &amp;ldquo;firewall request&amp;rdquo;
so your server can be reached from the internet (or reach out to the
internet!) then understand the layer 4 semantics; &lt;em&gt;who&lt;/em&gt; is initiating
the connection matters more than &amp;ldquo;who sends all the data&amp;rdquo;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>RSA wrapped AES</title>
      <link>https://www.sweharris.org/post/2019-09-15-rsa-aes/</link>
      <pubDate>Sun, 15 Sep 2019 12:20:40 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2019-09-15-rsa-aes/</guid>
      <description>

&lt;p&gt;Here&amp;rsquo;s a common requirement:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We want to transfer a file containing sensitive data to a partner; they
want us to put the data in their S3 bucket.  How can we do this securely?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now you might start with putting controls around the S3 bucket itself;
make sure it&amp;rsquo;s properly locked down, audit logs and so on.  But there&amp;rsquo;s
a number of issues with this.  In particular, S3 bucket permissions
are easy to get wrong.  There&amp;rsquo;s a long history of data leaks because
of misconfigurations.  Even if the setup is correct today, it may be
wrong tomorrow.  Since the bucket isn&amp;rsquo;t owned by &amp;ldquo;me&amp;rdquo;, I can&amp;rsquo;t verify
the setup.  So I&amp;rsquo;m transferring data into an untrusted environment.&lt;/p&gt;

&lt;h2 id=&#34;so-use-encryption&#34;&gt;So use encryption&lt;/h2&gt;

&lt;p&gt;Since I&amp;rsquo;m responsible for the data until it reaches the partner, I look
at encrypting it, instead.  Now even if the bucket is open by mistake,
the contents can&amp;rsquo;t be read.&lt;/p&gt;

&lt;p&gt;The obvious method of encryption would be to use AES.  This has a downside,
though.  It&amp;rsquo;s symmetric encryption and so the sender and receiver need to
have a &amp;lsquo;shared secret&amp;rsquo; (the encryption key).  This can be done, but it
introduces complexity.&lt;/p&gt;

&lt;p&gt;So let&amp;rsquo;s look at asymmetric encryption; RSA.  This just means the sender
needs to know the recipients public key.  So far so good.  But RSA is
quite slow and CPU intensive.  When sending lots of data this can have
a performance impact.&lt;/p&gt;

&lt;h2 id=&#34;hybrid-encryption&#34;&gt;Hybrid encryption&lt;/h2&gt;

&lt;p&gt;We can steal a technique used in various places.&lt;/p&gt;

&lt;p&gt;The underlying idea is that the data is AES256 encrypted using a unique
one-time-use key and then the AES key is encrypted by a recipient
generated RSA public key.  The encrypted data and the encrypted AES key
are placed in the bucket.  The recipient can then use their private key
to decrypt the AES key, and then use that to decrypt the data.&lt;/p&gt;

&lt;p&gt;The steps generally are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The recipient creates an RSA key pair.  This key can last a long time
(e.g. 1 year)&lt;/li&gt;
&lt;li&gt;The sender generates a random AES256 key.  This key is only used once.&lt;/li&gt;
&lt;li&gt;The data is encrypted with the AES key&lt;/li&gt;
&lt;li&gt;The AES key is encrypted with the RSA public key&lt;/li&gt;
&lt;li&gt;The encrypted data and the encrypted key is sent to the recipient
(e.g. via S3)&lt;/li&gt;
&lt;li&gt;The recipient uses their RSA private key to decrypt the AES key&lt;/li&gt;
&lt;li&gt;The recipient uses the AES key to decrypt the data&lt;/li&gt;
&lt;li&gt;The recipient deletes the encrypted data and encrypted AES key.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The benefits of this process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No shared secret is required.  The sender needs only know the public
key of the recipient&lt;/li&gt;
&lt;li&gt;Each data object is encrypted with a different key&lt;/li&gt;
&lt;li&gt;The large data objects are encrypted decrypted with the fast AES
algorithm; only the key, itself, uses the slower RSA algorithm.&lt;/li&gt;
&lt;li&gt;If permissions are set incorrectly (eg on the S3 bucket) then the data
is still fully protected even if an attacker obtains the data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the same data needs to be sent to multiple recipients then this process
is easily extended; for each recipient use their public key and store
multiple copies of the encrypted AES key, one copy for each recipient.&lt;/p&gt;

&lt;h2 id=&#34;requirements&#34;&gt;Requirements&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The RSA key must be at least 2048bits in size (giving 112bits of
strength); recommended to be 4096 bits (giving 128bits of strength).&lt;/li&gt;
&lt;li&gt;If a &amp;ldquo;Key Derivation Function&amp;rdquo; (KDF) is used to generate the key then
the password used to generate that key must be at least 45 characters long
(assuming a character set of 64 characters - 6 bits of entropy).&lt;/li&gt;
&lt;li&gt;If a &amp;ldquo;ZIP&amp;rdquo; tool is used to perform the encryption then it must support
AES256 mode (e.g. SmartCrypt).  Generic &amp;ldquo;zip&amp;rdquo; encryption is weak and
must not be used.&lt;/li&gt;
&lt;li&gt;We must be sure the public key used belongs to the recipient; if we
use a key supplied by an attacker then the attacker will be able to
decrypt the data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Typically the recipient can publish the key in a trusted location (e.g. on
a TLS protected website under their control).  This has advantages that
the recipient can replace their key and we can retrieve the new version
automatically.&lt;/p&gt;

&lt;p&gt;The security of the solution is dependent on using the correct public key&lt;/p&gt;

&lt;h2 id=&#34;example-using-unix-native-tools&#34;&gt;Example using Unix native tools&lt;/h2&gt;

&lt;p&gt;In Unix, the &lt;code&gt;openssl&lt;/code&gt; command does most of the hard work for us:&lt;/p&gt;

&lt;h4 id=&#34;generate-rsa-key&#34;&gt;Generate RSA key:&lt;/h4&gt;

&lt;p&gt;Recipient generates the RSA key and extract the public key.
This version has no password on the private key, so protection of the
private key is essential.   This only needs to be done once a year or two,
on the recipient schedule.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ openssl genrsa -out private.pem 4096
Generating RSA private key, 4096 bit long modulus
...++
............................................................++
e is 65537 (0x10001)
$ openssl rsa -in private.pem -outform PEM -pubout -out public.pem
writing RSA key
$ cat public.pem
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtIvkiOFgQfGYa2SIZCPO
dMg8qju6BRgpBAf7el8nr1D/0dG03CusYUzbd9j6/F07CriZpfO5XQE/0Bza8dyf
abZhXtxe8Sa9SUxaOzfyrXlBe5zvO+DSbQ2L326Nw6ScptsNM0yeDaMgfxp0/Kcx
3fW4U6s1RJ6D7B/XHJ6FZiIX4e4AKEoOWnJnNCKET9TsYn64TaL0zop3su5QzSbL
B70mrIJhme+9EVf91CdIU+efa4KF+bMiM8Kqgpb7UauI+5mWJN66JJ82i6xMz2hl
OOIysBZRJCG7UoURblQqgYMtBEhpX9DPZmAvfOWkqO7kouSLYT5S4ZRnys47Fi6K
Sj64XtMB63/HMCq0HXb6UXxm98mICA+vtVGVhJLt9nq7bmABaa+jluI27k62/hUI
WmpREiSt1U80gmU2c17PhQknVl2iioSpnO7p12U/xWq9oFJbnQ3OKgL1jxzQsfVD
U/wAnYiZiLm8Oro1yMd832LBBC01OcMG1v93FZ1g5UUiCecYhqTERRkkhYEltIML
01JDVxEJeWHrtzUdWNKV2pFBGedWuB0/hpJsub+Xcp4sycY4P8mSdFgL99uL1nJc
HsXDEZTS+DoRSo6x+Nf6ytSl7ShESERrubmlvbWrgUQTb/vzJIhwr/Ov1DvOjanU
kjBXt/d7eYhmeMgrHeB6itcCAwEAAQ==
-----END PUBLIC KEY-----
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;the-encryption-process&#34;&gt;The encryption process:&lt;/h4&gt;

&lt;p&gt;Generate a random 32byte (256bit) key in hex format:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ aes_key=$(openssl rand -hex 32)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Encrypt our data file with with this key.  For aes256, GCM
mode is preferred.  However, my copy of &lt;code&gt;openssl&lt;/code&gt; doesn&amp;rsquo;t support that,
so we&amp;rsquo;re using a CBC mode.  These are OK.  Do not use EFB!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ openssl enc -aes-256-cbc -K $aes_key -iv 0000000000000000 -in original_data -out encrypted_data
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this case we can use a fixed Initialization Vector (IV) of all
zero&amp;rsquo;s because the AES encryption key itself is only to be used once.
If we were using the key multiple times then we would need a random IV&lt;/p&gt;

&lt;p&gt;Encrypt the AES key with the public key&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ echo &amp;quot;$aes_key&amp;quot; | openssl rsautl -encrypt -pubin -inkey public.pem -out aeskey.enc
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The files &lt;code&gt;aeskey.enc&lt;/code&gt; and &lt;code&gt;encrypted_data&lt;/code&gt; can now be sent to the
recipient (e.g. placing them in their S3 bucket)&lt;/p&gt;

&lt;h2 id=&#34;to-decrypt-the-data&#34;&gt;To decrypt the data&lt;/h2&gt;

&lt;p&gt;The recipient now needs to decode the data, first by extracting the AES key.  Note it uses the private key to do this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ aes_key=$(openssl rsautl -decrypt -inkey private.pem -in aeskey.enc)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now they can decrypt the data file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ openssl enc -d -aes-256-cbc -K $aes_key -iv 0000000000000000 -in encrypted_data -out results
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The file &lt;code&gt;results&lt;/code&gt; matches the &lt;code&gt;original_data&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;This wrapping of a random AES key within an RSA key is a pretty common
technique for transmitting data.&lt;/p&gt;

&lt;p&gt;In this scenario we&amp;rsquo;re not providing any checksum or validation that
the data has been sent by us; we&amp;rsquo;re just ensuring that the data contents
are kept confidential.  This scheme could easily be extended by providing
a checksum file signed with the sender&amp;rsquo;s private key.  The recipient could
use the senders public key to verify the checksum was properly signed,
and the checksum matches the unencrypted datafile&amp;rsquo;s content.&lt;/p&gt;

&lt;p&gt;However, the recipient may be content in knowing that only the permitted
sender is allowed to write to the S3 bucket, and consider this additional
step unnecessary.  After all, they &lt;em&gt;can&lt;/em&gt; see the bucket configuration!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Capital One Breach</title>
      <link>https://www.sweharris.org/post/2019-08-21-capital-one/</link>
      <pubDate>Wed, 21 Aug 2019 11:47:37 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2019-08-21-capital-one/</guid>
      <description>&lt;p&gt;I was asked a question around the &lt;a href=&#34;https://www.capitalone.com/facts2019/&#34;&gt;Capital One breach&lt;/a&gt;.  It seems that, in some areas, fingers are being pointed
at Amazon, and they should be held (at least partly) to blame for this.&lt;/p&gt;

&lt;p&gt;It also seems as if &lt;a href=&#34;https://www.sweharris.org/AmazonLetter080519.pdf&#34;&gt;Senator Wyden&lt;/a&gt; is also
asking Amazon questions around this.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s also a question around Paige Thompson, the hacker, and her
previous relationship as an Amazon employee.  If she used any insider
knowledge to break into Capital One then this would erode a lot of trust
in Amazon&amp;rsquo;s Web Services, and the public cloud in general.&lt;/p&gt;

&lt;p&gt;And, finally, were code repo&amp;rsquo;s used in the attack?  Is there a whole
supply chain issue, here?&lt;/p&gt;

&lt;p&gt;Now I&amp;rsquo;m not convinced about any of this.  Pretty much all the chatter
I&amp;rsquo;ve heard in the InfoSec communities was &amp;ldquo;It&amp;rsquo;s all Capital One&amp;rsquo;s fault&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s not 100% clear from the &lt;a href=&#34;https://assets.documentcloud.org/documents/6224691/Paige-Thompson-DOJ-complaint.pdf&#34;&gt;indictment&lt;/a&gt;, but it looks like the attacker
made use of SSRF on the WAF to access the ec2 metadata URL, which included
role credentials and those credentials were overly broad and gave access
to S3 buckets.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s also not clear if this was a AWS WAF, or a hosted WAF (eg Imperva
WAF, F5 WAF) on an EC2 instance.&lt;/p&gt;

&lt;p&gt;So the first set of questions I have are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why didn&amp;rsquo;t the WAF block the metadata URL?&lt;/li&gt;
&lt;li&gt;Why was the WAF EC2 instance associated with an IAM role?&lt;/li&gt;
&lt;li&gt;Why was the role overly broad?&lt;/li&gt;
&lt;li&gt;Why wasn&amp;rsquo;t the data encrypted in the bucket?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Out of all of this, Amazon themselves may be partially implicated&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If it was an AWS WAF, why doesn&amp;rsquo;t that block the metadata URL by default?&lt;/li&gt;
&lt;li&gt;Did the attacker make use of knowledge obtained when she was working
for Amazon 3 years earlier?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So it&amp;rsquo;s really really looking like a pure Capital One misconfiguration.&lt;/p&gt;

&lt;p&gt;It is Interesting that Capital One created &lt;a href=&#34;https://cloudcustodian.io/&#34;&gt;Cloud
Custodian&lt;/a&gt; to try and detect misconfigs :-)
It&amp;rsquo;s clear that detection is a hard topic, and not necessarily so good
for those &amp;ldquo;unknown&amp;rdquo; edge cases.&lt;/p&gt;

&lt;p&gt;Note: S3 server-side encryption is inadequate because the &lt;em&gt;service&lt;/em&gt;
will decrypt data automatically if you get the right credentials.
I consider it the equivalent of &amp;ldquo;block device encryption&amp;rdquo; or &amp;ldquo;TDE -
Total Database Encryption&amp;rdquo;; an SA or a DBA can still get to the data,
and app level encryption is still required.  &lt;a href=&#34;https://www.sweharris.org/post/2017-06-04-encryption-rest/&#34;&gt;Indeed, I wrote about this 2 years ago!&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So I&amp;rsquo;m not willing to point fingers at Amazon at this stage.&lt;/p&gt;

&lt;p&gt;I don&amp;rsquo;t think code repos were used in the attack; at least
this time there wasn&amp;rsquo;t a supply chain issue!  But the attacker
&lt;em&gt;did&lt;/em&gt; put her results into github, and that may be where some of the
confusion came from.  There&amp;rsquo;s at least one &lt;a href=&#34;https://www.zdnet.com/article/github-sued-for-aiding-hacking-in-capital-one-breach/&#34;&gt;suit being
brought&lt;/a&gt;
against github for allowing this data to be stored there&lt;/p&gt;

&lt;p&gt;Senator Rob Wyden&amp;rsquo;s letter looks a lot like a fishing expedition along
the lines of &amp;ldquo;your customers keep f***ing up; what are you going to do
about it?&amp;ldquo;, with a side helping of &amp;ldquo;you created something easily broken;
you hold some responsibility&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;The thing is that SSRF attacks have been
known for a long time.  Indeed the &lt;a href=&#34;https://www.owasp.org/index.php/Server_Side_Request_Forgery&#34;&gt;OWASP page for
them&lt;/a&gt;
explicitly mentions the metadata service as an example&amp;hellip; and that&amp;rsquo;s
from 2017.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Cloud server meta-data - Cloud services such as AWS provide a REST
interface on &lt;a href=&#34;http://169.254.169.254/&#34;&gt;http://169.254.169.254/&lt;/a&gt; where important configuration
and sometimes even authentication keys can be extracted&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So that adds a new question&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why didn&amp;rsquo;t Capital One pentesters discover this?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now as I was writing this up I came across &lt;a href=&#34;https://www.sweharris.org/081319_Amazon_Letter_to_Sen_Wyden_RE_Consumer_Data.pdf&#34;&gt;Amazon&amp;rsquo;s reply&lt;/a&gt; to Senator Wyden.&lt;/p&gt;

&lt;p&gt;It doesn&amp;rsquo;t really clear up the WAF question, although it &lt;em&gt;feels&lt;/em&gt; to me as
if they&amp;rsquo;re talking about third-party WAFs.  They&amp;rsquo;re definitely putting
the blame at Capital One&amp;rsquo;s feet:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As Capital One outlined in their public announcement, the attack
occurred due to a misconfiguration error at the
application layer of a firewall installed by Capital One, exacerbated
by permissions set by Capital One there were likely broader than intended.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One interesting part of the letter is that they&amp;rsquo;re going to start scanning
their public IP ranges for similar misconfigs, and alert customers.  This
is similar to other sorts of scanning that Amazon pro-actively do (e.g.
searching github for API credentials).&lt;/p&gt;

&lt;p&gt;Is this tacit acknowledgment that they are partially to blame?  Maybe :-)&lt;/p&gt;

&lt;p&gt;My conclusions are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS are not to blame for the breach

&lt;ul&gt;
&lt;li&gt;AWS may have made it too easy for misconfigs to happen&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Github was not used to create the attack; it just stored the results&lt;/li&gt;
&lt;li&gt;This is a pure Capital One f**k up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Summary:&lt;/p&gt;

&lt;p&gt;I really am not a fan of the AWS security model; there&amp;rsquo;s far far too many
knobs and controls, and it&amp;rsquo;s not clear how the interact with each other.
It can be hard to even know something simple (&amp;ldquo;Is this server port 22 open
to the internet?&amp;ldquo;) because of how configurations interact (security groups,
routing tables, network ACLs, etc etc).&lt;/p&gt;

&lt;p&gt;It is critical that any company using the public cloud understand the
technology they are using.  Just because Amazon provide 100+ services doesn&amp;rsquo;t
mean you properly understand how to secure them.  How many data breaches
have occurred because of backups in insecure S3 buckets, for example?&lt;/p&gt;

&lt;p&gt;In the Capital One case, SSRFs and the metadata URL are well known.  It
&lt;em&gt;should&lt;/em&gt; have been detected during application security testing.  There&amp;rsquo;s
more than one problem, here!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>SecDevOps?  DevSecOps?  SecDevSecOpsSec!</title>
      <link>https://www.sweharris.org/post/2019-07-07-devsecops/</link>
      <pubDate>Sun, 07 Jul 2019 14:34:24 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2019-07-07-devsecops/</guid>
      <description>

&lt;p&gt;I was at a conference the other week and the discussion turned to
DevSecOps, and the comment of &amp;ldquo;it should have remained SecDevOps&amp;rdquo; was
made.  Now I&amp;rsquo;m a security guy so I joked that it really should be
&amp;ldquo;SecDevSecOpsSec&amp;rdquo;, which got a laugh.&lt;/p&gt;

&lt;p&gt;But I was actually serious because I feel the focus on DevSecOps is
causing a lot of other work to be missed.&lt;/p&gt;

&lt;h2 id=&#34;devsecops-is-good&#34;&gt;DevSecOps is good&amp;hellip;&lt;/h2&gt;

&lt;p&gt;A lot of the focus on DevSecOps is around improving code quality and
security without harming the productivity enhancements that DevOps has
brought to the table.&lt;/p&gt;

&lt;p&gt;So now security gets &lt;em&gt;embedded&lt;/em&gt; into the coding life cycle.  This may
be during code check-ins, during your CI/CD build pipeline, even
embedded the your IDE itself!  Different quality of results can be
performed a different times; an IDE checker may only perform basic
stuff, but a code merge may kick off a full SAST scan, and the CI/CD
process can do full integration and DAST scans.&lt;/p&gt;

&lt;p&gt;At the end of the day you have a greater level of confidence that your
developer hasn&amp;rsquo;t created a new buffer overflow or SQL Injection attack
vector, that passwords aren&amp;rsquo;t hard coded into the app&amp;hellip; the list goes
on!&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s all good stuff.&lt;/p&gt;

&lt;h2 id=&#34;but-it-s-not-enough&#34;&gt;&amp;hellip; But it&amp;rsquo;s not enough&lt;/h2&gt;

&lt;p&gt;The problem, though, is the &lt;em&gt;focus&lt;/em&gt;.  By concentrating on this code delivery
pipeline we start to forget that there&amp;rsquo;s more to an application than code
delivery.&lt;/p&gt;

&lt;p&gt;How was this application architected?  If you&amp;rsquo;ve stuck a MongoDB (with
default credentials) into your DMZ then you may have the best code delivery
in the world, but you&amp;rsquo;ve delivered an awful result.  How is authentication
in your application handled?  Does the development team even &lt;em&gt;know&lt;/em&gt; what
all the non-functional requirements are to deploy an app of this type?
If you&amp;rsquo;re writing a PCI app, or a HIPAA app, or dealing with PII data&amp;hellip;
Are you deploying to Singapore and so meeting MAS requirements?
Argentina and their Central Bank?  Are you logging properly?
Managing encryption keys?  What impact does this project have on
&lt;em&gt;other&lt;/em&gt; projects?&lt;/p&gt;

&lt;p&gt;So right at the start of the project, Security Architecture needs to be
at the table to ensure these requirements are documented and in place.&lt;/p&gt;

&lt;p&gt;Then we need some oversight; if you&amp;rsquo;re storing data in an S3 bucket
then the Security requirements may define how the bucket needs to be
restricted.  There may be regular validation that the policy hasn&amp;rsquo;t
changed, or that improperly scoped data hasn&amp;rsquo;t been put in the wrong
place (no credit card numbers in a public bucket, please!).&lt;/p&gt;

&lt;p&gt;Products live beyond the life of the primary development team; they
become &amp;ldquo;stable&amp;rdquo; with only minor break-fix changes.  Security monitoring
lives outside of the DevSecOps loop and acts as a check that configuration
and controls haven&amp;rsquo;t drifted.&lt;/p&gt;

&lt;p&gt;And then there&amp;rsquo;s product sunset (your original project plan &lt;em&gt;did&lt;/em&gt; have
a sunset phase, yes?).  Ensuring that EOL applications are properly
handled has more security concerns.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion.&lt;/h2&gt;

&lt;p&gt;DevSecOps is a pretty good solution to a &lt;em&gt;subset&lt;/em&gt; of the problem space.
It can be used to create better code quality, reduce errors (especially
security ones), speed up delivery by reducing the iteration cycle time,
and reduce friction.  All good things!  And the technology is getting
better all the time.&lt;/p&gt;

&lt;p&gt;But the role of security starts at project initiation, it lives through
the DevOps life-cycle, it monitors the result and keeps on monitoring
it even when the product is in &amp;ldquo;maintain&amp;rdquo; state, and is there when the
product is finally decommissioned to ensure secure data destruction and
everything else.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s Sec at the beginning; Sec in the middle; Sec at the end.&lt;/p&gt;

&lt;p&gt;SecDevSecOpsSec; it doesn&amp;rsquo;t trip off the tongue, but it&amp;rsquo;s important!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>When MFA isn&#39;t necessarily strong</title>
      <link>https://www.sweharris.org/post/2019-06-09-softtoken/</link>
      <pubDate>Sun, 09 Jun 2019 12:10:40 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2019-06-09-softtoken/</guid>
      <description>

&lt;p&gt;Every day we hear of yet another data breach.  One common reason is because
of password compromise.  The problem may be because of successfully phishing;
it may be due to password re-use; it may be due to brute force attacks; it
may just be weak passwords.&lt;/p&gt;

&lt;p&gt;So it is now considered best practice to use some form of &lt;a href=&#34;https://www.sweharris.org/post/2017-04-16-twofactor/&#34;&gt;Multi Factor Authentication&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To quickly summarise, MFA is 2-or-more of the following factors:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Something you know.  Typically this is a password&lt;/li&gt;
&lt;li&gt;Something you have.  Maybe a physical token of some form&lt;/li&gt;
&lt;li&gt;Something you are.  This is form of biometric, such as a fingerprint&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You don&amp;rsquo;t &lt;em&gt;repeat&lt;/em&gt; the same factor, so two passwords isn&amp;rsquo;t MFA.&lt;/p&gt;

&lt;h2 id=&#34;factor-strength&#34;&gt;Factor Strength&lt;/h2&gt;

&lt;p&gt;Ideally these are also &lt;em&gt;unique&lt;/em&gt;; it&amp;rsquo;s not just &amp;ldquo;something you know&amp;rdquo;, it&amp;rsquo;s
&amp;ldquo;something &lt;em&gt;only&lt;/em&gt; you know&amp;rdquo;, &amp;ldquo;something &lt;em&gt;only&lt;/em&gt; you have&amp;rdquo;, &amp;ldquo;something &lt;em&gt;only&lt;/em&gt;
you are&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;This unique part isn&amp;rsquo;t a strict requirement, but it feeds into the
strength of a factor.  A PIN that is only 1 digit long (&amp;ldquo;something you
know&amp;rdquo;) isn&amp;rsquo;t very strong &amp;lsquo;cos there&amp;rsquo;s a 1 in 10 chance of guessing it,
and the attacker may have multiple attempts.  A 4 digit PIN on a debit
card may be considered weak, but we can mitigate some of the weaknesses
by limiting the number of attempts.&lt;/p&gt;

&lt;p&gt;That debit card I just mentioned?  It&amp;rsquo;s a factor; &amp;ldquo;something
you have&amp;rdquo;.  Ideally only you have it&amp;hellip; but the card stripe
can be copied so the card duplicated.  This is what &lt;a href=&#34;https://krebsonsecurity.com/all-about-skimmers/&#34;&gt;card
skimmers&lt;/a&gt; do; they read
your card data and store it, allowing for a copy to be made.&lt;/p&gt;

&lt;p&gt;We need to consider how strong a factor is and what mitigations can be put
in place before deciding whether it&amp;rsquo;s suitable to be used as part of an
MFA solution.&lt;/p&gt;

&lt;p&gt;Human factors, of course, play a large part in evaluating the strength
which is why passwords are frequently panned; they can be stolen in so
so many different ways!&lt;/p&gt;

&lt;h2 id=&#34;even-strong-solutions-aren-t-perfect&#34;&gt;Even strong solutions aren&amp;rsquo;t perfect.&lt;/h2&gt;

&lt;p&gt;A very common solution to MFA is a hardware token such as the RSA SecurID.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&#34;https://www.sweharris.org/images/RSA-SecurID.png&#34; alt=&#34;RSA SecurID&#34; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Typically you also need a PIN to go with the token number;
the combination of the PIN+token is the authenticator.&lt;/p&gt;

&lt;p&gt;These are a relatively strong form of &amp;ldquo;something you have&amp;rdquo; because they are
close to impossible to copy; the magic numbers can&amp;rsquo;t be extracted from the
device.&lt;/p&gt;

&lt;p&gt;I say &amp;ldquo;close&amp;rdquo; because there are ways around it.  Is the provider securing
the magic number properly?  In 2011 RSA
&lt;a href=&#34;https://www.theregister.co.uk/2011/03/18/rsa_breach_leaks_securid_data/&#34;&gt;suffered a breach&lt;/a&gt; that &lt;a href=&#34;https://arstechnica.com/information-technology/2011/06/rsa-finally-comes-clean-securid-is-compromised/&#34;&gt;exposed the seed tokens&lt;/a&gt; meaning
that millions of SecurID tokens were compromised.&lt;/p&gt;

&lt;p&gt;But user factors also apply.  One I&amp;rsquo;ve seen, before,
is to just point a webcam at it and expose that webcam to the internet.
Now you can get to your token from anywhere in the world without carrying
it.  Of course this is bad security, but people do things to make life
easier.&lt;/p&gt;

&lt;p&gt;We understand this and accept that some people will be silly.&lt;/p&gt;

&lt;h2 id=&#34;when-similar-solutions-are-totally-different&#34;&gt;When similar solutions are totally different.&lt;/h2&gt;

&lt;p&gt;RSA also provide a &amp;ldquo;soft token&amp;rdquo; solution.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&#34;https://www.sweharris.org/images/RSA-softtoken.jpg&#34; alt=&#34;RSA Soft Token&#34; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;From their brochure:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;First introduced in 2002, RSA SecurID Software tokens are cost-effective,
convenient, and leverage the same algorithm as the RSA SecurID key fob style
token.  Instead of being stored in hardware, the software token symmetric key
is secured on the user&amp;rsquo;s PC, smart phone or USB device.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This sounds great!  All the benefits of SecurID, using the existing
authentication infrastructure, and without the cost of shipping around
physical tokens.  Why wouldn&amp;rsquo;t you want this?&lt;/p&gt;

&lt;p&gt;But is the solution of similar strength?&lt;/p&gt;

&lt;p&gt;A softtoken requires a number of inputs to work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Device ID.  This is used as a form of encryption key to protect the seed.&lt;/li&gt;
&lt;li&gt;The token seed.  This is the primary material used to generate the tokens&lt;/li&gt;
&lt;li&gt;A PIN.  This is a shared secret known to the user and the authentication server&lt;/li&gt;
&lt;li&gt;The current time.&lt;/li&gt;
&lt;li&gt;The algorithm.  This is pretty much &lt;a href=&#34;https://github.com/cernekee/stoken&#34;&gt;public knowledge&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you know all of these things then it&amp;rsquo;s possible to &lt;em&gt;copy&lt;/em&gt; this token.&lt;/p&gt;

&lt;p&gt;Here is where management of the solution is important.&lt;/p&gt;

&lt;p&gt;The RSA SecurID software exposes the Device ID.  This is needed to request
a token in the first place.  The user knows the PIN.  The algorithm is
known, and the time&amp;hellip; well, we better know the time!&lt;/p&gt;

&lt;p&gt;So the security of the solution depends purely on the handling of the
token seed.  And, unfortunately, older solutions (still in use) can
tell the user about this via email.  It typically looks like a URL
of the form&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://127.0.0.1/securid/ctf?ctfData=3D200040994....
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The number after &lt;code&gt;ctfData&lt;/code&gt; is the important part, and this is protected
by the deviceID.&lt;/p&gt;

&lt;p&gt;With this it becomes perfectly possible to import the same data into the
&lt;code&gt;stoken&lt;/code&gt; software:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% stoken import --token http://127.0.0.1/securid/ctf?ctfData=3D200040994...
This token is bound to a specific device.
Enter device ID from the RSA &#39;About&#39; screen: blahblahblah
Enter new password:
Confirm new password:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(Leave the password blank to not encrypt the resulting config file).&lt;/p&gt;

&lt;p&gt;Next we can store the PIN&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% stoken setpin
Enter new PIN:
Confirm new PIN:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This information is stored in a simple config file&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat /home/sweh/.stokenrc
version 1
token 200040994......
pin 12345678
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &amp;ldquo;token&amp;rdquo; value isn&amp;rsquo;t the one from the email; it&amp;rsquo;s been &amp;ldquo;unprotected&amp;rdquo;
using the entered Device ID.  And, no; that&amp;rsquo;s not my PIN!&lt;/p&gt;

&lt;p&gt;And now the moment of truth:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% stoken
31636434
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that matches the number displayed on my phone.  Without needing my
phone or entering the PIN or anything else.&lt;/p&gt;

&lt;p&gt;This is a simple configuration file that can be copied to 100 different
places and all of them will work identically.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s the easy way to get the data.  There&amp;rsquo;s always the hard way;
compromise the device, steal the contents from the phone&amp;rsquo;s storage.&lt;/p&gt;

&lt;p&gt;So, clearly, SecurID soft tokens have different security characteristics
to a hard token.  The data can easily be copied.  We no longer have a strong
&amp;ldquo;only&amp;rdquo; on the &amp;ldquo;something you have&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;We have effectively reduced the strength of SecurID to that of a TOTP
solution such as &amp;ldquo;Google Authenticator&amp;rdquo; or &amp;ldquo;Authy&amp;rdquo;.&lt;/p&gt;

&lt;h2 id=&#34;but-it-still-may-be-good-enough&#34;&gt;But it still may be good enough&lt;/h2&gt;

&lt;p&gt;You can mitigate the problem to some extent; newer SecurID softtoken
solutions can perform auto-registration and hide the token seed from
the user (if you don&amp;rsquo;t see it, you can&amp;rsquo;t copy it!).  You could have
an out-of-band management process that generates new seeds every week
(to limit the exposure of stolen/lost keys).  We can require rootkit
detection processes.&lt;/p&gt;

&lt;p&gt;There are ways of making it stronger.  None are perfect, but security
isn&amp;rsquo;t about &lt;em&gt;perfection&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But even with the weakness of the old system, we have raised the bar
to an attacker.&lt;/p&gt;

&lt;p&gt;Google &lt;a href=&#34;https://security.googleblog.com/2019/05/new-research-how-effective-is-basic.html&#34;&gt;did a study&lt;/a&gt; that showed that even the relatively weak SMS based
2FA protects against all automated bot attacks and 96% of bulk phish attacks.&lt;/p&gt;

&lt;p&gt;On-device authenticators prevented 99% of phish and 90% of targeted attacks.&lt;/p&gt;

&lt;p&gt;So is SecurID Softtoken strong enough, even with the gaps I&amp;rsquo;ve
identified?  Probably!&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;MFA is around gaining a level of confidence that a person authenticating
as a user &lt;em&gt;is&lt;/em&gt; the person authorised to authenticate.  If they have a
password &lt;em&gt;and&lt;/em&gt; a softtoken value then you have more confidence than if
they have a password, alone.&lt;/p&gt;

&lt;p&gt;It becomes a risk management evaluation as to how much money needs to
be spent to raise the bar; going from 0% to 90% is pretty easy; going
from 90% to 95% costs a lot more.&lt;/p&gt;

&lt;p&gt;You need to decide the cost/benefit point for yourself.  No solution is perfect.&lt;/p&gt;

&lt;p&gt;As for me, authy works sufficiently for my personal stuff; if an attacker
really wanted access to my account then this would probably work!&lt;/p&gt;

&lt;p&gt;&lt;a href=https://xkcd.com/538/&gt;&lt;img src=/images/xkcd-security.png&gt;&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Adding some smarts to a dumb aircon</title>
      <link>https://www.sweharris.org/post/2019-06-02-dumb-aircon/</link>
      <pubDate>Sun, 02 Jun 2019 12:26:27 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2019-06-02-dumb-aircon/</guid>
      <description>

&lt;p&gt;I have a Friedrich aircon.  It&amp;rsquo;s of the old school.  The only intelligent
part of it is &amp;ldquo;eco&amp;rdquo; mode (turn off the fan when the temperature is cold
enough) and a simple timer (&amp;ldquo;turn on in 9 hours time&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s this timer that annoys me; you have to set it every day.  A number
of days I would go to work, forgetting to set it, and come home to a house
in the mid-90F.&lt;/p&gt;

&lt;p&gt;So I wondered if there was a way I could remotely control it.  Now I&amp;rsquo;ve
previously played with an Arduino and the IR library and successfully
managed to have it send the POWER signal to the aircon.  Unfortunately
this is a toggle; if the aircon is already on then the signal turns it off.
For remote access I needed to know the current state of the aircon.&lt;/p&gt;

&lt;p&gt;I considered a smart plug to measure the power draw, but this won&amp;rsquo;t work
due to the &amp;ldquo;eco&amp;rdquo; mode.&lt;/p&gt;

&lt;p&gt;The front panel looks like this:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/aircon/air_con_control_panel.jpg&#34; alt=&#34;Friedrich panel&#34;&gt;
&lt;/div&gt;


&lt;p&gt;I thought that if I could detect if any of those LEDs were on then I could
use this as a proxy for if the aircon was &amp;ldquo;on&amp;rdquo; or not.&lt;/p&gt;

&lt;h2 id=&#34;the-hardware&#34;&gt;The hardware&lt;/h2&gt;

&lt;p&gt;Via a reddit chat, I came across a &lt;a href=&#34;https://blog.haschek.at/2018/making-a-smartmeter.html&#34;&gt;post&lt;/a&gt; around reading a smart-meter LED.  This lead me down the
path of a photo-resister.  You put these across an ADC port and a voltage
supply and the resistance of the component changes depending on how much
light is on them.  And they&amp;rsquo;re small; about the same size as the LED!  That
would fit nicely in that area.&lt;/p&gt;

&lt;p&gt;So I tried out a simple design, using a photo-resister, a pull-down resister
and a spare LED blaster I had from previous tests and hooked them to a
NodeMCU ESP8266.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/aircon/test_board.jpg&#34; alt=&#34;Test board&#34;&gt;
&lt;/div&gt;


&lt;p&gt;And it worked; if I covered the photo-resister then the value read from
A0 dropped to zero; if I shone a light on it then the value shot up.&lt;/p&gt;

&lt;p&gt;So now I needed to fit it all into the control panel space.  I decided to
use some doorbell wire left over from the garage project.  Only the IR
transmitter and the resister needed to be inside the panel:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/aircon/cable_with_ir_and_sensor.jpg&#34; alt=&#34;Cable End&#34;&gt;
&lt;/div&gt;


&lt;p&gt;I cut a hole in the side of the door to route the cable through.   I&amp;rsquo;m not
so happy with this; when I open the door it drags on the cable and moves
the photo-resister.  I may need to make the hole bigger.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/aircon/door.jpg&#34; alt=&#34;Drilled Door&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Nicely there was a small gap along the top of the control panel which the
doorbell wire fit into!&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/aircon/panel_with_components.jpg&#34; alt=&#34;Panel with components&#34;&gt;
&lt;/div&gt;


&lt;p&gt;On the ESP side I connected the wire to some cables that let me put it
on the legs.  I didn&amp;rsquo;t want to solder the cable to the board because I
wanted to be able to disconnect it for reprogramming.  I did solder the
pull-down resister to the board, for simplicity:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/aircon/final.jpg&#34; alt=&#34;Final board&#34;&gt;
&lt;/div&gt;


&lt;h2 id=&#34;the-software&#34;&gt;The software&lt;/h2&gt;

&lt;p&gt;So now I have a network accessible board capable of reading the on/off
state (OK, the state of the &amp;ldquo;Eco&amp;rdquo; LED!) and send IR signals to turn on/off
the aircon.   The rest is just a &lt;a href=&#34;https://github.com/sweharris/esp8266-aircon&#34;&gt;simple matter of programming&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Essentially I make the ESP send the current state of the sensor on an MQTT
queue once a second.  On another queue it can receive commands (&amp;ldquo;POWER ON&amp;rdquo;,
&amp;ldquo;POWER OFF&amp;rdquo;, &amp;ldquo;POWER&amp;rdquo;) and depending on the state of the sensor it can decide
whether to send an IR signal or not.  I had to use a rolling average of
the sensor readings because point readings weren&amp;rsquo;t too accurate.  But it
works!&lt;/p&gt;

&lt;h2 id=&#34;alexa-integration&#34;&gt;Alexa integration&lt;/h2&gt;

&lt;p&gt;It&amp;rsquo;s now pretty easy to add a &lt;a href=&#34;http://mercury7:1313/post/2018-11-19-virtual_hue_light/&#34;&gt;fake Hue bulb&lt;/a&gt;.  A loop can read the status channel&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/bin/ksh -p

# Dining Room Aircon

STATUS=${1:-/tmp/aircon}

temp=0
/home/sweh/bin/mqttcli sub --host hass -t aircon/EA42DF/status | while read line
do
  kill -0 $PPID 2&amp;gt;/dev/null || exit

  print $line &amp;gt; $STATUS
done
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So now the main program just has two simple functions:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;get_aircon()
{
  SWITCH[&amp;quot;DiningRoomAirCon&amp;quot;]=$(cat $AIRCON_STATUS)
}

set_aircon()
{
  /home/sweh/bin/mqttcli pub --host hass.spuddy.org -t aircon/EA42DF/control -m &amp;quot;POWER$1&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At this point I can now say &amp;ldquo;Alexa, turn the dining room aircon on&amp;rdquo;&amp;hellip; and
it works!&lt;/p&gt;

&lt;p&gt;And the first thing I did at that point was to add a &amp;ldquo;power off&amp;rdquo; to my
bedtime routine, because I&amp;rsquo;ve lost count of the number of times I&amp;rsquo;ve gone
to bed forgetting to turn the aircon off and been woken up as the compressor
kicks in (I&amp;rsquo;m a light sleeper).&lt;/p&gt;

&lt;h2 id=&#34;home-assistant-automation&#34;&gt;Home Assistant Automation&lt;/h2&gt;

&lt;p&gt;HA integration is also simple; just point to the message queues:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;switch:
  - platform: mqtt
    name: &amp;quot;Air Con&amp;quot;
    state_topic: &amp;quot;aircon/EA42DF/status&amp;quot;
    command_topic: &amp;quot;aircon/EA42DF/control&amp;quot;
    state_on: &amp;quot;ON&amp;quot;
    state_off: &amp;quot;OFF&amp;quot;
    payload_on: &amp;quot;POWER ON&amp;quot;
    payload_off: &amp;quot;POWER OFF&amp;quot;
&lt;/code&gt;&lt;/pre&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/aircon/aircon_status.png&#34; alt=&#34;HA status&#34;&gt;
&lt;/div&gt;


&lt;h2 id=&#34;plans-and-limitations&#34;&gt;Plans and limitations&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s still a limitation with this; I don&amp;rsquo;t know what the temperature is
set to.  But since I rarely change this (68F setting appears to make the
living room around 78-80F, which is comfortable) I&amp;rsquo;m not too worried.&lt;/p&gt;

&lt;p&gt;More interesting is the ability to now &lt;em&gt;control&lt;/em&gt; this via home assistant.
I already have a reading from my smart thermostat, so I know how warm the
living room is.  It&amp;rsquo;s possible I could set up an automation for something
like &amp;ldquo;if the living room is over 85F then turn on air-con&amp;rdquo;.  I&amp;rsquo;d probably
time-bound this so it only does it between 2pm and 9pm.  Also need to work
out how to not send the &amp;ldquo;ON&amp;rdquo; signal every 30 seconds :-).&lt;/p&gt;

&lt;p&gt;All possible and feasible.&lt;/p&gt;

&lt;p&gt;The result may not be a smart aircon, but it&amp;rsquo;s not as brain-dead as it was
before!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Extending automation to the garage</title>
      <link>https://www.sweharris.org/post/2019-05-19-garage/</link>
      <pubDate>Sun, 19 May 2019 12:03:45 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2019-05-19-garage/</guid>
      <description>

&lt;p&gt;My garage door is controlled my a Lynx 455 Plus garage opener&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/HA/lynx455.jpg&#34; alt=&#34;Lynx 455/Plus&#34;&gt;
&lt;/div&gt;


&lt;p&gt;This is a pretty traditional opener; a door-bell type button inside
the garage to open/close the door and a remote control for wireless
access.&lt;/p&gt;

&lt;p&gt;I wanted to see if I could make this smart-enabled.  Now the control
side is simple enough; just put a relay in parallel to the button.  If
the relay closes then the opener will think the button has been pressed.&lt;/p&gt;

&lt;p&gt;It would also be nice to have a sensor to detect if the door is open or
not.  For this a magnetic reed switch would work.  Mount the switch to
the frame and stick the magnet to the door.  When the door is closed
the switch activates (e.g. closes or opens, depending on if the switch
is &amp;ldquo;NC - normally closed&amp;rdquo; or &amp;ldquo;NO - normally open&amp;rdquo;) and when the door
opens the magnet moves away from the reed switch and the state changes.&lt;/p&gt;

&lt;p&gt;So the concept is easy, but what we can use to put all this together?&lt;/p&gt;

&lt;p&gt;Enter the &lt;a href=&#34;https://shelly.cloud/shelly1-open-source/&#34;&gt;Shelly 1&lt;/a&gt;.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/HA/shelly1.jpg&#34; alt=&#34;Shelly 1&#34;&gt;
&lt;/div&gt;


&lt;p&gt;This is a small device.  In some respects it&amp;rsquo;s a competitor to Sonoff switches
but has some nice features.  In particular it has a &amp;ldquo;switch sense&amp;rdquo;
line.  By default this controls the relay, but in the latest firmware
that can be disconnected and acts purely as a sensor.  Nicely this
device can also be powered from low voltage DC and the garage door
opener has 24V DC available, so this looked perfect for my needs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Spoiler: it turned out that the 24V from the opener wasn&amp;rsquo;t stable
enough to drive this, so I had to run a power line anyway.  But everything
else went to plan!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For Sonoff fans, the Shelly 1 &lt;em&gt;can&lt;/em&gt; be flashed with Tasmota firmware,
but I didn&amp;rsquo;t feel the need.  The latest firmware did everything I need
out of the box.&lt;/p&gt;

&lt;p&gt;The Shelly 1 &lt;em&gt;can&lt;/em&gt; also be connected to a cloud for remote control,
but I didn&amp;rsquo;t want this so I never enabled it.  Indeed I wanted other
functionality (MQTT) which prevents cloud action.  So all control
is local.&lt;/p&gt;

&lt;h2 id=&#34;setting-up-the-shelly-1&#34;&gt;Setting up the Shelly 1&lt;/h2&gt;

&lt;p&gt;On first powerup the Shelly works as a WiFi access point.  From here
connect a device (I used a Chromebook, but a phone would work), browse
to the configuration page, tell it to become a WiFi client of your normal
WiFi network.  And that&amp;rsquo;s all it takes to make it reachable.  I also added
a username/password requirement.  It&amp;rsquo;s only &amp;ldquo;basic auth&amp;rdquo; over a http
connection, so it&amp;rsquo;s not very secure, but at least it stops accidents.&lt;/p&gt;

&lt;p&gt;For the garage door opener use case I configured the &amp;ldquo;Settings&amp;rdquo; page
so that on power-up the device defaults to OFF.  I set the button type
to &amp;ldquo;Detached switch&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;On the &amp;ldquo;Internet and Security&amp;rdquo; tab, under advanced settings I configured
MQTT to point to an MQTT server on my HA machine.  Note that the server
has to be specified by IP address (eg 10.20.30.40:1883) and can not be
SSL enabled.  Fortunaly the common &amp;ldquo;mosquito&amp;rdquo; server works just fine, and
is common in HA setups.&lt;/p&gt;

&lt;p&gt;In case it helps, I also set up the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Min reconnect timeout: 2
Max reconnect timeout: 60
Keep alive: 60
Clean Session: y
Retain: n
Max QoS: 0
Will Topic: shellies/shelly-garage/online
Will Message: true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On the &amp;ldquo;Timer&amp;rdquo; tab I set &amp;ldquo;Auto Off: When ON Turn off after 2 seconds&amp;rdquo;.
What this means is that when the relay is triggered then it will auto
turn off after 2 seconds, so it acts like a press and release of the
button.  At least that&amp;rsquo;s how it will look to the door opener!&lt;/p&gt;

&lt;h2 id=&#34;monitor-and-control&#34;&gt;Monitor and control&lt;/h2&gt;

&lt;p&gt;Now with this running we should be able to see regular output messages
on the MQTT server.  The exact queue name will depend on the device ID.
In my case I can see&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% mqttcli sub -d --host hass -t shellies/shelly1-24DCEF/input/0
INFO[0000] Broker URI: tcp://hass:1883                  
INFO[0000] Topic: shellies/shelly1-24DCEF/input/0       
INFO[0000] connecting...                                
INFO[0000] client connected                             
INFO[0003] topic:shellies/shelly1-24DCEF/input/0 / msg:1 
1
INFO[0008] topic:shellies/shelly1-24DCEF/input/0 / msg:1 
1
INFO[0013] topic:shellies/shelly1-24DCEF/input/0 / msg:1 
1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So every 5 seconds there&amp;rsquo;s a message showing the state of the switch.
In this case the switch is closed.  If the switch was open then it
would show a 0.  Interestingly a state change causes a message to be
sent immediately.&lt;/p&gt;

&lt;p&gt;We can also control the relay by sending a message to the API&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;curl -X POST -u user:pass http://shelly-garage/relay/0 -d &#39;turn=on&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(&amp;ldquo;shelly-garage&amp;rdquo; is the DNS name I set for the Shelly).  This should turn
the relay on (you&amp;rsquo;ll hear it click) and then the timer should auto-turn it
off after 2 seconds.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s also possible
to control the relay by publishing to an MQTT queue, but I didn&amp;rsquo;t do that.&lt;/p&gt;

&lt;h2 id=&#34;alexa-integration&#34;&gt;Alexa integration&lt;/h2&gt;

&lt;p&gt;Now we&amp;rsquo;re in a position to start controlling things!&lt;/p&gt;

&lt;p&gt;Because I wanted to control this from Alexa, I used my &lt;a href=&#34;https://www.sweharris.org/post/2018-11-19-virtual_hue_light/&#34;&gt;fake Hue&lt;/a&gt; software to make it pretend to be a bulb.&lt;/p&gt;

&lt;p&gt;Reading the switch status was done with a background process:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/bin/ksh -p

# ON means Garage is open

STATUS=${1:-/tmp/garage}

temp=0
mqttcli sub --host hass -t shellies/shelly1-24DCEF/input/0 | while read line
do
  kill -0 $PPID 2&amp;gt;/dev/null || exit

  if [ $line == 1 ]
  then
    onoff=OFF
  else
    onoff=ON
  fi
  print $onoff &amp;gt; $STATUS
done
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I did it this way so the main loop just needs to read the &lt;code&gt;/tmp/garage&lt;/code&gt; file
to get the state, with no delays.&lt;/p&gt;

&lt;p&gt;Now there&amp;rsquo;s no true open/close control for this door; you just press the
button.  So for simplicity I just make on/off call the same function.
The routines used in the &lt;code&gt;media&lt;/code&gt; loop look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;get_garage()
{
  SWITCH[&amp;quot;GarageDoor&amp;quot;]=$(cat $GARAGE_STATUS)
}

set_garage()
{
  curl --max-time 2 -X POST -u user:pass http://shelly-garage/relay/0 -d &#39;turn=on&#39;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this fake switch discovered by Alexa I could now say &amp;ldquo;alexa turn garagedoor on&amp;rdquo; and the door opens.  Similarly &amp;ldquo;alexa turn garagedoor off&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s easy to create a routine now:  &amp;ldquo;Alexa open the garage door&amp;rdquo; and even
&amp;ldquo;Alexa open the pod bay doors&amp;rdquo; just calls the smart home bulb on function.&lt;/p&gt;

&lt;h2 id=&#34;monitor-and-alert-from-home-assistant&#34;&gt;Monitor and alert from Home Assistant&lt;/h2&gt;

&lt;p&gt;I thought it would be nice to have an alert whenever the door was opened
or closed.  Enter HA.&lt;/p&gt;

&lt;p&gt;First we need to set up a sensor to read the state of the switch:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sensor:

  - platform: mqtt
    name: &amp;quot;Garage Door&amp;quot;
    state_topic: &amp;quot;shellies/shelly1-24DCEF/input/0&amp;quot;
    value_template: &amp;gt;
      {% if value == &amp;quot;1&amp;quot; %}
        closed
      {% else %}
        open
      {% endif %}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This creates a sensor called &lt;code&gt;sensor.garage_door&lt;/code&gt; and has a state of
&amp;ldquo;open&amp;rdquo; or &amp;ldquo;closed&amp;rdquo;.  In my case my reed switch returns a &amp;ldquo;1&amp;rdquo; when the
door is closed.  If the switch you use returns a &amp;ldquo;0&amp;rdquo; then just change
this line.&lt;/p&gt;

&lt;p&gt;With this we can add a badge to the standard Lovelace UI&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    - sensor.garage_door
&lt;/code&gt;&lt;/pre&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/HA/garage_door_badge.png&#34; alt=&#34;Badge&#34;&gt;
&lt;/div&gt;


&lt;p&gt;An automation can now be triggered on the change of state of the door&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;- alias: Detect Garage
  initial_state: true
  trigger:
    platform: state
    entity_id: sensor.garage_door
  action:
    service: notify.alexa_media
    data_template:
      target: 
        - media_player.living_room
        - media_player.kitchen
        - media_player.stairs
      data:
        type: announce
      message: &amp;gt;
        {% if trigger.to_state.state == &amp;quot;closed&amp;quot; %}
        &amp;quot;Garage Door Closed&amp;quot;
        {% else %}
        &amp;quot;Garage Door Opened&amp;quot;
        {% endif %}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This makes use of the &lt;code&gt;alexa_media&lt;/code&gt; component.&lt;/p&gt;

&lt;h2 id=&#34;physically-setting-it-up&#34;&gt;Physically setting it up.&lt;/h2&gt;

&lt;p&gt;All the work, so far, can be done on a bench.&lt;/p&gt;

&lt;p&gt;Basically the wiring is as follows:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/HA/shelly_wiring.jpg&#34; alt=&#34;Wiring&#34;&gt;
&lt;/div&gt;


&lt;p&gt;The 0/1 lines should be connected, in parallel, to the existing button
push.  It doesn&amp;rsquo;t matter what way round the wires go.&lt;/p&gt;

&lt;p&gt;The SW and L lines should be connected to the reed switch.  Again it
doesn&amp;rsquo;t matter what way round the wires go.&lt;/p&gt;

&lt;p&gt;Finally the L and N should be connected to the power.  Since we&amp;rsquo;re using
low power DC the L should be connected to ground and the N connected to
the + voltage.  This &lt;em&gt;sounds&lt;/em&gt; backwards, but it&amp;rsquo;s not.&lt;/p&gt;

&lt;p&gt;My original intent was to use the 24V power line from the door opener, but
when I tried the Shelly just didn&amp;rsquo;t power up at all.  So in the end I used
a 12V power supply; cut the plug off it and connected the cables to the
terminals.&lt;/p&gt;

&lt;h2 id=&#34;future-state&#34;&gt;Future state&lt;/h2&gt;

&lt;p&gt;Going forwards I would like the HA notifications to be location aware.
For example if I&amp;rsquo;m away from home and the garage door is opened then ping
my phone.  Or if I&amp;rsquo;m leaving home and the garage door was left open then
alert me.  I haven&amp;rsquo;t yet found a good location tracker for HA that works
with my Android phone, so that&amp;rsquo;s still a work in progress.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Slowly making my home smart</title>
      <link>https://www.sweharris.org/post/2019-05-19-smarthome/</link>
      <pubDate>Sun, 19 May 2019 11:18:10 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2019-05-19-smarthome/</guid>
      <description>&lt;p&gt;This post isn&amp;rsquo;t in my normal theme.  I&amp;rsquo;m gonna describe how I made my
home smart.  Well, semi-smart.&lt;/p&gt;

&lt;p&gt;Over the past couple of years I&amp;rsquo;ve slowly been making my house lights be
smart.  In many places I&amp;rsquo;ve used &lt;a href=&#34;https://www2.meethue.com/en-us/p/hue-white-single-bulb-e26/046677530341&#34;&gt;Hue White Bulbs&lt;/a&gt;.  They&amp;rsquo;re frequently on sale
and can be got for around $10/bulb, which isn&amp;rsquo;t bad.  With the hub they
can be controlled by Alexa, or locally by using the API exposed on the hub.&lt;/p&gt;

&lt;p&gt;Where I can&amp;rsquo;t use Hue, I&amp;rsquo;ve been using &lt;a href=&#34;https://www.casetawireless.com/products/dimmers-switches&#34;&gt;Lutron Caseta&lt;/a&gt; switches.  These can work without a
neutral wire, so are a great retrofit for older houses.  It also has a
hub that works with Alexa, and some smart people have worked out how to
talk to the hub with python libraries.&lt;/p&gt;

&lt;p&gt;I was able to extend the use of Alexa to other areas by &lt;a href=&#34;https://www.sweharris.org/post/2018-11-19-virtual_hue_light/&#34;&gt;emulating Hue
bulbs&lt;/a&gt;.  So now when I come home
I can say &amp;ldquo;Alexa I&amp;rsquo;m home&amp;rdquo; and it will turn on the living room lights
and start iTunes playing on the media center (turning on stuff that&amp;rsquo;s
needed).  Other routines (&amp;ldquo;Alexa I&amp;rsquo;m going out&amp;rdquo;, &amp;ldquo;Alexa bedtime&amp;rdquo;) do
other useful stuff.&lt;/p&gt;

&lt;p&gt;I replaced my thermostat with a &lt;a href=&#34;https://www.radiothermostat.com/product-page/ct50-wi-fi-smart-thermostat&#34;&gt;Radio Thermostat
CT50&lt;/a&gt;.
This has a local API, so with my &amp;ldquo;fake hue&amp;rdquo; software I was also able to
add basic Alexa controls.&lt;/p&gt;

&lt;p&gt;But this is just the beginning.&lt;/p&gt;

&lt;p&gt;Enter &lt;a href=&#34;https://www.home-assistant.io/&#34;&gt;Home Assistant&lt;/a&gt;.  This is an
open source program written in python.  It can be run in docker, on a
Pi, as a VM, or inside a python &lt;code&gt;venv&lt;/code&gt;.  I chose the latter approach;
created a CentOS VM (chosen so all my management tools work with it)
and deployed HA.&lt;/p&gt;

&lt;p&gt;HA can integrate with Hue via the API, with Caseta via the previously
mentioned python libraries.  Someone even worked out how to talk to the
Alexa service (although it&amp;rsquo;s really not production ready).  This lets
me create a reporting interface such as&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/HA/all_the_stuff.png&#34; alt=&#34;all the things&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Or a simpler &amp;ldquo;light&amp;rdquo; panel.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/HA/all_the_lights.png&#34; alt=&#34;all the lights&#34;&gt;
&lt;/div&gt;


&lt;p&gt;These panels are reactive; if a light turns on then the corresponding
icon lights up.  You can also &lt;em&gt;control&lt;/em&gt; the lights from here; click on
a light and it will turn on/off the real light.&lt;/p&gt;

&lt;p&gt;OK, so far so controllable.  It&amp;rsquo;s providing interesting and new ways of
looking and managing the environment.  But there&amp;rsquo;s no smarts.&lt;/p&gt;

&lt;p&gt;Enter the &amp;ldquo;automation&amp;rdquo; part of HA.&lt;/p&gt;

&lt;p&gt;Firstly, my basement has two sets of old-school florescent bulbs; one
by the stairs and controlled by a switch outside the basement, and one
in the back (where I have my computers set up), controlled by another switch.
I wanted to treat these lights as one.  So if I turn on the basement light
then the one by the computer also turn on.&lt;/p&gt;

&lt;p&gt;With HA you can write a trigger:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;- alias: Basement Automation Turn On
  initial_state: true
  trigger:
    - platform: state
      entity_id: switch.basement_computer_lights, switch.basement_main_lights
      from: &#39;off&#39;
      to: &#39;on&#39;
  action:
    service: switch.turn_on
    entity_id:
      - switch.basement_computer_lights
      - switch.basement_main_lights
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This basically says that if either of the Caseta light switches are turned
on then make sure they&amp;rsquo;re both turned on.  There&amp;rsquo;s also an equivalent &amp;ldquo;off&amp;rdquo;
function (not shown); if one is turned off then both are turned off.  Now HA doesn&amp;rsquo;t
get instant notification of changes because it has to poll the hub, but
it generally fires within 3 to 5 seconds, which is good enough.&lt;/p&gt;

&lt;p&gt;We can also use this idea to cross environments.  In my laundry room I have
two Hue bulbs and a motion sensor.  When I enter the room the motion
sensor detects it, checks the lights levels and turns on the bulbs if necessary.  This is out of box Hue functionality.  But we can set up an automation
that detects the bulbs turn on and also turn on the florescent bulb in
that area.  This one is a bit more complicated because I&amp;rsquo;ve combined
on/off functionality &lt;em&gt;and&lt;/em&gt; the Caseta switch detection into one routine.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;- alias: Laundry Automation
  initial_state: true
  trigger:
    - platform: state
      entity_id: switch.laundry_main_lights, light.laundry
      from: &#39;off&#39;
      to: &#39;on&#39;
    - platform: state
      entity_id: switch.laundry_main_lights, light.laundry
      from: &#39;on&#39;
      to: &#39;off&#39;
  action:
    - service_template: &amp;gt;
        {% if trigger.to_state.state == &amp;quot;on&amp;quot; %}
        switch.turn_on
        {% else %}
        switch.turn_off
        {% endif %}
      entity_id: switch.laundry_main_lights
    - service_template: &amp;gt;
        {% if trigger.to_state.state == &amp;quot;on&amp;quot; %}
        light.turn_on
        {% else %}
        light.turn_off
        {% endif %}
      entity_id: light.laundry
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The result is that I can walk into the laundry room and all 3 lights
turn on, and a few minutes after I leave the hue motion sensor turns off
the Hue bulbs and all the lights go out.  Or I can manually turn on/off
the florescent bulb from the Caseta switch and the Hue bulbs will follow.&lt;/p&gt;

&lt;p&gt;This is just the beginning of making my home smart.  Just with what I&amp;rsquo;ve
got I could set up triggers based on, for example, sunset.  In most cases
I&amp;rsquo;m happy to have trigger based routines (&amp;lsquo;Alexa foobarbaz&amp;rsquo;) but it&amp;rsquo;s
nice to have the laundry lights work when my hands are full with a basket
of dirty clothes.&lt;/p&gt;

&lt;p&gt;Which reminds me&amp;hellip; I need to do laundry!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Emulating a Philips Hue light</title>
      <link>https://www.sweharris.org/post/2018-11-19-virtual_hue_light/</link>
      <pubDate>Mon, 19 Nov 2018 12:42:40 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2018-11-19-virtual_hue_light/</guid>
      <description>&lt;p&gt;Over the past couple of years I&amp;rsquo;ve been building out an Alexa skill for
my media center.  So now I can say things like &amp;ldquo;Alexa, tell media to play
music&amp;rdquo;.  That will turn my receiver on, switch it to the Mac input, and
start iTunes playing.  Similarly &amp;ldquo;Alexa, tell media to switch to TiVo&amp;rdquo;,
&amp;ldquo;Alexa tell media to pause&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;The backend code running on the Mac asks the receiver what input is
selected (TiVo, Mac, BluRay&amp;hellip;) and if on the Mac it works out what
application has focus (iTunes, DVD Player, Kodi, &amp;hellip;) so when a command
such as &amp;ldquo;pause&amp;rdquo; is received then it knows how to send the appropriate
action.&lt;/p&gt;

&lt;p&gt;This works pretty well.  But there&amp;rsquo;s a problem.  Skill actions can&amp;rsquo;t
(currently, anyway) be used in routines.  So I can not say &amp;ldquo;Alexa, I&amp;rsquo;m
home&amp;rdquo; and have it turn on the lights and start playing music.&lt;/p&gt;

&lt;p&gt;However, home automation devices &lt;em&gt;can&lt;/em&gt; be used in routines.  Since I
have a Philips Hue setup (&amp;ldquo;Alexa lights on&amp;rdquo;) I wondered if I could
create fake lights and have those lights map to actions.&lt;/p&gt;

&lt;p&gt;Looking around I found a number of Hue emulators; some in python, some
in perl, Java, Go&amp;hellip; However they were all &amp;ldquo;monoliths&amp;rdquo;.  They came with
a core library and then you added your own routines (&amp;ldquo;create this
light&amp;rdquo;).  None of them really worked the way I wanted.&lt;/p&gt;

&lt;p&gt;My plan was to have a &amp;ldquo;bridge&amp;rdquo; routine.  This would handle all the low
level API layer stuff (UPNP discovery, Hue API, etc) but wouldn&amp;rsquo;t do
any real work itself.  Instead there would be a child process that would
do the hard work.  This could be written in any language (e.g. bash)
and would communicate with the bridge via stdio, using a very simple
set of primitives.&lt;/p&gt;

&lt;p&gt;So now when the virtual light was turned on the bridge code would send
a &amp;ldquo;Turn on&amp;rdquo; message to the child, which can take any action it needs
to, and send a response back.  The bridge caches the response so that
status requests can be handled quickly, but the child can send updates
whenever it likes.&lt;/p&gt;

&lt;p&gt;This now allows the real world to be modelled.  If I turn the volume
up on the receiver then the child can send an updated &amp;ldquo;brightness&amp;rdquo;
value to the bridge, and anyone using the Hue API to get the status
will see the new value.  Similarly lights could be linked; if I switch
to BluRay input then that virtual light would be turned on, and the Mac,
TiVo lights automatically turned off.&lt;/p&gt;

&lt;p&gt;The Alexa app makes it seem like a normal bulb with brightness
&lt;center&gt;
&lt;img src=&#34;https://www.sweharris.org/images/Alexa_MediaPower.jpg&#34; alt=&#34;Bulb&#34; /&gt;
&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;The resulting code is &lt;a href=&#34;https://github.com/sweharris/huebridge-shell&#34;&gt;HueBridge&lt;/a&gt;.
I wrote the bridge code in Go.  There&amp;rsquo;s a simple shell script example
(&lt;code&gt;test-media&lt;/code&gt;) that shows how this might be used to control a media
system.&lt;/p&gt;

&lt;p&gt;Using this code I&amp;rsquo;ve also created a virtual &amp;ldquo;Christmas Music&amp;rdquo; light.
So in a month&amp;rsquo;s time I can say &amp;ldquo;Alexa, it&amp;rsquo;s Christmas!&amp;rdquo; and it&amp;rsquo;ll turn
on the tree lights (via a TP-Link power switch) and start playing
Slade&amp;rsquo;s &amp;ldquo;Merry Christmas Everyone&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Now that&amp;rsquo;s a good use for Smart Home technology!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Career advice</title>
      <link>https://www.sweharris.org/post/2018-10-08-career/</link>
      <pubDate>Mon, 08 Oct 2018 09:43:12 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2018-10-08-career/</guid>
      <description>&lt;p&gt;I get email&amp;hellip;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;What are your thoughts about making a career out of specialising in  Unix? It seems like you&amp;rsquo;ve done quite well&amp;hellip;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Interesting question&amp;hellip;&lt;/p&gt;

&lt;p&gt;Realise that I started doing this 30 years ago.  At that time there was
no Windows (Windows 1.0 was around the corner).  We had DOS.  Networking
was mostly serial based; if you were (un)lucky you might have had Banyon
Vines or Novell or some other proprietary network stack.&lt;/p&gt;

&lt;p&gt;Since my course work was hosted on Sun machines and the Microcomputer
Society had access to the Physics Dept Unix machines, I kinda fell into
Unix my default.  So I taught myself DOS, PC hardware&amp;hellip; and Unix.&lt;/p&gt;

&lt;p&gt;If the coursework had been on the Vax cluster then I might have been a
VMS person instead :-)  [ I just built a virtual cluster, using simh so
I can see what I missed out on! ]&lt;/p&gt;

&lt;p&gt;I got lucky; in particular the TCP/IP networking stack finally got
ported to the Microsoft world so I didn&amp;rsquo;t really miss anything by avoiding
all that messy stuff!&lt;/p&gt;

&lt;p&gt;But what I also learned was the lower levels; cabling, networking, telecoms,
databases, appdev, security&amp;hellip;&lt;/p&gt;

&lt;p&gt;So I&amp;rsquo;m a generalist, but with a Unix speciality focus.  After all, I&amp;rsquo;ve been
doing Unix for 30 years; I can do a lot of it in my sleep :-)&lt;/p&gt;

&lt;p&gt;Now, for you, it depends on what you want to be.&lt;/p&gt;

&lt;p&gt;Looking forward, I can see Unix (Linux, really) remaining a core product
on the internet.  I read a story recently (I can&amp;rsquo;t find the link) that said
that even on Azure, half of the VMs running are Linux based.  On AWS, of
course, it&amp;rsquo;s the vast majority.&lt;/p&gt;

&lt;p&gt;If you want to be a &amp;ldquo;full stack&amp;rdquo; developer, understanding Linux is very
beneficial; it&amp;rsquo;ll let you tune your app, understand why things work the
way they do.&lt;/p&gt;

&lt;p&gt;If you want to be a server sysadmin then Linux is the way to go; Windows
servers are great for supporting windows workstations but I can see that
become less important as things go cloudy (why run Active Directory servers,
when Microsoft can do it for you?  Why run fileservers when&amp;hellip;  When
all your desktop apps are cloudy SaaS offerings in Office365, who needs
on-prem servers?).   But sysadmin will be more &amp;ldquo;Infrastructure as Code&amp;rdquo;
related, so learning to script and automate will be essential.&lt;/p&gt;

&lt;p&gt;Desktop side is going to be Windows for a long time, even with the cloud;
they may be &lt;em&gt;virtual&lt;/em&gt; desktops running in Azure, but they&amp;rsquo;ll still be there,
so will have all the requirements around management (antivirus, privilege
control, etc etc).  Personally I find that tedious, but there&amp;rsquo;s a lot of
engineering work going into taking the Microsoft product and making it
suitable for Enterprise deployments.&lt;/p&gt;

&lt;p&gt;If you want to be an architect then spreading your awareness out of
one area and looking at others will help.  Or you could look at stuff
higher up the stack (eg Identity and Access Management; firewalls;
intrusion detection/prevention; monitoring; vulnerability scanning) which
may cross technology towers.&lt;/p&gt;

&lt;p&gt;Ugh, this got a bit long&amp;hellip;&lt;/p&gt;

&lt;p&gt;Summary: I don&amp;rsquo;t think you can go wrong, learning Unix.  This can be the
foundation and core skill set.  But it shouldn&amp;rsquo;t be the &lt;em&gt;only&lt;/em&gt; skill.
The more you know around how things fit together the better a technologist
you&amp;rsquo;ll be, and the more valuable your core skills become.  &amp;ldquo;I can do
&lt;em&gt;this&lt;/em&gt; with Unix&amp;rdquo; is great; &amp;ldquo;Here&amp;rsquo;s a problem, I know how to put A, B, C
together and solve it&amp;rdquo; is even better!&lt;/p&gt;

&lt;p&gt;Hope this helps :-)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>When Development is Production</title>
      <link>https://www.sweharris.org/post/2018-09-23-devisprod/</link>
      <pubDate>Sun, 23 Sep 2018 18:56:06 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2018-09-23-devisprod/</guid>
      <description>

&lt;p&gt;It&amp;rsquo;s an article of faith that the development process starts in
the part of the network set aside for development work.  Then the
code may go to the QA area for QA testing, UAT area for UAT, production
area for production.&lt;/p&gt;

&lt;p&gt;That statement almost looks like a truism; development work is done in
DEV.&lt;/p&gt;

&lt;p&gt;So a corporate network may be divided along dev/uat/prod lines, with
firewalls between them so that development code can&amp;rsquo;t impact production
services.  After all, we don&amp;rsquo;t want some development code that&amp;rsquo;s doing
application schema updates to accidentally drop the production database!&lt;/p&gt;

&lt;p&gt;But this is not always true.&lt;/p&gt;

&lt;h2 id=&#34;development-is-production&#34;&gt;Development is production&lt;/h2&gt;

&lt;p&gt;For the development team, themselves, they have expectations on the
platform infrastructure to be available so they can do their work.
If the VMware team decides to test a new patch set in the DEV environment
and brings down the development cluster then they&amp;rsquo;re gonna have a lot of
annoyed developers banging on the door.  Depending on the severity of
the outage this could cause application delivery timelines to slip,
for contracted delivery dates to be broken and cause actual financial
impact to the company.&lt;/p&gt;

&lt;p&gt;Further, some of the core infrastructure may be shared between
environments.  The SAN arrays may have LUNs assigned to DEV machines
and to PROD machines; networking switches (due to VLANs and trunks,
inter-datacenter links) may share paths.&lt;/p&gt;

&lt;p&gt;So if you&amp;rsquo;re going to do something that may impact core infrastructure
or large numbers of development machines, you don&amp;rsquo;t start in DEV&amp;hellip; you
start even earlier.&lt;/p&gt;

&lt;h2 id=&#34;the-lab-is-for-more-than-use-proof-of-concept-tests&#34;&gt;The lab is for more than use Proof of Concept tests&lt;/h2&gt;

&lt;p&gt;A lot of people think of &amp;ldquo;lab environments&amp;rdquo; as places to do tests.  &amp;ldquo;Hey,
we want to test out some piece of software, see if it does what we want.
Let&amp;rsquo;s spin up a proof of concept in the lab.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;And, yes, that&amp;rsquo;s the right place to do it.  Labs are typically isolated
from the main networks and needing jumphosts or bastion hosts to be
accessed in order to get to the machines.  They will have separate network
infrastructure, separate Active Directory domains.  They&amp;rsquo;re probably not
as well managed and domain admin privileges may be easy to get.  This
leads to some levels of instability.&lt;/p&gt;

&lt;p&gt;But despite this, the lab is also where &lt;em&gt;sustained engineering&lt;/em&gt; processes
start.&lt;/p&gt;

&lt;h2 id=&#34;sustained-engineering&#34;&gt;Sustained engineering&lt;/h2&gt;

&lt;p&gt;Products have a life cycle.  They get introduced to the company, tested,
deployed, updated, patched, and then (if you&amp;rsquo;re lucky) sunsetted and
shut down.&lt;/p&gt;

&lt;p&gt;The introduction is in the lab, as part of the aforementioned Proof Of
Concept.  Then rolled out to DEV&amp;hellip;&lt;/p&gt;

&lt;p&gt;But the lab testing doesn&amp;rsquo;t stop there.  &lt;em&gt;Updates&lt;/em&gt; should also start in
the lab.  Let&amp;rsquo;s say you want to test a new version of the anti-virus
package that you&amp;rsquo;ve been using for 4 years; this should start in the lab.
You want to test a new data collection command to be deployed to the
existing tooling; this new command should start life in the lab.  You want
to a new new ansible/chef/puppet/cfengine rule?  Start in the lab.&lt;/p&gt;

&lt;p&gt;What this means is the lab is a &lt;em&gt;persistent&lt;/em&gt; environment.  You may
destroy and rebuild components of it so the thing doesn&amp;rsquo;t diverge too
far from what is deployed to the main networks, but you&amp;rsquo;ll always have
your AV suite, your data collection tools, your automation tools in the
lab.&lt;/p&gt;

&lt;p&gt;You then need to deploy to the rest of the network, which may be done
in a risk-managed phased approach.&lt;/p&gt;

&lt;p&gt;For example, you may not have all the tools available in the lab to talk
to (HR systems, for example, may not be there).  So you need to perform
integration tests outside of the lab.  This should be in an &amp;ldquo;engineering
QA&amp;rdquo; environment; effectively &lt;em&gt;your&lt;/em&gt; area of the DEV environment, made
to look as close to production as possible.  Only when these tests have
passed can you start to deploy across the environment&amp;hellip;with caution.&lt;/p&gt;

&lt;p&gt;You need to look at what impact an outage may have; clearly production
impact is worst, but is the DEV environment more/less impactful than QA/UAT?
One may be customer facing&amp;hellip; but may not be used so often.   You may
also want to look at regional sizes; perhaps deploying to APAC/DEV first
will let you see how things work in the &amp;ldquo;real world&amp;rdquo; but having least
impact.  Then EMEA/DEV, then AMER/DEV&amp;hellip;&lt;/p&gt;

&lt;p&gt;Once that&amp;rsquo;s settled in (maybe a week) you could do {APAC,EMEA,AMER}/UAT&amp;hellip;
and then a week later, {APAC,EMEA,AMER}/PROD.  Any deployment issues
should be sorted by the time we get to PROD!&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;I look at these DEV/UAT/PROD segments this way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DEV is a production environment supporting application development&lt;/li&gt;
&lt;li&gt;UAT is a production environment supporting application testing&lt;/li&gt;
&lt;li&gt;PROD is a production environment supporting application production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key is that all of these are production.  If you are providing
services to these environments then they are not &lt;em&gt;your&lt;/em&gt; DEV/UAT area;
these are your production areas, and you need to treat them as such.
If you&amp;rsquo;re bringing in new technology that can impact large numbers of
machines (e.g. a new data collection tool, a new automation tool) then
you don&amp;rsquo;t do your testing in DEV; that&amp;rsquo;s your &lt;em&gt;production&lt;/em&gt; environment.&lt;/p&gt;

&lt;p&gt;Don&amp;rsquo;t break production&amp;hellip; whether it&amp;rsquo;s supporting DEV or not!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Privilege Escalation in Unix</title>
      <link>https://www.sweharris.org/post/2018-08-26-minimal-sudo/</link>
      <pubDate>Sun, 26 Aug 2018 15:31:16 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2018-08-26-minimal-sudo/</guid>
      <description>

&lt;p&gt;In a well controlled environment you typically do not want people logging
into servers with privileged access (absent of additional external
processes, such as a keystroke logged session manager).  If you have 5
SAs all logging in as &lt;code&gt;root&lt;/code&gt; then how can you audit activity and determine
if it was Tom, Dick or Harry that rebooted the server?  Similarly you don&amp;rsquo;t
want DBAs directly logging in as &lt;code&gt;oracle&lt;/code&gt;; how do you know who dropped
the production table?&lt;/p&gt;

&lt;p&gt;Typically this is solved by having the SA (or DBA, or AppOp, or&amp;hellip;)
login as &lt;em&gt;themselves&lt;/em&gt; and then use a privilege escalation method.  This
method can use alternative authentication processes (e.g. 2FA), audit
activity and, if properly configured, limit activity.&lt;/p&gt;

&lt;p&gt;On Unix the standard tool is &lt;code&gt;sudo&lt;/code&gt;.  Some vendors may provide alternatives
(e.g. Centrify has &lt;code&gt;dzdo&lt;/code&gt;, Fox Technology&amp;rsquo;s Server Control has &lt;code&gt;suexec&lt;/code&gt;)
but the principles apply.&lt;/p&gt;

&lt;h2 id=&#34;business-as-usual-vs-elevated-privileges&#34;&gt;Business As Usual vs Elevated privileges&lt;/h2&gt;

&lt;p&gt;Any discussion of privilege escalation needs to consider the user&amp;rsquo;s work
role.  What an &lt;em&gt;organisation&lt;/em&gt; considers privileged may not be the same
as the operating system.&lt;/p&gt;

&lt;p&gt;One simple example of this is the &lt;code&gt;df&lt;/code&gt; command.  If a normal user runs
this then they may not see every file system mount.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ df | grep dir1

$ sudo df | grep dir1
/dev/shm          249720       0    249720   0% /tmp/dir1/mountpoint
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This situation may occur because the mountpoint may not be reachable
from the normal user&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;drwx------ 3 root root 4096 Aug 26 15:42 /tmp/dir1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So from a Unix perspective, we need elevated permissions to run the &lt;code&gt;df&lt;/code&gt;
command and get a full listing.  But from a business perspective it
would seem reasonable to allow all the SAs to run &lt;code&gt;sudo df&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The distinction between what the platform considers privileged and what
the business considers privileged really needs to be kept in mind, especially
when formulating policies and procedures around how to &lt;em&gt;manage&lt;/em&gt; this stuff.&lt;/p&gt;

&lt;h2 id=&#34;read-only-vs-read-write&#34;&gt;Read-only vs Read-write&lt;/h2&gt;

&lt;p&gt;A number of commands may be obviously read-only; &lt;code&gt;cat&lt;/code&gt; is a great example
of this; it can read files, but not write to them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Side Bar: I&amp;rsquo;ve seen people ask for &lt;code&gt;sudo echo&lt;/code&gt; because they think they
can do things like &lt;code&gt;sudo echo hello &amp;gt; /etc/my.file&lt;/code&gt;.  That&amp;rsquo;s a
misunderstanding of how the shell evaluates things; the &lt;code&gt;&amp;gt;&lt;/code&gt; redirection
happens at the current shell level, with the normal user privileges.
Similarly &lt;code&gt;sudo cat myfile &amp;gt; /etc/my.file&lt;/code&gt; doesn&amp;rsquo;t work; the &lt;code&gt;cat&lt;/code&gt;
may have elevated permissions, but the &lt;code&gt;&amp;gt;&lt;/code&gt; redirect doesn&amp;rsquo;t.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Some commands can operate in both modes.  For example &lt;code&gt;miitool&lt;/code&gt; and
&lt;code&gt;ethtool&lt;/code&gt; can be used to see the state of the network adapter, including
the negotiated speed and duplex.  However it can &lt;em&gt;also&lt;/em&gt; change the
adapter settings, force renegotiation or even break network connectivity.&lt;/p&gt;

&lt;p&gt;Similarly, on some OS&amp;rsquo;s, &lt;code&gt;ifconfig&lt;/code&gt; will only show the MAC addresses if
run as &lt;code&gt;root&lt;/code&gt;.  But now the SA has the ability to change IP addresses
and other settings on the fly.&lt;/p&gt;

&lt;p&gt;Typically commands that can make changes should not be part of a BAU
profile because they may require a change control process before they
can be used.&lt;/p&gt;

&lt;p&gt;However, commands that can operate in read and write mode may be able to
be limited; &lt;code&gt;ifconfig&lt;/code&gt;, for example, could be limited to &lt;code&gt;sudo ifconfig -a&lt;/code&gt;
which would allow the SA to see the MAC addresses but not change things;
&lt;code&gt;sudo fdisk -l&lt;/code&gt; may be permitted because it allows listing of the
partition tables, without making changes.&lt;/p&gt;

&lt;p&gt;A number of commands can be limited to read-only access, and so may be
considered part of the BAU scope.&lt;/p&gt;

&lt;h2 id=&#34;read-only-may-also-be-bad&#34;&gt;Read-only may also be bad!&lt;/h2&gt;

&lt;p&gt;At a first glance, it might make sense to be able to grant lots of
read-only access commands to people.  After all, an SA may need to
read a root-only configuration file.  For example&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cat /etc/securetty
cat: /etc/securetty: Permission denied
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What would be the harm in allowing the SA to &lt;code&gt;cat&lt;/code&gt; every file?&lt;/p&gt;

&lt;p&gt;Unfortunately there may be files on the system that should be protected
from the SA.  Should the SA be allowed to read &lt;code&gt;/opt/my_app/etc/super_secret.txt&lt;/code&gt; ?  Unlimited &lt;code&gt;cat&lt;/code&gt; would allow this.&lt;/p&gt;

&lt;p&gt;Unlimited read access may also allow a &lt;em&gt;pivot&lt;/em&gt; to another server; for
example if there is an &lt;code&gt;ssh&lt;/code&gt; key used by a process to send data to another
server then this key is probably &lt;em&gt;passphrase-less&lt;/em&gt; (it&amp;rsquo;s a common scenario).
Allowing unlimited &lt;code&gt;cat&lt;/code&gt; would allow the SA to take a copy of the key and
then try and access the remote server.&lt;/p&gt;

&lt;p&gt;Obviously we may have audit logs of the abuse of this privilege, but
prevention is always better than detection!&lt;/p&gt;

&lt;h2 id=&#34;wildcards&#34;&gt;Wildcards&lt;/h2&gt;

&lt;p&gt;We need to be aware of how &lt;code&gt;sudo&lt;/code&gt; parses commands.  The &lt;code&gt;cat&lt;/code&gt; example
might be mitigated by only allowing read access to files in &lt;code&gt;/etc&lt;/code&gt;;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;%sa_group ALL=(root) /bin/cat /etc/*
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Unfortunately&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo -l
User sweh may run the following commands on test1:
    (root) /bin/cat /etc/*

$ cat /tmp/dir1/secret.txt
cat: /tmp/dir1/secret.txt: Permission denied

$ sudo cat /tmp/dir1/secret.txt
Sorry, user sweh is not allowed to execute &#39;/bin/cat /tmp/dir1/secret.txt&#39; as root on test1.spuddy.org.

$ sudo cat /etc/../tmp/dir1/secret.txt
hidden

$ sudo cat /etc/subgid /tmp/dir1/secret.txt
hidden
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this case I was able to make use of how filenames work to display the
protected file, &lt;em&gt;and&lt;/em&gt; just to use two filenames (one permitted) to match
the pattern.  Two problems with one configuration entry!&lt;/p&gt;

&lt;p&gt;If you plan on using wildcards then determine if that will allow for excessive
privileges this may expose.  In some cases this might be mitigated with the
&lt;code&gt;!&lt;/code&gt; configuration, which will deny commands.&lt;/p&gt;

&lt;h2 id=&#34;shell-escape&#34;&gt;Shell escape&lt;/h2&gt;

&lt;p&gt;Some commands allow for the user to drop into a subshell to perform
activity and then &lt;code&gt;exit&lt;/code&gt; back to the program.  A common example of this
is the &lt;code&gt;less&lt;/code&gt; command.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo less test
myfile
!sh
sh-4.2# id
uid=0(root) gid=0(root) groups=0(root)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now while the &lt;code&gt;less&lt;/code&gt; command itself was logged, all activity performed
inside the subshell isn&amp;rsquo;t properly tracked.  The SA has full &lt;code&gt;root&lt;/code&gt;
level permissions on the machine and we can&amp;rsquo;t audit their activity.&lt;/p&gt;

&lt;p&gt;This may, sometimes, be mitigated with the &lt;code&gt;NOEXEC&lt;/code&gt; option in the
configuration:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo -l
User sweh may run the following commands on test1:
    (root) NOEXEC: /bin/less

$ sudo less test
myfile
!sh
!done  (press RETURN)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This isn&amp;rsquo;t infallible, however, and may block functionality the application
needs.  It may also not work on every operating system.&lt;/p&gt;

&lt;p&gt;Sometimes the most unexpected of commands allows for a shell escape; the
one that surprised me was the Solaris &lt;code&gt;format&lt;/code&gt; command.&lt;/p&gt;

&lt;h2 id=&#34;open-additional-files&#34;&gt;Open additional files.&lt;/h2&gt;

&lt;p&gt;This is related to shell escapes, but allows for files to be read or
modified unexpectedly.&lt;/p&gt;

&lt;p&gt;For example, we might want to allow for &lt;code&gt;vi&lt;/code&gt; to be run on a single file,
but the user can open additional files.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo -l
User sweh may run the following commands on test1:
    (root) /bin/cat
    (root) NOEXEC: /bin/vi /home/sweh/test
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We&amp;rsquo;ve NOEXEC&amp;rsquo;d this, but the user can still do &lt;code&gt;:r&lt;/code&gt; inside the session
to read protected content.  (This is hard to screen shot&amp;hellip;)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo vi /home/sweh/test
myfile
:r /tmp/dir1/secret.txt
myfile
hidden
:w! /tmp/dir1/secret.txt
&amp;quot;/tmp/dir1/secret.txt&amp;quot; 2L, 14C written
:q!

$ sudo cat /tmp/dir1/secret.txt
myfile
hidden
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;sudoedit&#34;&gt;sudoedit&lt;/h3&gt;

&lt;p&gt;Editing of files is a common requirement, so &lt;code&gt;sudo&lt;/code&gt; adds another option,
called &lt;code&gt;sudoedit&lt;/code&gt;.  This can be invoked as &lt;code&gt;sudoedit&lt;/code&gt; or &lt;code&gt;sudo -e&lt;/code&gt;.  The
way it works is clever; it makes a &lt;em&gt;copy&lt;/em&gt; of the file you want to edit
in a temporary directory, then runs your editor as your real user, and
if changes have been detected copies the file back (with the correct
permissions, ownership, etc).  In this way any shell escape or file
reads are done as the real user, and not privileged.&lt;/p&gt;

&lt;p&gt;There are other limitations on &lt;code&gt;sudoedit&lt;/code&gt; (eg not in a writeable directory)
but it can handle a number of cases where BAU write-file access is
permitted.&lt;/p&gt;

&lt;h2 id=&#34;functional-access-passwordless&#34;&gt;Functional access (passwordless)&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve mostly been focusing on human level access (I&amp;rsquo;ve described SAs, but
this would also work for DBAs, AppOp, and similar, and the target user
need not be &lt;code&gt;root&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Sometimes there may be a need for a &lt;em&gt;functional&lt;/em&gt; (or service) account to
need to perform privileged activity.  Examples abound, but a simple one
might be a polling look that wants to see what servers have listening ports,
and what processes these are.  Consider this job being
called from &lt;code&gt;cron&lt;/code&gt; every hour:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;for host in test1 test2 test3
do
  ssh svc_acct@$host sudo netstat -anp | grep -w LISTEN
done
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We need &lt;code&gt;root&lt;/code&gt; here because of the &lt;code&gt;-p&lt;/code&gt; option to &lt;code&gt;netstat&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Obviously we can&amp;rsquo;t enter the password each time (indeed there may not be a
valid password, because we use key based authentication).  Fortunately there&amp;rsquo;s
a &lt;code&gt;NOPASSWD:&lt;/code&gt; option&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo -l
    (root) NOPASSWD: /bin/netstat -anp

$ ssh test1 sudo netstat -anp | grep -w LISTEN
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      859/master          
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      759/sshd            
tcp6       0      0 ::1:25                  :::*                    LISTEN      859/master          
tcp6       0      0 :::22                   :::*                    LISTEN      759/sshd  
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These &lt;code&gt;NOPASSWD:&lt;/code&gt; entries can also be applied to human user accounts if
you consider the activity to be sufficiently low risk that the human
doesn&amp;rsquo;t need to re-authenticate (the &lt;code&gt;df&lt;/code&gt; example from earlier may
apply).&lt;/p&gt;

&lt;h2 id=&#34;block-lists-don-t-work-example-of-a-bad-setup&#34;&gt;Block Lists don&amp;rsquo;t work &amp;ndash; Example of a bad setup&lt;/h2&gt;

&lt;p&gt;I was working with a team some time back who wanted to perform centralised
data collection and some of the data required &lt;code&gt;root&lt;/code&gt; level permissions.
Now, naturally, I refused them &lt;code&gt;ALL&lt;/code&gt; access; having a tool with access to
every server and having unlimited &lt;code&gt;root&lt;/code&gt; on all those servers was an
unacceptable concentration of risk.&lt;/p&gt;

&lt;p&gt;They went away and came back with the following request:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#List of commands svc_acct is not allowed to execute via sudo
Cmnd_Alias SVCNOEXEC=
adduser*,
chmod*,
chown*,
cp*,
...and so on

svc_acct ALL=NOPASSWD: ALL, !SVCNOEXEC
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(In all there were 30 commands listed in the SVCNOEXEC alias).&lt;/p&gt;

&lt;p&gt;Apart from the fact this wasn&amp;rsquo;t a valid &lt;code&gt;sudoers&lt;/code&gt; file, these block list
setups provide ZERO security in the environment.  I was able to think
of three approaches within a few minutes:&lt;/p&gt;

&lt;h3 id=&#34;first-obvious-way-to-bypass-those-restrictions&#34;&gt;First obvious way to bypass those restrictions:&lt;/h3&gt;

&lt;p&gt;Run the command under &lt;code&gt;/bin/sh&lt;/code&gt;, which wasn&amp;rsquo;t restricted:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo /bin/sh -c &#39;&amp;lt;any_command_in_that_list&amp;gt;&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;eg&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo /bin/sh -c &#39;halt&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;second-less-obvious-way-to-bypass-these-restrictions&#34;&gt;Second less obvious way to bypass these restrictions:&lt;/h3&gt;

&lt;p&gt;copy the file to a tmp directory and run that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cp /sbin/halt /tmp/myprogram
sudo /tmp/myprogram
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;a-third-way&#34;&gt;A third way&lt;/h3&gt;

&lt;p&gt;Create a wrapper and call that&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;echo halt &amp;gt; /tmp/myprogram
chmod 755 /tmp/myprogram
sudo /tmp/myprogram
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I could probably come up with more esoteric variations as well (symlinks,
ld.so, perl, python&amp;hellip; even use &lt;code&gt;sed&lt;/code&gt; to update the sudoers file,
itself!)&lt;/p&gt;

&lt;p&gt;Basically, block lists like this can be bypassed with zero effort and
should not be used.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The secure way of setting up a sudo profile is to default-deny and then
only permit the minimum necessary commands.&lt;/p&gt;

&lt;p&gt;These commands should be restricted with options to ensure they are
read-only and do not allow further privileges.  So, for example, on
Solaris &lt;code&gt;sudo format&lt;/code&gt; may not be permitted because you can shell out
of it.  Similarly &lt;code&gt;hbacmd&lt;/code&gt; may not be permitted without restriction
because it can be used to reset HBAs, change binding rules, etc. but
&lt;code&gt;hbacmd ListHBAs&lt;/code&gt; is OK.&lt;/p&gt;

&lt;p&gt;Of course, understanding business requirements and not blocking
efficiency also needs to feed into the decision of what commands
you allow an SA to run BAU.&lt;/p&gt;

&lt;p&gt;You may decide that &lt;code&gt;sudo cat&lt;/code&gt; is OK, trusting on the audit log to be a
sufficient activity trail (perhaps with reporting triggered from it if
a restricted file is accessed).  That&amp;rsquo;s a definite productivity gain!&lt;/p&gt;

&lt;p&gt;Also you may be able to use additional tools; e.g. &lt;code&gt;SELinux&lt;/code&gt; maybe able
to lock down access to &lt;code&gt;secret.txt&lt;/code&gt;, even to users running &lt;code&gt;sudo cat&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you have any additional guidelines for &lt;code&gt;sudo&lt;/code&gt; entry creation, please
leave a message in the contents!  I know I haven&amp;rsquo;t covered every
scenario (e.g. wrapper scripts) because some of those could be a post
in themselves!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Notes from the service for my Dad</title>
      <link>https://www.sweharris.org/dad_service/</link>
      <pubDate>Tue, 07 Aug 2018 23:19:02 -0500</pubDate>
      
      <guid>https://www.sweharris.org/dad_service/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve written about Dad&amp;rsquo;s &lt;a href=&#34;https://www.sweharris.org/dad/&#34;&gt;service&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In preparation for this, Mum and I had written down a bunch of notes
for David (the priest).  Well, Mum did most of it; I added a few things
and a few jokes.  David asked a few more questions, to fill in some
missing background.  This formed the main content of the ceremony.&lt;/p&gt;

&lt;p&gt;What I&amp;rsquo;ve done, here, is taken both sets of notes and put them
together, with some editing and tweaking.&lt;/p&gt;

&lt;p&gt;This is the story of my Dad.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Douglas Charles Harris, born 19th March 1938 in Dagenham; 2nd of 2 children.
His older sister, Rose, passed a number of years earlier.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;During the war he was evacuated to Ilkley, in Yorkshire, but after 6 months
the family came back to London.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;He went to school in Albion Road, Dagenham.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;He met Stella in October 1958; she&amp;rsquo;d just left school and he&amp;rsquo;d
been demobbed from National Service.  The relationship got off on a
misunderstanding as to where Stella lived; Western Avenue or Western
Green.  Sadly for Doug, Stella lived further away than he thought so he
had a long journey back home!&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;They got engaged when Stella was 17.  Doug changed jobs from being a
butcher at Sainsbury&amp;rsquo;s to work at Fords, so he could save money for
a house.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;They married on 22nd July 1961 at St Peter and St Paul, Dagenham.
People said it wouldn&amp;rsquo;t last&amp;hellip; but here we are, 56 &lt;sup&gt;1&lt;/sup&gt;&amp;frasl;&lt;sub&gt;2&lt;/sub&gt; years later!&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;They bought their first house in Dagenham.  Stella surprised Doug 2
years later by putting it up for sale while he was at work.  The house
sold the same day.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;They moved to Limburg Road, Canvey Island.  Doug worked in Basildon,
Stella traveled to London.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;1968 Stephen was born.  Never was a man more proud than Doug.  Then to
their delight Jason was born in 1970.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;The family spent many happy years camping on the Isle Of Wight, and
in France.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Both boys did well at school.  Jason was always popular with his
peers and enjoyed sport.  Doug and Stella even qualified as referees
to support Jason&amp;rsquo;s football team.  Jason gave up football and took up
squash, but Doug continued to referee for many more years.  He was so
devoted to football that he would fall asleep with it on TV at every
opportunity.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Stephen was the studious one. He was accepted to attend St Peters
College, Oxford.  Doug was proud; as he said, he didn&amp;rsquo;t even make
grammar school.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Jason began working in London and soon moved into a flat with a friend.
Stephen came back home when he graduated.  At last Doug had someone to
go down the pub with!  Stephen then moved to Hornchurch and Doug had to
wait until Christmas for the boys to take him down the pub!&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Doug decided to take early retirement at 52 and tried hard to keep
busy; golf three times a week, badminton and keep fit twice a week,
housework and gardening to fill in the time until Stella came home
from work as a teacher, something Doug encouraged and supported.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;One time, Doug decided to do some decorating and encourage Stella
to go to Spain with a friend.  She returned with a lovely present for
him&amp;hellip; another house, this time in Spain!&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Jason married Lorraine, and in 2001 Doug became a totally besotted
Grandad to Stuart.  This never changed.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Many happy times were spent in Spain, in every school holiday.  After
Stella retired more exotic places were added to the holiday itinerary,
including cruises to far flung places.  Always where it was sunny and
hot.  Doug hated the cold.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;This year Doug showed how much he loved Stella; he took her to chilly
Iceland for whale watching, then back to Spain to thaw out!  And then
the trip to Tenerife, to capture the last of the sun.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Stella and Doug had so many lovely memories of the trips they had
taken, and had more planned for next year.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Doug was a fiercely loyal man, devoted to family and friends.  He
enjoyed good food, good company and, after he gave up golf and
badminton, he took great pride in his garden.
His cry of &amp;ldquo;It&amp;rsquo;s Christmas!&amp;rdquo; will not soon be forgotten!&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Tori, Stephen&amp;rsquo;s partner, remembers Doug as the most welcoming, kindest and funny of men.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;He did most things his way, which usually turned out to be the right way.
Well&amp;hellip; except when he electrocuted himself changing a light bulb.  Or when
he fell off a ladder, cutting a tree branch.  Or breaking the computer.  Or&amp;hellip;&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;He will be greatly missed&amp;hellip; but the cry of &amp;ldquo;Stella, I&amp;rsquo;ve broken the
computer!&amp;rdquo; won&amp;rsquo;t be.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Doug&amp;rsquo;s death was sudden, and a shock to everyone.  He died in the
middle of living; he lived until he died!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;center&gt;
&lt;em&gt;Nothing is forever&lt;br&gt;And only fools would wish is so&lt;br&gt;Memory is the yesterday that gives us courage for tomorrow&lt;/em&gt;
&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;And that, my friends, was my Dad.  A sun worshipper. A good man.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In 1992 I had taken a vacation in Florida and bought a cheap disposable
camera (which is why these pictures aren&amp;rsquo;t so good).  I had 4 shots left
on it, so took these from my bedroom window in 1993.  They show my Dad
doing what he loved best; tending the garden and sleeping in the sun.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Dad_Files/dad_garden1.jpg&#34;&gt;&lt;img src=&#34;https://www.sweharris.org/Dad_Files/dad_garden1_small.jpg&#34; alt=&#34;Garden1&#34; /&gt;&lt;/a&gt;&lt;/center&gt;
&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Dad_Files/dad_garden2.jpg&#34;&gt;&lt;img src=&#34;https://www.sweharris.org/Dad_Files/dad_garden2_small.jpg&#34; alt=&#34;Garden2&#34; /&gt;&lt;/a&gt;&lt;/center&gt;
&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Dad_Files/dad_garden3.jpg&#34;&gt;&lt;img src=&#34;https://www.sweharris.org/Dad_Files/dad_garden3_small.jpg&#34; alt=&#34;Garden3&#34; /&gt;&lt;/a&gt;&lt;/center&gt;
&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Dad_Files/dad_garden4.jpg&#34;&gt;&lt;img src=&#34;https://www.sweharris.org/Dad_Files/dad_garden4_small.jpg&#34; alt=&#34;Garden4&#34; /&gt;&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;script type=&#34;text/javascript&#34;&gt;
  var passwd_on = &#39;no&#39;
  var sites_on = &#39;no&#39;
&lt;/script&gt;
&lt;script type=&#34;text/javascript&#34; src=&#34;https://www.sweharris.org/hashover.php?canon_url=https%3a%2f%2fwww.sweharris.org%2fdad_service%2f&#34;&gt;&lt;/script&gt;
&lt;noscript&gt;You must have JavaScript enabled to use the comments.&lt;/noscript&gt;


</description>
    </item>
    
    <item>
      <title>What I did on my weekend</title>
      <link>https://www.sweharris.org/post/2018-06-24-weekend/</link>
      <pubDate>Sun, 24 Jun 2018 16:43:53 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2018-06-24-weekend/</guid>
      <description>

&lt;p&gt;Every so often I get asked to do something that&amp;rsquo;s not related to my
employer, or is stuff that results from my activities for my employer.
Frequently this is some form of informal consulting/discussion.  There was
the &lt;a href=&#34;https://www.sweharris.org/post/2016-07-01-cloudexpo/&#34;&gt;cloud expo presentation&lt;/a&gt;.  I&amp;rsquo;ve been on
a couple of &amp;ldquo;Customer Advisory Boards&amp;rdquo; because of my container opinions
(I have opinions; sometimes people want to listen to them).&lt;/p&gt;

&lt;p&gt;This time I was asked to look at a mobile email configuration.  This
small company was wanting to move away from their expensive solution
to a cheaper, more native, setup.  I&amp;rsquo;d been chatting with one of their
security guys down the pub and expressed some reservations, so he asked
me to take a look.  He created me an account on his PoC project and
showed me how to onboard my phone.&lt;/p&gt;

&lt;h2 id=&#34;how-i-went-about-this&#34;&gt;How I went about this&lt;/h2&gt;

&lt;p&gt;Now I&amp;rsquo;m not a blackhat.  I&amp;rsquo;m not a pen-tester.  I don&amp;rsquo;t have toolkits
to try and break stuff.&lt;/p&gt;

&lt;p&gt;What I do have, though, is decades of experience in building things.  And
in making mistakes.&lt;/p&gt;

&lt;p&gt;So I look at this as &amp;ldquo;If I was building this, how would I do it?  What
mistakes might I make?&amp;ldquo;.  This works out pretty well when it comes to
supporting vendor products (if a bug appears I can pretty much understand
&lt;em&gt;how&lt;/em&gt; it came about and so have meaningful conversations wit the vendor;
one of them told me I knew their product as well as their own devs).&lt;/p&gt;

&lt;p&gt;It can also help find some of the errors in &lt;em&gt;integration&lt;/em&gt; between products;
when product A and product B need to be combined to provide a service, there&amp;rsquo;s
a chance for errors.&lt;/p&gt;

&lt;p&gt;Now in this case the organisation wanted to use an MDM (Mobile Device
Management) to provision to mobile phones and use the native email client
to talk to an on-premise Exchange environment.  They had worked hard
on protecting the gateway (need a certificate to authenticate to the
perimeter firewall; username/password to authenticate to the Exchange
service).  However I still felt this risky; it allowed for more ways of
leaking data from the device, itself.&lt;/p&gt;

&lt;h2 id=&#34;safetynet&#34;&gt;SafetyNet&lt;/h2&gt;

&lt;p&gt;The first issue was getting my phone registered.  I had a Moto X Pure
that I&amp;rsquo;d wiped back to factory defaults&amp;hellip; except it had an unlocked
bootloader.  Apparently this was enough to prevent the app registering,
saying it tripped SafetyNet.&lt;/p&gt;

&lt;p&gt;SafetyNet is a routine that Google provides that will evaluate your device
and report on its trustworthiness.  It seems they recently updated the
tests to report on the bootloader as well.&lt;/p&gt;

&lt;p&gt;Fortunately, MagiskRoot made rooting the phone easy.  Since I had an
unlocked bootloader I was able to boot into TWRP (not install, just boot),
flashed Magisk, rebooted&amp;hellip; and now &lt;code&gt;adb shell&lt;/code&gt; and &lt;code&gt;su&lt;/code&gt; works.  That maybe
the easiest device root I&amp;rsquo;ve ever done.&lt;/p&gt;

&lt;h2 id=&#34;hiding-root&#34;&gt;Hiding root&lt;/h2&gt;

&lt;p&gt;This lead to the next problem&amp;hellip; now the MDM app refused to register
because it detected root.  Magisk has a &amp;ldquo;root cloak&amp;rdquo; option.  Let&amp;rsquo;s turn
that on for the MDM app.  Try again.  Failure!  Hmm.&lt;/p&gt;

&lt;p&gt;Oh hey&amp;hellip; the MDM app has a debug mode and an option to send logs
to any email address.  So turn on debug mode, fail to onboard, send the
logs.&lt;/p&gt;

&lt;p&gt;Ah!  It&amp;rsquo;s detecting /sbin/su exists and so aborting.&lt;/p&gt;

&lt;p&gt;Intereresting, /sbin/su is just a symlink to /root/&lt;RANDOMSTRING&gt;.  It looks
like this gets regenerated each boot.  The last android device I rooted
was 2.4.3; things have changed a lot in the Android security model,
and this may be part of the &amp;ldquo;systemless root&amp;rdquo; design that&amp;rsquo;s needed
these days.  OK&amp;hellip; let&amp;rsquo;s just &amp;lsquo;rm&amp;rsquo; it.  I can recreate it if necessary
since I still have a root window open.&lt;/p&gt;

&lt;p&gt;And hmm&amp;hellip; The MDM gets to work.  Away we go!&lt;/p&gt;

&lt;p&gt;I now had a rooted phone and with the Android &amp;ldquo;work&amp;rdquo; profile installed
and configured.&lt;/p&gt;

&lt;h2 id=&#34;what-can-we-find&#34;&gt;What can we find&lt;/h2&gt;

&lt;p&gt;Because this using the native mail client (&amp;ldquo;gmail&amp;rdquo;) inside the profile,
it&amp;rsquo;s possible to read the contents of &lt;code&gt;/data/user/10/com.google.android.gm/databases/EmailProvider.db&lt;/code&gt;.  And, yes, this showed the test emails that had
been placed there.  Unencrypted, easy to extract.  Complete with attachments.&lt;/p&gt;

&lt;p&gt;So I&amp;rsquo;d already proven my point; it&amp;rsquo;s easy to take an untrusted device,
onboard it and extract the data.&lt;/p&gt;

&lt;p&gt;Further I was able to see certificates in &lt;code&gt;/data/misc/keystore/user_10&lt;/code&gt;.
I didn&amp;rsquo;t bother to try and decrypt them (they&amp;rsquo;re stored encrypted, but
the primary key is decryptable using the device password).  In theory
this would allow me to connect my Linux desktop to the Exchange environment.&lt;/p&gt;

&lt;p&gt;Definitely a way for data to leak the company&lt;/p&gt;

&lt;h2 id=&#34;but-it-turned-out-to-be-easier&#34;&gt;But it turned out to be easier&lt;/h2&gt;

&lt;p&gt;It turns out I wasted a lot of time and effort on this, though.  It was
a lot easier to export data.&lt;/p&gt;

&lt;p&gt;Inside the &amp;ldquo;work&amp;rdquo; profile was a copy of the &amp;lsquo;Google Play&amp;rsquo; application.
This allowed me to install other apps, such as &amp;ldquo;Word&amp;rdquo; and &amp;ldquo;Excel&amp;rdquo;.  It
worked well; I could open attachments from email directly in Word and
view them.  But it also opened a gap; I could connect Word to my personal
Dropbox account and then save these attachments to it.  Whoops!&lt;/p&gt;

&lt;h2 id=&#34;take-aways&#34;&gt;Take Aways&lt;/h2&gt;

&lt;p&gt;The company realised there would be a massive gap in their security
posture.  I was able to demonstrate two actual paths for data exfiltration
(one didn&amp;rsquo;t even require any specialised knowledge), and one potential.
Since &amp;ldquo;insider attacks&amp;rdquo; are a big issue, this is something to be
concerned about&amp;hellip;&lt;/p&gt;

&lt;p&gt;They are now looking at enhancing MDM with MAM (Mobile Application
Management).  The MDM will restrict what applications can be installed
to Microsoft ones (Outlook, Word, Excel) and the MAM will restrict what
those applications can do (e.g. force encryption at the app layer).&lt;/p&gt;

&lt;p&gt;This introduces more complications, but improves their security.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;m not a fan of &amp;ldquo;BYOD&amp;rdquo; type stuff for email.  It really makes keeping
your data secure a lot harder.  Security of the data is inherently
dependent on security of the device and protection of the data stored
on that device.  This means there a natural tension between the owner
the data (the company) and the owner of the device (the employee); the
company may want to enforce strong passwords, long PINs, force rotation,
disable cut&amp;rsquo;n&amp;rsquo;paste&amp;hellip;  all stuff that may make it harder for the user
to use the phone for their own purposes.&lt;/p&gt;

&lt;p&gt;This is why &amp;ldquo;sandbox&amp;rdquo; applications were popular in the early days; they
provided a (semi-)secure environment to hold the company data, while
only minimally impacting the device owner.&lt;/p&gt;

&lt;p&gt;Mobile operating systems are growing in functionality; Android user profiles
are a start in this direction.  But they&amp;rsquo;re still not a sandbox.  So
using MAM on top of MDM is a necessary component.&lt;/p&gt;

&lt;p&gt;I hope I&amp;rsquo;ll get a chance to kick the tyres on their new setup!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>DevOps and Separation of Duties</title>
      <link>https://www.sweharris.org/post/2018-06-03-devops-regulatory/</link>
      <pubDate>Sun, 03 Jun 2018 14:01:22 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2018-06-03-devops-regulatory/</guid>
      <description>

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Reducing the number of personnel with access to
the production environment and cardholder data
minimizes risk and helps ensure that access is
limited to those individuals with a business need to
know.
&lt;br&gt;
The intent of this requirement is to separate
development and test functions from production
functions. For example, a developer may use an
administrator-level account with elevated privileges
in the development environment, and have a
separate account with user-level access to the
production environment.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;PCI-DSS section 6.4.2 &amp;ldquo;Separation of duties between
development/test and production environments&amp;rdquo;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;So here&amp;rsquo;s a problem.  Regulatory environments, such as PCI, require a
strict separation of duties between the development teams and the
operate teams.  This can lead to &amp;ldquo;Application Dev&amp;rdquo; (AppDev) and &amp;ldquo;Application
Operate&amp;rdquo; (AppOp) teams.  In some places AppOps may also be combined
with Infrastructure Operate (InfraOps), but in others those two operate
teams may be separate.  The key, though, is that the Dev and Ops teams
are separate.&lt;/p&gt;

&lt;p&gt;If something goes wrong at 3am then it&amp;rsquo;s the operate team
that&amp;rsquo;s paged out, who doing primary analysis, call out to the dev
team, who may make a fix and have the ops team deploy.  In some cases
the dev team may not have any access to production at all and are doing
their work hands off, which can lead to extended times to repair.&lt;/p&gt;

&lt;p&gt;This separation also takes us down the path of requiring heavy hand-over
documentation so that AppOp are happy to take on the support.  This can
slow down release cycles and tends to lead to a waterfall workflow.&lt;/p&gt;

&lt;p&gt;DevOps, as a methodology, is designed to break down these barriers;
allow faster problem remediation, speed up the release cycle, support
agile methodologies.&lt;/p&gt;

&lt;p&gt;How can we do DevOps when the Dev team appears to need to be segregated
from the Operate team?&lt;/p&gt;

&lt;h2 id=&#34;interpretation-of-the-problem&#34;&gt;Interpretation of the problem&lt;/h2&gt;

&lt;p&gt;Let&amp;rsquo;s define what admin access means.  In my mind it&amp;rsquo;s the ability to
directly make changes to the environment.  An important thing
is that the Dev team &lt;em&gt;are&lt;/em&gt; permitted to see what is going on
in production.  They just can&amp;rsquo;t &lt;em&gt;change&lt;/em&gt; it.&lt;/p&gt;

&lt;p&gt;How the dev team sees the data is also pretty flexible.  It could
mean that they can log into the production server and view the logs;
they may be able to trace application execution or transactions as
they pass from subsystem to subsystem.&lt;/p&gt;

&lt;p&gt;Other concerns may impact this, though.  Allowing a developer to run
a command such as &lt;code&gt;sudo cat /app/log/file&lt;/code&gt; may fall afoul of a corporate
definition of &amp;lsquo;privileged access&amp;rsquo; and so automatically trip a separation
of duties flag.  It &lt;em&gt;can&lt;/em&gt; be argued that any server access is
privileged, because even unprivileged users can impact server operations.&lt;/p&gt;

&lt;h2 id=&#34;one-step-removed&#34;&gt;One step removed&lt;/h2&gt;

&lt;p&gt;So rather than give direct access we can focus on a hands-off approach.
Tools such as AppDynamics or DynaTrace can create application monitoring
dashboards; log collectors (Splunk, ELK stacks) can provide real-time
activity logs; apps can be written to allow for introspection.  Now it
is clear that our developers can get access to the data they need to
analyse issues, without going anywhere near the separation of duties
issue.&lt;/p&gt;

&lt;p&gt;A nice bonus to this is that this it the methodology you want to follow
for modern elastic compute environments.  It can also help with historical
analysis (&amp;ldquo;what happened 3 months ago&amp;rdquo;) because the logs are available,
which is useful to both the operate and security teams.  A central
cross-enterprise collector can make life easier for the app teams (no need
to stand up unique infrastructure they need to manage) and may provide
operational and threat insight, and allow for common development patterns
and libraries to be used.&lt;/p&gt;

&lt;p&gt;Just make sure the data that you are collecting is properly redacted
of any sensitive content (do &lt;em&gt;not&lt;/em&gt; push credit card numbers into your
log stream!).&lt;/p&gt;

&lt;h2 id=&#34;but-what-about-changes&#34;&gt;But what about changes?&lt;/h2&gt;

&lt;p&gt;We&amp;rsquo;ve solved the easy part of merging Dev and Ops; monitoring.  But
what about &lt;em&gt;changing&lt;/em&gt; the environment?  Pushing out fixes or new code
versions?&lt;/p&gt;

&lt;p&gt;This is where automation and CI/CD tools really help.&lt;/p&gt;

&lt;p&gt;In theory we could create a pipeline that allows the developer to merge
a branch into the &amp;ldquo;prod candidate&amp;rdquo; branch; this can kick off a build
cycle, automated unit tests, integration tests; it could spin up a QA
instance to verify all expected functionality works, and if that succeeds
to push to production.&lt;/p&gt;

&lt;p&gt;But do we really want that?  If we do this then the developer effectively
has the ability to change production and so we introduce a separation
of duties conflict via a side door.&lt;/p&gt;

&lt;p&gt;But the &lt;em&gt;concept&lt;/em&gt; is good; we just need some controls on it.  Call-outs
to an approval process.&lt;/p&gt;

&lt;p&gt;An example might be an emergency fix; the DevOps team member may be
able to say &amp;ldquo;release code with tag breakfix-201806031514 under
problem ticket 623493&amp;rdquo;.  The CI/CD tool can call out to the problem
ticket system, verify it is valid and covers the servers/application in
the code scope and perform the deployment.  Management oversight performs
post-fix reviews.&lt;/p&gt;

&lt;p&gt;Similarly a planned release could be done with a similar call, but to
the Change Request system, verifying the scope and time window and
CR approval state.&lt;/p&gt;

&lt;p&gt;A regular cadence may be developed with a &amp;ldquo;pre-approved regular change&amp;rdquo;,
by pushing the controls further into the dev stack (&amp;ldquo;merges to the
production candidate must have 2 additional developers signing off&amp;rdquo;).&lt;/p&gt;

&lt;h2 id=&#34;you-are-probably-not-google&#34;&gt;You are (probably) not Google.&lt;/h2&gt;

&lt;p&gt;(If you are Google, then you have pretty mature solutions to all this,
anyway!)&lt;/p&gt;

&lt;p&gt;People look at some of the modern internet giants with their claims of
tens of thousands of changes per day and then look at the change model
I wrote above and cry &amp;ldquo;That&amp;rsquo;s not how it&amp;rsquo;s done!&amp;rdquo;.  But remember, one
size does not fit all.  You are not Google; your organisation isn&amp;rsquo;t
structured to be Google.  Google is based around rapid iteration; if
a change fails it can be fixed with little harm (&amp;ldquo;Something went wrong;
that&amp;rsquo;s all we know&amp;rdquo;).  Twitter had the &amp;ldquo;Fail Whale&amp;rdquo; when stuff broke.&lt;/p&gt;

&lt;p&gt;But if you&amp;rsquo;re handling thousands of credit card transactions per second,
what is the consequence of an outage?  What will your clients (all those
stores who are paying you to process those card swipes) feel?  How many
of those clients will you lose, and how much future custom will be lost?&lt;/p&gt;

&lt;p&gt;Different organisations have different risk tolerances.  You are not
Google; can you afford this risk?&lt;/p&gt;

&lt;h2 id=&#34;exception-processes&#34;&gt;Exception processes&lt;/h2&gt;

&lt;p&gt;The problem with automation is that they only handle cases you&amp;rsquo;ve coded
for.  You just &lt;em&gt;know&lt;/em&gt; that something will go wrong and your AppOp
person will need privileged access to the server.  This may be a
&amp;ldquo;break glass&amp;rdquo; type process (&amp;ldquo;I have an emergency; I need the root password;
break glass to get it&amp;rdquo;) with strong oversight.  Initially you may
find this process executed a lot, but as your tools, your developers,
your procedures mature then this should truly become an exception.&lt;/p&gt;

&lt;p&gt;If you still feel the need for an InfraOps team (personally, I think
this is a good idea; trained DBAs are better than ad-hoc dev oriented DBAs,
similarly for trained SAs) then they may take over the vestigial AppOp
requirements that can&amp;rsquo;t be met by the new DevOps team.  Again, engaging
these teams may be on an exception basis so doesn&amp;rsquo;t slow down the
DevOps velocity.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;What I&amp;rsquo;m describing here isn&amp;rsquo;t &lt;em&gt;easy&lt;/em&gt;.  We&amp;rsquo;re talking about a requirement
that is firmly rooted in the traditional compute method.  Organisations
have a tonne of embedded processes in place to meet regulatory requirements,
and one process may meet multiple requirements so you can&amp;rsquo;t just skip it.
But if you&amp;rsquo;re looking to pivot towards a DevOps model then investing in
the tooling (logging, automation, approvals) can get you a long way towards
meeting your regulatory requirements.  And nicely set you up for newer
technologies (e.g. deployment to a PaaS; management K8S deployments).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>SRE is not new</title>
      <link>https://www.sweharris.org/post/2018-05-13-sre-not-new/</link>
      <pubDate>Sun, 13 May 2018 15:38:10 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2018-05-13-sre-not-new/</guid>
      <description>

&lt;p&gt;One of the &amp;ldquo;hot&amp;rdquo; things around today is the concepts of Site Reliability
Engineering (SRE).  I&amp;rsquo;m gonna be slightly provocative and state that
this is not a new thing; we were doing this 30 years ago.  Indeed, these
concepts go back to where we were when I started out in this industry.&lt;/p&gt;

&lt;p&gt;Although, to be fair, there is one new factor.&lt;/p&gt;

&lt;h2 id=&#34;history&#34;&gt;History&lt;/h2&gt;

&lt;p&gt;Now I&amp;rsquo;ll be the first to say that my take on history is very much biased
by my personal experiences, and how I worked.&lt;/p&gt;

&lt;p&gt;I started in a small company in 1990.  I had to deal with the servers, the
terminals, the printers, the fax machine, the phone system&amp;hellip;. even the
door entry system.  Pretty much if it was vaguely technology related it
became my problem.  Plus, of course, &amp;ldquo;systems development&amp;rdquo; and creation of
tools for the users.  Most of the communication was via serial terminals
(VT220/320, Wyse85/99) and modems running UUCP.  Most of the machines
didn&amp;rsquo;t even &lt;em&gt;have&lt;/em&gt; an ethernet port when I started.  Naturally this
lead to each machine being custom and unique.  I learned a lot.  Since I
was the only person supporting the London office every failure was mine
to fix.  Nothing like being called during Sunday Dinner to fix a problem
because a ship-broker was unable to dialin to complete a deal.&lt;/p&gt;

&lt;p&gt;My next job was at an internet publishing division of a traditional publisher.
Here we had a team of 5, all with Sun&amp;rsquo;s, all connected to the internet.
The original architect had tried to create a resilient design, but
didn&amp;rsquo;t know what he was doing.  It was over-engineered and full of single
points of failure.  I simplified it&amp;hellip; and then started to automate tasks;
want to register a new DNS domain?  Run &lt;em&gt;this&lt;/em&gt; command, answer the questions;
it will create the DNS entries on primary and secondary, create the email
form, PGP sign it, send it to Internic/Nominet/whoever.  Want to add
a new dialup?  Run &lt;em&gt;that&lt;/em&gt;; it&amp;rsquo;s create forward/reverse DNS, tacacs,
mailboxes, etc etc.  New web site?  Cisco IOS config&amp;hellip;&lt;/p&gt;

&lt;p&gt;When I moved into the central &amp;ldquo;systems&amp;rdquo; team I started to automate their
processes.  I even got zsh working on Windows NT so I could automate
tasks the help desk commonly did.  Automated monitoring (&amp;ldquo;Big Brother&amp;rdquo;,
for those who remember that).  Automated paging (Kermit, talking to a
TAP service).&lt;/p&gt;

&lt;p&gt;My third job was in a megacorp; I now had a thousand servers; more
than the previous company had people!  My first task was in Y2K
readiness; how can we test these thousand servers are all working
properly so the Y2K command center can tick their box.&lt;/p&gt;

&lt;p&gt;I created a tool that could check all the servers,
centrally coordinated (via ssh) with tunable (and self-tuning) parallelism.
It would run in under 30 minutes.  I wasn&amp;rsquo;t on call for Y2K, but the 2
people who were basically just watched the fireworks from the Embankment
(the office was right on the banks of the Thames) while the code ran.
(The Windows and Novell teams weren&amp;rsquo;t so lucky; they had to work).&lt;/p&gt;

&lt;p&gt;A good sysadmin is a lazy sysadmin; they automate everything.  I was a
VERY lazy sysadmin.&lt;/p&gt;

&lt;p&gt;So lazy that the code remained in daily use for years afterwards, as a general
purpose healthcheck.  Because I was in operations I wrote code to make my
life easier, and as a result &lt;em&gt;every&lt;/em&gt; ops guy in my team gained the benefit.&lt;/p&gt;

&lt;h2 id=&#34;where-it-started-to-break-down&#34;&gt;Where it started to break down&lt;/h2&gt;

&lt;p&gt;The company wanted me to do more and more complicated work.  Stuff that
required focus.  Systems architecture; engineering; deployment.  Stuff
that I couldn&amp;rsquo;t do if I was paged out at 3am because a server needed
attention.  I wasn&amp;rsquo;t the only one.  They &lt;em&gt;split&lt;/em&gt; the team into engineering
and operations.  Naturally the smart coders got moved into engineering;
the remaining ops guys were more &amp;ldquo;press the button&amp;rdquo; types.  Not stupid,
by a long stretch; they could do some really detailed problem analysis
and solve problems&amp;hellip; they were &lt;em&gt;good&lt;/em&gt; SAs.  But they were more incident
management focused, rather than problem management.  They might document
a solution and then next time it happened another team member could follow
the document.&lt;/p&gt;

&lt;p&gt;At the same time the engineering team started to be divorced from the
daily operations.  We were focused on higher level tasks set by management,
rather than scripting and automating BAU activities.  Barriers between the
teams were created by this organizational distinction; the automators
didn&amp;rsquo;t understand the ops problems, so they started to need requirements
docs and ops wanted handover docs and the slow decline into your structured
support model (level 1,2,3 even 4) was inevitable.&lt;/p&gt;

&lt;p&gt;The ops teams were considered by management to be a &amp;ldquo;cog&amp;rdquo; and each
person replaceable.  This lead to &amp;ldquo;cheapest person&amp;rdquo; type policies, which
naturally leads to off-shoring and stagnation; if a person in L2 learns
enough then they move into L3, and L2 gains a newbie with no institutional
knowledge.&lt;/p&gt;

&lt;p&gt;Where the original idea to split engineering from ops was meant to speed
up delivery (focused teams) the leaching of talent from ops lead to
slower processes as formal handover between teams became necessary; just
to protect themselves the ops teams required good tested procedures from
engineering; waterfall enforced by organizational and managerial boundaries.&lt;/p&gt;

&lt;h2 id=&#34;so-what-about-sre&#34;&gt;So what about SRE?&lt;/h2&gt;

&lt;p&gt;If you look back at my history, SRE is kinda what I was doing 20 years ago.
Find a problem, automate the solution so it never becomes a problem again.
Find a task, automate it.  Find a multi-step process, automate it to one
step.&lt;/p&gt;

&lt;p&gt;This is why I say that SRE isn&amp;rsquo;t anything new.&lt;/p&gt;

&lt;p&gt;But there is a change&amp;hellip; and it&amp;rsquo;s a good one.  It&amp;rsquo;s &lt;em&gt;formalization&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;When I did my ops work I was working mostly in a vacuum.  I was a single
contributor, inventing technologies and solutions as I went along.  I
worked with smart people who were also single contributors in their area.
Sometimes the areas overlapped and, if you were lucky, the solutions
could be combined.  But mostly each person just ran their own way.&lt;/p&gt;

&lt;p&gt;SRE, in comparison, is taking a modern software design approach towards
the solution.  Instead of individual contributors we now have a team
approach.  There may be agile techniques, but I don&amp;rsquo;t think that&amp;rsquo;s
necessarily so important.&lt;/p&gt;

&lt;p&gt;Today tools and technologies exist that were not around 20 years ago;
JIRA queues, wikis, deployment frameworks (ansible, cfengine, salt,&amp;hellip;).
We can create a common technology stack within the team that &lt;em&gt;anyone&lt;/em&gt; in
the team can use.  We no longer have &amp;ldquo;Stephen&amp;rsquo;s magic&amp;rdquo; and &amp;ldquo;Fred&amp;rsquo;s magic&amp;rsquo;
and &amp;ldquo;Matt&amp;rsquo;s magic&amp;rdquo;; we have automation.&lt;/p&gt;

&lt;p&gt;This is a massive step forward.&lt;/p&gt;

&lt;h2 id=&#34;so-why-will-the-sre-model-work&#34;&gt;So why will the SRE model work?&lt;/h2&gt;

&lt;p&gt;If we look at my history and look at SRE today, these common tools aren&amp;rsquo;t
enough to overcome the &amp;ldquo;I was paged at 3am; I can&amp;rsquo;t code today&amp;rdquo; problem.&lt;/p&gt;

&lt;p&gt;If SRE was just a &amp;ldquo;modern technique to an old solution&amp;rdquo; then it&amp;rsquo;ll die out
for the same reasons that my team got split in 2000.&lt;/p&gt;

&lt;p&gt;Fortunately, SRE isn&amp;rsquo;t the only change.  There&amp;rsquo;s also the DevOps model.
Now that has it&amp;rsquo;s own problems (a blog post for another day!) but it can
mean that the layer that SRE is working on &lt;em&gt;is&lt;/em&gt; the engineering team
problems of the last 20 years.&lt;/p&gt;

&lt;p&gt;When we look at containers and automated application delivery; when we look
at the &amp;ldquo;cattle&amp;rdquo; model of software delivery; when we look at hands off
automation and configuration management&amp;hellip; the old school &amp;ldquo;ops&amp;rdquo; model
is a lot smaller.  Some of the work has been pushed onto the Dev teams;
some of the work just disappears.&lt;/p&gt;

&lt;p&gt;And this is why, in my opinion, that SRE will succeed; it&amp;rsquo;s not in a vacuum,
but it lives within a larger operational model change.&lt;/p&gt;

&lt;h2 id=&#34;other-challenges&#34;&gt;Other challenges&lt;/h2&gt;

&lt;p&gt;Some regulatory environments (e.g. Payment Card Industry - PCI) have
restrictions around dev/prod access.&lt;/p&gt;

&lt;p&gt;Indeed PCI says&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Reducing the number of personnel with access to the production
environment and cardholder data minimizes risk and helps ensure that
access is limited to those individuals with a business need to know.&lt;/p&gt;

&lt;p&gt;The intent of this requirement is to separate development and test
functions from production functions. For example, a developer may use an
administrator-level account with elevated privileges in the development
environment, and have a separate account with user-level access to the
production environment.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the SRE model, the operations engineer &lt;em&gt;is&lt;/em&gt; a developer.  So can SRE
be adopted within these constraints?  I, personally, think it can&amp;hellip; but
it requires additional controls around the &lt;em&gt;process&lt;/em&gt;.  Fortunately,
the modern SRE tooling has a lot of process focus; after all, that&amp;rsquo;s
what modern software delivery methodology is all about!&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I was being slightly provocative in my opening statements.  I do believe
the the &lt;em&gt;concept&lt;/em&gt; of SRE is nothing new.  What has changed, though, is
the &lt;em&gt;practice&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Because of the mismanagement earlier discussed, &amp;ldquo;operations&amp;rdquo; has a
bad name.  The SRE branding is a way of avoiding this tainted reputation,
but it&amp;rsquo;s more than just a re-branding.  It&amp;rsquo;s a shift &lt;em&gt;back&lt;/em&gt; to the lazy
sysadmin role, and you really want lazy sysadmins because they can do things
at scale that can&amp;rsquo;t be done otherwise.&lt;/p&gt;

&lt;p&gt;This, along with the role change causing a responsibility shift, means
that the SRE model is a potentially viable one for organizations to
adopt.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Encumbering New Technology</title>
      <link>https://www.sweharris.org/post/2018-04-29-encumbering_new_technology/</link>
      <pubDate>Sun, 29 Apr 2018 17:36:42 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2018-04-29-encumbering_new_technology/</guid>
      <description>

&lt;p&gt;One of the exciting parts of the &amp;ldquo;new world&amp;rdquo; of cloud is the ability
to green field solutions.  We don&amp;rsquo;t have the legacy requirements and so
we&amp;rsquo;re free to do what we want.&lt;/p&gt;

&lt;p&gt;Or so the evangelists would have you believe.&lt;/p&gt;

&lt;h2 id=&#34;the-past-lingers-on&#34;&gt;The past lingers on&lt;/h2&gt;

&lt;p&gt;The reality is that many people are closer to a brown field environment.
The organisation their team is embedded into has a tonne of reporting
(&amp;ldquo;is your machine patched?&amp;rdquo;, &amp;ldquo;who has access?&amp;rdquo;).  These requirements
came from years of systems mismanagement (the best appdev team in the
world isn&amp;rsquo;t necessarily the best at running servers) and auditor questions.
To provide adequate reporting a series of centralised reporting tools
have been created to help prove to auditors that the environment
is controlled; &amp;ldquo;we have 30,000 servers; 357 of them are running Struts;
3 of them are unpatched and have change records for next week&amp;rdquo; is a
&lt;em&gt;great&lt;/em&gt; story to be able to tell, but it requires a level of conformity
to get there.&lt;/p&gt;

&lt;p&gt;And now you come along with your dynamically scaling app running inside
an environment that builds/destroys servers at will.  You can&amp;rsquo;t even
answer the question &amp;ldquo;what servers are your apps running on?&amp;rdquo; because
the question is &lt;em&gt;meaningless&lt;/em&gt; in your world; it changes from day to day,
even hour to hour.&lt;/p&gt;

&lt;p&gt;So new builds may start being encumbered with requirements that trickle
down from the traditional compute environment.  Of course the CMDB needs
to be kept up to date; of course you need privileged access monitoring;
of course you need configuration management tools; of course&amp;hellip;&lt;/p&gt;

&lt;p&gt;We need to prevent this encumbrance from crippling the benefits of
the new world.&lt;/p&gt;

&lt;p&gt;In some cases we might be able to kludge a solution.  &amp;ldquo;If we give you a
nightly update into CMDB of all our AWS EC2 instances, will you be
happy?&amp;ldquo;.  Beware, though; once a machine is listed in CMDB then it&amp;rsquo;ll be
expected to have all the &lt;em&gt;other&lt;/em&gt; corporate tools (monitoring, access
management, backups&amp;hellip;) installed.  Be aware of the consequences of
the kludge, and try to avoid it.&lt;/p&gt;

&lt;p&gt;The harder, but ultimately (IMHO) better path is to go back to square one
and design new controls and procedures that are better optimised for
this design.&lt;/p&gt;

&lt;p&gt;The corporate policies and standards are meant to be the distilled
guidance of everything that&amp;rsquo;s needed, based on legal reading of
regulations, from history of audit questions and issues, from experience.
These become your go-to documents.  You may also want to go to the source,
because regulations can change without your standards.  So read the PCI
docs, read MAS, read HIPAA&amp;hellip;&lt;/p&gt;

&lt;p&gt;And then design solutions based around the &lt;em&gt;requirements&lt;/em&gt;, not around the
existing practices.&lt;/p&gt;

&lt;p&gt;This is hard work on a &lt;em&gt;political&lt;/em&gt; level and requires a fair amount of
senior buy-in.  It requires vision and leadership because the organisation
is now taking a fair risk; &lt;em&gt;will&lt;/em&gt; you build a good solution that will pass
audit?  Will you expose the company to data theft?  Will the solution
scale to multiple appdev teams (you&amp;rsquo;re not a unique snowflake; other teams
want to do this as well).&lt;/p&gt;

&lt;p&gt;If you have management that support you, and can demonstrate compliance
to corporate and regulatory policies and standards &lt;em&gt;then&lt;/em&gt; you may be
greenfield enough and avoid too many encumbrances.&lt;/p&gt;

&lt;h2 id=&#34;new-encumbrances&#34;&gt;New encumbrances&lt;/h2&gt;

&lt;p&gt;Because this is new and because you&amp;rsquo;ve now designed new processes
and procedures, the people reviewing your work will be looking for
edge cases.  &lt;em&gt;How&lt;/em&gt; can this new thing go wrong?  It&amp;rsquo;s a natural
consequence of trying to protect the company, the data.&lt;/p&gt;

&lt;p&gt;The problem is when a potential gap is found.  Is this gap already
present in the traditional compute space?  Is it known?  Has the
company decided this is OK?  If so, it may be a problem you don&amp;rsquo;t
need to fix; acknowledge the gap and move on.  Don&amp;rsquo;t encumber your
work with things that aren&amp;rsquo;t necessary.&lt;/p&gt;

&lt;p&gt;Imagine building a PaaS solution and being required to tell the
application operate team everytime you are going to reboot a VM?
Technically it&amp;rsquo;s possible&amp;hellip; but it&amp;rsquo;s stupid, and negates some of the
benefits of a PaaS.&lt;/p&gt;

&lt;p&gt;We see this in various places, especially in new fields of automation;
for example, self-driving cars.  I&amp;rsquo;ve seen people ask &amp;ldquo;once we get to
fully automated cars capable of taking voice commands from the driver,
how do we make sure the driver has a license?&amp;ldquo;.  This is a perfect example
of &amp;ldquo;new &lt;em&gt;technological&lt;/em&gt; requirement&amp;rdquo; based on an existing requirement
(must have a license, must be insured) but isn&amp;rsquo;t currently enforceable.
People get excited by &amp;ldquo;we&amp;rsquo;re building something new; we can add this
feature&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;The idea may seem reasonable on the face of it, and it may be a solution
that is technically feasible.  But this is a case of scope creep and can
drag down your project.&lt;/p&gt;

&lt;p&gt;&amp;ldquo;Just because you can, doesn&amp;rsquo;t mean you should&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Don&amp;rsquo;t encumber your new solution with requirements that go above and
beyond the problem you&amp;rsquo;re trying to solve.  Try to keep project scope
under control.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Very few projects are really greenfield.  There&amp;rsquo;s always some small
amount of legacy that you need to keep up with.  Much of that legacy
is there for a good reason, and you can&amp;rsquo;t just ignore it with impunity.
However you can &lt;em&gt;replace&lt;/em&gt; it with better processes and procedures, with
better solutions.  Sometimes going back to the drawing board and
understanding the rationale is important.&lt;/p&gt;

&lt;p&gt;Don&amp;rsquo;t just say &amp;ldquo;we&amp;rsquo;re doing DevOps&amp;rdquo; and ignore everything that came before;
that&amp;rsquo;ll get you into trouble.  However &amp;ldquo;we&amp;rsquo;re doing DevOps with these
controls, procedures, enforcements, auditing&amp;hellip;&amp;ldquo;; now you&amp;rsquo;ve got a chance
to build things without the encumberance of traditional procedures.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>When does an AI become alive?</title>
      <link>https://www.sweharris.org/post/2018-04-01-life/</link>
      <pubDate>Sun, 01 Apr 2018 14:33:49 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2018-04-01-life/</guid>
      <description>

&lt;p&gt;This blog post is gonna be a little different; it&amp;rsquo;s more philosophical
than most of what I write.&lt;/p&gt;

&lt;p&gt;It rose out a question a friend asked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;When does a biological AI become life?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;My friend asked me this because he felt that SciFi must have covered
this topic, and I&amp;rsquo;ve read and watched more than my fair share :-)&lt;/p&gt;

&lt;h2 id=&#34;remove-the-limitations&#34;&gt;Remove the limitations&lt;/h2&gt;

&lt;p&gt;Now, I found the restriction to &amp;ldquo;biological AI&amp;rdquo; is unnecessary limiting.  I
can understand the thinking (we&amp;rsquo;re biological, we&amp;rsquo;re alive), but the question
can apply to a larger scope.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s go larger.&lt;/p&gt;

&lt;p&gt;I can see two possible interpretations of the question:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;when does something become &amp;ldquo;alive&amp;rdquo; (in the same aspect that a rat may be alive, or a tree, or maybe even a microbe).  We don&amp;rsquo;t need it to be an &amp;ldquo;AI&amp;rdquo; for this&lt;/li&gt;
&lt;li&gt;when does it become &lt;em&gt;sentient&lt;/em&gt;; we don&amp;rsquo;t need &amp;ldquo;biological&amp;rdquo; for this.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A related question is &amp;ldquo;what does it mean to be human&amp;rdquo;.  Having just
rewatched &amp;ldquo;Bladerunner&amp;rdquo; and &amp;ldquo;Bladerunner 2049&amp;rdquo; this question naturally
came to me; it&amp;rsquo;s one of the key themes in both of these movies.&lt;/p&gt;

&lt;p&gt;The problem with these questions is that we don&amp;rsquo;t really have good &lt;em&gt;definitions&lt;/em&gt; of what any of this means; philosophers have been debating it for millennia.&lt;/p&gt;

&lt;p&gt;Star Trek TNG asked this question a few times; e.g.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;is Data alive (&lt;a href=&#34;https://en.wikipedia.org/wiki/The_Measure_of_a_Man_%28Star_Trek:_The_Next_Generation%29&#34;&gt;The Measure of a Man&lt;/a&gt;)?&lt;/li&gt;
&lt;li&gt;Were the exocomps a life form (&lt;a href=&#34;https://en.wikipedia.org/wiki/The_Quality_of_Life_%28Star_Trek:_The_Next_Generation%29&#34;&gt;The Quality Of Life&lt;/a&gt;)?&lt;/li&gt;
&lt;li&gt;&amp;ldquo;other forms of life&amp;rdquo; (&lt;a href=&#34;https://en.wikipedia.org/wiki/Home_Soil&#34;&gt;ugly bags of mostly water&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even the original series covered some of this (&lt;a href=&#34;https://en.wikipedia.org/wiki/The_Devil_in_the_Dark&#34;&gt;The Devil in the
Dark&lt;/a&gt;).  Star Trek
Voyager took the concept even further with debate on whether a &lt;em&gt;hologram&lt;/em&gt;
could be sentient and if so, alive.&lt;/p&gt;

&lt;h2 id=&#34;slaves&#34;&gt;Slaves&lt;/h2&gt;

&lt;p&gt;A lot of these questions all come back to &amp;ldquo;creating an underclass&amp;rdquo;
- ie creating a &lt;em&gt;slave&lt;/em&gt; race.  We believe enslaving people is evil,
but if we create something or grow something and declare it &amp;ldquo;not human&amp;rdquo;
then can&amp;rsquo;t we treat them like slaves?  Asimov addressed some of that in
his Robot stories as well.&lt;/p&gt;

&lt;p&gt;So determining the answer to these questions (&amp;ldquo;what is life&amp;rdquo;, &amp;ldquo;what
is sentience&amp;rdquo;, &amp;ldquo;what is human&amp;rdquo;) and determining how we should &lt;em&gt;treat&lt;/em&gt;
the entities we create may become a critical question that could have
ramifications through history.&lt;/p&gt;

&lt;h2 id=&#34;will-we-remain-human&#34;&gt;Will we remain human?&lt;/h2&gt;

&lt;p&gt;This may also have consequences for our own evolution (cf X-Men stories
for mutants) or &amp;ldquo;Post-Human&amp;rdquo; (or Trans-human) for technology-enhanced
humans.&lt;/p&gt;

&lt;p&gt;What if we learn to create nanotechnology that can rewrite DNA to
enhance muscle power; heart function; brain power?  What if we have
computer technology that can be implanted into the brain and act as an
enhancement to memory, thinking, communication?&lt;/p&gt;

&lt;p&gt;Will we define these people as &amp;ldquo;human&amp;rdquo; or will they be &amp;ldquo;sub-human&amp;rdquo;?&lt;/p&gt;

&lt;p&gt;Since many of these technologies may come out of the defence industry and
initially applied to soldiers who sign away their rights some of the early
decisions may be &lt;em&gt;against&lt;/em&gt; calling these people human, which could have
long term ramifications.  This was a thread in &amp;ldquo;Nexus&amp;rdquo; trilogy of books,
by Ramez Naam.  (Aside: I could do with some technology to help me remember
names like that; I forgot the author and book title, but I knew exactly
where it was on my book shelves, so had to go and physically find the book!)&lt;/p&gt;

&lt;h2 id=&#34;my-grandfather-s-axe&#34;&gt;My grandfather&amp;rsquo;s axe&lt;/h2&gt;

&lt;p&gt;Law loves bright lines; &amp;ldquo;This is human&amp;rdquo;; &amp;ldquo;this is not human&amp;rdquo;.  It&amp;rsquo;s really
not so good with blurred areas.  This became a big deal in an obscenity
case that appeared in front of the US Supreme Court:&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;I shall not today attempt further to define the kinds of material I
understand to be embraced within that shorthand description [&amp;ldquo;hard-core
pornography&amp;rdquo;], and perhaps I could never succeed in intelligibly doing
so. But &lt;a href=&#34;https://en.wikipedia.org/wiki/I_know_it_when_I_see_it&#34;&gt;I know it when I see it&lt;/a&gt;, and the motion picture involved in this case is not that.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;We&amp;rsquo;re already starting down this path.  We can replace limbs with
artificial equivalents, we can replace organs (eg artificial hearts),
we can even use organs from other species (pig hearts).  So where does
&amp;ldquo;human&amp;rdquo; end?  When does man become &lt;a href=&#34;https://en.wikipedia.org/wiki/Cyberman&#34;&gt;Cyberman&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So far the line appears to be &amp;ldquo;brain&amp;rdquo;&amp;hellip; but what when we start to
enhance that?&lt;/p&gt;

&lt;h2 id=&#34;brains&#34;&gt;Brains!&lt;/h2&gt;

&lt;p&gt;For a long time we&amp;rsquo;ve had the ability to &lt;em&gt;alter&lt;/em&gt; consciousness.  &amp;ldquo;Beer, you&amp;rsquo;re
my best friend! &lt;em&gt;hic&lt;/em&gt;&amp;rdquo;.  We&amp;rsquo;ve gone some step towards overcoming natural
limitations (e.g. drugs to counter ADHD, reduce epilepsy).  But what happens
when we surgically make &lt;em&gt;permanent&lt;/em&gt; changes to the brain?&lt;/p&gt;

&lt;p&gt;Well, we&amp;rsquo;re already doing some of that, as well; cochlear ear implants
where the implant connects directly to the nervous system.  The are
experimental artificial eyes to allow blind people to see.  There&amp;rsquo;s
even &lt;a href=&#34;https://en.wikipedia.org/wiki/Neil_Harbisson&#34;&gt;one person&lt;/a&gt; with an artificial eye that translates colours into sound.&lt;/p&gt;

&lt;p&gt;So far we&amp;rsquo;re at the early stages of direct brain manipulation, but we&amp;rsquo;re
definitely going down this path!&lt;/p&gt;

&lt;h2 id=&#34;human-life&#34;&gt;Human life&lt;/h2&gt;

&lt;p&gt;We can&amp;rsquo;t even tell when &lt;em&gt;human&lt;/em&gt; life starts.  When does a random
collection of cells (egg+sperm) become &amp;ldquo;human&amp;rdquo;.  Anti-abortionists claim
&amp;ldquo;life begins at conception&amp;rdquo; but that&amp;rsquo;s meaningless and would result in
a crime investigation being warranted whenever a mother spontaneously
aborts (and in the first few days of implantation that&amp;rsquo;s common).&lt;/p&gt;

&lt;p&gt;If we can&amp;rsquo;t even define this for humans, how can we expect to define it
for our creations?&lt;/p&gt;

&lt;h2 id=&#34;what-even-is-artificial-intelligence&#34;&gt;What even is Artificial &lt;em&gt;Intelligence&lt;/em&gt;?&lt;/h2&gt;

&lt;p&gt;When I was a kid I thought that we &lt;em&gt;would&lt;/em&gt; encounter alien intelligence&amp;hellip;
but it wouldn&amp;rsquo;t be from outer space; it&amp;rsquo;d be something we created.
An AI, basically.  After all, there&amp;rsquo;s no reason that an AI would be an
artificial &lt;em&gt;human&lt;/em&gt; intelligence (AHI); given the lack of sensory input
and control mechanisms that human&amp;rsquo;s grow up with (your body!) there&amp;rsquo;s
little reason to assume that an emergent AI would be human.&lt;/p&gt;

&lt;p&gt;So we have another problem; how do we &lt;em&gt;identify&lt;/em&gt; this intelligence?  Clearly
the Turing test is aimed at AHI, and not alien intelligence.  Do we even
have a way of identifying this?&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;We&amp;rsquo;ve come a long way from the original question (&amp;ldquo;When does a biological AI become life?&amp;rdquo;).  It&amp;rsquo;s exposed a tonne of questions to which we don&amp;rsquo;t, yet,
have answers.&lt;/p&gt;

&lt;p&gt;But these are questions we do need to start thinking about; not from an
AI perspective, but from a human perspective.  When does man start? Where
does he end?&lt;/p&gt;

&lt;p&gt;The reality is that there is no hard line between &amp;ldquo;not alive&amp;rdquo; and
&amp;ldquo;alive&amp;rdquo;, as exposed by the &amp;ldquo;abortion&amp;rdquo; question.  The law tries its best,
but there are legal, ethical, and religious components to the question.&lt;/p&gt;

&lt;p&gt;When does an AI become alive?  I don&amp;rsquo;t know!&lt;/p&gt;

&lt;p&gt;And then there&amp;rsquo;s &lt;a href=&#34;https://rationalwiki.org/wiki/Roko&#39;s_basilisk&#34;&gt;Roko&amp;rsquo;s Basilisk&lt;/a&gt; to be aware of&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>How I learned to stop worrying and love the cloud</title>
      <link>https://www.sweharris.org/post/2018-02-19-love-the-cloud/</link>
      <pubDate>Mon, 19 Feb 2018 19:38:07 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2018-02-19-love-the-cloud/</guid>
      <description>

&lt;p&gt;I&amp;rsquo;ve spent the past far-too-many years working in the finance industry,
in mega-banks and card processors.  These companies are traditionally very
&lt;em&gt;worried&lt;/em&gt; about information security.  It&amp;rsquo;s not to say they always do it
well (everyone makes a mistake), but it leads to a conservative attitude.&lt;/p&gt;

&lt;p&gt;These types of companies end up creating a massive set of standards
and procedures to protect themselves.  &amp;ldquo;Thou MUST do this.  Thou MUST
do that.&amp;rdquo;  Any deviance from the norm (in a weaker situation) is a risk
and needs documenting and tracking.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s a number of assumptions involved in these standards. For example,
the physical disk is in our datacenter; the SAs with logical access
have gone through corporate vetting; the physical access controls to
datacenters are known; network connectivity is known.  At a higher layer,
all internet facing services have been signed off (firewalls need to be
opened to allow incoming connections); 3 tier architectures are defined
and maintained; data loss prevention tools exist.  In essence we&amp;rsquo;ve built
both physical and logical barriers to control ingress and egress of data.
You might even hear phrases such as &amp;ldquo;within the company&amp;rsquo;s four walls&amp;rdquo;
to refer to this.&lt;/p&gt;

&lt;p&gt;Now this scenario does assume staff can be trusted; there&amp;rsquo;s a whole
another set of controls and processes to protect against that, but that&amp;rsquo;s
kinda out of scope of this blog posting.&lt;/p&gt;

&lt;h2 id=&#34;how-does-the-cloud-change-this&#34;&gt;How does the cloud change this?&lt;/h2&gt;

&lt;p&gt;Before we can answer this question we need to consider what is &lt;em&gt;meant&lt;/em&gt; by
cloud.  &lt;a href=&#34;http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-145.pdf&#34;&gt;NIST&lt;/a&gt; defines cloud in terms of three primary services; IaaS (Infrastructure as a Service), PaaS (Platform as..) and SaaS (Software&amp;hellip;).  These really
are rough demarcation points because a cloud engagement may include components
of all of these (e.g. a Big Data offering is a SaaS, but it may offer
&amp;ldquo;compute VMs&amp;rdquo; where you can install your own software&amp;hellip; an IaaS).&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not going to consider SaaS here because, in essence, this isn&amp;rsquo;t really
much different to traditional service outsourcing.  HR departments have
outsourced to specialist providers for decades; we&amp;rsquo;re now seeing this at
the IT technology layer.  You put your data into someone else&amp;rsquo;s software,
run on their machines, and trust it.  Where things have changed is that
your outsourced provider now may, themselves, run on an IaaS.  To trust
the SaaS provider you may need to know their dependencies and the underlying
IaaS provider.&lt;/p&gt;

&lt;p&gt;Similarly with a PaaS; now you throw your software into someone else&amp;rsquo;s
compute environment&amp;hellip; which may run on an IaaS.&lt;/p&gt;

&lt;p&gt;In both the SaaS and PaaS model we have to worry about controls at the service
layer level, and potentially controls at the IaaS layer.&lt;/p&gt;

&lt;p&gt;Which leads us to IaaS solutions.  The worry, here, is commonly around
the management of the physical infrastructure.&lt;/p&gt;

&lt;p&gt;Sure, there&amp;rsquo;s a &lt;em&gt;challenge&lt;/em&gt; around using Cloud Service Providers (CSPs)
such as Amazon, simply because they provide so many services and tools.
But we can work on that.  We can define standards.  We can build logical
constructs that compare to the traditional four-wall security model.&lt;/p&gt;

&lt;p&gt;But we&amp;rsquo;ve still got the &lt;em&gt;lower&lt;/em&gt; layers.  This is what Amazon called
the Shared Responsibility Model.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href=/images/NewSharedResponsibilityModel.png&gt;&lt;img src=/images/NewSharedResponsibilityModel.png width=516px height=263px border=1&gt;&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Effectively, the CSP has replaced your Datacenter Operate team and portion
of your SA team.  And these are people you don&amp;rsquo;t know; they&amp;rsquo;ve not been
through your corporate vetting process, had their fingerprint taken,
peed in a cup for drug testing&amp;hellip;  how can you trust these guys?&lt;/p&gt;

&lt;p&gt;The shared responsibility model also applies for PaaS and SaaS offerings;
just the line of responsibility moves upwards.  I like to call this
&amp;ldquo;above the line&amp;rdquo; and &amp;ldquo;below the line&amp;rdquo;.  The CSP is responsible for
stuff below the line; you&amp;rsquo;re responsible for stuff above the line.
Where that line is drawn is unique to each engagement and CSP.&lt;/p&gt;

&lt;h2 id=&#34;mitigations&#34;&gt;Mitigations&lt;/h2&gt;

&lt;p&gt;The first thing we do is try to limit our exposure.  Encrypt things
where you can.  Replicate as far as is required your existing controls (it&amp;rsquo;ll
be a new implementation but you need firewalls, DLP, logging&amp;hellip;).  Determine
what those controls &lt;em&gt;really&lt;/em&gt; are, rather than just the decade old &amp;ldquo;this is
how we&amp;rsquo;ve always done it&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;There are some cloud specific new stuff; always encrypt data at rest
(block store, S3, databases).  Automate detection of misconfiguration
(an open S3 bucket? That&amp;rsquo;s not right!  Open egress from your VM to the
internet?  Huh, that bypasses DLP!).  Can your application work purely
on encrypted data, and never need to see the plain text?&lt;/p&gt;

&lt;p&gt;But at the end of the day we need to have a level of trust in the CSP.
What&amp;rsquo;s to stop them snooping memory from the hypervisor?  How far do
we trust them to run the &amp;ldquo;below the line&amp;rdquo; stuff properly?&lt;/p&gt;

&lt;p&gt;What can we about that?&lt;/p&gt;

&lt;h2 id=&#34;trust&#34;&gt;Trust&lt;/h2&gt;

&lt;p&gt;Here&amp;rsquo;s where things start to get a little fuzzy.  We no longer have
direct visibility into these operations.  It&amp;rsquo;s all below the line, and
so an opaque box.&lt;/p&gt;

&lt;p&gt;But, really, this isn&amp;rsquo;t much different to any other technology outsourcing
contract.  The more I&amp;rsquo;ve delved into &amp;ldquo;cloud&amp;rdquo; the more I&amp;rsquo;ve realised that
we already have (or should have!) processes in place to handle this.  Far
too frequently I hear people discuss the complexities of a solution in
the cloud and I ask &amp;ldquo;How does cloud change this?&amp;rdquo;.  Most of the time
it doesn&amp;rsquo;t.&lt;/p&gt;

&lt;p&gt;So what &lt;em&gt;does&lt;/em&gt; cloud change?  Staffing is an obvious one; people have
access to physical machines that didn&amp;rsquo;t go through your vetting process.
Access management is another; these staff don&amp;rsquo;t authenticate via your
corporate systems.  Patch management?  Inventory management?  Physical
security?   The list of things &amp;lsquo;below the line&amp;rsquo; goes on and on.&lt;/p&gt;

&lt;p&gt;Which is where we have to start to trust, but have a level of verification.
There are now a number of certifications that companies can attain to
help you gain confidence in the opaque box.  The primary one is the SOC2
report, which is part of SSAE18 and replaces the older SAS70 reports.&lt;/p&gt;

&lt;p&gt;The SOC reports can be used as a baseline and audited by a trusted
auditor.  You don&amp;rsquo;t want a SOC report from &amp;ldquo;Joe&amp;rsquo;s bait and audit shop&amp;rdquo;!
A properly performed audit can help provide assurance that many of the
below the line controls a company would provide on-premise are also being
met by the CSP in the cloud.  You may also be interested in the SOC1 and
SOC3 reports; all in all they provide a pretty comprehensive picture
of the control state of a CSP.&lt;/p&gt;

&lt;p&gt;Similarly, a CSP that claims to be Payment Card Industry (PCI) compliant
will have additional audits via a QSA.  It&amp;rsquo;s important to note the
limitations of these certifications, though; a CSP like Amazon have
over a hundred services but not all of them are PCI certified.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Personally, I&amp;rsquo;ve been using virtual machines from providers for over a
decade (my linode was first deployed in 2004).  But I&amp;rsquo;m not processing
credit cards or bank accounts so I&amp;rsquo;m not a big risk.  As long as I
avoid being an idiot then my biggest opponent is a script; who wants
to break into me?  (No no no; that&amp;rsquo;s not an invitation!!)&lt;/p&gt;

&lt;p&gt;But a bank?  Ah, that&amp;rsquo;s a different matter entirely.  They have data
people want; they&amp;rsquo;re an attraction.  Delegating control of some of the
base layers is scary.&lt;/p&gt;

&lt;p&gt;It all boils down to how much you can trust your CSP, and how much you
can verify that trust.  SOC reports, COAs, contractual obligations and
insurance can all help with this verification and indemnity.&lt;/p&gt;

&lt;p&gt;10 years ago I would not have placed critical processing in the cloud
but, today, I think things have matured enough that PCI data can be
handled there securely.&lt;/p&gt;

&lt;p&gt;If you look at most of the recent &amp;ldquo;cloud based&amp;rdquo; data breaches they&amp;rsquo;ve
not been at the CSP layer of the shared responsibility model, it&amp;rsquo;s
always been at the &lt;em&gt;customer&lt;/em&gt; layer; most frequently an open S3 bucket,
but also open unauthenticated mongoDBs, and similar.&lt;/p&gt;

&lt;p&gt;Yes, there is a risk your CSP might be broken into&amp;hellip; but this is a
micro-hole of a risk compared to the tank-sized hole you&amp;rsquo;re unwittingly
building!&lt;/p&gt;

&lt;p&gt;Manage the risk accordingly.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The cloud is not your friend</title>
      <link>https://www.sweharris.org/post/2018-02-04-cloud-friend/</link>
      <pubDate>Sun, 04 Feb 2018 19:45:10 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2018-02-04-cloud-friend/</guid>
      <description>

&lt;p&gt;Even after all this time I hear statements like &amp;ldquo;Oh, we can just run our
code in the cloud&amp;rdquo;. This is the core of the &lt;em&gt;lift and shift&lt;/em&gt; school of
cloud usage.&lt;/p&gt;

&lt;p&gt;And these people are perfectly correct; they &lt;em&gt;can&lt;/em&gt; just run their stuff
in the cloud.  But it won&amp;rsquo;t work so well.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve &lt;a href=&#34;https://www.sweharris.org/post/2016-08-08-lift_and_shift/&#34;&gt;previously written&lt;/a&gt; about lift
and shift issues, but here I want to focus on the &amp;ldquo;resiliency&amp;rdquo; issue.
People get annoyed when I point out that their design is unreliable and
subject to failure modes.&lt;/p&gt;

&lt;p&gt;&amp;ldquo;Oh but the cloud is reliable!&amp;rdquo; they cry.  &amp;ldquo;Major companies like Netflix
and even Amazon themselves never go down.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;If only it was that simple&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;existing-designs&#34;&gt;Existing designs&lt;/h2&gt;

&lt;p&gt;In a traditional datacenter environment a &lt;em&gt;lot&lt;/em&gt; of work has been put in
place to make underlying infrastructure reliable.  We spend lots of
money trying to get to that mythical &amp;ldquo;five nines&amp;rdquo; reliability.  We
build clusters of servers and use VMware vmotion to migrate workloads
around the cluster to allow for nodes to be taken down for management.
We dual connect machines to independent network switches.  Similarly for
SAN fabrics.  And, on top of all that, we then duplicate all this in another
datacenter and configure our application stacks for HA (e.g. Oracle
data replication, global load balancing).&lt;/p&gt;

&lt;p&gt;This is expensive to build, and hard to maintain.  And very easy to
get wrong.  Who here has &lt;em&gt;not&lt;/em&gt; been stuck on a &amp;ldquo;DR Failover&amp;rdquo; call where
the DR component hasn&amp;rsquo;t started up properly because testing has assumed
clean shutdown of primary&amp;hellip; something that doesn&amp;rsquo;t happen in a real
failure.&lt;/p&gt;

&lt;p&gt;No wonder people want to move to the cloud; it&amp;rsquo;s so much more reliable!
Except&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;the-cloud-is-not-reliable&#34;&gt;The cloud is not reliable&lt;/h2&gt;

&lt;p&gt;If you look at SLAs from major Cloud Service Providers (CSPs) then you&amp;rsquo;ll
see they talk about a &lt;em&gt;service&lt;/em&gt; SLA.   Let&amp;rsquo;s take &lt;a href=&#34;https://aws.amazon.com/ec2/sla/&#34;&gt;Amazon EC2&lt;/a&gt; as an example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The Service Commitment does not apply [&amp;hellip;] that result from failures of individual instances or volumes not attributable to Region Unavailability&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Basically, Amazon provide a &amp;ldquo;four nines&amp;rdquo; SLA for a region, and not for
individual running instances.&lt;/p&gt;

&lt;p&gt;Your CSP running instance is probably &lt;em&gt;less&lt;/em&gt; reliable than the VM you
run in house.  Maintenance likely isn&amp;rsquo;t going to happen on your schedule!&lt;/p&gt;

&lt;h2 id=&#34;plan-for-failure&#34;&gt;Plan for failure&lt;/h2&gt;

&lt;p&gt;This is a core requirement for moving to the cloud.  If you want to get
cloudy infrastructure to be as resilient as your on-premise stuff then
you need to build solutions that match the existing patterns and designs.
You may no longer have the ability to do things like VMotion, so how will
you take instances down for patching?  You will need to replicate databases,
even cross region.  You&amp;rsquo;ll still have requirements for DR testing, and this
will be even more important, because of the lower underlying resiliency.&lt;/p&gt;

&lt;p&gt;So now you have more VMs, more data transit charges, more headaches&amp;hellip;
this cloud lark isn&amp;rsquo;t looking so friendly now, is it?&lt;/p&gt;

&lt;p&gt;Or you can look at how companies like Netflix actually get their
reliability; their application assumes failure.&lt;/p&gt;

&lt;p&gt;This turns the existing reliability model on its head; instead of having
four-nines infrastructure that the app can rely on (and so mostly ignore),
assume we have three-nines (or even two-nines!) and the application has
to make up the difference.&lt;/p&gt;

&lt;p&gt;Developers now take on the majority of the resiliency requirements.  There&amp;rsquo;s
a whole new set of programming patterns that need to be used; keeping state
externalised, using a &lt;a href=&#34;https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern&#34;&gt;circuit break pattern&lt;/a&gt;, providing service state visibility&amp;hellip;
Tooling such as &lt;a href=&#34;https://github.com/Netflix/Hystrix&#34;&gt;Netflix Hysterix&lt;/a&gt; can
help with this.&lt;/p&gt;

&lt;p&gt;Both approaches are possible; each have their pros and cons, challenges
and costs.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;You &lt;em&gt;can&lt;/em&gt; make friends with the cloud.  It requires thinking about.  An
application redesign host a lot of up-front costs but can lead to long
term benefits.  A lift-and-shift approach is simpler but can bring in
a lot of legacy processes and procedures (&amp;ldquo;ugh, another broken DR failover!&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;Whatever you do, though, you can&amp;rsquo;t ignore resiliency and reliability in
the cloud; you don&amp;rsquo;t get it &amp;ldquo;out of the box&amp;rdquo;.  Done properly, however,
then the cloud can start to work for you, and you&amp;rsquo;ll be best of friends
and never want to work with traditional methods ever again!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What we can learn from the rebellion leadership failures in The Last Jedi</title>
      <link>https://www.sweharris.org/post/2018-01-22-last_jedi/</link>
      <pubDate>Mon, 22 Jan 2018 20:31:28 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2018-01-22-last_jedi/</guid>
      <description>

&lt;p&gt;This is an odd post for me.  I&amp;rsquo;m terrible as a manager.  I&amp;rsquo;m terrible as
a team leader.  I &lt;em&gt;think&lt;/em&gt; I&amp;rsquo;m good as a teacher and mentor, but that&amp;rsquo;s a
different role.  Lead by example, teach what I know, learn when I can.
I&amp;rsquo;ve definitely not been in the military.  And yet I&amp;rsquo;m about to write
about effective leadership&amp;hellip;  or maybe &lt;em&gt;bad&lt;/em&gt; leadership.&lt;/p&gt;

&lt;p&gt;Finally I get to see The Last Jedi.  And one thing stood out.&lt;/p&gt;

&lt;p&gt;(&amp;ldquo;One thing?&amp;rdquo;  Hush from the peanut gallery!)&lt;/p&gt;

&lt;p&gt;Poe make a decision; he ignores his command hierarchy; he achieves his
goal, but at terrible expense.  As a result Leia demotes him.  Then,
and this is the part I have trouble with, Holdo, cuts him out of
the command loop and tells him to shut up and obey orders.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve &lt;em&gt;heard&lt;/em&gt; that being a good soldier means &amp;ldquo;obey orders&amp;rdquo;.  I&amp;rsquo;ve also
heard that if you go beyond being a grunt then you&amp;rsquo;re meant to be able
to think; an officer is meant to be able to make decisions in order
to best obtain the objective.  Even soldiers aren&amp;rsquo;t automatons, and
the higher up the chain you are the bigger the perspective you get.
The officer on the ground needs to be able to evaluate the local
tactical situation in terms of the greater goals.&lt;/p&gt;

&lt;p&gt;This is true in a corporate environment.  Well, assuming senior
management know what they&amp;rsquo;re doing :-)&lt;/p&gt;

&lt;p&gt;As a lead engineer you&amp;rsquo;re meant to know the organizational goals and
the immediate product goals, and make decisions (design, architecture,
engineering) that best achieve those goals.  If you have questions then
you&amp;rsquo;re &lt;em&gt;meant&lt;/em&gt; to engage your leadership team and discuss it with them.&lt;/p&gt;

&lt;p&gt;Same if you&amp;rsquo;re a program manager.  Or an SME.  Or anyone!  By understanding
the goals, you can deliver better.&lt;/p&gt;

&lt;p&gt;In an organisation, the worst thing your leadership can do is tell you
&amp;ldquo;just do what you are told&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;As a leader you want your team to be invested in your projects and plans,
and that means explaining the rationale to them.  People work better
when they understand things.  Even better, they may not inadvertently
work &lt;em&gt;against&lt;/em&gt; the plan.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve been in the situation where my management tree got replaced;
basically they all quit and new people from outside the company came in.
They brought their own vision and plans.  However they were unable
to &lt;em&gt;justify&lt;/em&gt; it.  It boiled down to &amp;ldquo;I&amp;rsquo;m going to throw away a working
solution and replace it with a new technology because that&amp;rsquo;s what I want&amp;rdquo;.
There was no logic, no rationale; indeed the replacement solution would
be &lt;em&gt;less&lt;/em&gt; secure and performant than the existing one.  At least from
my perspective as the SME in the area, and management did not explain
otherwise (and 5 years later I still believe I was right).&lt;/p&gt;

&lt;p&gt;In my case I found another role in the company so I didn&amp;rsquo;t have to fight
that problem.&lt;/p&gt;

&lt;p&gt;In Poe&amp;rsquo;s case he felt he had to take direct action (took control of the
bridge) and potentially compromised the master plan.  A whole mess could
have been circumvented if Holdo has just spent 1 minute explaining the
strategy to a person who had previously been part of the trusted
advisory council (as much as the rebellion had any structure).&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Good leadership requires all levels of the management tree to be to
explain themselves.  Simplistically, the seniors set the direction, the
middle management set the targets, the juniors set the tasks.  But at
each level management &lt;em&gt;must&lt;/em&gt; listen to the layers below; they must hear
the questions, hear the problems, hear the ideas.  They must be able to
integrate new information from SMEs and respond beyond &amp;ldquo;because I say so&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;If you can&amp;rsquo;t explain, you&amp;rsquo;ll end up with people, in good faith, working
against the plan.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Can&#39;t Patch, Won&#39;t Patch</title>
      <link>https://www.sweharris.org/post/2018-01-15-cant_patch/</link>
      <pubDate>Mon, 15 Jan 2018 15:09:21 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2018-01-15-cant_patch/</guid>
      <description>

&lt;p&gt;Whenever a new &amp;ldquo;critical&amp;rdquo; vulnerability is found, the cry goes out
across the land;&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Patch!&lt;br&gt;
Patch!&lt;br&gt;
Patch!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Whenever a major incident is caused by known vulnerabilities the
question is always&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Why didn&amp;rsquo;t they patch?&lt;br&gt;
We&amp;rsquo;ve known about this for months!&lt;br&gt;
They should have patched!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sometimes this is valid criticism, and learning &lt;em&gt;why&lt;/em&gt; the organisation
wasn&amp;rsquo;t patched can lead to some &lt;a href=&#34;https://www.sweharris.org/post/2017-10-08-equifax-keyman&#34;&gt;insights into failure modes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Other times, however, it may not be possible.&lt;/p&gt;

&lt;h2 id=&#34;why-can-t-we-always-patch&#34;&gt;Why can&amp;rsquo;t we always patch?&lt;/h2&gt;

&lt;p&gt;Sometimes patching raises challenges that aren&amp;rsquo;t always obvious.
An annoying use case is where the computer may control some regulated
piece of equipment.  Let&amp;rsquo;s take the X-Ray machine at your dentist&amp;rsquo;s
office; I&amp;rsquo;ve seen some of those controlled with software running on
Microsoft Windows.  I don&amp;rsquo;t know about you, but I&amp;rsquo;d rather not have
non-experts apply a Windows patch that causes radiation exposure 100x
greater than planned!  Further, in the medical field, may be computers
controlling CAT or MRI machines, which cost megabucks to replace.  Now you
may argue that users shouldn&amp;rsquo;t buy into this sort of hardware in the
first place, but when it&amp;rsquo;s that industry standard then they don&amp;rsquo;t have
a lot of choice.  Here we&amp;rsquo;re definitely into &amp;ldquo;can&amp;rsquo;t patch&amp;rdquo; territory.&lt;/p&gt;

&lt;p&gt;Related to this are the &amp;ldquo;appliance&amp;rdquo; type devices, where you are forced
to wait for a vendor to release updates.  You can&amp;rsquo;t patch until that
happens!&lt;/p&gt;

&lt;p&gt;Another scenario may be that legacy hardware needs to be supported; the
software that drives that hardware doesn&amp;rsquo;t work under newer versions of
the OS, so you&amp;rsquo;ve been limited to old unsupported unpatchable installs.
In some cases there may be a path, but the cost is prohibitive; in other
cases it may be a legal requirement (document retention requirements
are big here; a need to restore backups from 7 years ago means needing
to maintain equipment that can drive the hardware to do the restore).
We may be in a combination of can&amp;rsquo;t/won&amp;rsquo;t patch.&lt;/p&gt;

&lt;p&gt;And, of course, there&amp;rsquo;s a potential resource constraint issue; how long
would it take you to patch your estate?&lt;/p&gt;

&lt;p&gt;Whatever the reason, sometimes patching just isn&amp;rsquo;t feasible.  Pointing
fingers at victims of a cyber breach and shouting &amp;ldquo;you shoulda patched!&amp;rdquo;
without knowing the full set of constraints the organisation was under
doesn&amp;rsquo;t help you learn from these incidents and prevent them in your
own organisation.&lt;/p&gt;

&lt;h2 id=&#34;compensating-controls&#34;&gt;Compensating controls&lt;/h2&gt;

&lt;p&gt;So if we can&amp;rsquo;t always patch, then what can we do?  This is where the
&amp;ldquo;defense in depth&amp;rdquo; type controls can come in handy.&lt;/p&gt;

&lt;p&gt;Web servers should be behind a WAF, for example.  Can&amp;rsquo;t patch against
shellshock (to take an example) because you have a gazillion instances?
If your WAF can block the pattern, then it should do so.  Beware false
positives, of course&amp;hellip;&lt;/p&gt;

&lt;p&gt;Legacy devices may need to be placed on a protected network behind firewalls,
requiring explicit permission (jumphosts, firewall ingress rules, whatever)
to be reachable from the core network.  Of course, such devices may need to
be protected from each other, leading to a proliferation of firewall rules!&lt;/p&gt;

&lt;p&gt;Emulation may work in some cases; run the older app under an emulation layer.
It may work and may mitigate some of the issues&amp;hellip;&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s no one solution to these problems; the mitigation will be unique
to the challenge.&lt;/p&gt;

&lt;h2 id=&#34;risk-management&#34;&gt;Risk management&lt;/h2&gt;

&lt;p&gt;In some cases no mitigation may be possible (e.g. an MRI scanner that expects
to write results to a standard Windows share; WannaCry will happily encrypt
all that data!).  So now we need to look at managing the risk.&lt;/p&gt;

&lt;p&gt;The first step, as always, is to be &lt;em&gt;aware&lt;/em&gt; that you have a risk.  Inventory
tracking, patch state&amp;hellip; all the standard vulnerability management stuff
is a prerequisite; you can&amp;rsquo;t evaluate what you don&amp;rsquo;t know.&lt;/p&gt;

&lt;p&gt;Perform an assessment; is an unpatched device really at risk?  My TiVo
runs Linux at its heart; is it at risk to Meltdown or Spectre?  Given
the software stack on top, I&amp;rsquo;d guestimate &amp;ldquo;low risk&amp;rdquo; (even if the hardware
was susceptible, which it may not be) due to the limited input channels
to the OS.  Is your Windows 95 machine, running your door swipe system,
at risk?&lt;/p&gt;

&lt;p&gt;Determine what mitigation is possible.  Stop the caretaker using the door
entry PC to surf the web :-)&lt;/p&gt;

&lt;p&gt;And so on.  Y&amp;rsquo;know&amp;hellip; all the standard risk management stuff.&lt;/p&gt;

&lt;p&gt;At the end of the day you end up with an evaluation of the criticality of
the exposure, the likelyhood of it happening, the consequences.  Outside
of a VM farm (including clouds), is Meltdown a big risk to your organisation?
Possibly not.  Shellshock may have been, though.&lt;/p&gt;

&lt;p&gt;And then you decide whether to carry that risk, or plan a remediation
strategy (spend money, upgrade, convert backups to a new format&amp;hellip;).&lt;/p&gt;

&lt;p&gt;And perhaps consider insurance, just in case you&amp;rsquo;re wrong!  (Although
can you insure against reputational loss when you leak a gazillion
credit cards?)&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Not every issue can be patched.  Not ever issue &lt;em&gt;needs&lt;/em&gt; to be patched.
But organisations need to be aware of their risk and determine an
approach.&lt;/p&gt;

&lt;p&gt;Risk management and vulnerability management needs to be a critical
function in any organisation.  Doing it wrong can cost lots of money
(either in wasted effort due to emergency &amp;lsquo;patch now patch now&amp;rsquo; mentality,
or in incident response after a breach).  It&amp;rsquo;s not a side issue to be
minimally funded just because some NIST or SANS chart tells you it should
be there.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Meltdown and Spectre</title>
      <link>https://www.sweharris.org/post/2018-01-04-meltdown_spectre/</link>
      <pubDate>Thu, 04 Jan 2018 18:57:41 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2018-01-04-meltdown_spectre/</guid>
      <description>

&lt;p&gt;Unless you&amp;rsquo;ve been living under a rock, you may have heard of two
&lt;em&gt;panic panic panic&lt;/em&gt; bugs, known as &lt;a href=&#34;https://spectreattack.com/&#34;&gt;Meltdown and Spectre&lt;/a&gt;.  People
are panicking about them because they are CPU level issues that may
impact almost every modern CPU around.  Meltdown is Intel specific,
but Spectre affects Intel, AMD, and potentially others (&lt;a href=&#34;https://access.redhat.com/security/vulnerabilities/speculativeexecution&#34;&gt;Redhat
claims POWER and zSeries is impacted&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id=&#34;what-is-the-problem&#34;&gt;What is the problem?&lt;/h2&gt;

&lt;p&gt;In short, modern CPUs may execute instructions out of order, especially
when the order doesn&amp;rsquo;t matter.  If you have&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;a:=1
b:=1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;then does it matter what way round they run?&lt;/p&gt;

&lt;p&gt;Now modern CPUs also &lt;em&gt;speculate&lt;/em&gt; about branch instructions and may
pre-emptively execute the branch it predicts as being the one to be
followed.  If the guess about the branch is correct then the out of
order execution results are valid and your code runs faster.  If it guesses
wrong then &amp;ldquo;no harm, no foul&amp;rdquo; we just throw away the guessed results
and run the right branch.&lt;/p&gt;

&lt;p&gt;Except it turns out there &lt;em&gt;is&lt;/em&gt; a foul.  The predicted branch impacts the
CPU cache.  And it turns out it&amp;rsquo;s possible to use this fact to derive
further information about memory locations you shouldn&amp;rsquo;t normally have
access to.&lt;/p&gt;

&lt;p&gt;The result is an information leak.  Inside a single VM one process
could read kernel memory data.  Want to read secrets out of memory?
It&amp;rsquo;s theoretically doable.  Worse, on a virtual server one VM could read
memory from &lt;em&gt;another&lt;/em&gt; VM.  Oh dear, do you trust everyone sharing the
Amazon Cloud server that your EC2 VM is running on?&lt;/p&gt;

&lt;h2 id=&#34;why-are-people-panicking&#34;&gt;Why are people panicking?&lt;/h2&gt;

&lt;p&gt;CPUs have bugs all the time.  Most of them can be patched at boot
time with a microcode update.  But in this case the problem is at
a lower level; it&amp;rsquo;s all to do with the cache.  Now the Meltdown
issue can be &lt;em&gt;mitigated&lt;/em&gt; at the OS layer by modifying how the kernel
handles virtual memory.  This mitigation isn&amp;rsquo;t free; it may have an
estimated 5-&amp;gt;30% performance impact.  That sounds like a lot!  The 30%
impact, though, is almost the worst case scenario (in testing it
required a specific pattern of reads to an SSD).  More commonly the
impact is 5%, and if your application is compute intensive then there
may be almost no impact (I saw some gaming desktop testing where the
patch had an impact smaller than measurable error).  But 30% is the
headline number.&lt;/p&gt;

&lt;p&gt;The Spectre bug apparently &lt;em&gt;can not&lt;/em&gt; be fixed through software.  We can
block known paths to exploit and make it harder to exploit (it&amp;rsquo;s already
pretty hard to do more than a proof of concept) but we can&amp;rsquo;t block it
totally.&lt;/p&gt;

&lt;p&gt;So people are now panicking like mad; do they apply the patches ASAP to
prevent exploitation and risk the performance hit, or do they leave
servers exposed?&lt;/p&gt;

&lt;h2 id=&#34;why-am-i-not-panicking&#34;&gt;Why am I not panicking?&lt;/h2&gt;

&lt;p&gt;In essence this is a read-only local privilege escalation bug.  Sure,
it&amp;rsquo;s at the hardware layer rather than at the kernel, but the impact
is still comparable to that of local privilege escalation.&lt;/p&gt;

&lt;p&gt;In comparison, &lt;a href=&#34;https://en.wikipedia.org/wiki/Shellshock_(software_bug)&#34;&gt;Shellshock&lt;/a&gt; was remotely executable and trivial to exploit.  That&amp;rsquo;s scarey.&lt;/p&gt;

&lt;p&gt;Many places tend to have a &amp;lsquo;one workload per VM&amp;rsquo; model.  Privilege
escalation, there, isn&amp;rsquo;t so great a risk.  However
&lt;em&gt;hypervisor&lt;/em&gt; technology means that one physical server can serve
multiple logical VMs and so multiple workloads.  Similarly &lt;em&gt;container&lt;/em&gt;
technology allows one VM to handle multiple workloads.&lt;/p&gt;

&lt;p&gt;So I look at it from layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&amp;ldquo;Top priority&amp;rdquo;&lt;br&gt;
Hypervisors should be patched.  This protects one VM from another.
A cloud service provider should treat this as critical, because they host
untrusted workloads (indeed Amazon and Microsft have already patched and
rebooted a majority of their servers; operations at scale!).  Inside
your enterprise your VMware/KVM/Xen/Openstack/&amp;hellip; environments should
be patched.  Any host running containers (eg docker) should be patched.
Any on-premise cloudy environment (e.g. Cloud Foundry, Apprenda) should
be patched.&lt;br&gt; Basically any environment with &amp;ldquo;neighbours&amp;rdquo; should be
treated as top priority priority, so one neighbour can not impact another.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&amp;ldquo;High&amp;rdquo;&lt;br&gt;
Server OSes should be patched, of course, but the urgency is less.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;risk-management&#34;&gt;Risk management&lt;/h2&gt;

&lt;p&gt;Of course you don&amp;rsquo;t want to leave known vulnerabilities in your environment,
but the whole point of measured risk management is to understand the
impact of a vulnerability on your organisation and prepare an appropriate
response.  Ask yourself questions around ease of exploitation, risk of
exploitation, consequence of exploitation.  At present this appears to
be a local read-only privilege escalation issue; what is the impact?&lt;/p&gt;

&lt;p&gt;Can remote attacks trigger the bug?  Well with Spectre there&amp;rsquo;s a proof
of concept javascript attack, so maybe ensure your desktop browsers are
up to date.  Do you have code that may dynamically build eBPF filters
into the kernel?  If so, ensure the inputs are trusted (the right thing
to do, anyway).&lt;/p&gt;

&lt;p&gt;Your organisation should already have vulnerability management processes
to handle new vulnerabilities.  Treat these the same way.  It doesn&amp;rsquo;t
matter that it&amp;rsquo;s a hardware issue; it&amp;rsquo;s just another issue.  Follow your
patch guidelines, follow your processes.  Don&amp;rsquo;t panic.&lt;/p&gt;

&lt;p&gt;Unless you&amp;rsquo;re a cloud vendor of course.  Then panic and patch immediately!
You don&amp;rsquo;t want one customer stealing data from another.  Your risk
analysis is different to a traditional enterprise!&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Bugs are bugs; whether it&amp;rsquo;s a hardware bug or a kernel bug, or an application
bug.  Follow your processes.&lt;/p&gt;

&lt;p&gt;What&amp;rsquo;s &lt;em&gt;interesting&lt;/em&gt; is that this is next along the class of attacks at
the hardware level.  Rowhammer showed that memory could be made to do
things outside of the knowledge of the OS.  Meltdown and Spectre show
that the CPU, itself, can be abused in a similar way.  What will be next?
What core assumption are we building on that is shakey?  That might bring
the whole house of cards known as &amp;ldquo;secure computing&amp;rdquo; tumbling down?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Douglas Charles Harris</title>
      <link>https://www.sweharris.org/dad/</link>
      <pubDate>Sat, 30 Dec 2017 23:13:02 -0500</pubDate>
      
      <guid>https://www.sweharris.org/dad/</guid>
      <description>&lt;p&gt;My Dad died, at the age of 79, in Tenerife doing what he loved&amp;hellip;
falling asleep in the sun while on holiday.&lt;/p&gt;

&lt;p&gt;I might write another post around what Dad meant to me, but I&amp;rsquo;m going
to limit this to the ceremony itself.&lt;/p&gt;

&lt;p&gt;The cremation was held on 13th December.  Dad was a &amp;ldquo;believer&amp;rdquo; but
low key about it (Mum doesn&amp;rsquo;t believe) so we had the local priest
perform the ceremony.  All in all, as these things go, it was OK.&lt;/p&gt;

&lt;p&gt;The procession to the crematorium consisted of just the hearse and
a car containing family (Mum, me, Jason, Stuart, Tori). The funeral
director walked in front of the car while on our local back streets,
and tears came to my eyes at the amount of deference he showed to the
body whenever he passed it (paused, took off his hat, bowed his head).
It&amp;rsquo;s probably the most repsect Dad has ever been shown!  The drive
was pretty slow and I remember laughing to myself; Dad would have been
annoyed if he&amp;rsquo;d been stuck behind the procession with no way to overtake!&lt;/p&gt;

&lt;p&gt;The ceremony itself was almost as we planned; we&amp;rsquo;d given the priest a
good outline and set of jokes.  For example, Mum had written that Dad
always wanted to do stuff his way, and that way was normally the right
way.  I added a joke; &amp;ldquo;well, except for when he electrocuted himself
changing a light bulb.  Or when he fell off a ladder cutting a tree branch.
Or when he broke the computer.  Or&amp;hellip;&amp;rdquo;  The priest told it well, and a
number of people mentioned that he&amp;rsquo;d known Dad well.  Oh nononono, we
just gave him a &lt;a href=&#34;https://www.sweharris.org/dad_service/&#34;&gt;good story outline&lt;/a&gt; :-)&lt;/p&gt;

&lt;p&gt;The music choices were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://www.sweharris.org/Dad_Files/1.Un_bel_di_vedremo.mp3&#34;&gt;Un bel di vendro - Madame Butterfly&lt;/a&gt;&lt;br&gt;
Dad loved this song&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://www.sweharris.org/Dad_Files/2.My_Way.mp3&#34;&gt;My Way - Frank Sinatra&lt;/a&gt;&lt;br&gt;
I think this shows up in many a funeral, but it also fit in with the joke&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://www.sweharris.org/Dad_Files/3.Fly_Me_to_the_Moon.mp3&#34;&gt;Fly Me To The Moon - Frank Sinatra&lt;/a&gt;&lt;br&gt;
This played to another joke; Mum can&amp;rsquo;t stand Sinatra but she had two songs
by him
because she loved Dad so much.  This song (or a variation from someone
else) was the first song they danced to when they first met, so it was
fitting that it also be their last song.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One further poem was read out during the service:&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Remember Me&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To the living, I am gone&lt;br&gt;
To the sorrowful, I will never return&lt;br&gt;
To the angry, I was cheated&lt;br&gt;
But to the happy, I am at peace&lt;br&gt;
And to the faithful, I have never left&lt;br&gt;&lt;/p&gt;

&lt;p&gt;I cannot speak, but I can listen&lt;br&gt;
I cannot be seen, but I can be heard&lt;br&gt;&lt;/p&gt;

&lt;p&gt;So as you stand upon the shore&lt;br&gt;
Gazing at the beautiful sea, remember me&lt;br&gt;
As you look in awe at a mighty forest&lt;br&gt;
And in its grand majesty, remember me&lt;br&gt;&lt;/p&gt;

&lt;p&gt;Remember me in your hearts,&lt;br&gt;
In your thoughts, and the memories of the&lt;br&gt;
Times we loved, the times we cried,&lt;br&gt;
the battle we fought and the times we laughed&lt;br&gt;&lt;/p&gt;

&lt;p&gt;For if you always think of me,&lt;br&gt;
I will never have gone.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Goodbye, Dad.  Thank you for loving me, for believing in me, for everything
you did for me.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Dad_Files/Dad_Flowers.jpg&#34; alt=&#34;Flowers&#34;&gt;
&lt;/div&gt;
&lt;/center&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Dad_Files/page_1.jpg&#34;&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Dad_Files/small_page_1.jpg&#34; alt=&#34;Page1&#34;&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/center&gt;
&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Dad_Files/page_2.jpg&#34;&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Dad_Files/small_page_2.jpg&#34; alt=&#34;Page2&#34;&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/center&gt;
&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Dad_Files/page_3.jpg&#34;&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Dad_Files/small_page_3.jpg&#34; alt=&#34;Page3&#34;&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/center&gt;
&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Dad_Files/page_4.jpg&#34;&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Dad_Files/small_page_4.jpg&#34; alt=&#34;Page4&#34;&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/center&gt;
&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Dad_Files/page_5.jpg&#34;&gt;
&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/Dad_Files/small_page_5.jpg&#34; alt=&#34;Page5&#34;&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;script type=&#34;text/javascript&#34;&gt;
  var passwd_on = &#39;no&#39;
  var sites_on = &#39;no&#39;
&lt;/script&gt;
&lt;script type=&#34;text/javascript&#34; src=&#34;https://www.sweharris.org/hashover.php?canon_url=https%3a%2f%2fwww.sweharris.org%2fdad%2f&#34;&gt;&lt;/script&gt;
&lt;noscript&gt;You must have JavaScript enabled to use the comments.&lt;/noscript&gt;


</description>
    </item>
    
    <item>
      <title>Technology is not enough</title>
      <link>https://www.sweharris.org/post/2017-11-19-technology-people/</link>
      <pubDate>Sun, 19 Nov 2017 15:33:31 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-11-19-technology-people/</guid>
      <description>

&lt;p&gt;&lt;em&gt;&amp;ldquo;To summarise the summary of the summary; people are a problem&amp;rdquo;&lt;/em&gt; - Douglas
Adams, The Restaurant At The End Of The Universe&lt;/p&gt;

&lt;p&gt;The above quote is one of my favourite jokes (I&amp;rsquo;ve used it in a previous
post); it highlights how people can
complicate any situation.  We can try to avoid this by
&lt;a href=&#34;https://www.sweharris.org/post/2016-05-08-people/&#34;&gt;automating&lt;/a&gt; as much as possible but, at the
end of the day, there&amp;rsquo;s always a human involved somewhere; even if it&amp;rsquo;s
the team that manages the automation!&lt;/p&gt;

&lt;p&gt;A few weeks back I was down the pub with some friends and they got to
talking about a Red Team run against the solution they managed.  Now I
was interested in this because I&amp;rsquo;d been involved in some of the design
and implementation of this solution.&lt;/p&gt;

&lt;p&gt;It had great technology in place; firewalls, segregated networks, jumphosts,
keystroke logging, multi-factor requirements and, of course, automation at
multiple levels of the stack.&lt;/p&gt;

&lt;p&gt;This team had developed a robust set of processes and procedures.  Key
credentials were stored in a password vault that only non-operations staff
could access, thus enforcing &amp;ldquo;two person&amp;rdquo; controls.  All admin access was
audited and tickets generated for review and signoff.&lt;/p&gt;

&lt;p&gt;Now there was a gap; the product&amp;rsquo;s admin interface is accessed via the same
server as applications running on the platform.  This isn&amp;rsquo;t uncommon; in a
PaaS many of the admin tools run on the PaaS itself.  This made it hard to
segregate admin API traffic from application traffic so this stuff was
hard to block at layer 4, and layer 7 would have introduced complications
and performance problems - especially for microservice architectures, adding
overhead to every service call really hurt things.&lt;/p&gt;

&lt;p&gt;So the team accepted this risk.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m sure you can see where this is going&amp;hellip;&lt;/p&gt;

&lt;p&gt;The Red Team were unable to break the design; the technology was secure.
The endpoints had no flaws (no SQLi, no XSS, no buffer overflows).  The
interactive admin pathway was secure and they couldn&amp;rsquo;t break that.&lt;/p&gt;

&lt;p&gt;So they turned to the staff.  This path bore fruit.  An intern in the
Ops team followed a phishing link and entered his AD details.  The Red Team
used those to access his VDI.  They found, on his desktop, a text file with
the admin password in it.  They were able to use this to access the API.&lt;/p&gt;

&lt;p&gt;At this point the detective audit controls tripped but it was too late; an
attacker had admin in the environment and it&amp;rsquo;s now considered compromised.
The best we can do is limit the spread of damage and determine if any
sensitive data had been exposed.&lt;/p&gt;

&lt;p&gt;At this point it&amp;rsquo;s tempting to point fingers.  Why did an intern have
the admin password?  Why did he store it on his desktop?  Who was his
supervisor?  But that doesn&amp;rsquo;t help; finger pointing doesn&amp;rsquo;t solve the
underlying problem.  &lt;a href=&#34;https://www.sweharris.org/post/2017-01-16-slowdown/&#34;&gt;Stop, step back, take a minute, slow down&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;the-human-weakness&#34;&gt;The human weakness&lt;/h2&gt;

&lt;p&gt;Any technology deployment needs to recognise that, at some point, humans will
be involved and that humans will make mistakes.&lt;/p&gt;

&lt;p&gt;Many organisations have &amp;ldquo;cyber awareness training&amp;rdquo; processes.  It&amp;rsquo;s even
a requirement in some regulatory environments.  But these tend to be
a &amp;ldquo;one size fits all&amp;rdquo; training, and don&amp;rsquo;t take into account unique
circumstances; an operations person with admin access to a PaaS has a
different risk profile than an admin assistant and the consequences of
succumbing to an attack is different, so why do they have the same training?&lt;/p&gt;

&lt;p&gt;Additionally this training is typically done on a yearly basis with some
form of online &amp;ldquo;click click click&amp;rdquo; course.  It becomes more of a box ticking
exercise than a true training exercise.  I really loved learning about
&amp;ldquo;Know Your Customer&amp;rdquo; requirements and &amp;ldquo;structuring money transfers&amp;rdquo;; that
training was so relevant to my job!&lt;/p&gt;

&lt;p&gt;Also our poor intern probably fell between training cycles and never did
any of the courses; he hadn&amp;rsquo;t been there long enough!  Even new hires
typically have a window to get the training completed by, and in the
mean time they may have access to production systems.&lt;/p&gt;

&lt;h2 id=&#34;what-can-be-done&#34;&gt;What can be done?&lt;/h2&gt;

&lt;p&gt;Earlier I described a number of technology controls this team had in place
to protect their service.  What was lacking was a set of non-technology
controls.  An obvious one might be &amp;ldquo;no one gets admin access to production
systems before they&amp;rsquo;ve completed &lt;em&gt;these&lt;/em&gt; training courses&amp;rdquo;.  Another might
be &amp;ldquo;people with privileged access to production systems require &lt;em&gt;those&lt;/em&gt;
additional courses&amp;rdquo;.  Yet another might be having some people require
refresher courses more frequently than the minimum standard.&lt;/p&gt;

&lt;p&gt;Of course there are reasons why organisations don&amp;rsquo;t do this; primarily
cost.  If someone can&amp;rsquo;t do their job until they&amp;rsquo;ve done a handful of
courses then that&amp;rsquo;s a week or two of time wasted.  Who has that kind of
slack?  I would counter than these are false economies and may open you
to greater expense in the future.&lt;/p&gt;

&lt;p&gt;This means that the people creating courses also need to be trained, in
order to create effective security &lt;em&gt;programs&lt;/em&gt;.  SANS calls this
&lt;a href=&#34;https://securingthehuman.sans.org/&#34;&gt;Securing The Human&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;m not a security training expert.  I don&amp;rsquo;t know the answer.  I can
create great technology controls, but if I don&amp;rsquo;t take into account human
fallibilities then these controls will not be sufficient.  I can teach
people on a one-on-one basis (and I do!) but this training doesn&amp;rsquo;t easily
propagate through the enterprise.&lt;/p&gt;

&lt;p&gt;Organisations need to create a &amp;ldquo;secure human&amp;rdquo; process that encourages
culture change so that new people automatically get inducted into the
correct way of doing things, both via tollgates and via co-workers.&lt;/p&gt;

&lt;p&gt;And this means more than pop up boxes &amp;ldquo;By accessing this system I promise
not to be a bloody idiot  [ OK ]&amp;ldquo;.  They don&amp;rsquo;t work.  But that&amp;rsquo;s a rant
for another day.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The three tier network is dead</title>
      <link>https://www.sweharris.org/post/2017-11-05-3tier-network/</link>
      <pubDate>Sun, 05 Nov 2017 13:59:28 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-11-05-3tier-network/</guid>
      <description>

&lt;p&gt;It&amp;rsquo;s a fairly common design in enterprise networks; a three tier network
architecture, with firewalls between the tiers.&lt;/p&gt;

&lt;p&gt;Typically these layers are split up with variations of the following names:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Presentation Layer  (Web)&lt;/li&gt;
&lt;li&gt;Application Layer   (App)&lt;/li&gt;
&lt;li&gt;Data (or storage) Layer  (Data)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&#34;https://www.sweharris.org/images/3tier.png&#34; alt=&#34;3tier diagram&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Typically you may have additional tooling in front of each layer; e.g
a load balancer, a web application firewall, data loss protection tools,
intrusion detection tools, database activity monitoring&amp;hellip;&lt;/p&gt;

&lt;p&gt;This gives a relatively good set of protections; attackers from the internet
can only see servers in the DMZ; if this server does get attacked then the
intruder can not see the data layer; they can only see the application
server.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s not perfect, of course.  Many organisations don&amp;rsquo;t have much protection
between servers inside each tier; an attacker who breaks into one web
server may be able to attack a second web server and use this to &lt;em&gt;pivot&lt;/em&gt;
through the organisation.  &amp;ldquo;Micro segmentation&amp;rdquo; is a concept that could
protect against this, but it&amp;rsquo;s very difficult to retro-fit this into an
existing environment.&lt;/p&gt;

&lt;h2 id=&#34;modern-application-design&#34;&gt;Modern application design&lt;/h2&gt;

&lt;p&gt;Unfortunately this type of environment doesn&amp;rsquo;t necessarily work so well
with modern dynamic applications.  If you deploy something like CloudFoundry
then your presentation layer and your application layer may both be on
the same network segment, or even running on the same server.  With
docker compose or swarm you can build a 3-tier design on a single machine,
and you can have &lt;em&gt;many&lt;/em&gt; 3-tier apps all segregated from each other on the
one box.  Dynamic scaling can mean that firewall rules may have to be
updated programmatically.  Network Address Translation (NAT) can make it
difficult to write firewalls at all, since the firewall can no longer
distinguish between the applications.&lt;/p&gt;

&lt;h2 id=&#34;the-new-3-tier-network&#34;&gt;The new 3-tier network&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;idea&lt;/em&gt; of the 3-tier network is a good one, and we should try and
keep it.  But the separation of network control devices (eg firewalls)
and application servers causes issues.  Fortunately technology has
moved on and we can start to take advantage of this&lt;/p&gt;

&lt;h3 id=&#34;tier-1&#34;&gt;Tier 1&lt;/h3&gt;

&lt;p&gt;Modern load balancers can do a lot more than just direct traffic.  They
can also &lt;em&gt;inspect&lt;/em&gt; it, acting as a WAF.  They can validate API traffic
matching XML or JSON rules.  They can act as authenticating endpoints,
eg talking back to an LDAP server&amp;hellip;&lt;/p&gt;

&lt;p&gt;Pretty much a modern device like this can &lt;em&gt;be&lt;/em&gt; the presentation layer.
Start to remove traditional web servers out of the DMZ and replace them
with these appliances.  This is a good thing to do, anyway, because
it reduces the footprint of devices exposed to the internet.  Why run
hundreds of full RedHat instances and JBoss servers with the associated
management requirements when a handful of dedicated appliances can do
the job?&lt;/p&gt;

&lt;p&gt;Once we accept the appliance can do the presentation layer role then we&amp;rsquo;ve
also removed one of the problems holding up the deployment of modern
applications.&lt;/p&gt;

&lt;h3 id=&#34;tier-2-and-3&#34;&gt;Tier 2 and 3&lt;/h3&gt;

&lt;p&gt;This is where things get a little more challenging, but where the concept
of micro-segmentation comes in.&lt;/p&gt;

&lt;p&gt;With Amazon Security Groups, with Docker Swarm networks, with Kubernetes
network structures, with Cloud Foundry Application Security Groups&amp;hellip; all
of these technologies can control the &lt;em&gt;egress&lt;/em&gt; of traffic from a container
or server, and in some cases also control ingress rules.  These rules allow
you to define tightly controlled access paths; application A instances
can &lt;em&gt;only&lt;/em&gt; talk to other services and data stores that have been
authorised.  Since the rules are defined to the application it doesn&amp;rsquo;t
matter where they are running; the rules follow the instance.&lt;/p&gt;

&lt;p&gt;This is new and scary for traditional network architects, who like to &lt;em&gt;know&lt;/em&gt;
where traffic flows are.  Paradoxically this lack of knowledge is what
increases security; we don&amp;rsquo;t need to care about IP addresses any more; instead
we define rules in terms of intent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&amp;ldquo;I want application A web server to talk to API servers from application B and C&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;I want application B API servers to talk to application B data servers&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;I want application C API servers to talk to application C data servers&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;This sort of approach is still its infancy in many places.  It&amp;rsquo;s very hard
to retro-fit this model onto existing networks; it requires a massive
discovery process, especially when the majority of communication may be
within a single tier and so no existing firewall rules may be present.&lt;/p&gt;

&lt;p&gt;In new deployments, however, it can be made a requirement.  Ensure your
Amazon instances are behind locked down security groups that restrict
egress as well as ingress.  Monitor deployments and alert on overly open
access (does your database server really need the ability to reach any server
on the internet?).  Set up flowlogs if you need traffic logging.&lt;/p&gt;

&lt;p&gt;In a container world, use orchestration tools that can define communication
between services.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;re now moving from a &amp;ldquo;discovered&amp;rdquo; communication model to a &amp;ldquo;defined by
intent&amp;rdquo; model.&lt;/p&gt;

&lt;p&gt;The 3-tier network isn&amp;rsquo;t dead, after all&amp;hellip; it just changed to a multi-tier
micro-segmented network!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Software for my digital safe</title>
      <link>https://www.sweharris.org/post/2017-10-28-digital_safe-software/</link>
      <pubDate>Sat, 28 Oct 2017 21:58:54 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-10-28-digital_safe-software/</guid>
      <description>

&lt;p&gt;A few weeks back I completed my &lt;a href=&#34;https://www.sweharris.org/post/2017-10-09-digital_safe&#34;&gt;Arduino hack for a digital safe&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What was missing, however, was the software to drive it.&lt;/p&gt;

&lt;p&gt;One requirement I had was to let it work with password managers.  I also
had the idea that maybe remote access (e.g. control the safe while away
from home, to grant a guest access) might be useful.&lt;/p&gt;

&lt;p&gt;This kinda meant it&amp;rsquo;d be easiest to do as a web site,
with internet connections forwarded via the router.&lt;/p&gt;

&lt;p&gt;In case other people also want to use this software, I decided to write it
in &lt;a href=&#34;https://golang.org/&#34;&gt;Go&lt;/a&gt;; now Linux, Windows, Mac and other
users could run it on their machines.&lt;/p&gt;

&lt;p&gt;So, &lt;a href=&#34;https://www.sweharris.org/Safe/safe.zip&#34;&gt;here it is&lt;/a&gt;.  That zip file is 7Mb in
size and contains the source, plus binaries, and the web site.&lt;/p&gt;

&lt;p&gt;Note that at least once Windows Defender false alerted on the windows
binary.  If you don&amp;rsquo;t trust my compilation then read the source and
compile it yourself.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&#34;source-code&#34;&gt;Source code&lt;/h2&gt;

&lt;p&gt;The zip file contains a number of files.  The source code is
in the &lt;code&gt;safe.go, vend, vendor, build.sh&lt;/code&gt; files.  You don&amp;rsquo;t
need these to run the program.  If you want to recompile it yourself
then set GOPATH and run &lt;code&gt;go build safe.go&lt;/code&gt;.  The &lt;code&gt;build.sh&lt;/code&gt;
script does this for Linux/MacOS.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&#34;running-the-code&#34;&gt;Running the code&lt;/h2&gt;

&lt;p&gt;What you do need is one of the executables, for your OS (eg &lt;code&gt;safe.linux.amd64&lt;/code&gt;)
and the &lt;code&gt;static/&lt;/code&gt; directory.  This directory contains the web site
contents, and a simple JPEG image file, which we&amp;rsquo;ll discuss later.&lt;/p&gt;

&lt;p&gt;Running the code may be as simple as running the binary.  With no
additional configuration it will run the web server on port 5000 and
try to find the safe on a default serial port (&lt;code&gt;/dev/ttyUSB0&lt;/code&gt; or
&lt;code&gt;COM1:&lt;/code&gt;).&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&#34;set-up&#34;&gt;Set up&lt;/h2&gt;

&lt;p&gt;The default values are probably not correct for you.  You might see
an error such as:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ./safe.linux.amd64 
Using configuration file /home/sweh/.safe.cfg
  Serial Port = /dev/ttyUSB0
  Listen Port = 5000
  HTML static = /tmp/safe/src/safe/static
  Lock image loaded

Could not open serial port: open /dev/ttyUSB0: no such file or directory
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first line lets you know what configuration file can be used to
override the defaults.
On Windows it will look for
&lt;code&gt;%HOMEDIR%%HOMEPATH%&lt;/code&gt; or &lt;code&gt;%USERPROFILE&lt;/code&gt;.  On Linux/MacOS it
will look in &lt;code&gt;$HOME&lt;/code&gt;.  Examples may be:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;C:\Documents and Settings\sweh\.safe.cfg
C:\Users\sweh\.safe.cfg
/Users/sweh/.safe.cfg
/home/sweh/.safe.cfg
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This file is a JSON format file.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;quot;ListenPort&amp;quot;:12345,
  &amp;quot;SerialPort&amp;quot;:&amp;quot;COM3&amp;quot;,
  &amp;quot;AuthUser&amp;quot;:&amp;quot;username&amp;quot;,
  &amp;quot;AuthPass&amp;quot;:&amp;quot;password&amp;quot;,
  &amp;quot;HTMLDir&amp;quot;:&amp;quot;/path/to/static&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Each line is optional.  The smallest file might be&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;quot;SerialPort&amp;quot;:&amp;quot;COM3&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you have multiple lines then separate them with a ,&lt;/p&gt;

&lt;table border=1 cellpadding=10&gt;
&lt;tr&gt;&lt;td&gt;ListenPort&lt;/td&gt;&lt;td&gt;Defaults to 5000.  What port to run the webserver on&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;SerialPort&lt;/td&gt;&lt;td&gt;Defaults to COM1 or /dev/ttyUSB0.  Where the safe is&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;AuthUser&lt;/td&gt;&lt;td&gt;If set, require this username/password for the website&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;AuthPass&lt;/td&gt;&lt;td&gt;See AuthUser&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;HTMLDir&lt;/td&gt;&lt;td&gt;If the code can not find the static directory, you can set it here&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;If you plan on making this available over the internet
then I strongly recommend setting AuthUser and AuthPass.&lt;/p&gt;

&lt;p&gt;On Linux, if you have multiple USB serial ports then it may make sense
to use the &lt;code&gt;/dev/serial/by-id/...&lt;/code&gt; path to the serial port,
rather then &lt;code&gt;/dev/ttyUSB...&lt;/code&gt; values to ensure that the right serial
port is picked up (just in case the order changes on next reboot).&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&#34;successful-startup&#34;&gt;Successful startup&lt;/h2&gt;

&lt;p&gt;Once you&amp;rsquo;ve correctly configured the software, the startup would look
something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Using configuration file /home/sweh/.safe.cfg
  Serial Port = /dev/serial/by-id/usb-1a86_USB2.0-Ser_-if00-port0
  Listen Port = 12345
  HTML static = /tmp/safe/src/safe/static
  Lock image loaded
  Successfully connected to Safe
  OK Safe is unlocked
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &amp;ldquo;Successfully connected&amp;rdquo; means it was able to talk to the safe.  The
last line is the current state of the safe.&lt;/p&gt;

&lt;p&gt;You can now access the website.  In this case, I&amp;rsquo;m running on port 12345
and so &lt;code&gt;http://localhost:12345&lt;/code&gt; would work.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.sweharris.org/Safe/first_page.png&#34; alt=&#34;homepage&#34; /&gt;&lt;/p&gt;

&lt;p&gt;You can see that web site design isn&amp;rsquo;t my strong point.  This could have
been written by somebody back in 1996&amp;hellip; and will probably still work in
a browser from that time!&lt;/p&gt;

&lt;p&gt;The controls are in the left frame, and the results on the right.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Status&lt;br&gt;Reports the status of the safe (eg unlocked, locked, etc)&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Open Safe&lt;br&gt;If the safe is unlocked then it will open the solenoid
for this period of time.  On the right we&amp;rsquo;ll see a countdown.  During
this period the door can be physically unlocked and opened.
&lt;pre&gt;
OK opening safe for 5 seconds
OK opening safe for 4 seconds
OK opening safe for 3 seconds
OK opening safe for 2 seconds
OK opening safe for 1 seconds
OK completed
&lt;/pre&gt;
If the safe is locked then you&amp;rsquo;ll get an error instead&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Test password:&lt;br&gt;
This will let you verify the password you enter is correct.  It will not
unlock the safe.  This may be of use before a session is started, to verify
the password you entered to lock the safe is correct&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Unlock Once:&lt;br&gt;
If the password is correct then you can press the &amp;ldquo;Open Safe&amp;rdquo; button once.
Once the open period is over then the safe is locked again.  This is very
close to the original &amp;ldquo;enter code&amp;rdquo; function on the safe keypad.  It may
be used, for example, to grant temporary access to the safe remotely,
or just to gain everyday access without clearing the password out.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Unlock Permanent:&lt;br&gt;
If the password is correct then it is cleared out of the safe and the
safe is returned to unlocked mode.  Unlimited use of &amp;ldquo;Open Safe&amp;rdquo; is
possible.  This is useful when the safe no longer needs to be locked.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Lock:&lt;br&gt;
As expected, if the safe is currently unlocked then a new lock code can
be entered, and the safe locked.  Any string up to 100 characters, consisting
of letters (upper and lower case) and numbers is allowed.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Unlock file with image:&lt;br&gt;
These options work the same way, but with the password embedded in a JPEG
file; see the &amp;ldquo;Randomize&amp;rdquo; function for details&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Randomize:&lt;br&gt;
This will generate a random password.  It then takes the &lt;code&gt;static/lock_image.jpg&lt;/code&gt; file and &lt;em&gt;embeds&lt;/em&gt; the password as a comment.  It will then
send the image to the browser; you should (all going well) be prompted
to save the result.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: there is no encryption of the password inside the file; it&amp;rsquo;s just
stored as a comment.  You could look inside and file it.  But it may
be used to &amp;ldquo;hide&amp;rdquo; the password; eg inside a cat picture.  No one looking
at &lt;code&gt;my_funny_cat.jpg&lt;/code&gt; would expect to see your safe password in the comments.
It might stand out for someone using &lt;code&gt;exiftool&lt;/code&gt; or similar, though!&lt;/p&gt;

&lt;p&gt;If you wish, a different JPEG file can be used.  The code &lt;em&gt;should&lt;/em&gt;
strip out unnecessary sections.  Make sure you test carefully if you do
this.  Yes, your unlock picture could be an anime cat, if you really
wanted it to be!&lt;/p&gt;

&lt;p&gt;(Actually I don&amp;rsquo;t recommend using this option; it&amp;rsquo;s kinda just a joke
function.  You might want to remove it from the HTML so you can&amp;rsquo;t
select it).&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&#34;normal-password-functionality&#34;&gt;Normal password functionality&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The safe door should be open and the bolts in the unlock position&lt;/li&gt;
&lt;li&gt;The owner would enter a password (twice) and click on the &amp;ldquo;Lock&amp;rdquo;
button&lt;/li&gt;
&lt;li&gt;The owner can then test the password with the &amp;ldquo;Test password&amp;rdquo; button.&lt;/li&gt;
&lt;li&gt;All looking good, the owner can then close and lock the safe.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&#34;silly-picture-use-case&#34;&gt;Silly picture use case&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The safe door should be open and the bolts in the unlock position&lt;/li&gt;
&lt;li&gt;The owner will click the Randomize button, and save the image&lt;/li&gt;
&lt;li&gt;The owner can then test this works with the &amp;ldquo;test image&amp;rdquo; function&lt;/li&gt;
&lt;li&gt;All looking good, the owner can then close and lock the safe.&lt;/li&gt;
&lt;li&gt;The owner should rename the image file to something innocuous.&lt;/li&gt;
&lt;li&gt;The picture can be used to unlock the safe&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&#34;restarting&#34;&gt;Restarting&lt;/h2&gt;

&lt;p&gt;The safe can be powered down and powered up again.  The PC software can
be stopped and restarted.  It should all automatically recover.  If the
serial port is disconnected while the software is running then you may
need to kill and restart the software.  But don&amp;rsquo;t worry; the password is
stored safely inside the Arduino and the safe is kept locked :-)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Know your threats and defend accordingly</title>
      <link>https://www.sweharris.org/post/2017-10-22-threat-vector/</link>
      <pubDate>Sun, 22 Oct 2017 16:33:56 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-10-22-threat-vector/</guid>
      <description>

&lt;p&gt;A couple of weeks ago I was asked a question around the disposal of SSDs.
The question went along the lines of &amp;ldquo;In the old days we could just overwrite
the disk many times (eg with &lt;a href=&#34;https://en.wikipedia.org/wiki/Darik%27s_Boot_and_Nuke&#34;&gt;DBAN&lt;/a&gt;).  What should we do, now, with SSDs?&amp;rdquo;&lt;/p&gt;

&lt;p&gt;Recently, a bunch of Infineon TPMs were found to have a flaw that &lt;a href=&#34;https://www.infineon.com/cms/en/product/promopages/rsa-update/rsa-background&#34;&gt;generated
weak RSA keys&lt;/a&gt;.  This could have lots of impact, including Bitlocker disk
encryption.&lt;/p&gt;

&lt;p&gt;Around the same time, &lt;a href=&#34;https://en.wikipedia.org/wiki/KRACK&#34;&gt;KRACK&lt;/a&gt; flaws
were found in WPA2, the mechanism used to secure WiFi networks.&lt;/p&gt;

&lt;p&gt;Earlier this year, flaws in how mobile networks work (&amp;ldquo;SS7&amp;rdquo;) allowed hackers
to &lt;a href=&#34;https://thehackernews.com/2017/05/ss7-vulnerability-bank-hacking.html&#34;&gt;steal money from banks&lt;/a&gt; by stealing 2FA passcodes sent by SMS.&lt;/p&gt;

&lt;p&gt;I can keep going on.  But what do all these completely different things
have to do with each other?&lt;/p&gt;

&lt;p&gt;Their &lt;em&gt;impact&lt;/em&gt; is different, depending on who you are.&lt;/p&gt;

&lt;h4 id=&#34;disk-data-destruction&#34;&gt;Disk data destruction&lt;/h4&gt;

&lt;p&gt;Since that&amp;rsquo;s what got me thinking about this, let&amp;rsquo;s start here.  How should
you destroy the data on your SSDs?  Now I could go into some depth on how
the old methods didn&amp;rsquo;t really do a complete erase (eg due to bad block
reallocation), and the wear leveling on SSDs makes it even harder.  But
this really missed the point.&lt;/p&gt;

&lt;p&gt;Ask the question; who was going to do a low level forensics analysis of
the disk?  If you&amp;rsquo;re an average &amp;ldquo;John Smith&amp;rdquo; then the answer will be
different than if you&amp;rsquo;re a bank storing credit card numbers.&lt;/p&gt;

&lt;p&gt;Another question; is this my biggest risk?  If you are using a laptop
(or phone) or carrying about portable media (USB drives) then a bigger
risk is losing the laptop, or having it stolen.  This means you should
really &lt;em&gt;encrypt&lt;/em&gt; your data on these devices (eg with Bitlocker, on Windows).&lt;/p&gt;

&lt;p&gt;If you&amp;rsquo;re a businessman with the laptop then you might also want to have
a BIOS password to prevent &lt;a href=&#34;https://www.schneier.com/blog/archives/2009/10/evil_maid_attac.html&#34;&gt;Evil Maid&lt;/a&gt; attacks for industrial espionage.&lt;/p&gt;

&lt;p&gt;So how do you clean a disk?  If it&amp;rsquo;s encrypted, just destroy the
encryption key!  If you&amp;rsquo;re in a bank&amp;rsquo;s datacenter you might want to
physically shred the disk.  If you&amp;rsquo;re recycling your old home computer
to give to your local charity then a full format (&lt;em&gt;not&lt;/em&gt; quick format)
followed by reinstalling the OS will probably be good enough.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s no one solution.&lt;/p&gt;

&lt;h4 id=&#34;infineon-tpm&#34;&gt;Infineon TPM&lt;/h4&gt;

&lt;p&gt;We can ask similar issues about the other issues; let&amp;rsquo;s take the
Infineon one&amp;hellip;  this has some people worried because the TPM RSA key
may be the whole root of trust for an environment.  In particular, Bitlocker
encryption may use this key (and we&amp;rsquo;ve just said that laptops should be
encrypted!).  So we should be panicking, right?  Well, it&amp;rsquo;s estimated
that it would take &lt;a href=&#34;https://arstechnica.com/information-technology/2017/10/crypto-failure-cripples-millions-of-high-security-keys-750k-estonian-ids/&#34;&gt;1000 Amazon instances 17 days and cost
$40,000&lt;/a&gt; to break this.&lt;/p&gt;

&lt;p&gt;Is your data worth $40k to an attacker?  Or, rather, do they think it may
be worth that much money?  My personal laptop?  Nope, not at all.  A
laptop used by SAs to login for support work?  Probably not.  A laptop
holding personal banking details, or medical records, or mergers/acquisitions?
That&amp;rsquo;s more likely.&lt;/p&gt;

&lt;p&gt;As an individual, this issue doesn&amp;rsquo;t really impact me and I probably
won&amp;rsquo;t update the firmware to fix this.  As a security
person for my company we risk-rated and created a priority fix.&lt;/p&gt;

&lt;h4 id=&#34;krack&#34;&gt;KRACK&lt;/h4&gt;

&lt;p&gt;If you&amp;rsquo;re using Starbucks then you better be using VPNs or only visiting
SSL protected sites, anyway, because &lt;a href=&#34;https://www.sweharris.org/post/2016-07-16-mitm/&#34;&gt;MITM&lt;/a&gt; attacks
are easily possible.  KRACK doesn&amp;rsquo;t change this.&lt;/p&gt;

&lt;p&gt;Your home network?  Most people only use home WiFi to connect to the internet,
eg for mail, browsing, streaming.  This is normally SSL as well.  Maybe
you have a wireless printer?  Or some unprotected &amp;ldquo;Internet of Things&amp;rdquo;
device?  In theory these may be vulnerable to KRACK&amp;hellip; but who is going to
attack you?  What will they learn?&lt;/p&gt;

&lt;p&gt;At work, though&amp;hellip; many places have an employee WiFi network that&amp;rsquo;s
behind the perimeter firewalls.  Ah, now we have a risk that may need
to be addressed.  It may be that we should re-architect our WiFi designs
and only allow VPN access from this network.  Effectively treat it as
being &lt;em&gt;outside&lt;/em&gt; the perimeter and don&amp;rsquo;t trust it.&lt;/p&gt;

&lt;h4 id=&#34;ss7-flaws-in-sms&#34;&gt;SS7 flaws in SMS&lt;/h4&gt;

&lt;p&gt;This one always causes fights.  NIST has &lt;a href=&#34;https://pages.nist.gov/800-63-3/sp800-63b.html&#34;&gt;deprecated SMS&lt;/a&gt; as an authentication factor.  So we should
stop using it, right?&lt;/p&gt;

&lt;p&gt;Well, once again, it depends.  We all know passwords are terrible, and people
pick bad passwords.  Now the attack the average person cares about isn&amp;rsquo;t
an attack on &lt;em&gt;them&lt;/em&gt;, but an attack against the server; for example, an
attack on the bank.  This attack just randomly throws usernames and
passwords at the server, and some may work!  Our average person has their
money taken.  The defense is some form of 2FA, and even SMS is better
than no 2FA.&lt;/p&gt;

&lt;p&gt;If you &lt;em&gt;work&lt;/em&gt; in the bank though, then your logins to the VPN gateway
may well be targeted.  For that SMS may not be good enough.&lt;/p&gt;

&lt;p&gt;And if you&amp;rsquo;re the CEO of the bank worth a gazillion dollars then you may,
personally, be targeted.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I just picked a random handful of attacks and risks, and demonstrated how
these risks are &lt;em&gt;different&lt;/em&gt;, depending on the scenario you are in.&lt;/p&gt;

&lt;p&gt;As security professionals we have a habit of &amp;ldquo;absolutism&amp;rdquo;; if something
is known to be weak then it&amp;rsquo;s considered bad.  But this is a perfect
example of &amp;ldquo;the best being the enemy of the good&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;For your average home user, a password manager is better than using the
same password everywhere (heck, even a password book is better than
using the same password everywhere!).  SMS 2FA is better than just a
standard password.&lt;/p&gt;

&lt;p&gt;For a person at risk (e.g. vengeful ex; targeted by trolls; abusive partner;
a high wealth individual; a famous name) the risks change; you may have
your phone stolen, your laptop hacked, your email accounts targeted.  Is
someone willing to spend $40000 to decrypt your hard disk?  If so, update
your TPM and change the encryption keys!&lt;/p&gt;

&lt;p&gt;An organisation (and the employees working at the organisation) have another
set of challenges, and this may depend on the industry they&amp;rsquo;re in.  We&amp;rsquo;ve
heard stories of laptops being found in taxis with large databases on them.&lt;/p&gt;

&lt;p&gt;We need to move away from the &amp;ldquo;one size fits all&amp;rdquo; mentality, and start
looking at a &amp;ldquo;good enough&amp;rdquo; solution.  Even &amp;ldquo;poor&amp;rdquo; 2FA is better than
no 2FA.&lt;/p&gt;

&lt;p&gt;Most people don&amp;rsquo;t &lt;em&gt;need&lt;/em&gt; perfect security; they just need
&amp;ldquo;good enough&amp;rdquo; security.  If you&amp;rsquo;re in a risky situation then this XKCD
may actually describe your biggest risk!
&lt;center&gt;
&lt;a href=https://xkcd.com/538/&gt;&lt;img src=/images/xkcd-security.png&gt;&lt;/a&gt;
&lt;/center&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Adapting a digital safe to be computer controlled</title>
      <link>https://www.sweharris.org/post/2017-10-09-digital_safe/</link>
      <pubDate>Mon, 09 Oct 2017 21:58:54 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-10-09-digital_safe/</guid>
      <description>

&lt;p&gt;For a number of years I had one of these cheap electronic safes.  They allow
for a combination to be set.&lt;/p&gt;

&lt;p&gt;I bought this one from Harbor Freight in 2004:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Safe/large/safe_1.jpg&#34;&gt;&lt;img src=&#34;https://www.sweharris.org/Safe/safe_1.jpg&#34; alt=&#34;Old safe&#34; /&gt;&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;This post isn&amp;rsquo;t about that safe though.&lt;/p&gt;

&lt;p&gt;About 10 years later the safe started to stop working; the control panel
stop responding, it made horrible noises&amp;hellip;  Fortunately anger lifting and
dropping the safe got it working again to open the door.  I pulled it
apart and pretty much there&amp;rsquo;s just a motherboard and a solenoid and a
ribbon cable to the front panel.&lt;/p&gt;

&lt;p&gt;So I bought a new safe.  I got this one from Staples&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Safe/large/safe_2.jpg&#34;&gt;&lt;img src=&#34;https://www.sweharris.org/Safe/safe_2.jpg&#34; alt=&#34;New safe&#34; /&gt;&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;I was curious and took this one apart.  And it looked VERY similar!&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Safe/large/internals.jpg&#34;&gt;&lt;img src=&#34;https://www.sweharris.org/Safe/internals.jpg&#34; alt=&#34;Internals&#34; /&gt;&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;When I looked closer, the only difference between the two setups appeared
to be the connector to the battery/reset switch had the alignment notch on
the other side (the white connector in the picture).  So I did a little
kludging and put the new safe&amp;rsquo;s board into the old safe.  And it worked!
The old safe is still in use, with the new board.&lt;/p&gt;

&lt;p&gt;So I had a safe with no electronics.  I wondered if it was possible to
replace the electronics with an Arduino, and set complicated passwords
via a computer.&lt;/p&gt;

&lt;p&gt;And &lt;em&gt;that&lt;/em&gt; is what this post is about!&lt;/p&gt;

&lt;h2 id=&#34;requirements&#34;&gt;Requirements&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;An electronic safe.  Pretty much most of these safes use the same
technique as the two I have.  We don&amp;rsquo;t care about the front panel or the
electronics; all we need is the solenoid locking mechanism.&lt;/li&gt;
&lt;li&gt;An Arduino Nano.  You can find cheap clones on Ebay for a few dollars&lt;/li&gt;
&lt;li&gt;An Arduino relay.  The Solenoid needs more power than the Arduino can
provide, so we use the Arduino to switch a relay, and this switches power
to the safe.  I found one for $4.&lt;/li&gt;
&lt;li&gt;A DB9 female serial port plug.  This is how we communicate to the safe.&lt;/li&gt;
&lt;li&gt;A USB serial adapter.  These are also on Ebay for a few bucks.  Doesn&amp;rsquo;t
need to be expensive!  Indeed the cheaper ones are normally better; the real
RS232 standard allows for voltages up to 12V, which is more than an Arduino
can handle.  But the cheaper devices tend to stick to USB voltage levels
(5V) which still works and is compatible with the Arduino.&lt;/li&gt;
&lt;li&gt;A 5V power adapter.  I took an old USB adapter and cut the end off.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;overview-of-the-solution&#34;&gt;Overview of the solution&lt;/h2&gt;

&lt;p&gt;The Arduino will determine if the safe can be opened or not.  It will be
embedded inside the safe.  To talk to the Arduino we use a serial port
plugged into the PC.  Using this we can send commands such as &amp;ldquo;lock the
safe with password 12345&amp;rdquo;, &amp;ldquo;unlock the safe with password 12345&amp;rdquo;, &amp;ldquo;open the
solenoid lock&amp;rdquo;.  The Arduino will save the password into its EEPROM so
even if the power is removed then applied later it will remember.&lt;/p&gt;

&lt;p&gt;Originally I was going to use the USB port on the Arduino for both power
and communication, until I realised that this would let me upload a new
sketch and open the safe at any time.  Doh!  Fortunately there&amp;rsquo;s a
software serial solution, so we don&amp;rsquo;t need access to the USB port.&lt;/p&gt;

&lt;p&gt;So this is what we&amp;rsquo;re going to try and build (click for a larger
image).  Sorry for the awfulness of my sketch!&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Safe/large/diagram.jpg&#34;&gt;&lt;img src=&#34;https://www.sweharris.org/Safe/diagram.jpg&#34; alt=&#34;Diagram&#34; /&gt;&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;h2 id=&#34;putting-it-together&#34;&gt;Putting it together&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First remove the inside cover of the safe.  This is normally just 4
screws.
&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Safe/large/inside_safe_cover.jpg&#34;&gt;&lt;img src=&#34;https://www.sweharris.org/Safe/inside_safe_cover.jpg&#34; alt=&#34;Cover&#34; /&gt;&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Unplug the power/reset cable from the main board.  Unplug the solenoid
cable from the main board.  Unplug the ribbon cable from the main board.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;You can now unscrew the board from the safe door.  We don&amp;rsquo;t need it
any more.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;The reset switch on the side of the door can be unscrewed and pushed
through.  This frees up a nice hole, which we&amp;rsquo;ll use later.  If you
cut the two wires to the battery compartment then you&amp;rsquo;ll be able to
remove that cable harness as well.  We don&amp;rsquo;t need that anymore, either.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;At this point you should have the door cover free and the safe door
has the ribbon cable and the wires to the solenoid.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;We need to run a cable through a mounting hole on the back of the safe,
and then through the hole in the door cover.   We only need 4 strands
of this cable (2 for power, 2 for serial).
I used a few feet of spare ethernet cable I have.  It works well.  The
unneeded 4 cables add strength and don&amp;rsquo;t hurt.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Now on the outside of the safe pick one of the twisted pairs (I used
orange but it doesn&amp;rsquo;t matter).  Connect them to the power supply.  In my
case I just cut the USB end off an old LG USB power adapter and wrapped
the wires together.  It&amp;rsquo;s important to remember which side is +5 and which
side is GND, so I made &amp;lsquo;orange&amp;rsquo; to be +5 and &amp;lsquo;white/orange&amp;rsquo; GND.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Pick another pair (&amp;ldquo;blue&amp;rdquo;).  These will go to pins 2 and 3 of the DB9
connector.  You &lt;em&gt;also&lt;/em&gt; need to connect pin 5 (GND) of the DB9 to
GND of the power supply.   I&amp;rsquo;m terrible at soldering so, for me, this
was the hardest part!  This is also why I chose ethernet cable; the
thickness of the cable means it can be secured nicely to the DB9 and is
unlikely to break free.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Take a break; we&amp;rsquo;ve finished on the outside of the safe.  Now we&amp;rsquo;re
starting on the inside&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;The two cables used for serial communication need to be connected to
pins 10 and 11 of the Nano.  Now I cheated a little, here.  I took a standard
cable used to connect to Arduino pins and cut one end off, and connected
that to the ethernet cable.  Now I can just slip the cable onto the pin.
If you&amp;rsquo;re better at soldering than me then you could solder directly to the
board.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;The power cables need splitting; one set will go the Arduino (so
another pair of standard cables), the other positive side will go to the
input of the switched side of the relay, and the negative will go to
one side of the solenoid.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;We also need a connection from +5V, GND and pin 7 of the Arduino
to the logic side of the relay, and a connection from the ON switched
side of the relay to the other connection on the solenoid.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now the reason I used standard cables is that I can put all this together
and test it (see later) and adjust cables as necessary.  Once it&amp;rsquo;s all
been proven to work we can then mount it.&lt;/p&gt;

&lt;h2 id=&#34;summary-of-connections&#34;&gt;Summary of connections&lt;/h2&gt;

&lt;pre&gt;
Arduino Nano pinout requirements
================================
 (See https://forum.arduino.cc/index.php?topic=147582.0 for a reference card)


                      +---------+
                      |         |
                      | o     o | VIN Power +5V in
                      | o     o | GND Ground in
  Ground to relay GND | o     o |
                      | o     o | 5V  5V to relay
                      | o     o |
                      | o     o |
                      | o     o |
                      | o     o |
                      | o     o |
   Signal to Relay D7 | o     o |
                      | o     o |
                      | o     o |
  Serial Pin 3 RX D10 | o     o |
  Serial Pin 2 TX D11 | o     o |
                      | o     o |
                      |         |
                      +---------+

Relay connections
=================
  Control side
     VCC - from  5V on Arduino   
     GND - from GND on Arduino
      IN - from  D7 on Arduino

   Switch side:
     Central pin +5V power in
          ON pin to safe solenoid
                 (if the solenoid opens when the safe should be locked
                  you&#39;ve picked the wrong side)

Solenoid
========
   (direction doesn&#39;t matter)
   +5V from Relay
   GND from power in

RS232
=====
   Pin 2: Connect to Arduino D11
   Pin 3: Connect to Arduino D10
   Pin 5: Connect to power ground  (important!)
&lt;/pre&gt;

&lt;h2 id=&#34;mounting-it&#34;&gt;Mounting it&lt;/h2&gt;

&lt;p&gt;This kit is small enough that we can install it inside the cover.  I wanted
to keep some air gap around the arduino and relay and I realised I could
mount them sideways.   The easiest way would be to use some folded carboard!&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Safe/large/carrier.jpg&#34;&gt;&lt;img src=&#34;https://www.sweharris.org/Safe/carrier.jpg&#34; alt=&#34;Carrier&#34; /&gt;&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;If you&amp;rsquo;re worried about the cardboard springing loose then you can
just put some tape around the ends to add some pressure.&lt;/p&gt;

&lt;p&gt;Now I recently got a 3D printer, so I printed a couple of carriers
from &lt;a href=&#34;https://www.thingiverse.com/thing:2083266/&#34;&gt;thingiverse&lt;/a&gt;.
It does the same thing, but plastic rather than carboard.&lt;/p&gt;

&lt;p&gt;Glue the carriers down.  It should be below the battery compartment,
because this is where the old controller board fitted and so there&amp;rsquo;s
space.&lt;/p&gt;

&lt;p&gt;Connect the cables.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Safe/large/glued_down.jpg&#34;&gt;&lt;img src=&#34;https://www.sweharris.org/Safe/glued_down.jpg&#34; alt=&#34;Glued Down&#34; /&gt;&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;You can see I put a cable tie just before the hole; this is an attempt to
prevent the cable from being pulled from the outside and breaking a
connection.&lt;/p&gt;

&lt;p&gt;I decided to add a USB cable (and realised I should have oriented the
pieces a different way; there wasn&amp;rsquo;t enough space for it) and poked
the USB cable out through the battery compartment.  This allows me to
reprogram (upgrade/bug fix) without pulling the whole thing apart.
The USB cable fits just inside the battery compartment so it&amp;rsquo;s not
accessible from outside unless the door is open.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Safe/large/with_usb.jpg&#34;&gt;&lt;img src=&#34;https://www.sweharris.org/Safe/with_usb.jpg&#34; alt=&#34;USB&#34; /&gt;&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Test the setup and then screw the cover back to the door.  This hides
a multitude of sins and it looks pretty neat!&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href=&#34;https://www.sweharris.org/Safe/large/inside.jpg&#34;&gt;&lt;img src=&#34;https://www.sweharris.org/Safe/inside.jpg&#34; alt=&#34;Inside&#34; /&gt;&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;h2 id=&#34;arduino-software&#34;&gt;Arduino software&lt;/h2&gt;

&lt;p&gt;&lt;a href=&#34;https://www.sweharris.org/Safe/safe.ino&#34;&gt;This sketch&lt;/a&gt; should be loaded onto the Arduino.  It&amp;rsquo;s
pretty simple and is purely used to control the solenoid.  It listens on
the serial port at 9600 baud and will respond to a few instructions.&lt;/p&gt;

&lt;p&gt;Each instruction begins with a : character.  After the instruction is
another : and then an optional parameter, and then ends with another :
character.  No RETURN is needed.&lt;/p&gt;

&lt;p&gt;When power is applied the board says &amp;ldquo;hello&amp;rdquo; and tells you if the safe
is locked or not.  Except for the PING command responses will either
start with OK or ERROR.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;:PING:message:&lt;/code&gt;&lt;br&gt;
Response is &lt;code&gt;PINGACK:message:&lt;/code&gt;&lt;br&gt;
Used to test communication&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;:LOCK:password:&lt;/code&gt;&lt;br&gt;
Sets the safe to locked state.  Can not be used if already locked&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;:UNLOCK:password:&lt;/code&gt;&lt;br&gt;
Unlocks the safe&amp;hellip; if the password is correct!  Allows for one time use of the &lt;code&gt;OPEN&lt;/code&gt; command&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;:CLEAR:password:&lt;/code&gt;&lt;br&gt;
Clears the password and resets the safe to unlocked state.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;:TEST:password:&lt;/code&gt;&lt;br&gt;
Tests the password but leaves the safe locked.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;:OPEN:time:&lt;/code&gt;&lt;br&gt;
Opens the solenoid for &amp;ldquo;time&amp;rdquo; seconds (default to 5 seconds)&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;:STATUS::&lt;/code&gt;&lt;br&gt;
Returns if the safe is locked or unlocked&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;testing&#34;&gt;Testing&lt;/h2&gt;

&lt;p&gt;I use Linux and the &lt;code&gt;kermit&lt;/code&gt; command, but any terminal emulator
would work.  The Arduino does not echo what you type, so I&amp;rsquo;ve turned on
local echo mode so I can see what I&amp;rsquo;m typing.  I run the &lt;code&gt;kermit&lt;/code&gt;
command and then apply power to the safe.  You should see the onboard LED
start flashing once a second while it is waiting for commands.  (You won&amp;rsquo;t
be able to see this when the safe is closed and locked, but it&amp;rsquo;s useful
while testing the setup).   Remember, there&amp;rsquo;s no need to press RETURN
(indeed you&amp;rsquo;ll get an error if you do).
&lt;pre&gt;
% kermit -l /dev/ttyUSB4 -b 9600
C-Kermit&amp;gt;set local on
C-Kermit&amp;gt;c
Connecting to /dev/ttyUSB4, speed 9600
 Escape character: Ctrl-\ (ASCII 28, FS): enabled
Type the escape character followed by C to get back,
or followed by ? to see other options.
----------------------------------------------------
OK Safe code started.  Safe is unlocked
:ping:1234:PINGACK:1234:
:status::OK Safe is unlocked
:lock:12345:OK Safe locked
:status::OK Safe is locked
:open::ERROR State is locked
:unlock:9876:ERROR Wrong password
:unlock:12345:OK Safe unlocked
:open::OK opening safe for 5 seconds
OK opening safe for 4 seconds
OK opening safe for 3 seconds
OK opening safe for 2 seconds
OK opening safe for 1 seconds
OK completed
&lt;/pre&gt;
When the open command is run then the solenoid should click open and
the safe door can be opened.  At the end of the time the solenoid
should click back again, allowing you to lock the door closed.  The
open command is also the only command that will return more than one
line of results.&lt;/p&gt;

&lt;h2 id=&#34;main-code&#34;&gt;Main code&lt;/h2&gt;

&lt;p&gt;The safe code simply provides control over the solenoid.  It effectively
just replaces the front panel keypad.  But since it&amp;rsquo;s over a serial
port it means that we can write programs for our PC to control it
(eg pick a random password).  The limits of what the program can do are
bounded purely by your imagination.  Because the password is stored inside
the Arduino, and that&amp;rsquo;s inside the safe, you can&amp;rsquo;t cheat&amp;hellip; except in one
way; you could write a program that will try and brute-force guess the
password.  Now the safe can handle 100 character long passwords.  Let&amp;rsquo;s
assume a standard A-Za-z0-9 character set and 100 guesses per second,
that&amp;rsquo;s 62^100 /100 seconds needed to check every combination.  Or
54962310687024123417094664250549034290648513960863640477969506441019257048928403777873869677398592797712143671632918789906836353961913573996848721028517534334752940880822 years.&lt;/p&gt;

&lt;p&gt;Good luck with that :-)&lt;/p&gt;

&lt;p&gt;I might modify the safe code to sleep for
30 seconds after 3 failed attempts to make it even harder&amp;hellip;&lt;/p&gt;

&lt;p&gt;My plan is to write a web server interface that will allow for local
control of the safe.  By making it a web server then normal password
managers should also work.  Your digital safe&amp;rsquo;s password can now be
stored in the same place as the passwords for your bank account.&lt;/p&gt;

&lt;p&gt;Maybe it&amp;rsquo;s just me, but that idea appeals to me!&lt;/p&gt;

&lt;p&gt;I haven&amp;rsquo;t written this code, yet&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Key man dependencies and resilient processes</title>
      <link>https://www.sweharris.org/post/2017-10-08-equifax-keyman/</link>
      <pubDate>Sun, 08 Oct 2017 13:13:50 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-10-08-equifax-keyman/</guid>
      <description>

&lt;p&gt;Unless you&amp;rsquo;ve been living in a cave for the past couple of months, you&amp;rsquo;ll have
heard that Equifax, one of the &amp;lsquo;big three&amp;rsquo; credit reporting agencies,
&lt;a href=&#34;https://www.consumer.ftc.gov/blog/2017/09/equifax-data-breach-what-do&#34;&gt;suffered a massive breach&lt;/a&gt; leaking privileged data on over 143 million US people
(and millions outside the US as well).&lt;/p&gt;

&lt;p&gt;The story went from bad to worse as the company completely failed to
handle the response properly, with poor communication, staff giving
out the URL to phishing sites, web site failures and the story that
three executives sold millions of dollars of shares before the leak
notification was made.&lt;/p&gt;

&lt;p&gt;As a technologist, I&amp;rsquo;m more interest on &lt;em&gt;how&lt;/em&gt; the breach occurred.
Reports from the company are that the web site was susceptible to a
Struts2 vulnerability that had been known for months, but hadn&amp;rsquo;t been
patched.&lt;/p&gt;

&lt;p&gt;This, naturally, led the question of &lt;em&gt;why&lt;/em&gt; it hadn&amp;rsquo;t been patched.  In
testimony to Congress, Richard Smith (the Equifax ex-CEO) laid the
blame on one unnamed person who &lt;a href=&#34;https://www.theverge.com/2017/10/3/16410806/equifax-ceo-blame-breach-patch-congress-testimony&#34;&gt;failed to require deployment the patch&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;The human error was that the individual who&amp;rsquo;s responsible for communicating in the organization to apply the patch, did not,&amp;rdquo; Smith said in the hearing.&lt;/p&gt;

&lt;p&gt;&amp;ldquo;So does that mean that that individual knew the software was there,&amp;rdquo; Rep. Greg Walden replied, &amp;ldquo;and it needed to be patched, and did not communicate that to the team that did the patching?&amp;rdquo;&lt;/p&gt;

&lt;p&gt;&amp;ldquo;That is my understanding, sir,&amp;rdquo; Smith said.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;This short segment highlights a number of &lt;em&gt;process&lt;/em&gt; failures.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;An &lt;em&gt;individual&lt;/em&gt; who is responsible&lt;br&gt;
This is an obvious failure mode, and is inherently fragile.  It&amp;rsquo;s almost
a textbook example of a &amp;ldquo;key man dependency.&amp;rdquo;  What if that
person was on vacation?  Or was sick?  Or quit?  (Or, for an example
of a worst-case scenario, fell under a bus?)&lt;br&gt;
In any critical process (and vulnerability management &lt;em&gt;is&lt;/em&gt; a critical
process) all steps need to have redundancy in them.  This implies a team
with cross-checks, a workflow process (new vulnerability reported from
upstream, assigned, worked on, tasks initiated&amp;hellip; with reporting and
alerting if a workflow shows no progress) and so on.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Asset management&lt;br&gt;
To a lot of people, asset management merely means tracking what hardware
you have out there.  However the true scope is greater than that; it also
encompasses software, and it also encompasses &lt;em&gt;components&lt;/em&gt;.  If this was
an inhouse developed application then there needs to be a record of all the
opensource components used in the application.  This can help from a legal
perspective to ensure the license is suitable, but it can also help with
identifying applications with vulnerable components.  This also implies
the need for internal repository services that are used to serve approved
code, with firewalls blocking direct access to upstream servers.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Asset discovery&lt;br&gt;
This works in conjunction with the management piece; people make mistakes,
developers take shortcuts, vendor products don&amp;rsquo;t always list their
components.  Where possible every OS and appliance should be scanned
and the discovered components properly catalogued.  Workflows can then
be spun off to remediate the catalogue (eg license validation).  Were
you aware that your Oracle product &lt;a href=&#34;https://www.theregister.co.uk/2017/09/27/oracle_emergency_apache_struts_2_patches/&#34;&gt;may have Struts2 in it&lt;/a&gt;?&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Perimeter protection&lt;br&gt;
You do host your applications behind protection technologies such as WAFs,
yes?  These WAFs must be kept up to date with the latest signatures.  Even
if you don&amp;rsquo;t think you host that technology, you may find you are (vendor
supplied, developer inclusion) and that your asset reports don&amp;rsquo;t show it.
Vulnerability scanning may not show it, if the path is sufficiently hidden,
but that doesn&amp;rsquo;t mean you don&amp;rsquo;t have it.  The WAF acts as an additional
defense layer, and can also be used to help highlight external attack
attempts via SIEM reporting.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Internal protection&lt;br&gt;
Related to this would be IDS that may have been able to detect the
persistent shell sessions, DAMs to detect anomalous query patterns,
multi-tier application architectures (a breach at the presentation
layer doesn&amp;rsquo;t give direct access to the database), sending logs
to the SIEM, and so on.  This may not have prevented the breach,
but may have detected them sooner, before data had been exfiltrated.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Proper deployment of these processes and technologies would have
prevented or mitigated the breach; even if the vulnerability hadn&amp;rsquo;t
been patched then the WAF could have blocked access.  If neither patching
or WAFs worked then IDS and DAM may have alerted and limited the exposure.&lt;/p&gt;

&lt;p&gt;This is a classic in-depth scenario, with overlapping solutions in place
to mitigate failures elsewhere.&lt;/p&gt;

&lt;p&gt;Aside: One thing that would &lt;em&gt;not&lt;/em&gt; have helped here, is container technology.
I&amp;rsquo;m getting tired of people telling me &amp;ldquo;if their app was in a container
then they could just redploy with the fixed version&amp;rdquo;.  This wasn&amp;rsquo;t
the problem.  Why would someone redeploy containers if they weren&amp;rsquo;t
told?&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;We could argue there was a single person to blame for the Equifax issue,
but this was not the person Richard Smith suggested.  The blame lies at
the CTO layer for not ensuring resilient processes and technologies
were deployed.  Vulnerability Management is a critical function in any
organisation that handles PII data; it&amp;rsquo;s a core requirement of PCI for
anyone who handles credit card data.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ve also learned how little use auditors are!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Where to run Docker?</title>
      <link>https://www.sweharris.org/post/2017-09-24-where-to-run/</link>
      <pubDate>Sun, 24 Sep 2017 17:21:45 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-09-24-where-to-run/</guid>
      <description>

&lt;p&gt;I was asked an interesting question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I am about to investigate Docker.  We are moving to AWS too. So in your opinion, should I put energy on EC2 Container services or should I put my energy on Docker on EC2? Which is better ?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I find this type of question interesting because there&amp;rsquo;s not, really, a
&amp;ldquo;one size fits all&amp;rdquo; answer.  It depends on your use cases.&lt;/p&gt;

&lt;p&gt;For example, If you want to use Docker Swarm mode then you&amp;rsquo;ll need
to use standard EC2 VMs and manage the environment in a traditional
way. Similarly if you&amp;rsquo;re dealing with vendor containers and need to use
&lt;code&gt;docker-compose&lt;/code&gt; or similar.&lt;/p&gt;

&lt;p&gt;But you need to be careful with EC2; for example, there&amp;rsquo;s a rate limiter
on the disk I/O and this can hit if you &lt;a href=&#34;https://jeremyeder.com/2017/07/25/docker-operations-slowing-down-on-aws-this-time-its-not-dns/&#34;&gt;spin up/down containers too
quickly&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On the other hand, if you&amp;rsquo;re creating in-house software from scratch
then you might find the Amazon Container Service to be more useful,
especially if integrated with Amazon&amp;rsquo;s secrets management and IAM
roles.  You definitely get a few useful features&amp;hellip;&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s a downside to using these features, though; you are tying
yourself to Amazon. If you use standard docker then you could migrate
to any cloud provider that lets you run VMs.  Indeed this is one reason
why vendors are beginning to distribute containers in Docker format; once
you have the Docker engine running then the app should run unchanged.&lt;/p&gt;

&lt;p&gt;Another dimension to think about is support; do you want official Docker
support? If so, docker EE running on EC2 may be where you go. If you
don&amp;rsquo;t care then Amazon container service may suffice.&lt;/p&gt;

&lt;p&gt;Similarly cost; Docker on EC2 means pretty much running an EC2 cluster
full time, but Container Service can scale more dynamically&amp;hellip; which may
save money now that Amazon will &lt;a href=&#34;https://aws.amazon.com/blogs/aws/new-per-second-billing-for-ec2-instances-and-ebs-volumes/&#34;&gt;charge per-second rather than per-hour&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What about application support processes?  Do your developers need access
to the host running Docker (something I consider a bad idea, but&amp;hellip;).
Do your apps need to talk to backend systems that aren&amp;rsquo;t so forgiving of
elasticity?  Do your data controls even permit you to run this app in
Amazon in the first place?&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;I totally expect large organisations will need to run traditional docker
installs just because of vendor provided containers and the model they&amp;rsquo;ll
support.  You may need Swarm mode; you may need Kubernetes.  All of these
point to EC2.&lt;/p&gt;

&lt;p&gt;But there are some good use cases for Amazon Container Services; it can
definitely lead to a more PaaS-like usage of Docker, but with the &amp;ldquo;tie-in&amp;rdquo;
caveats.&lt;/p&gt;

&lt;p&gt;As we can see, really, there&amp;rsquo;s no &amp;ldquo;one-size fits all&amp;rdquo; solution; you
may use Container Service for one problem space and Docker EE on EC2
instances for another.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s where I think many people will end up.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Docker High Level Challenges with vendor containers</title>
      <link>https://www.sweharris.org/post/2017-09-17-docker-highlevel/</link>
      <pubDate>Sun, 17 Sep 2017 14:32:27 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-09-17-docker-highlevel/</guid>
      <description>

&lt;p&gt;In &lt;a href=&#34;https://www.sweharris.org/tags/dockerbasics&#34;&gt;previous posts&lt;/a&gt; I&amp;rsquo;ve gone into some detail
around how Docker works, and some of the ways we can use and configure
it.  These have been aimed at technologists who want to use Docker,
and for security staff who want to control it.&lt;/p&gt;

&lt;p&gt;It was pointed out to me that this doesn&amp;rsquo;t really help &lt;em&gt;leadership&lt;/em&gt; teams.
They&amp;rsquo;re getting shouted at; &amp;ldquo;We need Docker! We need Docker!&amp;rdquo;.  They don&amp;rsquo;t
have the time (and possibly not the skills) to delve into the low levels
the way I have.  So I&amp;rsquo;ve put together this higher level overview of
the problems with using Docker.&lt;/p&gt;

&lt;p&gt;I jokingly call it &amp;ldquo;Docker Security for CISOs&amp;rdquo;, and it&amp;rsquo;s primarily focused
on dealing with vendor supplied applications.&lt;/p&gt;

&lt;h2 id=&#34;executive-summary&#34;&gt;Executive Summary&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Docker is a virtualization technology that encompasses

&lt;ul&gt;
&lt;li&gt;Virtual Hosts&lt;/li&gt;
&lt;li&gt;Virtual Networks&lt;/li&gt;
&lt;li&gt;Virtual Storage&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Docker can run any workload

&lt;ul&gt;
&lt;li&gt;Web servers, application servers, databases, &amp;hellip;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Docker maturity is approximately where Virtual Machine management was 15 years ago&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This last point is quite important; we&amp;rsquo;ve had well over a decade&amp;rsquo;s worth
of experience in dealing with virtual machines and incorporating them into
control environments (CMDB, vulnerability management, configuration
management, etc).  Most of our tooling just doesn&amp;rsquo;t fit, conceptually,
into a container management system (we&amp;rsquo;re also seeing issues with elastic
compute at the VM level).  This leads to an important point:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Companies need to prioritize creation of a standard technology stack and support model to enable business lines and dev teams to use this.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;container-technology-is-a-form-of-os-virtualization&#34;&gt;Container technology is a form of OS Virtualization&lt;/h2&gt;

&lt;p&gt;Tools such as VMware ESX virtualize hardware&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&amp;ldquo;Here is a virtual Intel server&amp;rdquo;

&lt;ul&gt;
&lt;li&gt;One physical server, multiple virtual servers&lt;/li&gt;
&lt;li&gt;Each virtual server can be different, but needs to run on the Intel platform

&lt;ul&gt;
&lt;li&gt;Windows and Linux living together&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Can run most OS&amp;rsquo;s unchanged&lt;/li&gt;
&lt;li&gt;Can present &amp;ldquo;virtual&amp;rdquo; hardware (e.g. network, disk interfaces) that are optimized

&lt;ul&gt;
&lt;li&gt;May require special drivers in the guest&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Container technologies virtualize the OS&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&amp;ldquo;Here is a virtual Linux instance&amp;rdquo;

&lt;ul&gt;
&lt;li&gt;One Kernel, multiple OS user spaces&lt;/li&gt;
&lt;li&gt;Each OS user space can be different, but needs to run on the Linux kernel

&lt;ul&gt;
&lt;li&gt;Debian and RedHat living together&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Can run everything from init/systemd down to a single process&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;docker-docker-docker-what-is-docker&#34;&gt;Docker, Docker, Docker.  What is Docker?&lt;/h2&gt;

&lt;p&gt;Docker can be looked at in various different ways&amp;hellip;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A container run-time engine

&lt;ul&gt;
&lt;li&gt;Uses Linux kernel constructs to segregate workloads&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;An application packaging format

&lt;ul&gt;
&lt;li&gt;Provides a standard way of deploying an application image&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;A build engine

&lt;ul&gt;
&lt;li&gt;Provides a way of creating the application image&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;An ecosystem

&lt;ul&gt;
&lt;li&gt;Repositories, tools, images, workflows, &amp;hellip;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;layers-upon-layers&#34;&gt;Layers upon layers&lt;/h2&gt;

&lt;p&gt;The Docker engine runs as a privileged process in user space, and so sits
on top of a running kernel.  This means it can run on a VM or on a bare
metal OS deployment.  Indeed both forms may exist at the same time.  In
a VM world the physical host may run both containerized and traditional
apps inside different VMs.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s important to remember that Docker sits on top of an OS (eg RedHat); it&amp;rsquo;s not &amp;ldquo;standalone&amp;rdquo;
&lt;center&gt;
&lt;img src=&#34;https://www.sweharris.org/images/container-layer.png&#34; alt=&#34;layers&#34; /&gt;
(Image from &lt;a href=&#34;https://blog.docker.com/2016/04/containers-and-vms-together/&#34;&gt;https://blog.docker.com/2016/04/containers-and-vms-together/&lt;/a&gt; )
&lt;/center&gt;&lt;/p&gt;

&lt;h2 id=&#34;docker-container-images&#34;&gt;Docker container images&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A Docker image can contain anything from a single file to a complete OS

&lt;ul&gt;
&lt;li&gt;Ubuntu, Debian, CentOS, Alpine, &amp;hellip;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;This is an opaque box to our existing tooling and processes

&lt;ul&gt;
&lt;li&gt;Are there any known vulnerabilities in it?&lt;/li&gt;
&lt;li&gt;What about new vulnerabilities (new CVEs) found after container deployed?&lt;/li&gt;
&lt;li&gt;Our usual agents can not be installed inside the container&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;A Docker container should be considered immutable

&lt;ul&gt;
&lt;li&gt;Don&amp;rsquo;t patch a running instance, we destroy it and replace it with a fixed copy&lt;/li&gt;
&lt;li&gt;How often does the vendor update their containers with patches?

&lt;ul&gt;
&lt;li&gt;This may result in more pushes to production than a traditional app&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;A Docker container should be considered stateless

&lt;ul&gt;
&lt;li&gt;Stateful information (configuration files, log files, data files&amp;hellip;) live outside the container&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This impacts how we manage our container environment; so many of our tools
and processes just don&amp;rsquo;t work!&lt;/p&gt;

&lt;h2 id=&#34;docker-runtime&#34;&gt;Docker runtime&lt;/h2&gt;

&lt;p&gt;&amp;ldquo;Rogue&amp;rdquo; containers&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker run debian&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;We&amp;rsquo;ve now pulled down a copy of a Debian container from the internet and run it&lt;/li&gt;
&lt;li&gt;Container images could be stored anywhere on the internet&lt;/li&gt;
&lt;li&gt;How do we ensure only approved containers can be run?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Privilege escalation&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Giving people access to the &lt;code&gt;docker&lt;/code&gt; command grants them root access inside the container&lt;/li&gt;
&lt;li&gt;This can also be used to effectively give them root access to the whole machine&lt;/li&gt;
&lt;li&gt;Access to the machine may allow people to see config files containing passwords or secrets (API keys, SSL certs, etc) needed by the container application&lt;/li&gt;
&lt;li&gt;We may need to consider all interactive access to Docker hosts to be privileged&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;image-deployment-and-inventory&#34;&gt;Image deployment and inventory&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How do we &lt;em&gt;ingest&lt;/em&gt; new vendor containers?

&lt;ul&gt;
&lt;li&gt;What is the process for going from DEV-&amp;gt;SIT/UAT-&amp;gt;PROD?&lt;/li&gt;
&lt;li&gt;How do we ensure the image promoted to prod is the same as the one in UAT?&lt;/li&gt;
&lt;li&gt;What is the deployment model required for this vendor application

&lt;ul&gt;
&lt;li&gt;Standalone?  Compose?  Swarm mode?  Kubernetes? Something else?&lt;/li&gt;
&lt;li&gt;What networking constructs are created?&lt;/li&gt;
&lt;li&gt;What ports are opened?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Inventory of containers

&lt;ul&gt;
&lt;li&gt;What images have been approved for use?

&lt;ul&gt;
&lt;li&gt;What have been denied (e.g. too many CRITICAL vulnerabilities)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Do we know what containers are running, what version, and where?

&lt;ul&gt;
&lt;li&gt;CMDB may be too static, containers may move around a cluster&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Are the containers running that should be running?

&lt;ul&gt;
&lt;li&gt;How do we monitor application availability?&lt;/li&gt;
&lt;li&gt;Does the deployment include HA designs?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A number of these questions also apply to traditional applications,
and can be carried over but I&amp;rsquo;ve heard senior managers say &amp;ldquo;it&amp;rsquo;s a
container, just deploy it&amp;rdquo; bypassing standard code promotion paths.&lt;/p&gt;

&lt;p&gt;Some of these questions also apply to virtual appliances (eg applications
shipped as an OVA file).  Do we have good processes we can adapt, or is
this also a gap?&lt;/p&gt;

&lt;h2 id=&#34;image-integrity-and-logging&#34;&gt;Image integrity and logging&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Transient filesystem changes

&lt;ul&gt;
&lt;li&gt;A vulnerable app may allow &lt;em&gt;temporary&lt;/em&gt; changes to be made inside the container

&lt;ul&gt;
&lt;li&gt;These are lost when the container is restarted&lt;/li&gt;
&lt;li&gt;Could be used as a pivot point to attack the rest of the network&lt;/li&gt;
&lt;li&gt;Could be used to host rogue content (phishing site?)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Existing File Integrity Monitoring tools can not detect this&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;How does the application log activity?

&lt;ul&gt;
&lt;li&gt;Each application may do things differently&lt;/li&gt;
&lt;li&gt;How can we get those logs into Splunk?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;exposed-services&#34;&gt;Exposed services&lt;/h2&gt;

&lt;p&gt;One application may effectively introduce a handful of new technologies&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A vendor application may consist of multiple containers

&lt;ul&gt;
&lt;li&gt;Each container may contain a different open source technology component

&lt;ul&gt;
&lt;li&gt;Tomcat, MySQL, MongoDB, Hadoop, ActiveMQ, Memcached, Zookeeper, &amp;hellip;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;These services may be exposed onto the main corporate network

&lt;ul&gt;
&lt;li&gt;How do we control them?

&lt;ul&gt;
&lt;li&gt;SSL?&lt;/li&gt;
&lt;li&gt;Usernames/passwords?&lt;/li&gt;
&lt;li&gt;Encryption of data at rest&lt;/li&gt;
&lt;li&gt;Backups&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;How do we monitor access to these services?

&lt;ul&gt;
&lt;li&gt;Database Access Monitoring&lt;/li&gt;
&lt;li&gt;Usage logs?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;so-many-options-we-can-t-support-them-all&#34;&gt;So many options, we can&amp;rsquo;t support them all&lt;/h2&gt;

&lt;p&gt;&lt;center&gt;
&lt;img src=&#34;https://www.sweharris.org/images/docker-ecosystem.png&#34; alt=&#34;ecosystem&#34; /&gt;
(Source: Docker)
&lt;/center&gt;&lt;/p&gt;

&lt;h2 id=&#34;the-support-model&#34;&gt;The support model&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Docker becomes a critical core infrastructure component

&lt;ul&gt;
&lt;li&gt;As critical as the traditional Hypervisor&lt;/li&gt;
&lt;li&gt;There are &amp;ldquo;community supported&amp;rdquo; editions and commercial enterprise editions&lt;/li&gt;
&lt;li&gt;The enterprise edition includes additional functionality not in the community edition&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Different vendors provide different solutions

&lt;ul&gt;
&lt;li&gt;VMware provides &amp;ldquo;vSphere Integrated Containers&amp;rdquo; (VIC) and additional tooling

&lt;ul&gt;
&lt;li&gt;Not 100% Docker compatible (e.g. no Swarm Mode)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Third party support tools exist (management, security, monitoring, etc)

&lt;ul&gt;
&lt;li&gt;Some provide real benefits, others are FUD&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;The organization needs to determine when it can use open source/community supported tools, and how much vendor enterprise level support is required.

&lt;ul&gt;
&lt;li&gt;And then build the tooling and processes around it&lt;/li&gt;
&lt;li&gt;We can use this to also provide a target platform for in-house developed Docker based apps&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;it-s-complicated&#34;&gt;It&amp;rsquo;s complicated&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Docker was designed to be flexible&lt;/li&gt;
&lt;li&gt;Can host anything from a single process to a complete database

&lt;ul&gt;
&lt;li&gt;&amp;hellip; or even a whole multi-tier solution!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;We can&amp;rsquo;t support every possible deployment model&lt;/li&gt;
&lt;li&gt;And let&amp;rsquo;s not talk about other  container ecosystems

&lt;ul&gt;
&lt;li&gt;OCI (Open Container Initiative)&lt;/li&gt;
&lt;li&gt;RKT (CoreOS Rocket)&lt;/li&gt;
&lt;li&gt;LXD (Ubuntu)&lt;/li&gt;
&lt;li&gt;OpenVZ&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There&amp;rsquo;s a lot of engineering work that needs to be done!&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;This kinda grew a little bit too long for a real CISO deck.  It&amp;rsquo;s maybe
14 pages of powerpoint.  But that&amp;rsquo;s because there&amp;rsquo;s so much, there!&lt;/p&gt;

&lt;p&gt;This isn&amp;rsquo;t even trying to defend against deliberately bad code (if you
can&amp;rsquo;t trust your vendor, why are you using them?) but against &lt;em&gt;mistakes&lt;/em&gt;.
Everyone makes them, and this technology is so new.&lt;/p&gt;

&lt;p&gt;Just last week I was
on a call where the vendor had provided a container with 7 HIGH vulnerabilities
in it; we wouldn&amp;rsquo;t allow a normal app to be deployed that way, so why would
we allow this container?  It turns out the vendor didn&amp;rsquo;t &lt;em&gt;have&lt;/em&gt; a scanning
process in their build pipeline, and so (on my prompting) introduced
&lt;a href=&#34;https://github.com/coreos/clair&#34;&gt;CLAIR&lt;/a&gt; into tooling.  Hopefully this
will mean less mistakes of this nature &lt;em&gt;and&lt;/em&gt; better visibility of new
vulnerabilities.&lt;/p&gt;

&lt;p&gt;We can&amp;rsquo;t rely on all vendors doing this, though; we need the tooling inhouse
to monitor the environment.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Monitoring my router with graphs</title>
      <link>https://www.sweharris.org/post/2017-09-03-router-graphs/</link>
      <pubDate>Sun, 03 Sep 2017 17:10:12 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-09-03-router-graphs/</guid>
      <description>

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;WARNING: technical content ahead!  There&amp;rsquo;s also a tonne of config files,
which make this page look longer than it really is, but hopefully they&amp;rsquo;ll
help other people who want to do similar work.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;A few months back I replaced my OpenWRT router with a &lt;a href=&#34;https://www.sweharris.org/post/2017-05-07-home-grown-router/&#34;&gt;CentOS 7 based one&lt;/a&gt;.  This machine has been working very
well, and handles my Gigabit FIOS traffic without any issues.&lt;/p&gt;

&lt;p&gt;I came across a post from &lt;a href=&#34;https://twitter.com/BitIntegrity&#34;&gt;Jim Perrin&lt;/a&gt;
around using tools to &lt;a href=&#34;http://jperrin.org/2017/08/04/keeping-an-eye-on-centos-performance-with-grafana.html&#34;&gt;collect data and draw graphs on it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now I&amp;rsquo;d started to play with collectd a few years ago, but never went
anywhere with it (I still had the source tree from where I compiled it!).
Jim&amp;rsquo;s solution looked simple enough&amp;hellip;&lt;/p&gt;

&lt;p&gt;He had everything running on the router, but I wanted to keep as much
load off the router as possible; let it handle the job of routing packets;
databases and graphing can be done elsewhere :-)  So I built a small
VM (512Mb RAM, 15Gb disk) and called it &amp;ldquo;monitor&amp;rdquo;.  This also allows me
to collect data from other machines and consolidate to one point.&lt;/p&gt;

&lt;h2 id=&#34;starting-with-influxdb&#34;&gt;Starting with influxDB&lt;/h2&gt;

&lt;p&gt;I did things in a slightly different order; I started with the database.
That way I could check that collectd was sending data correctly.&lt;/p&gt;

&lt;p&gt;So, following Jim&amp;rsquo;s instructions, I added the repo and installed the software.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat /etc/yum.repos.d/influxdb.repo 
[influxdb]
name = InfluxDB Repository - RHEL $releasever
baseurl = https://repos.influxdata.com/centos/$releasever/$basearch/stable
enabled = 1
gpgcheck = 1
gpgkey = https://repos.influxdata.com/influxdb.key

% sudo yum install influxdb
[...]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We now need to configure it.   I noticed that the defaults log a lot of
information; so this configuration turns off all that.  You might want
to leave it on while building, but beware that your &lt;code&gt;/var/log/messages&lt;/code&gt;
file will grow large!&lt;/p&gt;

&lt;p&gt;The effective configuration is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;reporting-disabled = true
[meta]
  dir = &amp;quot;/var/lib/influxdb/meta&amp;quot;
  logging-enabled=false

[data]
  dir = &amp;quot;/var/lib/influxdb/data&amp;quot;
  wal-dir = &amp;quot;/var/lib/influxdb/wal&amp;quot;
  query-log-enabled=false

[http]
  enabled = true
  bind-address = &amp;quot;:8086&amp;quot;
  log-enabled=false

[[collectd]]
  enabled = true
  bind-address = &amp;quot;:8096&amp;quot;
  database = &amp;quot;collectd&amp;quot;
  typesdb = &amp;quot;/usr/share/collectd&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are more sections in the file which probably need to be kept
there, but everything inside those sections are commented out; they&amp;rsquo;re the defaults.&lt;/p&gt;

&lt;p&gt;Now the &lt;code&gt;collectd&lt;/code&gt; section needs to see &lt;code&gt;types.db&lt;/code&gt; file from &lt;code&gt;collectd&lt;/code&gt;.
If you have the collectd RPM installed then this lives in &lt;code&gt;/usr/share/collectd/types.db&lt;/code&gt;, otherwise you&amp;rsquo;ll need to copy the file over.  The config file
points to the &lt;em&gt;directory&lt;/em&gt; the file lives in.&lt;/p&gt;

&lt;p&gt;Startup and run the server:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% sudo systemctl enable --now influxdb

% ps -ef | grep influx
influxdb  2597     1  0 Aug31 ?        00:25:34 /usr/bin/influxd -config /etc/influxdb/influxdb.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;collectd&#34;&gt;collectd&lt;/h2&gt;

&lt;p&gt;Now we can configure &lt;code&gt;collectd&lt;/code&gt; on the router.  Since this is in EPEL,
make sure you have the repo enabled and then it&amp;rsquo;s simple to install:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% sudo yum install collectd
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The configuration file is pretty simple:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Hostname    &amp;quot;router&amp;quot;
FQDNLookup   true

BaseDir     &amp;quot;/var/lib/collectd&amp;quot;
PIDFile     &amp;quot;/var/run/collectd.pid&amp;quot;
PluginDir   &amp;quot;/usr/lib64/collectd&amp;quot;
TypesDB     &amp;quot;/usr/share/collectd/types.db&amp;quot;

LoadPlugin syslog
&amp;lt;Plugin syslog&amp;gt;
        LogLevel info
&amp;lt;/Plugin&amp;gt;

LoadPlugin cpu
LoadPlugin df
LoadPlugin disk
LoadPlugin interface
LoadPlugin load
LoadPlugin memory
LoadPlugin network

&amp;lt;Plugin df&amp;gt;
        ReportInodes true
&amp;lt;/Plugin&amp;gt;

&amp;lt;Plugin disk&amp;gt;
        Disk &amp;quot;/^([hsv]|xv)d[a-z][0-9]?$/&amp;quot;
&amp;lt;/Plugin&amp;gt;

&amp;lt;Plugin network&amp;gt;
        Server &amp;quot;10.0.0.150&amp;quot; &amp;quot;8096&amp;quot;
&amp;lt;/Plugin&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(I&amp;rsquo;ll come to the &amp;ldquo;Disk&amp;rdquo; line a little later).&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s start it up!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;systemctl enable --now collectd
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;verifying-it-works&#34;&gt;Verifying it works&lt;/h3&gt;

&lt;p&gt;At this point &lt;code&gt;collectd&lt;/code&gt; should be sending data into InfluxDB.  We
can check this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% influx
Connected to http://localhost:8086 version 1.3.5
InfluxDB shell version: 1.3.5
&amp;gt; use collectd;
Using database collectd
&amp;gt; show measurements;
name: measurements
name
----
cpu_value
df_value
disk_io_time
disk_read
disk_value
disk_weighted_io_time
disk_write
interface_rx
interface_tx
load_longterm
load_midterm
load_shortterm
memory_value
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Excellent!  InfluxDB has a simple &lt;code&gt;SELECT&lt;/code&gt; syntax so you can look
inside each of the measurements for the raw data.&lt;/p&gt;

&lt;p&gt;The default settings for &lt;code&gt;influxDB&lt;/code&gt; allows it to retain data for 7
days.  If you want to keep data for longer then you&amp;rsquo;ll need to create
a new retention schedule.  In my case I wanted 2 months:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; create retention policy two_month on collectd duration 62d replication 1 default;
&amp;gt; drop retention policy autogen on collectd;
&amp;gt; show retention policies;
name      duration  shardGroupDuration replicaN default
----      --------  ------------------ -------- -------
two_month 1488h0m0s 24h0m0s            1        true
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;grafana&#34;&gt;Grafana&lt;/h2&gt;

&lt;p&gt;Let&amp;rsquo;s head back to Jim&amp;rsquo;s tutorial&amp;hellip; we can now install Grafana on
the &lt;code&gt;monitor&lt;/code&gt; machine.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat /etc/yum.repos.d/grafana.repo 
[grafana]
name=grafana
baseurl=https://packagecloud.io/grafana/stable/el/6/$basearch
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://packagecloud.io/gpg.key https://grafanarel.s3.amazonaws.com/RPM-GPG-KEY-grafana
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt

% sudo yum install grafana
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Configuration is pretty simple; just set the admin user/password in
the &lt;code&gt;[security]&lt;/code&gt; section.  (We&amp;rsquo;ll take a look at security in a little
bit).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% sudo systemctl enable --now grafana
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At this point I was able to go to &lt;code&gt;http://monitor:3000/&lt;/code&gt; and
login as the admin user.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ll be required to set up a datasource.  Because influxDB is on the
same machine, we can simply use these settings:
&lt;center&gt;
&lt;img src=&#34;https://www.sweharris.org/images/grafana-source.png&#34; alt=&#34;grafana datasource&#34; /&gt;
&lt;/center&gt;
It&amp;rsquo;s important to make sure the &lt;code&gt;localhost&lt;/code&gt; URL is highlighted and not
dim.&lt;/p&gt;

&lt;h3 id=&#34;creating-a-dashboard&#34;&gt;Creating a dashboard&lt;/h3&gt;

&lt;p&gt;We&amp;rsquo;re now ready to create a dashboard to look at all this data.  Jim recommended
the &lt;a href=&#34;https://grafana.com/dashboards/554&#34;&gt;Host overview&lt;/a&gt; dashboard, so
that&amp;rsquo;s where I started.&lt;/p&gt;

&lt;p&gt;I realised that some of these graphs were not suitable for a router;
for example the networking graphs take the total over all interfaces,
which means that &amp;ldquo;received&amp;rdquo; and &amp;ldquo;sent&amp;rdquo; values are almost identical.  After
all a router receives data on one interface and sends it back out again
on another :-)&lt;/p&gt;

&lt;p&gt;The GUI makes it pretty easy to edit panels, move them around, add/remove
entries.  I wanted the network panels to only refer to &lt;code&gt;br-wan&lt;/code&gt; (the
interface I use for connecting to the internet).  I also didn&amp;rsquo;t care too
much about disk space on this dashboard.&lt;/p&gt;

&lt;p&gt;The resulting JSON file is &lt;a href=&#34;https://www.sweharris.org/Grafana-Router_Overview.txt&#34;&gt;here&lt;/a&gt;, if it
helps.  I can now quickly see my internet usage and CPU load on the
server.&lt;/p&gt;

&lt;h2 id=&#34;multiple-hosts&#34;&gt;Multiple hosts&lt;/h2&gt;

&lt;p&gt;At this point it becomes very easy to deploy this to other servers.
Since my internet hosts are connected via a VPN I can use the same
file everywhere.  A simple &lt;code&gt;ansible&lt;/code&gt; script let me deploy to all
the hosts I wanted:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;---
- name: Set up collected
  hosts: collectd
  become: False

  tasks:
    - yum: name=collectd state=present

    - service: name=collectd enabled=yes state=started

    - name: collectd.conf
      template: src=Files/collectd/collectd.conf.j2 dest=/etc/collectd.conf owner=root group=root mode=644
      notify:
      - reconfig

  handlers:
    - name: reconfig
      service: name=collectd state=restarted
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &amp;ldquo;conf&amp;rdquo; file is identical to the one previously shown, except for the
one line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Hostname    &amp;quot;{{ ansible_hostname }}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I also added a line for my VM server to collect &lt;code&gt;virt&lt;/code&gt; stats:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{% if ansible_hostname == &amp;quot;penfold&amp;quot; %}
LoadPlugin virt
{% endif %}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A quick &lt;code&gt;ansible-playbook&lt;/code&gt; command and a few minutes and now I have 7
machines all sending data to influxDB and they now all magically show
in the &amp;lsquo;Host Overview&amp;rdquo; dashboard.&lt;/p&gt;

&lt;p&gt;This also explains the odd &amp;ldquo;Disk&amp;rdquo; line in the config.  The various
machines may show hd* or sd* or vd* or even xvd* (Xen client).  I also
wanted to &lt;em&gt;not&lt;/em&gt; collect data for metadisks (md0, md6, etc).&lt;/p&gt;

&lt;h2 id=&#34;security&#34;&gt;Security&lt;/h2&gt;

&lt;p&gt;Now this configuration has a lot of things that I&amp;rsquo;d scream about at
work.  We&amp;rsquo;re exposing services to the network without proper access
control (primarily &lt;code&gt;influxDB&lt;/code&gt;).  This means that anyone on my network
could send funky data and pollute my database or even &lt;em&gt;read&lt;/em&gt; data.  There&amp;rsquo;s
no sensitive data stored here, but it&amp;rsquo;s not a good configuration and would
never be acceptable in an enterprise environment.&lt;/p&gt;

&lt;p&gt;The tools &lt;em&gt;do&lt;/em&gt; allow for authentication and TLS; InfluxDB documentation
goes into quite some detail on how to configure this, and both &lt;code&gt;collectd&lt;/code&gt;
and Grafana can be configured to authenticate to talk to it.&lt;/p&gt;

&lt;p&gt;However, I&amp;rsquo;m not an enterprise; guests are on the guestnet and can&amp;rsquo;t
see this server; I&amp;rsquo;m not exposing it to the internet&amp;hellip;&lt;/p&gt;

&lt;p&gt;No doubt this will come back to haunt me at some point :-)&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;m actually not a fan of GUIs for management.  This form of &amp;ldquo;eyes on
glass&amp;rdquo; monitoring means that issues may be lost.  However they &lt;em&gt;do&lt;/em&gt; have
benefits; oddities may stand out.&lt;/p&gt;

&lt;p&gt;Indeed, one oddity showed up almost immediately:
&lt;center&gt;
&lt;img src=&#34;https://www.sweharris.org/images/grafana-network.png&#34; alt=&#34;grafana network&#34; /&gt;
&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Why is my network baseline downloaded 800Mbytes/hour?  That seems high!&lt;/p&gt;

&lt;p&gt;I was about to hunt down what server was doing a constant 200Kbyte/sec
when it struck me&amp;hellip;  my speed check tester downloads 200Mbytes every
15 minutes; 4 times an hour.  That&amp;rsquo;s 800Mbytes, right there :-)&lt;/p&gt;

&lt;p&gt;This graph also clearly shows when I downloaded backups from my internet
hosted servers, and when I uploaded my backups to Amazon cloud :-)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Remembering history</title>
      <link>https://www.sweharris.org/post/2017-08-27-history/</link>
      <pubDate>Sun, 27 Aug 2017 13:48:37 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-08-27-history/</guid>
      <description>

&lt;p&gt;&lt;em&gt;&amp;ldquo;Those who cannot remember the past are condemned to repeat it.&amp;rdquo;&lt;/em&gt; &amp;ndash; George Santayana&lt;/p&gt;

&lt;h2 id=&#34;default-broken&#34;&gt;Default broken&lt;/h2&gt;

&lt;p&gt;I was reminded, last week, of how old issues repeat.&lt;/p&gt;

&lt;p&gt;Back in the 90s it was a truism that if you put an &amp;ldquo;Out Of The Box&amp;rdquo; RedHat
4 (not RedHat Enterprise; the original freeware version) server on the
internet then it would be compromised within hours.  And so we learned;
our default builds didn&amp;rsquo;t have telnet, didn&amp;rsquo;t have every possible
service installed, didn&amp;rsquo;t have vulnerable configurations.  The installer
would try and install patches at built time.  The root account may not be
directly accessed via &lt;code&gt;ssh&lt;/code&gt;.  Windows machines now have firewalls to block
non-local traffic&amp;hellip;&lt;/p&gt;

&lt;p&gt;Lots of security improvements.&lt;/p&gt;

&lt;p&gt;Of course you &lt;em&gt;can&lt;/em&gt; put bad machines on the net, but it&amp;rsquo;s harder to do.&lt;/p&gt;

&lt;p&gt;Unfortunately there&amp;rsquo;s a new generation of developers who failed to
learn these lessons.  The Mirai botnet spread via Internet Of Things (IoT)
devices that failed to do basic security (exposed telnet ports, default
unchangeable passwords).  This was made worse by using UPnP to expose
many of these machines directly onto the internet.  These are 20+ year
old mistakes, being repeated today.&lt;/p&gt;

&lt;h2 id=&#34;new-ingress-points&#34;&gt;New ingress points&lt;/h2&gt;

&lt;p&gt;We learned how to protect environments; firewalls, WAFs, traffic monitoring
and so on.  We track CVEs, we patch, we have configuration management tools&amp;hellip;
all in an effort to prevent bad services from being exposed, and to defend
against incoming rogue traffic.&lt;/p&gt;

&lt;p&gt;However these can only protect against known paths.  What happens when
a new ingress method is created?  For example, IPv6.  This can create
routes and methods of ingress that bypass existing technologies.  For
home users used to being behind NAT it may now expose desktops and IoT
devices directly to the outside world that were previously protected.&lt;/p&gt;

&lt;p&gt;What&amp;rsquo;s that, you say?  No IoT?  You don&amp;rsquo;t have a DVR?  A games console?
A cellphone?  A smart TV?  Nothing?  Then you&amp;rsquo;re lucky.  So many devices,
these days, talk to the internet&amp;hellip; and many of those may become directly
reachable when IPv6 becomes prevalent.&lt;/p&gt;

&lt;h2 id=&#34;cloud&#34;&gt;Cloud&lt;/h2&gt;

&lt;p&gt;Repeating the mistakes of the past is pretty common when it comes to
companies moving into the cloud.&lt;/p&gt;

&lt;p&gt;Your traditional corporate datacenter has a &lt;em&gt;lot&lt;/em&gt; of technology in place
to protect servers within the (virtual) 4 walls of the company.  Starting
with multi-tier architectures and firewalls (both internal and
external), proxies, automation, access controls&amp;hellip;  companies spend a
fortune on technology to help protect servers and data.&lt;/p&gt;

&lt;p&gt;And yet it&amp;rsquo;s not uncommon to see teams deploying servers and software
out in the cloud on their own.  This &amp;ldquo;shadow IT&amp;rdquo; is being created by
teams who don&amp;rsquo;t know (and may not even be aware) of the technology
protecting their apps.  So they spin up an Amazon account, create networks,
expose servers to the internet&amp;hellip; and then wonder why they got broken into.&lt;/p&gt;

&lt;h2 id=&#34;containers&#34;&gt;Containers&lt;/h2&gt;

&lt;p&gt;The same problem applies to container based solutions.  We may expose
software directly from inside a container (eg a tomcat instance, or
something running Apache Struts, or a bad version of OpenSSL), and this
is not controlled or even visible to corporate monitoring systems
(containers tend to be opaque boxes, and are so dynamic that existing tools
may not even be able to handle them, requiring new tools and solutions).&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;People deploying solutions need to remember the lessons of the past.  We
can never go backwards because attacks against those old issues still
happen; they&amp;rsquo;ve been automated into scripts and don&amp;rsquo;t require any
human action to be probed for.  Out of curiousity I told my firewall
to report incoming port 23 (telnet) connections&amp;hellip; I turned the reporting
off again a few hours later because the logs were being flooded.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;re not talking about targeted attacks, this is just random background
internet noise.  But if you make a mistake then you &lt;em&gt;will&lt;/em&gt; be breached
and find your server part of a botnet, or a bitcoin miner.  If you&amp;rsquo;re
being targeted then these decade old issues will be attempted before
the attacker has even sat down with his first cup of coffee.&lt;/p&gt;

&lt;p&gt;This isn&amp;rsquo;t a technology problem, although many companies approach it in
that manner.  This is an &lt;em&gt;education&lt;/em&gt; problem.  We need to teach teams
&lt;em&gt;why&lt;/em&gt; certain processes and procedures exist; &lt;em&gt;why&lt;/em&gt; they shouldn&amp;rsquo;t
use shiny-toy-of-the-month; &lt;em&gt;why&lt;/em&gt;&amp;hellip;   Don&amp;rsquo;t dictate rules, but bring
them in as partners.&lt;/p&gt;

&lt;p&gt;There will still be tension (&amp;ldquo;move faster!&amp;rdquo;) but maybe they&amp;rsquo;ll be willing
to help &lt;em&gt;build&lt;/em&gt; the solutions needed to use the shiny-shiny.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Secrets management with Docker Swarm</title>
      <link>https://www.sweharris.org/post/2017-08-06-docker-secrets/</link>
      <pubDate>Sun, 06 Aug 2017 17:34:48 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-08-06-docker-secrets/</guid>
      <description>

&lt;p&gt;One of the big problems with a cloudy environment is in how to allow
the application to get the username/password needed to reach a backend
service (e.g. a MySQL database).  With a normal application the application
operate team can inject these credentials at install time, but a cloudy
app needs to be able to start/stop/restart/scale without human intervention.
This can get worse with containers because these may be started a lot more
frequently.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s tempting to just put the information into a config file that&amp;rsquo;s
part of the container build, but this has a number of issues, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The container can be pulled apart and the credentials exposed&lt;/li&gt;
&lt;li&gt;The config file may be checked into source control&lt;/li&gt;
&lt;li&gt;Passwords may change; you don&amp;rsquo;t want to rebuild and redeploy each time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href=&#34;https://12factor.net&#34;&gt;12 Factor&lt;/a&gt; approach is to have credentials
passed in via the environment (typically an environment variable).
Docker &lt;em&gt;secrets&lt;/em&gt; is the model that Docker Swarm Mode uses to achieve this.&lt;/p&gt;

&lt;p&gt;Note: this doesn&amp;rsquo;t work with standalone Docker, nor with containers not
started as part of a &lt;a href=&#34;https://www.sweharris.org/post/2017-07-16-dockerswarm/&#34;&gt;service&lt;/a&gt;.  It will
work with a single-host swarm and a scale 1 service, though.&lt;/p&gt;

&lt;h2 id=&#34;what-is-a-secret&#34;&gt;What is a secret?&lt;/h2&gt;

&lt;p&gt;A secret, in Docker, is pretty much any string of text.  This means you
could put pretty much anything into it; a JSON file, an SSL certificate,
API keys, a password&amp;hellip; anything.  The limit is around 500K, which should be large
enough!&lt;/p&gt;

&lt;p&gt;This is stored in the Docker Swarm raft log, which means it&amp;rsquo;s replicated
across all the management nodes for resiliency.  It&amp;rsquo;s also (since Docker
1.13) &lt;em&gt;encrypted&lt;/em&gt;, which means the secrets are never stored in plain text
on any disk.&lt;/p&gt;

&lt;h2 id=&#34;creating-a-secret&#34;&gt;Creating a secret&lt;/h2&gt;

&lt;p&gt;This is pretty straight forward.  You can specify a file that has the
secret, or use &lt;code&gt;-&lt;/code&gt; to mean STDIN.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% echo hello | docker secret create my-secret
aqfet0saziaqzspvih6p6w72n

% docker secret ls
ID                          NAME                CREATED             UPDATED
aqfet0saziaqzspvih6p6w72n   my-secret           13 seconds ago      13 seconds ago

% docker secret inspect my-secret
[
    {
        &amp;quot;ID&amp;quot;: &amp;quot;aqfet0saziaqzspvih6p6w72n&amp;quot;,
        &amp;quot;Version&amp;quot;: {
            &amp;quot;Index&amp;quot;: 893
        },
        &amp;quot;CreatedAt&amp;quot;: &amp;quot;2017-08-06T21:53:38.771368641Z&amp;quot;,
        &amp;quot;UpdatedAt&amp;quot;: &amp;quot;2017-08-06T21:53:38.771368641Z&amp;quot;,
        &amp;quot;Spec&amp;quot;: {
            &amp;quot;Name&amp;quot;: &amp;quot;my-secret&amp;quot;,
            &amp;quot;Labels&amp;quot;: {}
        }
    }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;rsquo;s all there is!&lt;/p&gt;

&lt;h2 id=&#34;using-secrets&#34;&gt;Using secrets&lt;/h2&gt;

&lt;p&gt;We can create a service that refers to the secret.  This will then
appear in &lt;code&gt;/run&lt;/code&gt; inside the container&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker service create --detach=true --name secret-service \
         --secret my-secret --entrypoint /bin/sh --tty=true centos
iqdxqenn4hrmo6meobq95rinl

% docker service ps secret-service
ID                  NAME                IMAGE               NODE                   DESIRED STATE       CURRENT STATE                    ERROR               PORTS
kv3uo8qm95h3        secret-service.1    centos:latest       docker-ce.spuddy.org   Running             Running less than a second ago

% docker exec -it secret-service.1.kv3uo8qm95h3anox5q372pojh /bin/sh
sh-4.2# ls /run/secrets
my-secret
sh-4.2# cat /run/secrets/my-secret
hello
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that &lt;code&gt;/run&lt;/code&gt; is a tmpfs filesystem and so the secret still doesn&amp;rsquo;t
appear on disk; it&amp;rsquo;s only stored in memory.&lt;/p&gt;

&lt;h2 id=&#34;using-secrets-with-a-stack&#34;&gt;Using secrets with a stack&lt;/h2&gt;

&lt;p&gt;Because a stack can have private namespaces as well as using the global
one we have to define this as an &lt;code&gt;external&lt;/code&gt; resource.  The model looks
very similar to what we&amp;rsquo;ve seen for networks.  That&amp;rsquo;s deliberate.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat secret_stack.yml
version: &#39;3.1&#39;

services:
  os:
    image: centos
    deploy:
      replicas: 1
    entrypoint: /bin/sh
    stdin_open: true
    tty: true
    secrets:
      - source: my-secret

secrets:
  my-secret:
    external: true

% docker stack deploy -c secret_stack.yml secret-stack
Creating network secret-stack_default
Creating service secret-stack_os

% docker service ps secret-stack
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
eh1ta48g3gfy        secret-stack_os.1   centos:latest       test2.spuddy.org    Running             Running 17 seconds ago

% ssh test2 docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
2e17c5b3a50a        centos:latest       &amp;quot;/bin/sh&amp;quot;           31 seconds ago      Up 30 seconds                           secret-stack_os.1.eh1ta48g3gfyduvgxxx7f0uev

% ssh test2 docker exec secret-stack_os.1.eh1ta48g3gfyduvgxxx7f0uev cat /run/secrets/my-secret
hello
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;updating-secrets&#34;&gt;Updating secrets&lt;/h2&gt;

&lt;p&gt;This is where we start to hit limits.  A secret, once in use, can not be
changed or even removed.  There&amp;rsquo;s not even a &lt;code&gt;docker secret update&lt;/code&gt; option,
and &lt;code&gt;docker secret rm&lt;/code&gt; fails&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker secret

Usage:  docker secret COMMAND

Manage Docker secrets

Options:
      --help   Print usage

Commands:
  create      Create a secret from a file or STDIN as content
  inspect     Display detailed information on one or more secrets
  ls          List secrets
  rm          Remove one or more secrets

Run &#39;docker secret COMMAND --help&#39; for more information on a command.

% docker secret rm my-secret
Error response from daemon: rpc error: code = 3 desc = secret &#39;my-secret&#39; is in use by the following services: secret-service, secret-stack_os
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This may be a bit of a problem; if you have placed an SSL cert into the
secret store and it now needs to be updated then how can you do this?&lt;/p&gt;

&lt;p&gt;We have to cheat a little.  We can create a new secret and then update
the service(s) to use this new secret but under the old name:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% echo A new secret | docker secret create my-secret.v2
kolmhlqxh8wsle75j4siv6dl8

% docker service update --secret-rm my-secret --detach=true \
        --secret-add source=my-secret.v2,target=my-secret secret-service
secret-service

% docker service ps secret-service
ID                  NAME                   IMAGE               NODE                   DESIRED STATE       CURRENT STATE            ERROR               PORTS
4hf3m0rwroeh        secret-service.1       centos:latest       docker-ce.spuddy.org   Ready               Ready 9 seconds ago
kv3uo8qm95h3         \_ secret-service.1   centos:latest       docker-ce.spuddy.org   Shutdown            Running 11 seconds ago

% docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
7ac269ffb300        centos:latest       &amp;quot;/bin/sh&amp;quot;           35 seconds ago      Up 21 seconds                           secret-service.1.4hf3m0rwroehf57evqdowmbsz

% docker exec -it secret-service.1.4hf3m0rwroehf57evqdowmbsz cat /run/secrets/my-secret
A new secret
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;rsquo;s &lt;em&gt;messy&lt;/em&gt;; the &lt;code&gt;docker service update&lt;/code&gt; command causes the service to
be restarted.  In theory that shouldn&amp;rsquo;t cause downtime to your app, but
it&amp;rsquo;s still a restart and any internal state will be lost.&lt;/p&gt;

&lt;p&gt;We also need to update every service that uses a secret
before we can remove the old secret&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker service update --secret-rm my-secret --detach=true \
        --secret-add source=my-secret.v2,target=my-secret secret-stack_os
secret-stack_os

% docker secret rm my-secret
my-secret

% docker secret ls
ID                          NAME                CREATED             UPDATED
kolmhlqxh8wsle75j4siv6dl8   my-secret.v2        6 minutes ago       6 minutes ago
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;using-secrets-as-a-seed&#34;&gt;Using secrets as a &amp;ldquo;seed&amp;rdquo;&lt;/h2&gt;

&lt;p&gt;Docker secrets enable us to use an &lt;em&gt;external&lt;/em&gt; password vault (e.g.
&lt;a href=&#34;https://www.vaultproject.io/&#34;&gt;Hashivault&lt;/a&gt;).  The secret stored inside
the Swarm would be sufficient to let your application log into the
vault and then get the password it needs (e.g. for the database).  It
could be used to talk to an API to generate and retrieve an SSL certificate,
with the management happening at the enterprise system (e.g. renewal; next
time your container starts it will automatically get the new cert).&lt;/p&gt;

&lt;p&gt;These &amp;ldquo;seed&amp;rdquo; credentials still need to be controlled because they provide
access to the final system, but it allows for greater flexibility, especially
where credentials may be short lived (Hashivault can generate short-lived
passwords in the database; &lt;a href=&#34;https://letsencrypt.org/&#34;&gt;Lets Encrypt&lt;/a&gt; certs
live 90 days&lt;/p&gt;

&lt;h2 id=&#34;related-docker-configuration-items&#34;&gt;Related: Docker configuration items&lt;/h2&gt;

&lt;p&gt;Since Docker 17.06 there is also &lt;code&gt;docker config&lt;/code&gt;.  These work conceptually
in a similar way to secrets but are implemented slightly differently at
the backend; in particular they&amp;rsquo;re not encrypted at rest and they&amp;rsquo;re
mounted directly into the container.&lt;/p&gt;

&lt;p&gt;Management of configs (and the limitations in rotation) are very
similar to secrets, just using the &lt;code&gt;docker config&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Docker configs can work with secrets; e.g. you could create a web server
where the config and the HTML index file come from config entries and the
SSL certificate comes from the secret entry.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Docker secrets are currently very limited in what they can do.  In particular
rotation and updating of secrets is painful and requires your service to
be redeployed.&lt;/p&gt;

&lt;p&gt;However they do provide a way of handling the &amp;ldquo;how to get secrets into a container&amp;rdquo;, which is a &lt;em&gt;hard&lt;/em&gt; problem to solve without technology like this.&lt;/p&gt;

&lt;p&gt;Using them as a &amp;ldquo;seed&amp;rdquo; to access a fully fledged secrets solution (eg a Vault
or a Cert management system) overcomes many of the limitations and allows
enterprise scale secret management.&lt;/p&gt;

&lt;p&gt;Note, however, that anyone in the &lt;code&gt;docker&lt;/code&gt; group can get the plain text!
This is yet another reason to treat all access to these servers as highly
privileged.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Using placement constraints with Docker Swarm</title>
      <link>https://www.sweharris.org/post/2017-07-30-docker-placement/</link>
      <pubDate>Sun, 30 Jul 2017 13:32:52 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-07-30-docker-placement/</guid>
      <description>

&lt;p&gt;As we&amp;rsquo;ve &lt;a href=&#34;https://www.sweharris.org/post/2017-07-16-dockerswarm/&#34;&gt;previously seen&lt;/a&gt;, Docker Swarm mode
is a pretty powerful tool for deploying containers across a cluster.  It
has self-healing capabilities, built in network load balancers, scaling,
private VXLAN networks and more.&lt;/p&gt;

&lt;p&gt;Docker Swarm will automatically try and place your containers to provide
maximum resiliency within the service.  So, for example, if you request
3 running copies of a container then it will try and place these on three
different machines.  Only if resources are unavailable will two containers
be placed on the same host.&lt;/p&gt;

&lt;p&gt;We saw this with our simple &lt;code&gt;pinger&lt;/code&gt; application; it ran on 3 nodes:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker service ps pinger
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
xxn5tnej6bao        pinger.1            centos:latest       test1.spuddy.org    Running             Running 5 minutes ago
dcmno194ymjf        pinger.2            centos:latest       test2.spuddy.org    Running             Running 2 second ago
g89lpi6xeuji        pinger.3            centos:latest       test3.spuddy.org    Running             Running 2 second ago
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Sometimes, however, you need to control &lt;em&gt;where&lt;/em&gt; a container is run.
This may be for functionality reasons; for example a container that
monitors and reports on the Swarm state needs to run on a manager node
in order to get the data it needs.  Or there may be OS requirements (a
container designed to run on a Windows machine shouldn&amp;rsquo;t be deployed to
a Linux machine!).&lt;/p&gt;

&lt;p&gt;Frequently, however, this due to some nodes having the necessary
resources, and the most common of these are &amp;ldquo;volume&amp;rdquo; dependencies.
Remember that while the containers may be run on multiple nodes, a Swarm
is really just a collection of standalone Docker engines pulling images
from a registry.  That means that backend resources, such as file system
volumes, are served locally from each node.  The contents of &lt;code&gt;/myapp&lt;/code&gt; on
server &lt;code&gt;test1&lt;/code&gt; may be different from &lt;code&gt;/myapp&lt;/code&gt; on &lt;code&gt;test2&lt;/code&gt;.  We also saw
this, in passing, with the MySQL container; it was constrained to only
run on a specific node so that the backing datafiles were consistent.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  db:
    image: mysql:5.5
    networks:
      - appdb
    environment:
      - MYSQL_ROOT_PASSWORD=foobar
      - MYSQL_DATABASE=mydb1
    volumes:
      - db-data:/var/lib/mysql
    deploy:
      placement:
        constraints: [node.hostname == test1.spuddy.org]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this case we use a named volume rather than a filesystem directory,
but the constraint is still required; each node would have its own unique
&amp;ldquo;db-data&amp;rdquo; volume.&lt;/p&gt;

&lt;p&gt;Now constraining a host by hostname works, but you&amp;rsquo;re limited to just
a single host.  What if you wanted to run 3 copies of Tomcat?  We
need to constrain it to run, just where the config files are and we
can&amp;rsquo;t just list all three names (the rules are ANDed together).&lt;/p&gt;

&lt;p&gt;So, instead, we can define a &lt;em&gt;label&lt;/em&gt; and constrain it to that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  tomcat:
    image: sweh/test:fake_tomcat
    deploy:
      replicas: 2
      placement:
        constraints: [node.labels.Tomcat == true ]
    volumes:
      - &amp;quot;/myapp/apache/certs:/etc/pki/tls/certs/myapp&amp;quot;
      - &amp;quot;/myapp/apache/logs:/etc/httpd/logs&amp;quot;
      - &amp;quot;/myapp/tomcat/webapps:/usr/local/apache-tomcat-8.5.3/webapps&amp;quot;
      - &amp;quot;/myapp/tomcat/logs:/usr/local/apache-tomcat-8.5.3/logs&amp;quot;
    ports:
      - &amp;quot;8443:443&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(&amp;ldquo;fake_tomcat&amp;rdquo; is just a dummy program I wrote that listens on the requested
port; it doesn&amp;rsquo;t do any real work).&lt;/p&gt;

&lt;p&gt;I want to run this on &lt;code&gt;test1&lt;/code&gt; and &lt;code&gt;test2&lt;/code&gt; so on those two machines I make
the necessary directories.&lt;/p&gt;

&lt;p&gt;We now need to add the labels to tell the Swarm these are able to run
Tomcat:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ docker node update --label-add Tomcat=true test1.spuddy.org
test1.spuddy.org
$ docker node update --label-add Tomcat=true test2.spuddy.org
test2.spuddy.org
$   docker node inspect --format &#39;{{ .Spec.Labels }}&#39; test1.spuddy.org
map[Tomcat:true]
$   docker node inspect --format &#39;{{ .Spec.Labels }}&#39; test2.spuddy.org
map[Tomcat:true]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I then create the stack, and we can see it running&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ docker stack deploy -c stack.tomcat myapp
Creating network myapp_default
Creating service myapp_tomcat

$ docker stack ls
NAME                SERVICES
myapp               1

$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                   PORTS
bnhvu1cc3orx        myapp_tomcat        replicated          2/2                 sweh/test:fake_tomcat   *:8443-&amp;gt;443/tcp

$ docker service ps myapp_tomcat
ID                  NAME                IMAGE                   NODE                DESIRED STATE       CURRENT STATE                ERROR               PORTS
to0yvevap2om        myapp_tomcat.1      sweh/test:fake_tomcat   test2.spuddy.org    Running             Running about a minute ago
dk9pnthgvdcp        myapp_tomcat.2      sweh/test:fake_tomcat   test1.spuddy.org    Running             Running about a minute ago
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can see this is working by testing port 8443:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ echo hello | nc localhost 8443
You are caller #1 to have reached fake_tomcat on 38be98384cb9:443
fake_tomcat has received message `hello&#39;

$ echo hello | nc localhost 8443
You are caller #1 to have reached fake_tomcat on d095e9f2490f:443
fake_tomcat has received message `hello&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Two calls hit the different containers (as shown by the different hostname
in the output).&lt;/p&gt;

&lt;h2 id=&#34;multiple-services&#34;&gt;Multiple services&lt;/h2&gt;

&lt;p&gt;Let&amp;rsquo;s create a more complicated stack which has Tomcat and Memcached and
Zookeeper.&lt;/p&gt;

&lt;p&gt;The additional lines to the stack are:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  zookeeper:
    image: sweh/test:fake_zookeeper
    deploy:
      replicas: 2
      placement:
        constraints: [node.labels.Zookeeper == true ]
    volumes:
      - &amp;quot;/myapp/zookeeper/data:/usr/zookeeper/data&amp;quot;
      - &amp;quot;/myapp/zookeeper/logs:/usr/zookeeper/logs&amp;quot;
      - &amp;quot;/myapp/zookeeper/conf:/usr/zookeeper/conf&amp;quot;
    environment:
      CFG_FILE: /usr/zookeeper/conf/zoo.cfg

  memcached:
    image: sweh/test:fake_memcached
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.Memcached == true ]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And let&amp;rsquo;s create the relevant labels to distribute over the three
servers.  The resulting labels look like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;docker-ce.spuddy.org
    map[]

test1.spuddy.org
    map[Memcached:true Tomcat:true]

test2.spuddy.org
    map[Tomcat:true Zookeeper:true]

test3.spuddy.org
    map[Zookeeper:true]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note there&amp;rsquo;s nothing labeled on the manager node; my app won&amp;rsquo;t run there.&lt;/p&gt;

&lt;p&gt;Again, ensure the directories exist with the necessary configuration
and deploy:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ docker stack rm myapp
Removing service myapp_tomcat
Removing network myapp_default

$ docker stack deploy -c stack.full myapp
Creating network myapp_default
Creating service myapp_memcached
Creating service myapp_tomcat
Creating service myapp_zookeeper

$ docker stack ps myapp
ID                  NAME                IMAGE                      NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
iidao6f3vt6z        myapp_zookeeper.1   sweh/test:fake_zookeeper   test2.spuddy.org    Running             Running 34 seconds ago
haq4vvben495        myapp_tomcat.1      sweh/test:fake_tomcat      test1.spuddy.org    Running             Running 35 seconds ago
6u4s6w4fs0cm        myapp_memcached.1   sweh/test:fake_memcached   test1.spuddy.org    Running             Running 37 seconds ago
zixk0eu2aahu        myapp_zookeeper.2   sweh/test:fake_zookeeper   test3.spuddy.org    Running             Running 35 seconds ago
4u8ytws4kl5v        myapp_tomcat.2      sweh/test:fake_tomcat      test2.spuddy.org    Running             Running 35 seconds ago
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;rescale&#34;&gt;Rescale&lt;/h2&gt;

&lt;p&gt;In my fake environment I decided that memcached is running slow (and, besides,
only having one copy isn&amp;rsquo;t very resilient!).  Now we can see the power of
labels; I can &lt;em&gt;add&lt;/em&gt; the Memcached label to another node and then rescale:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ docker node update --label-add Memcached=true test3.spuddy.org
test3.spuddy.org

$ docker service scale myapp_memcached=2
myapp_memcached scaled to 2

$ docker service ps myapp_memcached
ID                  NAME                IMAGE                      NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
6u4s6w4fs0cm        myapp_memcached.1   sweh/test:fake_memcached   test1.spuddy.org    Running             Running 3 minutes ago
pf56ix45e887        myapp_memcached.2   sweh/test:fake_memcached   test3.spuddy.org    Running             Running 7 seconds ago
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now that was easy because it didn&amp;rsquo;t have any external volumes to depend on,
but we could do the same for zookeeper or tomcat; just create the necessary
volumes and configurations on the new node, then add the label.&lt;/p&gt;

&lt;h3 id=&#34;what-if-you-forget-the-volumes&#34;&gt;What if you forget the volumes?&lt;/h3&gt;

&lt;p&gt;Let&amp;rsquo;s add Zookeeper to test1 but &amp;ldquo;forget&amp;rdquo; to make the volumes:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ docker node update --label-add Zookeeper=true test1.spuddy.org
test1.spuddy.org
$ docker service scale myapp_zookeeper=3
myapp_zookeeper scaled to 3
$ docker service ps myapp_zookeeper
ID                  NAME                    IMAGE                      NODE                DESIRED STATE       CURRENT STATE                     ERROR                              PORTS
iidao6f3vt6z        myapp_zookeeper.1       sweh/test:fake_zookeeper   test2.spuddy.org    Running             Running 6 minutes ago
zixk0eu2aahu        myapp_zookeeper.2       sweh/test:fake_zookeeper   test3.spuddy.org    Running             Running 6 minutes ago
ytyp3impjzyf        myapp_zookeeper.3       sweh/test:fake_zookeeper   test1.spuddy.org    Ready               Rejected less than a second ago   &amp;quot;invalid mount config for type�
sudgw3w694ja         \_ myapp_zookeeper.3   sweh/test:fake_zookeeper   test1.spuddy.org    Shutdown            Rejected 5 seconds ago            &amp;quot;invalid mount config for type�
3gv64qgli504         \_ myapp_zookeeper.3   sweh/test:fake_zookeeper   test1.spuddy.org    Shutdown            Rejected 6 seconds ago            &amp;quot;invalid mount config for type�
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;rsquo;s messy!&lt;/p&gt;

&lt;p&gt;Eventually the system settles down and runs two copies on an existing node:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ docker service ps myapp_zookeeper
ID                  NAME                    IMAGE                      NODE                DESIRED STATE       CURRENT STATE                 ERROR                              PORTS
iidao6f3vt6z        myapp_zookeeper.1       sweh/test:fake_zookeeper   test2.spuddy.org    Running             Running 8 minutes ago
zixk0eu2aahu        myapp_zookeeper.2       sweh/test:fake_zookeeper   test3.spuddy.org    Running             Running 8 minutes ago
ib7eiekpes3c        myapp_zookeeper.3       sweh/test:fake_zookeeper   test2.spuddy.org    Running             Running 49 seconds ago
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Monitoring of service state becomes very important in this environment!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;migration-of-services-between-nodes&#34;&gt;Migration of services between nodes&lt;/h2&gt;

&lt;p&gt;For performance reasons I want to move the memcached currently run on
&lt;code&gt;test3&lt;/code&gt; and migrate it to &lt;code&gt;test2&lt;/code&gt;, so it&amp;rsquo;s on the same machine as the
tomcat instance.  We can force a migration of the container by adding
the label to the new node and removing it from the old.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ docker service ps myapp_memcached
ID                  NAME                IMAGE                      NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
6u4s6w4fs0cm        myapp_memcached.1   sweh/test:fake_memcached   test1.spuddy.org    Running             Running 13 minutes ago
pf56ix45e887        myapp_memcached.2   sweh/test:fake_memcached   test3.spuddy.org    Running             Running 9 minutes ago

$ docker node update --label-add Memcached=true test2.spuddy.org
test2.spuddy.org

$ docker node update --label-rm Memcached test3.spuddy.org
test3.spuddy.org

$ docker service ps myapp_memcached
ID                  NAME                    IMAGE                      NODE                DESIRED STATE       CURRENT STATE             ERROR               PORTS
6u4s6w4fs0cm        myapp_memcached.1       sweh/test:fake_memcached   test1.spuddy.org    Running             Running 14 minutes ago
n7bv9331opoq        myapp_memcached.2       sweh/test:fake_memcached   test2.spuddy.org    Running             Running 8 seconds ago
pf56ix45e887         \_ myapp_memcached.2   sweh/test:fake_memcached   test3.spuddy.org    Shutdown            Rejected 14 seconds ago
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The instance that had been running on &lt;code&gt;test3&lt;/code&gt; has been rejected and a new
instance started on &lt;code&gt;test2&lt;/code&gt;.  Remember the Docker scheduler will attempt to
pick a node that isn&amp;rsquo;t already running a copy of the container.  In this
case the only valid servers to meet the placement constraints were test1
and test2, and test1 already had a copy running.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Using labels allows for a very dynamic way of determining where your workloads
run; you can rescale, migrate and even extend the cluster (add new nodes,
add labels to the node, modify the scaling) without needing to redeploy
the stack.&lt;/p&gt;

&lt;p&gt;This can become more important as multiple workloads in multiple stacks
are deployed to the same swarm; the stack owners don&amp;rsquo;t need to know
about the underlying node names, they can just use labels and the same
stack can be deployed to different targets (how easy would this be to
spin up on AWS EC2 instances?  No stack changes needed at all!)&lt;/p&gt;

&lt;p&gt;Of course this doesn&amp;rsquo;t come for free; it takes time for containers to spin
up (about 6 seconds in my fake_memcached migration) so make sure your
services can handle short outages.  The closer to 12factor your apps are,
the better they are at handling dynamic migration of containers.&lt;/p&gt;

&lt;p&gt;And, of course, there&amp;rsquo;s still the persistent data volume question to handle;
this can complicate your deployments.&lt;/p&gt;

&lt;p&gt;But despite these complications I would recommend taking a look at labels
if you have a need to constrain where your containers run.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A look at Docker Swarm</title>
      <link>https://www.sweharris.org/post/2017-07-16-dockerswarm/</link>
      <pubDate>Sun, 16 Jul 2017 09:24:01 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-07-16-dockerswarm/</guid>
      <description>

&lt;p&gt;In my &lt;a href=&#34;https://www.sweharris.org/post/2017-07-02-dockerorch/&#34;&gt;previous entry&lt;/a&gt; I took a quick look
at some of the Docker orchestration tools.  I spent a bit of time poking
at &lt;code&gt;docker-compose&lt;/code&gt; and mentioned Swarm.&lt;/p&gt;

&lt;p&gt;In this entry I&amp;rsquo;m going to poke a little at Swarm; after all, it now comes
as part of the platform and is a key foundation of Docker Enterprise
Edition.&lt;/p&gt;

&lt;p&gt;Docker Swarm tries to take some of the concepts of a single host model
and convert it into a cluster.  Some of the same concepts (e.g. networking)
are extended to a cluster aware manner (e.g. using VXLAN overlay networks).
Where possible it tries to hide this stuff.&lt;/p&gt;

&lt;p&gt;Now this entry may look long&amp;hellip; but that&amp;rsquo;s because Swarm does a lot.  I&amp;rsquo;m
really only touching on some highlights!  There&amp;rsquo;s a lot more happening
behind the scenes.&lt;/p&gt;

&lt;h2 id=&#34;complications&#34;&gt;Complications&lt;/h2&gt;

&lt;p&gt;Now a Swarm &lt;em&gt;is&lt;/em&gt; a collection of Docker Engines.  This means that a lot of
the stuff we&amp;rsquo;ve seen in previous entries still applies.  In particular, you
can still access each node directly and examine the running state.  A
bit of a gotcha is that you really need a &lt;em&gt;registry&lt;/em&gt; to run images.&lt;/p&gt;

&lt;p&gt;In previous examples I did something similar to&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;docker build -t myimage .
docker run myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now this works because the engine has a copy of the image.  If I tried to
do the &lt;code&gt;docker run&lt;/code&gt; command on &lt;em&gt;another&lt;/em&gt; machine then it&amp;rsquo;d fail, because
it wouldn&amp;rsquo;t have a copy of &lt;code&gt;myimage&lt;/code&gt; (indeed, it&amp;rsquo;d try to reach out to
&lt;code&gt;docker.io&lt;/code&gt; to find a copy there).&lt;/p&gt;

&lt;p&gt;There are a few solutions to this; e.g. manually copy images around the
cluster, but they don&amp;rsquo;t really scale.  The correct solution is to run
a &lt;em&gt;registry&lt;/em&gt;, and configure your engines to talk to that.&lt;/p&gt;

&lt;p&gt;Docker provides a hosted registry at &lt;a href=&#34;https://hub.docker.com/&#34;&gt;Docker hub&lt;/a&gt;.
The free offering is suitable for public storage of images (you can
create one private repo, for free).  You can pay for additional private
repos, which can be configured to require authentication (a number of
vendors do this).  There is a freebie image that you can &lt;code&gt;pull&lt;/code&gt; and run
your own &lt;a href=&#34;https://docs.docker.com/registry/&#34;&gt;internal registry&lt;/a&gt;.  And
there are private registries (eg Docker Datacenter, or
VMware &lt;code&gt;harbor&lt;/code&gt;); some are commercial.   For an enterprise you should
look carefully at running your own private repo.  For this blog I&amp;rsquo;m
going to use the &lt;code&gt;sweh&lt;/code&gt; repo on Docker Hub.&lt;/p&gt;

&lt;h2 id=&#34;initializing-a-swarm&#34;&gt;Initializing a Swarm&lt;/h2&gt;

&lt;p&gt;Once you have your servers built and the Docker software installed and
configured (datastores, etc) then we can get started and build a swarm
out of it.&lt;/p&gt;

&lt;p&gt;On my network I have 4 VMs configured&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;docker-ce&lt;/li&gt;
&lt;li&gt;test1&lt;/li&gt;
&lt;li&gt;test2&lt;/li&gt;
&lt;li&gt;test3&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;(my hostnames are so imaginative!).  &lt;code&gt;docker-ce&lt;/code&gt; will be the manager node,
so we can initialize it.&lt;/p&gt;

&lt;p&gt;Before we do this, let&amp;rsquo;s quickly check the
state of the network.  It should match what we&amp;rsquo;ve seen before&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
20b900380c5e        bridge              bridge              local
9a4091b44793        host                host                local
5e9fc3c20b10        none                null                local

% brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.02420dfebfca       no

% ip -4 addr show dev docker0
3: docker0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc noqueue state DOWN
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we can start the swarm.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker swarm init
Swarm initialized: current node (f8t7omvmys6pa0nx66wpathuf) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-1234567890123456789069ugkou4sr7k476qlulvi9y3rkpsbt-9ynm7135rlebwycgqnlcap824 10.0.0.164:2377

To add a manager to this swarm, run &#39;docker swarm join-token manager&#39; and follow the instructions.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;rsquo;s it!  We now have a swarm!  A swarm of one node, but a swarm.&lt;/p&gt;

&lt;p&gt;What does the network look like, now?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
20b900380c5e        bridge              bridge              local
4c524f9b4565        docker_gwbridge     bridge              local
9a4091b44793        host                host                local
7yg0jizx89dt        ingress             overlay             swarm
5e9fc3c20b10        none                null                local

% brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.02420dfebfca       no
docker_gwbridge 8000.024293da454e       no              veth9368d19

% ip -4 addr show dev docker_gwbridge
8: docker_gwbridge: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP
    inet 172.18.0.1/16 scope global docker_gwbridge
       valid_lft forever preferred_lft forever
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So we can see there&amp;rsquo;s a new bridge network (&lt;code&gt;docker_gwbridge&lt;/code&gt;) and an
overlay network created.&lt;/p&gt;

&lt;p&gt;Now the &amp;ldquo;swarm token&amp;rdquo; presented should be kept secret; this is needed to
join another Docker node to the swarm.  If you don&amp;rsquo;t keep it secret than
anyone (who can reach the manager) can add their machine&amp;hellip; and potentially
get access to your programs or data.&lt;/p&gt;

&lt;p&gt;Fortunately you don&amp;rsquo;t need to &lt;em&gt;remember&lt;/em&gt; this or write it down; you can
ask Docker to repeat it&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker swarm join-token worker
To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-1234567890123456789069ugkou4sr7k476qlulvi9y3rkpsbt-9ynm7135rlebwycgqnlcap824 10.0.0.164:2377
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;workers-and-managers&#34;&gt;Workers and managers&lt;/h4&gt;

&lt;p&gt;There are two types of nodes in Swarm&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Workers&lt;br&gt;
A worker node is where the compute happens; when you tell Swarm to run
5 copies of your image then it will distribute the jobs across the
workers.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Managers&lt;br&gt;
A manager node is &lt;em&gt;also&lt;/em&gt; a worker node, so can run jobs.  But a manager
node is also used to manage the swarm.  You can (should!) have multiple
managers, for resiliency.  Now the managers communicate using the Raft consensus protocol.
This means that &lt;em&gt;over half&lt;/em&gt; of the managers need to agree on the state
of the swarm.  Typically that means you need an &lt;em&gt;odd&lt;/em&gt; number of managers.
With 3 managers you can suffer the loss of 1, and still keep running; with
5 managers you can lose 2; with 7 managers you can lose 3.. picking the
right number of managers is an availability question and may depend
on the underlying infrastructure &amp;ldquo;availability zones&amp;rdquo;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Side note; managers can be made to not be workers by setting their
worker availability to &amp;ldquo;drain&amp;rdquo; (&lt;code&gt;docker node update --availability
drain&lt;/code&gt;), which tells Swarm to remove any running
jobs and don&amp;rsquo;t schedule new ones.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;A worker can be promoted to a manager (&lt;code&gt;docker node promote&lt;/code&gt;), and a
manager can be demoted to a worker (&lt;code&gt;docker node demote&lt;/code&gt;).&lt;/p&gt;

&lt;h2 id=&#34;adding-workers&#34;&gt;Adding workers&lt;/h2&gt;

&lt;p&gt;You simply need to run the &lt;code&gt;docker swarm join&lt;/code&gt; command that was mentioned
when the swarm was initialized (and that &lt;code&gt;docker swarm join-token worker&lt;/code&gt;
reports).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker swarm join --token SWMTKN-1-1234567890123456789069ugkou4sr7k476qlulvi9y3rkpsbt-9ynm7135rlebwycgqnlcap824 10.0.0.164:2377
This node joined a swarm as a worker.
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;You can also join a node directly as a manager using the token returned by &lt;code&gt;docker swarm join-token manager&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now my swarm has some compute power!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker node ls
ID                            HOSTNAME               STATUS              AVAILABILITY        MANAGER STATUS
k4rec71pftizbzjfcmgio6cz5 *   docker-ce.spuddy.org   Ready               Active              Leader
vbhqixyoe8lcvotwav5dfhf7i     test2.spuddy.org       Ready               Active
wqg2tdlbfow7bftzu5sexz32g     test1.spuddy.org       Ready               Active
zqx3vkx0cdqswlq9q9xn91ype     test3.spuddy.org       Ready               Active
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;You might have noticed my prompt was &lt;code&gt;%&lt;/code&gt;; you don&amp;rsquo;t need to be &lt;code&gt;root&lt;/code&gt; to
do any of this if you are in the &lt;code&gt;docker&lt;/code&gt; group; membership of this group
is very powerful!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you look at a worker node network it also has the new
&lt;code&gt;docker_gwbridge&lt;/code&gt; and &lt;code&gt;ingress&lt;/code&gt; networks created.  But, importantly, the
ID of the &lt;code&gt;ingress&lt;/code&gt; network is consistent across all nodes.  This shows
it&amp;rsquo;s shared across the swarm, whereas the other networks are still local
to the node.  (Indeed &lt;code&gt;docker_gwbridge&lt;/code&gt; is &lt;code&gt;172.18.0.1/16&lt;/code&gt; on each node).&lt;/p&gt;

&lt;h2 id=&#34;first-service&#34;&gt;First service&lt;/h2&gt;

&lt;p&gt;Docker Swarm works on the concepts of &lt;em&gt;services&lt;/em&gt;.  These define the unit
to be deployed across the swarm.  It can be as simple as a single container,
or it could be a complicated setup similar to those described by &lt;code&gt;docker-compose&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s just start a copy of &lt;code&gt;centos&lt;/code&gt;, and just set it pinging localhost:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker service create --detach=true --replicas 1 --name pinger centos ping localhost
vfdxae3ck4r2xt5ig4fd7aqqv
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, that looks very similar to a &lt;code&gt;docker run&lt;/code&gt; command&amp;hellip;&lt;/p&gt;

&lt;p&gt;We can see the service state, and we can even see what server is running it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
vfdxae3ck4r2        pinger              replicated          1/1                 centos:latest

% docker service ps pinger
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE                ERROR               PORTS
xxn5tnej6bao        pinger.1            centos:latest       test1.spuddy.org    Running             Running 25 seconds ago
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;OK, so that&amp;rsquo;s running on &lt;code&gt;test1&lt;/code&gt;.  We can login to that machine and use
the &lt;code&gt;docker&lt;/code&gt; commands we know to look at this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% ssh test1 docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
3aac8b07c701        centos:latest       &amp;quot;ping localhost&amp;quot;    About a minute ago   Up About a minute                       pinger.1.xxn5tnej6bao96up565ak1xny

% ssh test1 docker logs pinger.1.xxn5tnej6bao96up565ak1xny | tail -3
64 bytes from localhost (127.0.0.1): icmp_seq=160 ttl=64 time=0.017 ms
64 bytes from localhost (127.0.0.1): icmp_seq=161 ttl=64 time=0.347 ms
64 bytes from localhost (127.0.0.1): icmp_seq=162 ttl=64 time=0.048 ms

% ssh test1 docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              &amp;lt;none&amp;gt;              36540f359ca3        10 days ago          193MB

% ssh test3 docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

%
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This should be a big clue that Swarm really just sits on top of the existing
docker constructs!  &lt;code&gt;test3&lt;/code&gt; doesn&amp;rsquo;t have the &lt;code&gt;centos&lt;/code&gt; image, because
it hasn&amp;rsquo;t needed to pull it, yet.&lt;/p&gt;

&lt;h2 id=&#34;re-scale&#34;&gt;Re-scale&lt;/h2&gt;

&lt;p&gt;One container is boring.  I want 3 of them!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker service scale pinger=3
pinger scaled to 3

% docker service ps pinger
ID                  NAME                IMAGE               NODE                   DESIRED STATE       CURRENT STATE              ERROR               PORTS
xxn5tnej6bao        pinger.1            centos:latest       test1.spuddy.org       Running             Running 4 minutes ago
dcmno194ymjf        pinger.3            centos:latest       test2.spuddy.org       Running             Preparing 14 seconds ago
g89lpi6xeuji        pinger.2            centos:latest       test3.spuddy.org       Running             Preparing 14 seconds ago

% ssh test3 docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              &amp;lt;none&amp;gt;              36540f359ca3        10 days ago          193MB
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can see state is &lt;code&gt;Preparing&lt;/code&gt;, which means it isn&amp;rsquo;t running yet.  Part of
this preparation is pulling down the image from the repository.  Once the
image is down then the container will start up.&lt;/p&gt;

&lt;p&gt;But finally:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker service ps pinger
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
xxn5tnej6bao        pinger.1            centos:latest       test1.spuddy.org    Running             Running 5 minutes ago
dcmno194ymjf        pinger.2            centos:latest       test2.spuddy.org    Running             Running 2 second ago
g89lpi6xeuji        pinger.3            centos:latest       test3.spuddy.org    Running             Running 2 second ago
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The service can be stopped with &lt;code&gt;docker service rm&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&#34;self-healing&#34;&gt;Self-healing&lt;/h2&gt;

&lt;p&gt;Let&amp;rsquo;s start again, and run 3 new copies of my service:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker service ps pinger
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
k9myef61ebqe        pinger.1            centos:latest       test3.spuddy.org    Running             Running 9 seconds ago
quelws25339z        pinger.2            centos:latest       test1.spuddy.org    Running             Running 9 seconds ago
r020adnj1nbd        pinger.3            centos:latest       test2.spuddy.org    Running             Running 9 seconds ago
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On &lt;code&gt;test1&lt;/code&gt; I&amp;rsquo;m going to kill the image:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% ssh test1 docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
e49af88bdfac        centos:latest       &amp;quot;ping localhost&amp;quot;    About a minute ago   Up 59 seconds                           pinger.2.quelws25339z0zkfxek89k5fa
% ssh test1 docker kill e49af88bdfac
e49af88bdfac
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We told the Swarm we wanted three replicas, so what did it do?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker service ps pinger
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE                ERROR                         PORTS
k9myef61ebqe        pinger.1            centos:latest       test3.spuddy.org    Running             Running about a minute ago
qul4kor2n9j1        pinger.2            centos:latest       test1.spuddy.org    Running             Running 18 seconds ago
quelws25339z         \_ pinger.2        centos:latest       test1.spuddy.org    Shutdown            Failed 24 seconds ago        &amp;quot;task: non-zero exit (137)&amp;quot;
r020adnj1nbd        pinger.3            centos:latest       test2.spuddy.org    Running             Running about a minute ago
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ha!  It noticed that one container (&lt;code&gt;pinger.2&lt;/code&gt;) had failed and brought up a new one to replace it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Docker Swarm maintains a history of terminated containers to assist in
diagnostics; by default this is something like 5 containers per replica,
but can be changed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let&amp;rsquo;s be a little more drastic; hard power down &lt;code&gt;test1&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker service ps pinger
ID                  NAME                IMAGE               NODE                   DESIRED STATE       CURRENT STATE                     ERROR                         PORTS
k9myef61ebqe        pinger.1            centos:latest       test3.spuddy.org       Running             Running 7 minutes ago
838i3nnx6ptj        pinger.2            centos:latest       docker-ce.spuddy.org   Running             Starting less than a second ago
qul4kor2n9j1         \_ pinger.2        centos:latest       test1.spuddy.org       Shutdown            Running 6 minutes ago
quelws25339z         \_ pinger.2        centos:latest       test1.spuddy.org       Shutdown            Failed 6 minutes ago              &amp;quot;task: non-zero exit (137)&amp;quot;
r020adnj1nbd        pinger.3            centos:latest       test2.spuddy.org       Running             Running 7 minutes ago
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In under a minute the Swarm detected the worker node had failed, and
restarted the required job on another node.&lt;/p&gt;

&lt;p&gt;This is a great way of doing HA; if you have multiple copies of your
service running (scale &amp;gt; 1) then you can handle single server failures
almost unnoticed!&lt;/p&gt;

&lt;p&gt;The Swarm also tells us the node isn&amp;rsquo;t available:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker node ls
ID                            HOSTNAME               STATUS              AVAILABILITY        MANAGER STATUS
k4rec71pftizbzjfcmgio6cz5 *   docker-ce.spuddy.org   Ready               Active              Leader
vbhqixyoe8lcvotwav5dfhf7i     test2.spuddy.org       Ready               Active
wqg2tdlbfow7bftzu5sexz32g     test1.spuddy.org       Down                Active
zqx3vkx0cdqswlq9q9xn91ype     test3.spuddy.org       Ready               Active
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;planned-outages&#34;&gt;Planned outages&lt;/h4&gt;

&lt;p&gt;If a server is planned to be taken down (e.g. for patching, rebooting) then
the work load can be drained off of it first, and the node made quiescent:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker service ps pinger
ID                  NAME                IMAGE               NODE                   DESIRED STATE       CURRENT STATE             ERROR               PORTS
vobdvumj1ve3        pinger.1            centos:latest       test3.spuddy.org       Running             Running 6 seconds ago
q1z3333fmcxa        pinger.2            centos:latest       docker-ce.spuddy.org   Running             Preparing 4 seconds ago
5ddwrc3dcuh8        pinger.3            centos:latest       test1.spuddy.org       Running             Running 1 second ago

% docker node update --availability drain docker-ce.spuddy.org
docker-ce.spuddy.org

% docker node ls
ID                            HOSTNAME               STATUS              AVAILABILITY        MANAGER STATUS
k4rec71pftizbzjfcmgio6cz5 *   docker-ce.spuddy.org   Ready               Drain               Leader
vbhqixyoe8lcvotwav5dfhf7i     test2.spuddy.org       Ready               Active
wqg2tdlbfow7bftzu5sexz32g     test1.spuddy.org       Ready               Active
zqx3vkx0cdqswlq9q9xn91ype     test3.spuddy.org       Ready               Active

% docker service ps pinger
ID                  NAME                IMAGE               NODE                   DESIRED STATE       CURRENT STATE            ERROR               PORTS
vobdvumj1ve3        pinger.1            centos:latest       test3.spuddy.org       Running             Running 47 seconds ago
3ww4npd4yc9g        pinger.2            centos:latest       test2.spuddy.org       Ready               Ready 9 seconds ago
q1z3333fmcxa         \_ pinger.2        centos:latest       docker-ce.spuddy.org   Shutdown            Running 9 seconds ago
5ddwrc3dcuh8        pinger.3            centos:latest       test1.spuddy.org       Running             Running 41 seconds ago
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can see the job that was on &lt;code&gt;docker-ce&lt;/code&gt; node has been shutdown and migrated
to &lt;code&gt;test2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Remember, this is a restart of the service, so &lt;em&gt;state&lt;/em&gt; internal to the
container is lost&amp;hellip; but you&amp;rsquo;re externalizing your state, aren&amp;rsquo;t you?&lt;/p&gt;

&lt;p&gt;After maintenance is complete, the node can be made available again:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker node update --availability active docker-ce.spuddy.org
docker-ce.spuddy.org
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;load-balancer&#34;&gt;Load balancer&lt;/h2&gt;

&lt;p&gt;Docker Swarm has a built in load balancer.  Let&amp;rsquo;s build a simple web server
that has a CGI which reports on the hostname.  I&amp;rsquo;m going to push this to
docker hub with the name &lt;code&gt;sweh/test&lt;/code&gt;.  Once it&amp;rsquo;s pushed I can delete the
local version (and the base image I built on)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker build -t test .
[...stuff happens...]
Successfully tagged test:latest

% docker tag test sweh/test

% docker push sweh/test
The push refers to a repository [docker.io/sweh/test]
[...stuff happens...]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let&amp;rsquo;s run 3 copies of this, exposing port 80.  Notice I&amp;rsquo;m referring to the
&lt;code&gt;docker.io&lt;/code&gt; container name, so each engine can pull from the repo.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker service create --detach=true --replicas 3 --publish 80:80 --name httpd sweh/test
0fsfgeylod67ff4iwx9uiu4i9

% docker service ps httpd
ID                  NAME                IMAGE               NODE                   DESIRED STATE       CURRENT STATE            ERROR               PORTS
v1uwsqfpho2c        httpd.1             sweh/test:latest    docker-ce.spuddy.org   Running             Running 32 seconds ago
40z9wjqhokwq        httpd.2             sweh/test:latest    test1.spuddy.org       Running             Running 9 seconds ago
jwnab0dz2d1s        httpd.3             sweh/test:latest    test2.spuddy.org       Running             Running 19 seconds ago
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;OK, so I exposed port 80&amp;hellip; but what IP address is the service on?  The
answer is &lt;em&gt;all IP addresses&lt;/em&gt; in the swarm.  Each node (even if it&amp;rsquo;s not
running the service) will listen on port 80 and direct the request to the
a running container.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% curl localhost/cgi-bin/t.cgi
Remote: 10.255.0.2
Hostname: baded58d0501
My Addresses:
    lo 127.0.0.1/8
  eth0 10.255.0.9/16 10.255.0.6/32
  eth1 172.18.0.3/16

% curl localhost/cgi-bin/t.cgi
Remote: 10.255.0.2
Hostname: 69b94822a2f4
My Addresses:
    lo 127.0.0.1/8
  eth0 10.255.0.7/16 10.255.0.6/32
  eth1 172.18.0.3/16

% curl test3/cgi-bin/t.cgi
Remote: 10.255.0.5
Hostname: baded58d0501
My Addresses:
    lo 127.0.0.1/8
  eth0 10.255.0.9/16 10.255.0.6/32
  eth1 172.18.0.3/16
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So two calls to &lt;code&gt;localhost&lt;/code&gt; hit different containers (different hostnames),
and hitting a node not running the service still worked.&lt;/p&gt;

&lt;p&gt;This makes it pretty easy to put a HA Proxy (or similar) instance in front
of your swarm; it doesn&amp;rsquo;t matter &lt;em&gt;where&lt;/em&gt; your container is running, the
combination of HA Proxy and Swarm load balancer means the request will
be forwarded.&lt;/p&gt;

&lt;p&gt;The underlying constructs used are very similar to those seen previously,
on a single node.  Some interesting IP addresses in there, which hint
at how Docker is doing this magic; note that the primary address on &lt;code&gt;eth0&lt;/code&gt;
is unique to the instance, but that a secondary address and the address
on &lt;code&gt;eth1&lt;/code&gt; is consistent.&lt;/p&gt;

&lt;p&gt;Now we know &lt;code&gt;eth1&lt;/code&gt; is on the &lt;code&gt;docker_gwbridge&lt;/code&gt; bridge local to each node.
But what is this &lt;code&gt;10.255.0.0/16&lt;/code&gt; network?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker network inspect --format=&#39;{{ .IPAM.Config }}&#39; ingress
[{10.255.0.0/16  10.255.0.1 map[]}]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ah ha!  It&amp;rsquo;s on the &lt;code&gt;ingress&lt;/code&gt; network that we&amp;rsquo;d previously seen flagged
consistently across the nodes.  Yet this doesn&amp;rsquo;t appear as a network
interface to the host.&lt;/p&gt;

&lt;p&gt;This &lt;code&gt;ingress&lt;/code&gt; network is the Swarm equivalent of &lt;code&gt;docker0&lt;/code&gt;, but using
the &lt;code&gt;overlay&lt;/code&gt; driver across the swarm.  If you look back at the example
web server output, you&amp;rsquo;ll see the &amp;ldquo;Remote&amp;rdquo; address was a 10.255.0.x
value; we&amp;rsquo;re seeing the load balancer at work on the ingress network.&lt;/p&gt;

&lt;h2 id=&#34;docker-swarm-and-docker-compose&#34;&gt;Docker Swarm and &lt;code&gt;docker-compose&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Swarm can not run &lt;code&gt;docker-compose&lt;/code&gt; directly.  If you try it&amp;rsquo;ll warn you
that you&amp;rsquo;re just running a single node service.  Your compose file &lt;em&gt;will&lt;/em&gt;
work, but just on the node you started it on; there&amp;rsquo;s no Swarm interaction.&lt;/p&gt;

&lt;p&gt;However, &lt;code&gt;docker stack&lt;/code&gt; can read a compose file and create a stack of
services out of it.&lt;/p&gt;

&lt;p&gt;There are limitations, of course, due to the distributed nature of the
run time.  A big one, for example, is that filesystem based volumes don&amp;rsquo;t
work so well (&lt;code&gt;/my/dir&lt;/code&gt; on the manager may not be present on all the
compute nodes!).  There are work-arounds (different volume drivers; NFS;&amp;hellip;)
but this complexity is inherent in a multi-server model.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&#34;https://www.sweharris.org/post/2017-07-02-dockerorch/&#34;&gt;earlier examples of docker-compose&lt;/a&gt; I
created a 3-tier architecture (web,app,DB).  Let&amp;rsquo;s see if we can do the
same with Swarm.  Now the DB is awkward; it needs access to specific
files, so let&amp;rsquo;s run that on a fixed node.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat deploy.yaml
version: &amp;quot;3&amp;quot;

networks:
  webapp:
  appdb:

volumes:
  db-data:

services:
  web:
    image: sweh/test
    networks:
      - webapp
    ports:
      - 80:80

  app:
    image: centos
    networks:
      - webapp
      - appdb
    entrypoint: /bin/sh
    stdin_open: true
    tty: true

  db:
    image: mysql:5.5
    networks:
      - appdb
    environment:
      - MYSQL_ROOT_PASSWORD=foobar
      - MYSQL_DATABASE=mydb1
    volumes:
      - db-data:/var/lib/mysql
    deploy:
      placement:
        constraints: [node.hostname == test1.spuddy.org]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;WARNING: This is a really bad setup.  &lt;code&gt;db-data&lt;/code&gt; is local to each node
and so there&amp;rsquo;s no data persistency if the database is allowed to bounce
around the swarm.  It&amp;rsquo;s why we only allow it to run on &lt;code&gt;test1&lt;/code&gt;.
Do not do this for any production setup (use a better network aware
volume setup!); I&amp;rsquo;m just showing it here for simplicity.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker stack deploy -c deploy.yaml 3tier
Creating network 3tier_appdb
Creating network 3tier_webapp
Creating service 3tier_db
Creating service 3tier_web
Creating service 3tier_app
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can see this looks very similar to the previous compose file.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker stack ls
NAME                SERVICES
3tier               3

% docker stack services 3tier
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
7f02afdt674n        3tier_app           replicated          1/1                 centos:latest
qj9ken7d69tq        3tier_web           replicated          1/1                 sweh/test:latest    *:80-&amp;gt;80/tcp
u97lwk6kc8cj        3tier_db            replicated          1/1                 mysql:5.5
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course a stack uses services, so everything we&amp;rsquo;ve seen still works&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker service ps 3tier
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
b0kk8dkq7n1i        3tier_app.1         centos:latest       test3.spuddy.org    Running             Running 47 seconds ago
a5wrrwjh07ni        3tier_web.1         sweh/test:latest    test2.spuddy.org    Running             Running 48 seconds ago
fs0owmxbm45h        3tier_db.1          mysql:5.5           test1.spuddy.org    Running             Running 28 seconds ago
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It should be no surprise to see the &lt;code&gt;mysql&lt;/code&gt; instance running on &lt;code&gt;test1&lt;/code&gt;!&lt;/p&gt;

&lt;h4 id=&#34;swarm-stack-networks&#34;&gt;Swarm stack networks&lt;/h4&gt;

&lt;p&gt;We can see the networking type stuff as well.  &lt;code&gt;test1&lt;/code&gt; only runs the db
layer, so&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% ssh test1 docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
1b5cs8cs2sf3        3tier_appdb         overlay             swarm
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(output edited to remove other networks we&amp;rsquo;ve already seen)&lt;/p&gt;

&lt;p&gt;Similarly, &lt;code&gt;test2&lt;/code&gt; only has the webapp network, but &lt;code&gt;test3&lt;/code&gt; runs
the app and so needs both networks:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% ssh test2 docker network ls | grep 3t
s6u8tobcz9rp        3tier_webapp        overlay             swarm

% ssh test3 docker network ls | grep 3t
1b5cs8cs2sf3        3tier_appdb         overlay             swarm
s6u8tobcz9rp        3tier_webapp        overlay             swarm
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again, these networks are overlay networks across the swarm, and they
match the bridges we saw for &lt;code&gt;docker-compose&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can inspect each service to see what IPs have been assigned:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker service inspect --format=&#39;{{ .Endpoint.VirtualIPs }}&#39; 3tier_web
[{7yg0jizx89dtc9t5kurmpxn95 10.255.0.6/16} {s6u8tobcz9rpcezii6gpuh6c6 10.0.1.2/24}]

% docker service inspect --format=&#39;{{ .Endpoint.VirtualIPs }}&#39; 3tier_app
[{1b5cs8cs2sf3zxjo9n40f7g80 10.0.0.4/24} {s6u8tobcz9rpcezii6gpuh6c6 10.0.1.4/24}]

% docker service inspect --format=&#39;{{ .Endpoint.VirtualIPs }}&#39; 3tier_db 
[{1b5cs8cs2sf3zxjo9n40f7g80 10.0.0.2/24}]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So the AppDB network is 10.0.0.0/24 and the WebApp network is 10.0.1.0/24.
Web also shows on the &lt;code&gt;ingress&lt;/code&gt; network because of the port forwarding.&lt;/p&gt;

&lt;p&gt;Name resolution works similarly to &lt;code&gt;docker-compse&lt;/code&gt;; e.g. from the web
instance:&lt;/p&gt;

&lt;p&gt;Now this seems to be hitting an issue on my setup; I use 10.0.0.0/24
for my main network (e.g. &lt;code&gt;test1&lt;/code&gt; is 10.0.0.158).  There seems to
be the occasional slowdown in resolving hostnames (e.g. &lt;code&gt;ping db&lt;/code&gt; may
take 5 seconds, but then it works).&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m wondering if the docker instance start to have trouble in routing
between the VXLAN and the primary network.  So let&amp;rsquo;s shut this
down (&lt;code&gt;docker stack rm 3tier&lt;/code&gt;) and modify our stack definition to
include network ranges:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;networks:
  webapp:
    ipam:
      config:
        - subnet: 10.20.1.0/24
  appdb:
    ipam:
      config:
        - subnet: 10.20.2.0/24
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now when we run the stack we can see the services work as we expect
and mirrors what we saw with &lt;code&gt;docker-compose&lt;/code&gt;; the web layer can not
see the db layer, but the app layer can see both.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;  web: eth0=10.20.1.3/24, 10.20.1.2/32   (webapp)
       eth1=172.18.0.3/16                (docker_gwbridge)
       eth2=10.255.0.7/16, 10.255.0.6/32 (ingress)

  app: eth0=10.20.2.3/24, 10.20.2.2/32   (appdb)
       eth1=172.18.0.3/16                (docker_gwbridge)
       eth2=10.20.1.5/24, 10.20.1.4/32   (webapp)

   db: eth0=10.20.2.5/24, 10.20.2.4/32   (appdb)
       eth1=172.18.0.3/16                (docker_gwbridge)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In all cases the default route is to 172.18.0.1 (i.e. the local bridge
on each node).&lt;/p&gt;

&lt;p&gt;e.g. on the app instance&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;default via 172.18.0.1 dev eth1
10.20.1.0/24 dev eth2  proto kernel  scope link  src 10.20.1.5
10.20.2.0/24 dev eth0  proto kernel  scope link  src 10.20.2.3
172.18.0.0/16 dev eth1  proto kernel  scope link  src 172.18.0.3
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Argh, this post has grown far too long.  I didn&amp;rsquo;t even talk about secrets
management&amp;hellip;&lt;/p&gt;

&lt;p&gt;Docker Swarm is a powerful extension of the standalone Docker Engine model
to a distributed resilient model; run your containers over multiple machines
and let Swarm handle the uptime.  With stacks it becomes relatively easy
to migrate from a one-node compose to a multi-node clustered setup.&lt;/p&gt;

&lt;p&gt;Of course there are complications; &lt;em&gt;resources&lt;/em&gt; (e.g. directories,
repositories) may not be consistent across the cluster.  This is inherent
complexity in a multi-service solution, and you&amp;rsquo;ll see similar constraints
on other orchestration systems (e.g. Kubernetes).  The closer your apps
are to &lt;a href=&#34;https://12factor.net&#34;&gt;12 Factor&lt;/a&gt; the easier it will be to run
in a swarm.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not sure why Swarm decided it was free to re-use my primary network
range; that definitely caused issues.  This probably only a problem
with the &lt;code&gt;stack&lt;/code&gt; command; if I had manually created networks and
attached services this wouldn&amp;rsquo;t have been a problem.  If you&amp;rsquo;ve seen
this issue then please let me know in the comments :-)&lt;/p&gt;

&lt;p&gt;Understanding Docker Swarm is important to understanding Docker Datacenter
(and Docker Enterprise Edition), since that uses Swarm as the underlying
technology.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Simple Docker Orchestration</title>
      <link>https://www.sweharris.org/post/2017-07-02-dockerorch/</link>
      <pubDate>Sun, 02 Jul 2017 20:27:15 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-07-02-dockerorch/</guid>
      <description>

&lt;p&gt;In earlier posts I looked at &lt;a href=&#34;https://www.sweharris.org/post/2017-06-18-buildcontainer&#34;&gt;what a Docker image looks like&lt;/a&gt;
and a dig into how it &lt;a href=&#34;https://www.sweharris.org/post/2017-06-24-dockerrun&#34;&gt;looks at runtime&lt;/a&gt;.  In this
entry I&amp;rsquo;m going to look at ways of running containers beyond a simple
&lt;code&gt;docker run&lt;/code&gt; command.&lt;/p&gt;

&lt;h2 id=&#34;docker-compose&#34;&gt;docker-compose&lt;/h2&gt;

&lt;p&gt;This is an additional program to be &lt;a href=&#34;https://docs.docker.com/compose/install/&#34;&gt;installed&lt;/a&gt;, but it&amp;rsquo;s very common in use.  Basically, it takes a YAML
configuration file.  This can describe networks, dependencies, scaling
factors, volumes etc etc.   Pretty much anything that can be done via
the CLI can be described with the compose YAML file.  The reason why
it is used is that it makes it very easy to describe a reasonably
complex run-time and have it all started with a single command.&lt;/p&gt;

&lt;h4 id=&#34;building-an-app-and-a-mysql-database&#34;&gt;Building an app and a MySQL database&lt;/h4&gt;

&lt;p&gt;A typical use case for &lt;code&gt;docker-compose&lt;/code&gt; could be to have an application
in one container and a database in another.  The application could talk
to the database and can be scaled independently of the database.&lt;/p&gt;

&lt;p&gt;In this example, we&amp;rsquo;ll just build a generic &lt;code&gt;centos&lt;/code&gt; container, rather
than an app; this will let us explore stuff.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat docker-compose.yaml
version: &#39;2&#39;
services:
  os:
    image: centos
    entrypoint: /bin/sh
    stdin_open: true
    tty: true

  db:
    image: mysql:5.5
    environment:
    - MYSQL_ROOT_PASSWORD=foobar
    - MYSQL_DATABASE=mydb1
    volumes:
    - /tmp/mysqldata:/var/lib/mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;rsquo;s that simple.  As with normal Docker, if the &lt;code&gt;mysql&lt;/code&gt; image isn&amp;rsquo;t present
then the daemon will download it automatically.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;This is bad practice, hard coding usernames and passwords into files,
so don&amp;rsquo;t do this in real life :-)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;What&amp;rsquo;s useful about this is that the containers are started on a private
network so the database can&amp;rsquo;t be reached from the outside world; only the
&amp;ldquo;app&amp;rdquo; can see the database.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s start it up!  I want two copies of the OS, and one database:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker-compose up --scale os=2
Creating network &amp;quot;compose_default&amp;quot; with the default driver
Creating compose_db_1 ...
Creating compose_db_1 ... done
Creating compose_os_1 ...
Creating compose_os_2 ...
Creating compose_os_1 ... done
Creating compose_os_2 ... done
Attaching to compose_db_1, compose_os_2, compose_os_1
db_1  | Initializing database
db_1  | 170602 16:56:52 [Note] Ignoring --secure-file-priv value as server is running with --bootstrap.
db_1  | 170602 16:56:52 [Note] /usr/local/mysql/bin/mysqld (mysqld 5.5.56) starting as process 64 ...
db_1  | 170602 16:56:52 [Note] Ignoring --secure-file-priv value as server is running with --bootstrap.
db_1  | 170602 16:56:52 [Note] /usr/local/mysql/bin/mysqld (mysqld 5.5.56) starting as process 70 ...
[ ... More MySQL startup messages ... ]
db_1  | 170602 16:56:58 [Note] mysqld: ready for connections.
db_1  | Version: &#39;5.5.56&#39;  socket: &#39;/tmp/mysql.sock&#39;  port: 3306  MySQL Community Server (GPL)
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;how-does-this-look-what-did-docker-compose-do&#34;&gt;How does this look? What did docker-compose do?&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;docker-compose&lt;/code&gt; created a new bridge (separate from &lt;code&gt;docker0&lt;/code&gt;),
and connected the three containers to it.  Notice that the name of the
containers match the entries from the YAML file, with a count.  There&amp;rsquo;s
a prefix of &amp;ldquo;compose&amp;rdquo;, which is the name of the current directory.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker-compose ps
    Name                 Command             State    Ports
-------------------------------------------------------------
compose_db_1   docker-entrypoint.sh mysqld   Up      3306/tcp
compose_os_1   /bin/sh                       Up
compose_os_2   /bin/sh                       Up

% brctl show
bridge name      bridge id               STP enabled     interfaces
br-3f3e56827113  8000.024265371f31       no              veth0e1b53a
                                                         veth55868a8
                                                         vethe42d74c

% docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
3f3e56827113        compose_default     bridge              local
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;( I edited the output a little, for readability; removed unnecessary
data!)&lt;/p&gt;

&lt;p&gt;Docker creates resolvable hostnames (internal DNS server) so that
each container can reach the other on known names:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker exec -it compose_os_1  /bin/sh
sh-4.2# getent hosts os
172.18.0.4      os
172.18.0.3      os

sh-4.2# getent hosts db
172.18.0.2      db

sh-4.2# getent hosts compose_os_2
172.18.0.3      compose_os_2

sh-4.2# ping db
PING db (172.18.0.2) 56(84) bytes of data.
64 bytes from compose_db_1.compose_default (172.18.0.2): icmp_seq=1 ttl=64 time=0.035 ms
64 bytes from compose_db_1.compose_default (172.18.0.2): icmp_seq=2 ttl=64 time=0.047 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since we have two &amp;ldquo;OS&amp;rdquo; containers, both of these can be resolved by
the &amp;ldquo;os&amp;rdquo; hostname (as shown by the &lt;code&gt;getent&lt;/code&gt; output).  We can also see that
each container can be directly named and that there&amp;rsquo;s an FQDN hiding
behind the scenes based on the prefix and the network bridge.&lt;/p&gt;

&lt;p&gt;This makes it easy to connect to the database:&lt;/p&gt;

&lt;p&gt;With the mysql client inside the OS we can then connect to the database:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sh-4.2# mysql -h db -u root --password=foobar mydb1
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.5.56 MySQL Community Server (GPL)

Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.

Type &#39;help;&#39; or &#39;\h&#39; for help. Type &#39;\c&#39; to clear the current input statement.

MySQL [mydb1]&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;a-three-tier-architecture&#34;&gt;A three tier architecture&lt;/h4&gt;

&lt;p&gt;We can take this model a step further and create a web/app/db type
of solution, purely out of &lt;code&gt;docker-compose&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;version: &#39;2&#39;
networks:
  webapp:
    driver: bridge
  appdb:
    driver: bridge

services:
  web:
    image: web-server
    networks:
      - webapp
    volumes:
    - /home/sweh/Docker-Tests/Web-Server/web_base:/var/www/html
    - /home/sweh/Docker-Tests/Web-Server/log:/var/log/httpd
    ports:
    - &amp;quot;80:80&amp;quot;

  app:
    image: centos
    networks:
      - webapp
      - appdb
    entrypoint: /bin/sh
    stdin_open: true
    tty: true

  db:
    image: mysql:5.5
    networks:
      - appdb
    environment:
    - MYSQL_ROOT_PASSWORD=foobar
    - MYSQL_DATABASE=mydb1
    volumes:
    - /tmp/mysqldata:/var/lib/mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This defines two bridges (&amp;ldquo;webapp&amp;rdquo; is for communication between the
web layer and the app layer; &amp;ldquo;appdb&amp;rdquo; is between the app and db), and
then places each container on the relevant bridges.  We only expose
port 80 to the main network, which means that only the web service can
be accessed from the outside.&lt;/p&gt;

&lt;p&gt;We can see the structures this builds (I ran it from a directory called
&lt;code&gt;Compose_3_Tier&lt;/code&gt; and so the prefix is &lt;code&gt;compose3tier&lt;/code&gt;).  Firstly
the networks.  By default they&amp;rsquo;re a /16 and assigned IP ranges automatically,
but this &lt;em&gt;can&lt;/em&gt; be overridden in the YAML file.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker network ls
NETWORK ID          NAME                  DRIVER              SCOPE
ad325365d45d        compose3tier_appdb    bridge              local
4d3f4c902ff2        compose3tier_webapp   bridge              local

% docker network inspect --format=&#39;{{ .IPAM.Config }}&#39; compose3tier_webapp
[{172.18.0.0/16  172.18.0.1 map[]}]

% docker network inspect --format=&#39;{{ .IPAM.Config }}&#39; compose3tier_appdb
[{172.19.0.0/16  172.19.0.1 map[]}]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can see that each container has been given IP addresses on the
relevant networks; the &amp;ldquo;app&amp;rdquo; container has two addresses, one for each
network:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker inspect compose3tier_web_1 | grep IPAdd.*172
                    &amp;quot;IPAddress&amp;quot;: &amp;quot;172.18.0.3&amp;quot;,
% docker inspect compose3tier_app_1 | grep IPAdd.*172
                    &amp;quot;IPAddress&amp;quot;: &amp;quot;172.19.0.2&amp;quot;,
                    &amp;quot;IPAddress&amp;quot;: &amp;quot;172.18.0.2&amp;quot;,
% docker inspect compose3tier_db_1 | grep IPAdd.*172
                    &amp;quot;IPAddress&amp;quot;: &amp;quot;172.19.0.3&amp;quot;,
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And we can see that the web layer can see the app layer, but can not see
the DB.  It can&amp;rsquo;t even resolve the db hostname!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker exec -it compose3tier_web_1 /bin/sh
sh-4.2# ping app
64 bytes from compose3tier_app_1.compose3tier_webapp (172.18.0.2): icmp_seq=1 ttl=64 time=0.069 ms

sh-4.2# ping db
ping: db: Name or service not known
sh-4.2# ping 172.19.0.3
PING 172.19.0.3 (172.19.0.3) 56(84) bytes of data.
^C
--- 172.19.0.3 ping statistics ---
6 packets transmitted, 0 received, 100% packet loss, time 4999ms
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course this isn&amp;rsquo;t a true 3-tier network; the DB layer is still NATted
to the main network and so can reach the outside world.  We&amp;rsquo;d need to be
a little more complicated with out set up.  And, of course, it doesn&amp;rsquo;t
have enterprise features (eg packet capture or flow logs between tiers).
But it shows us how a single host can use Docker to create a more secure
architecture than traditionally done.&lt;/p&gt;

&lt;h2 id=&#34;briefly-docker-swarm&#34;&gt;Briefly - docker swarm&lt;/h2&gt;

&lt;p&gt;This was originally an optional extra but (since Docker v1.12) it&amp;rsquo;s now
built in.  The idea, here, is to extend the &amp;lsquo;single host&amp;rsquo; model of
Docker and make it into a cluster.  You can add multiple hosts to the
&amp;ldquo;swarm&amp;rdquo; and Docker will build VXLAN overlay networks between them, much
in a similar way that the single host model builds bridges.  Containers
will be assigned addresses from the overlay network, which means that
containers in the same service can talk to each other, even if they&amp;rsquo;re
running on different machines.&lt;/p&gt;

&lt;p&gt;Swarm mode can also replace a lot of the functionality of &lt;code&gt;docker-compose&lt;/code&gt;,
although there are some complications due to the distributed nature of
the environment (in the earlier example I used local filesystems as volume
mounts&amp;hellip; that won&amp;rsquo;t necessarily work across 10 machines without NFS or
a different volume solution!)&lt;/p&gt;

&lt;p&gt;Naturally it handles scaling and instance recovery.&lt;/p&gt;

&lt;p&gt;Between managers (you can have multiple of them, as well) Docker uses
the Raft protocol for consensus.&lt;/p&gt;

&lt;p&gt;A feature (since v1.13) is present to handle &lt;em&gt;secrets&lt;/em&gt; (e.g. passwords,
SSL certs).  This data is stored &lt;em&gt;encrypted&lt;/em&gt; in the managers.  When a
container starts up that has been granted access to the secret then the
information can be read from &lt;code&gt;/run&lt;/code&gt; inside the container (an in-memory
filesystem).  This is the only place where the secret is unencrypted.
Unfortunately these secrets are static in nature; if you change them in
the swarm configuration (a complicated process) then the container needs
to restart to pick up the changes.  This can be done in a rolling nature
so it&amp;rsquo;s not quite as bad as it seems.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;I think a good use case for this may be to present an initial credential
to allow the container to login to a vault such as
&lt;a href=&#34;https://www.vaultproject.io&#34;&gt;HashiCorp vault&lt;/a&gt; where the real credential
can be stored and managed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;I&amp;rsquo;m likely to take a deeper look at swarm mode in a later blog entry
because it is built into the product and forms the foundation for
Docker Enterprise Edition.&lt;/p&gt;

&lt;h2 id=&#34;briefly-kubernetes&#34;&gt;Briefly - kubernetes&lt;/h2&gt;

&lt;p&gt;Kubernetes started as a Google project,
based on their internal container scheduler (&amp;ldquo;borg&amp;rdquo;).  The original
name was &amp;ldquo;Project Seven&amp;rdquo; (a Star Trek Voyager joke on
&lt;a href=&#34;https://en.wikipedia.org/wiki/Seven_of_Nine&#34;&gt;Seven of Nine&lt;/a&gt;; the logo
has seven spikes as a nod to this.  It need not be limited to just Docker;
other runtimes are available.  Docker is a very common scenario, though.&lt;/p&gt;

&lt;p&gt;Kubernetes takes a different approach to container application management.
Here we bundle a group of containers into a &lt;em&gt;pod&lt;/em&gt;.  This pod is the basic
unit of control in Kubernetes, and all the containers inside a pod
are co-located on a single host.  For resiliency and scalability you
deploy more pods across the cluster.&lt;/p&gt;

&lt;p&gt;Inside a pod all the containers share a single IP address (unique across
the cluster), just listening on different ports.  Additional resources
(e.g. disk volumes) can also be associated with the pods.  As with Docker
swarm, these resources need to be available across the cluster.&lt;/p&gt;

&lt;p&gt;Multi-tier applications can be defined as a &lt;em&gt;service&lt;/em&gt;, which consists of
a collection of pods.  Kubernetes provides discovery tools via DNS, and
can load balance across pods as necessary.&lt;/p&gt;

&lt;p&gt;Secrets management is basic, but has gained better &lt;a href=&#34;https://siliconangle.com/blog/2017/06/29/kubernetes-1-7-release-adds-extensibility-security-improvements/&#34;&gt;access controls in
v1.7&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&#34;briefly-mesos&#34;&gt;Briefly - Mesos&lt;/h2&gt;

&lt;p&gt;Originally from UCB, this is now an Apache sponsored project.  It takes
the approach of a &amp;ldquo;datacenter operating system&amp;rdquo; (DCOS).  Take the
concepts of a normal server (management of processes, memory, disk etc etc),
and now treat them as a single distributed entity across your datacenter.
Of course locality is important for performance, but this can parallel
cache coherency on a single machine.  You don&amp;rsquo;t normally care about what
CPU your program runs on; should you care what machine it runs on?  Let
the DCOS handle the hard bits :-)&lt;/p&gt;

&lt;p&gt;To this end it provides a number of services, such as &amp;ldquo;Chronos&amp;rdquo;; a cron
like program to schedule programs across the datacenter.&lt;/p&gt;

&lt;p&gt;Originally Mesos used its own container format, but since v0.20 it can
now be used to run Docker containers as well.&lt;/p&gt;

&lt;p&gt;A large component of Mesos is &amp;ldquo;Marathon&amp;rdquo;; this allows Mesos to be used
much like a PaaS (Platform as a Service).&lt;/p&gt;

&lt;p&gt;I haven&amp;rsquo;t really spent any real time looking into Mesos; I really only
mention it because large companies (Twitter, AirBnB, eBay&amp;hellip; even the CIA)
use it and it comes up in conversation.  I&amp;rsquo;m not sure I&amp;rsquo;d want to use this
as a general purpose scheduler, but if you have hyper-scale requirements
(thousands of servers) then it&amp;rsquo;s worth taking a look it.&lt;/p&gt;

&lt;h2 id=&#34;argl-too-many-options&#34;&gt;Argl, too many options!&lt;/h2&gt;

&lt;p&gt;&lt;center&gt;
&lt;img src=&#34;https://www.sweharris.org/images/docker-ecosystem.png&#34; alt=&#34;ecosystem&#34; /&gt;
(Source: Docker)
&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s a full time job just keeping up with this!  Which is why I&amp;rsquo;ve only
briefly covered some of the solutions, and may have missed something
really important and clever (or made mistakes).  I focused on &lt;code&gt;docker-compose&lt;/code&gt;
because it&amp;rsquo;s simple and powerful, and I&amp;rsquo;m going to write some more on
Swarm mode&amp;hellip; but I just don&amp;rsquo;t have time to run down every alley.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Docker has grown from a simple container execution engine into a complete
ecosystem of products and partner solutions; every day something new comes
along.  Even the existing stuff changes (eg the new Kubernetes secrets
management stuff had changed since I first drafted this out
a few weeks back).&lt;/p&gt;

&lt;p&gt;Docker also has a lot more complicated functions (security based around
SELinux, seccomp) and the ability to have containers &lt;em&gt;share&lt;/em&gt; address
spaces (for example, you could add a log management container alongside
another one, to forward the logs into Splunk).&lt;/p&gt;

&lt;p&gt;From an infrastructure perspective it helps to understand &lt;em&gt;how&lt;/em&gt; Docker
works (which was the driver for this series of blog posts), so that
you can understand the consequences of using Docker.  I&amp;rsquo;m a fan of
&amp;ldquo;knowledge in depth&amp;rdquo; :-)&lt;/p&gt;

&lt;p&gt;But, of course, infrastructure has no use if it&amp;rsquo;s not to run applications.
Docker can be used to create &lt;em&gt;more&lt;/em&gt; secure solutions (multi-tier in a
single host)&amp;hellip; but only if we manage it properly.  If developers
are allowed to put anything they like inside a container then we
can end up in a &lt;a href=&#34;https://www.sweharris.org/post/2016-04-02-container-security/&#34;&gt;Wild West&lt;/a&gt; scenario
and expose vulnerable code to external attackers.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Looking at how a Docker container runs</title>
      <link>https://www.sweharris.org/post/2017-06-24-dockerrun/</link>
      <pubDate>Sat, 24 Jun 2017 09:53:31 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-06-24-dockerrun/</guid>
      <description>

&lt;p&gt;In the &lt;a href=&#34;https://www.sweharris.org/post/2017-06-18-buildcontainer/&#34;&gt;previous entry&lt;/a&gt; we looked at
how a Docker container image is built.&lt;/p&gt;

&lt;p&gt;In this entry we&amp;rsquo;re going to look a little bit about how a container &lt;em&gt;runs&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s take another look at the container we built last time, running apache:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat Dockerfile
FROM centos

RUN yum -y update
RUN yum -y install httpd

CMD [&amp;quot;/usr/sbin/httpd&amp;quot;,&amp;quot;-DFOREGROUND&amp;quot;]

% docker build -t web-server .

% docker run --rm -d -p 80:80 -v $PWD/web_base:/var/www/html \
-v /tmp/weblogs:/var/log/httpd web-server
63250d9d48bb784ac59b39d5c0254337384ee67026f27b144e2717ae0fe3b57b

% docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
63250d9d48bb        web-server          &amp;quot;/usr/sbin/httpd -...&amp;quot;   2 minutes ago       Up 2 minutes        0.0.0.0:80-&amp;gt;80/tcp   modest_shirley
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So how does network traffic get into this container?  And what does
that &lt;code&gt;-p&lt;/code&gt; flag mean?&lt;/p&gt;

&lt;h2 id=&#34;basic-docker-networking&#34;&gt;Basic Docker networking&lt;/h2&gt;

&lt;p&gt;By default, Docker creates a bridge called &lt;code&gt;docker0&lt;/code&gt;.  This bridge
is not connected to the primary network, so there&amp;rsquo;s no communication
to containers on this bridge.  The bridge is associated with a private
network.&lt;/p&gt;

&lt;p&gt;When a container starts up, it is given a &lt;em&gt;virtual ethernet&lt;/em&gt; (veth)
device, that allows for IP communication between the host and the
container.  Inside the container it looks just like a normal network
device.&lt;/p&gt;

&lt;p&gt;This veth device is added to the bridge, and an IP address associated.&lt;/p&gt;

&lt;p&gt;With our test Apache container we can see how this looks:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.024234e17ca9       no              veth336564a

% ip -4 addr show dev docker0
3: docker0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever

%  docker inspect --format=&#39;{{ .NetworkSettings.IPAddress }}&#39; modest_shirley
172.17.0.2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So we can see our container&amp;rsquo;s &amp;ldquo;veth&amp;rdquo; device is on the bridge.  The bridge
itself has an IP address (172.17.0.1) on a /16 network (allowing for
65k addresses). Our container has an address 172.17.0.2 on this
network.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ve effectively created a private network, 172.17.0.0/16; the host
acts as the default gateway for the containers.&lt;/p&gt;

&lt;p&gt;Now, of course, the rest of your network (other hosts, etc) do not
know how to reach this private network, so a
set of &lt;code&gt;iptable&lt;/code&gt; rules are created so that outgoing
traffic from the container is &lt;em&gt;NAT&amp;rsquo;d&lt;/em&gt; to the host&amp;rsquo;s IP address.
In this way containers can reach &lt;em&gt;out&lt;/em&gt; to the main network.&lt;/p&gt;

&lt;p&gt;Incoming traffic needs to be port forwarded, and this is set up with
the &lt;code&gt;-p&lt;/code&gt; flag; you can specify a port on the host and the port on the
container it should move to.  So &lt;code&gt;-p 80:80&lt;/code&gt; means forward port 80 from
the host to port 80 inside the container.&lt;/p&gt;

&lt;p&gt;It gets a little messy handling traffic from the outside network to the
container, traffic between containers, and traffic from the container
to itself&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% ps -ef | grep docker-proxy
root     10054   760  0 10:18 ?        00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 -container-ip 172.17.0.2 -container-port 80

% sudo iptables -v -t nat -L POSTROUTING
Chain POSTROUTING (policy ACCEPT 11 packets, 754 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   78  4961 MASQUERADE  all  --  any    !docker0  172.17.0.0/16        anywhere            
    0     0 MASQUERADE  tcp  --  any    any     172.17.0.2           172.17.0.2           tcp dpt:http

% sudo iptables -v -t nat -L DOCKER     
Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 RETURN     all  --  docker0 any     anywhere             anywhere            
    0     0 DNAT       tcp  --  !docker0 any     anywhere             anywhere             tcp dpt:http to:172.17.0.2:80
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Exercise for those following on at home.  See what other rules are
in the complete &lt;code&gt;iptables&lt;/code&gt; output, including the main FORWARD chain&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is just the default; it can be changed!&lt;/p&gt;

&lt;h2 id=&#34;container-processes&#34;&gt;Container processes&lt;/h2&gt;

&lt;p&gt;With the &lt;code&gt;CMD&lt;/code&gt; entry we told the Docker daemon to start this container
by running the &lt;code&gt;httpd&lt;/code&gt; process.  We know Apache creates a number of
child processes.  We can see this, pretty easily:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker top modest_shirley
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                6458                6442                0                   14:08               ?                   00:00:00            /usr/sbin/httpd -DFOREGROUND
apache              6471                6458                0                   14:08               ?                   00:00:00            /usr/sbin/httpd -DFOREGROUND
apache              6472                6458                0                   14:08               ?                   00:00:00            /usr/sbin/httpd -DFOREGROUND
apache              6473                6458                0                   14:08               ?                   00:00:00            /usr/sbin/httpd -DFOREGROUND
apache              6474                6458                0                   14:08               ?                   00:00:00            /usr/sbin/httpd -DFOREGROUND
apache              6475                6458                0                   14:08               ?                   00:00:00            /usr/sbin/httpd -DFOREGROUND
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note the PIDs are those as seen from the host.  When we go inside the container,
later, we&amp;rsquo;ll see the PID numbers look different&lt;/p&gt;

&lt;h2 id=&#34;container-files&#34;&gt;Container files&lt;/h2&gt;

&lt;p&gt;The normal running of program like Apache causes temporary files to be generated
(eg the PID file, at the very least).  Your app may make use of &lt;code&gt;/tmp&lt;/code&gt;,
or &lt;code&gt;/run&lt;/code&gt; or other areas.&lt;/p&gt;

&lt;p&gt;By default Docker running containers are &lt;em&gt;transient&lt;/em&gt;; when you shut them
down the changes are lost.  But while they&amp;rsquo;re running we can see what
changes have been made:&lt;/p&gt;

&lt;p&gt;We can see what files have changed&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker diff modest_shirley
C /run
A /run/mount
A /run/mount/utab
C /run/httpd
A /run/httpd/httpd.pid
A /run/httpd/authdigest_shm.1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note the log files don&amp;rsquo;t show because they&amp;rsquo;re not part of the container image; they were written to a mounted volume (-v flag)&lt;/p&gt;

&lt;h2 id=&#34;going-inside-the-container&#34;&gt;Going inside the container&lt;/h2&gt;

&lt;p&gt;We&amp;rsquo;ve seen some ways of looking at a container from the outside, using
the &lt;code&gt;docker top&lt;/code&gt; and &lt;code&gt;docker diff&lt;/code&gt; commands.  But what does the container
look like from the inside?  We can use &lt;code&gt;docker exec&lt;/code&gt; to run a command.
(The details of how it works involve selecting the same namespaces for
your new container, but you can think of it as if you were running a new
process inside the container)&lt;/p&gt;

&lt;h4 id=&#34;the-filesystem-from-inside&#34;&gt;The filesystem from inside&lt;/h4&gt;

&lt;pre&gt;&lt;code&gt;% docker exec -it modest_shirley /bin/sh
sh-4.2# ls
anaconda-post.log  dev   lib         media  proc  sbin  tmp
bin                etc   lib64       mnt    root  srv   usr
boot               home  lost+found  opt    run   sys   var
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The filesystem looks like a normal CentOS one.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sh-4.2# df -h
Filesystem        Size  Used Avail Use% Mounted on
/dev/mapper/docker-252:1-131082-0940ddeec345786e6a77a45645d662721d239266ede70f2620b21d4abe11ad0d
                   10G  355M  9.7G   4% /
tmpfs             245M     0  245M   0% /dev
tmpfs             245M     0  245M   0% /sys/fs/cgroup
/dev/mapper/dockerce-fs                                                         
                  8.8G   23M  8.3G   1% /etc/hosts
shm                64M     0   64M   0% /dev/shm
/dev/vda3         3.0G  1.6G  1.3G  56% /var/log/httpd
tmpfs             245M     0  245M   0% /sys/firmware
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you look carefully, you can see some &amp;ldquo;data leakage&amp;rdquo;.  For example,
the &lt;code&gt;/var/log/httpd&lt;/code&gt; has exposed the filesystem mount point &lt;code&gt;/dev/vda3&lt;/code&gt;
(which is where &lt;code&gt;/tmp&lt;/code&gt; lives on my test machine).  The root disk is
showing how much space I allocated to the docker data volume.&lt;/p&gt;

&lt;p&gt;Other data may be exposed, eg via the &lt;code&gt;dmesg&lt;/code&gt; command&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sh-4.2# dmesg | grep Hypervisor
[    0.000000] Hypervisor detected: KVM
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can see that Docker, in its default setup, doesn&amp;rsquo;t hide so much of
the host machine as we might like!  That&amp;rsquo;s the consequence of a virtualised
OS, as opposed to virtualised hardware.&lt;/p&gt;

&lt;h4 id=&#34;processes-from-inside&#34;&gt;Processes from inside&lt;/h4&gt;

&lt;pre&gt;&lt;code&gt;sh-4.2# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 14:08 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache       5     1  0 14:08 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache       6     1  0 14:08 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache       7     1  0 14:08 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache       8     1  0 14:08 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache       9     1  0 14:08 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
root        27     0  1 14:22 ?        00:00:00 /bin/sh
root        31    27  0 14:22 ?        00:00:00 ps -ef
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note the PIDs; the container has its own PID namespace and so our first
Apache process now shows as PID 1.  Recall, from earlier, that it showed
as 6458 in the &lt;code&gt;docker top&lt;/code&gt; output.&lt;/p&gt;

&lt;h4 id=&#34;networking-from-inside&#34;&gt;Networking from inside&lt;/h4&gt;

&lt;p&gt;This image doesn&amp;rsquo;t have an &lt;code&gt;ip&lt;/code&gt; or &lt;code&gt;ifconfig&lt;/code&gt; command inside, but if it
did (or if we copied it in) then the output would look something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;4: eth0@if5: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP  link-netnsid 0
    inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Similarly the routing table would look like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         172.17.0.1      0.0.0.0         UG        0 0          0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U         0 0          0 eth0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So we can see it shows as a normal network interface, with a default route
to the bridge IP address.&lt;/p&gt;

&lt;h2 id=&#34;output-from-a-docker-container&#34;&gt;Output from a Docker container&lt;/h2&gt;

&lt;p&gt;A program may send output to stdout or stderr.  In a normal VM this might
be considered the equivalent of the console.  Docker allows us to inspect
this as well.  Let&amp;rsquo;s create a simple container that just writes out a line
once a minute&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/bin/sh
while [ 1 ]
do
  echo Hello, the time is `date`
  sleep 1
done
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let&amp;rsquo;s run this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker run --rm -d timeloop 
c03f1a63e4c7e55ab37c973a2fe231621340c48aae633865049f2588168b1c1e

% docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
c03f1a63e4c7        timeloop            &amp;quot;/hello&amp;quot;            7 seconds ago       Up 2 seconds                            eloquent_torvalds

% docker logs eloquent_torvalds
Hello, the time is Sat Jun 24 14:55:19 UTC 2017
Hello, the time is Sat Jun 24 14:55:20 UTC 2017
Hello, the time is Sat Jun 24 14:55:21 UTC 2017
Hello, the time is Sat Jun 24 14:55:22 UTC 2017
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Docker supports different logging modules; we can see what one the container is using:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker inspect -f &#39;{{.HostConfig.LogConfig.Type}}&#39; eloquent_torvalds
json-file
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is the default driver and has no default limits; can fill up the disk!&lt;/p&gt;

&lt;h2 id=&#34;being-nasty&#34;&gt;Being nasty&lt;/h2&gt;

&lt;p&gt;We&amp;rsquo;ve seen enough in this blog entry to see how we can be nasty.  If
you look closely, you&amp;rsquo;ll notice that we did &lt;code&gt;docker exec&lt;/code&gt; we were &lt;em&gt;root&lt;/em&gt;
inside the container.  We can abuse this!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sh-4.2# rpm -e passwd
sh-4.2# cat &amp;gt; /bin/passwd
echo Hahahahaha
sh-4.2# chmod 755 /bin/passwd
sh-4.2#
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;OK, that&amp;rsquo;s not much of an abuse, but it shows we can make changes.&lt;/p&gt;

&lt;p&gt;Fortunately we can detect this type of abuse:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker diff modest_shirley
C /root
A /root/.bash_history
[ ... ]
C /etc
C /etc/pam.d
D /etc/pam.d/passwd
C /var
C /var/lib
C /var/lib/rpm
[ ... ]
C /usr/bin
C /usr/bin/passwd
[ ... ]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we know what files should change (the &lt;code&gt;/tmp&lt;/code&gt; and &lt;code&gt;/run&lt;/code&gt; files?) then
we may be able to use this for intrusion detection (only if filesystem
artifacts are left behind) and File Integrity Monitoring (FIM).&lt;/p&gt;

&lt;h4 id=&#34;changes-are-transient&#34;&gt;Changes are transient&lt;/h4&gt;

&lt;p&gt;If we destroy and recreate this container then those changes are lost
and a &amp;ldquo;virgin&amp;rdquo; image is restarted.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker kill modest_shirley
modest_shirley

% docker run --rm -d -p 80:80 -v $PWD/web_base:/var/www/html -v /tmp/weblogs:/var/log/httpd web-server
2118033d42f2fe6bfe10861e838adb7a5df0c408431ba070d77ff6fa213ff45d

% docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
2118033d42f2        web-server          &amp;quot;/usr/sbin/httpd -...&amp;quot;   3 seconds ago       Up 3 seconds        0.0.0.0:80-&amp;gt;80/tcp   compassionate_liskov

% docker diff compassionate_liskov
C /run
C /run/httpd
A /run/httpd/authdigest_shm.1
A /run/httpd/httpd.pid
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is useful for recovering from a broken container, but it
loses a potentially useful audit trail (which could hamper incident response).&lt;/p&gt;

&lt;h4 id=&#34;keeping-changes-after-termination&#34;&gt;Keeping changes after termination&lt;/h4&gt;

&lt;p&gt;We can keep terminated containers by not using the &lt;code&gt;--rm&lt;/code&gt; flag, but this will start using up disk space.&lt;/p&gt;

&lt;p&gt;To demonstrate this I created a simple container that just creates three
files and terminates (by now you should be able to do this yourself, so
I won&amp;rsquo;t show the Dockerfile or script).&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ll run it &lt;em&gt;without&lt;/em&gt; the &lt;code&gt;--rm&lt;/code&gt; flag:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker image ls change
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
change              latest              7627c3a09d4e        30 minutes ago      124 MB

% docker run change

% docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The container doesn&amp;rsquo;t show in the &lt;code&gt;ps&lt;/code&gt; listing.  We need to use an
additional flag to show these terminated containers:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
b216fbcca2c0        change              &amp;quot;/hello&amp;quot;            7 seconds ago       Exited (0) 6 seconds ago                       naughty_sinoussi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There it is!&lt;/p&gt;

&lt;p&gt;Because the results have been kept around we can inspect it and even
pull the contents.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker diff naughty_sinoussi
C /tmp
A /tmp/testfile2
C /run
A /run/testfile3
A /testfile1

% docker cp naughty_sinoussi:/tmp/testfile2 - | tar tvf -
-rw-r--r-- 0/0              29 2017-06-09 14:40 testfile2

% docker cp naughty_sinoussi:/tmp/testfile2 - | tar xOf - testfile2
I am modifying a file in tmp
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;docker cp&lt;/code&gt; command is useful; it can be used to extract (or push!)
files and directories from a container.  The output is in a &lt;code&gt;tar&lt;/code&gt; format.
You can do this on running containers as well.&lt;/p&gt;

&lt;p&gt;Finally we can clear this up:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker rm naughty_sinoussi
naughty_sinoussi
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;disk-space-used&#34;&gt;Disk space used&lt;/h4&gt;

&lt;p&gt;Obviously keeping these changes (and &amp;ldquo;console&amp;rdquo; log output) around takes up
disk space.  But how much?&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s start with a clean system:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker info | grep Space.Used
 Data Space Used: 840.2 MB
 Metadata Space Used: 1.217 MB

% docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              10                  0                   660.8 MB            660.8 MB (100%)
Containers          0                   0                   0 B                 0 B
Local Volumes       0                   0                   0 B                 0 B
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now let&amp;rsquo;s run the &lt;code&gt;docker run change&lt;/code&gt; command 100 times (obviously
by cheating and run it in a loop).&lt;/p&gt;

&lt;p&gt;Now how much space is used?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; Data Space Used: 1.45 GB
 Metadata Space Used: 6.554 MB

Images              10                  1                   660.8 MB            660.8 MB (99%)
Containers          100                 0                   8.8 kB              8.8 kB (100%)
Local Volumes       0                   0                   0 B                 0 B
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now I know my script changes around 88 bytes of data inside the container.
The &lt;code&gt;df&lt;/code&gt; command only shows a 8.8K increase in size (which matches 88
bytes changed in 100 containers), but the &lt;code&gt;info&lt;/code&gt; command shows
usage has grown by over 600M&lt;/p&gt;

&lt;p&gt;Important note: The &lt;code&gt;df&lt;/code&gt; command is slow with so many terminated containers&lt;/p&gt;

&lt;p&gt;This gives us the ability to create a management process around running
containers.  For example we could start them up without the &lt;code&gt;--rm&lt;/code&gt; flag.
Periodically during the running we can check the &lt;code&gt;docker diff&lt;/code&gt; results
and if something looks bad we can alert the SOC.  Potentially terminate
the container.  Similarly on container termination we can check the &lt;code&gt;diff&lt;/code&gt;
results and if that looks clean then we can &lt;code&gt;rm&lt;/code&gt; the results to recover
disk space, or else retain it for forensic analysis.&lt;/p&gt;

&lt;h4 id=&#34;read-only-containers&#34;&gt;Read-only containers&lt;/h4&gt;

&lt;p&gt;There&amp;rsquo;s another way of running Docker that can help protect against
modification: use the &lt;code&gt;--read-only&lt;/code&gt; flag.  With this the whole filesystem
is made immutable.  Now your normal app requires some temporary space;
we can do this with &lt;code&gt;--tmpfs&lt;/code&gt;.  Annoyingly the permissions on &lt;code&gt;/run&lt;/code&gt; may
not be correct, so we can create a simple startup wrapper.&lt;/p&gt;

&lt;p&gt;Going back to our Apache example, we build it the same way but with a
startup wrapper instead&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat startup
#!/bin/sh
mkdir -m 0777 /run/httpd
exec /usr/sbin/httpd -DFOREGROUND

% cat Dockerfile
FROM centos
RUN  yum -y update
RUN  yum -y install httpd
ADD /startup /
CMD [&amp;quot;/startup&amp;quot;]

% docker build -t readonly-web .

% docker run -d --rm --read-only -p80:80 -v $PWD/web_base:/var/www/html:ro -v /tmp/weblogs:/var/log/httpd --tmpfs /run --tmpfs /tmp readonly-web
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note the &lt;code&gt;:ro&lt;/code&gt; on the &lt;code&gt;/var/www/html&lt;/code&gt; directory to make the html tree
also immutable, and &lt;code&gt;/run&lt;/code&gt; and &lt;code&gt;/tmp&lt;/code&gt; are set as tmpfs directories&lt;/p&gt;

&lt;p&gt;If we try to make changes inside the container it fails, but the web server can still write out its logs&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker exec -it f17484a0529f /bin/sh
sh-4.2# touch /foo
touch: cannot touch &#39;/foo&#39;: Read-only file system

sh-4.2# rpm -e passwd
error: can&#39;t create transaction lock on /var/lib/rpm/.rpm.lock (Read-only file system)

sh-4.2# touch /tmp/foo

sh-4.2# touch /var/www/html/bar
touch: cannot touch &#39;/var/www/html/bar&#39;: Read-only file system

sh-4.2# tail -1 /var/log/httpd/error_log
[Mon Jun 12 17:01:11.024721 2017] [core:notice] [pid 1] AH00094: Command line: &#39;/usr/sbin/httpd -D FOREGROUND&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A bit of a gotcha, here, is that &lt;code&gt;docker diff&lt;/code&gt; shows no files have changed, which may hide intrusion indicators!  We&amp;rsquo;ve been inside the container and
looked around, but no history file was generated.  This may be a small
price for preventing abuse in the first place.&lt;/p&gt;

&lt;h2 id=&#34;being-nasty-outside-the-container&#34;&gt;Being nasty &lt;em&gt;outside&lt;/em&gt; the container&lt;/h2&gt;

&lt;p&gt;We can take what we&amp;rsquo;ve learned and use that to break into the host.&lt;/p&gt;

&lt;p&gt;For example, we could map the root directory!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker run --rm -it -v /:/mnt centos /bin/sh
sh-4.2# cp /bin/id /mnt/tmp/badperson
sh-4.2# chmod 4711 /mnt/tmp/badperson
sh-4.2# exit
exit

% id
uid=500(sweh) gid=500(sweh) groups=500(sweh),499(docker)

% /tmp/badperson
uid=500(sweh) gid=500(sweh) euid=0(root) groups=500(sweh),499(docker)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note the &lt;code&gt;euid&lt;/code&gt; has changed.&lt;/p&gt;

&lt;p&gt;If you give a normal user permission to run the &lt;code&gt;docker&lt;/code&gt; command (which,
basically, means being in the &lt;code&gt;docker&lt;/code&gt; group) then they have effective root on the whole machine.&lt;/p&gt;

&lt;p&gt;SELinux can mitigate this, to some extent, by preventing the container
from having permissions to modify stuff.  Indeed, I had to &lt;em&gt;disable&lt;/em&gt;
SELinux to do this test.  These security features are there for a reason,
but sometimes they&amp;rsquo;re disabled.&lt;/p&gt;

&lt;p&gt;The best defense is to not allow people to be in the &lt;code&gt;docker&lt;/code&gt; group in
the first place!&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;In this blog entry we&amp;rsquo;ve looked at the running container:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Networking, Processes, file changes&lt;/li&gt;
&lt;li&gt;Container stdout/stderr logs&lt;/li&gt;
&lt;li&gt;Abusing docker privileges (root exploit!)

&lt;ul&gt;
&lt;li&gt;And how we can detect this&lt;/li&gt;
&lt;li&gt;Some protections we can do against this&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Docker also has a lot of advanced security functions (SELinux, AppArmour,
seccomp, capabilities) which can protect the system &lt;em&gt;and&lt;/em&gt; the application.
These are beyond the scope of this &amp;ldquo;basics&amp;rdquo; blog entry, but are definitely
something an enterprise user of Docker needs to be aware of.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What is a Docker container?</title>
      <link>https://www.sweharris.org/post/2017-06-18-buildcontainer/</link>
      <pubDate>Sun, 18 Jun 2017 16:23:36 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-06-18-buildcontainer/</guid>
      <description>

&lt;p&gt;Container technology, specifically Docker, is becoming an important
part of any enterprise.  Even if you don&amp;rsquo;t have development teams
targeting Docker you may have a vendor wanting to deliver their software
in container form.  I&amp;rsquo;m not so happy with that, but we&amp;rsquo;re going to have
to live with it.&lt;/p&gt;

&lt;p&gt;In order to properly control the risk around this I feel it helps to have
a feeling for the basics of what a Docker container is, and since I come
from a technical background I like to look at it from a technology driven
perspective.&lt;/p&gt;

&lt;p&gt;This is the first in a series of &amp;ldquo;Docker basics&amp;rdquo; that will try to explain
the what and the why&amp;rsquo;s of a Docker container.&lt;/p&gt;

&lt;h2 id=&#34;container-technology-is-a-form-of-os-virtualisation&#34;&gt;Container technology is a form of OS virtualisation&lt;/h2&gt;

&lt;p&gt;We&amp;rsquo;re used to virtualisation in the form of VMware or Xen or KVM (or
LDOMs on Solaris, or LPARs on AIX).&lt;/p&gt;

&lt;p&gt;Tools such as VMware ESX virtualize hardware&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&amp;ldquo;Here is a virtual Intel server&amp;rdquo;

&lt;ul&gt;
&lt;li&gt;One physical server, multiple virtual servers&lt;/li&gt;
&lt;li&gt;Each virtual server can be different, but needs to run on the Intel platform

&lt;ul&gt;
&lt;li&gt;Windows and Linux living together&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Can run most OS&amp;rsquo;s unchanged&lt;/li&gt;
&lt;li&gt;Can present &amp;ldquo;virtual&amp;rdquo; hardware (e.g. network, disk interfaces) that are optimized

&lt;ul&gt;
&lt;li&gt;May require special drivers in the guest&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the other hand, container technologies virtualize the OS&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&amp;ldquo;Here is a virtual Linux instance&amp;rdquo;

&lt;ul&gt;
&lt;li&gt;One Kernel, multiple OS userspaces&lt;/li&gt;
&lt;li&gt;Each OS userspace can be different, but needs to run on the Linux kernel

&lt;ul&gt;
&lt;li&gt;Debian and RedHat living together&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Can run everything from init/systemd down to a single process&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;docker-docker-docker-what-is-docker&#34;&gt;Docker, Docker, Docker.  What is Docker?&lt;/h2&gt;

&lt;p&gt;Docker can be thought of in a number of different ways&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A container run-time engine

&lt;ul&gt;
&lt;li&gt;Uses Linux kernel constructs

&lt;ul&gt;
&lt;li&gt;LXC&lt;/li&gt;
&lt;li&gt;Namespaces&lt;/li&gt;
&lt;li&gt;cgroups&lt;/li&gt;
&lt;li&gt;Networking&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;An application packaging format

&lt;ul&gt;
&lt;li&gt;Provides a standard way of deploying an application image

&lt;ul&gt;
&lt;li&gt;The &amp;ldquo;container&amp;rdquo; contains the code, dependencies, etc inside the image&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;A build engine

&lt;ul&gt;
&lt;li&gt;Provides a way of &lt;em&gt;creating&lt;/em&gt; the application image&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;An ecosystem

&lt;ul&gt;
&lt;li&gt;Repositories, tools, images, workflows&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;layers-upon-layers&#34;&gt;Layers upon layers&lt;/h2&gt;

&lt;p&gt;The Docker engine runs as a privileged process in user space, and so sits
on top of a running kernel.  This means it can run on a VM or on a bare
metal OS deployment.  Indeed both forms may exist at the same time.  In
a VM world the physical host may run both containerised and traditional
apps inside different VMs.
&lt;center&gt;
&lt;img src=&#34;https://www.sweharris.org/images/container-layer.png&#34; alt=&#34;layers&#34; /&gt;
(Image from &lt;a href=&#34;https://blog.docker.com/2016/04/containers-and-vms-together/&#34;&gt;https://blog.docker.com/2016/04/containers-and-vms-together/&lt;/a&gt; )
&lt;/center&gt;&lt;/p&gt;

&lt;h2 id=&#34;the-worlds-simplest-container&#34;&gt;The worlds simplest container&lt;/h2&gt;

&lt;p&gt;Let&amp;rsquo;s get down to basics and build our first container.  First a
simple &amp;ldquo;Hello world&amp;rdquo; program in C:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat hello.c
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;

int main(int argc,char *argv[])
{
  printf(&amp;quot;Hello, World\n&amp;quot;);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We compile it &lt;em&gt;static&lt;/em&gt; (which we&amp;rsquo;ll get to in a moment)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% gcc -static -o hello hello.c
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To build a Docker image we can use a Dockerfile, which contains the
instructions:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat Dockerfile
FROM scratch
COPY hello /
CMD [&amp;quot;/hello&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This file means&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&amp;ldquo;start from a blank (scratch) image&amp;rdquo;&lt;/li&gt;
&lt;li&gt;copy the file &amp;ldquo;hello&amp;rdquo; into the root directory of the container.&lt;/li&gt;
&lt;li&gt;When the container is started run the command &amp;ldquo;/hello&amp;rdquo;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We can now tell the system to build the container:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker build -t hello .
Sending build context to Docker daemon 852.5 kB
Step 1/3 : FROM scratch
 ---&amp;gt;
Step 2/3 : COPY hello /
 ---&amp;gt; ff932a2c2088
Removing intermediate container 60fa0962d256
Step 3/3 : CMD /hello
 ---&amp;gt; Running in a6375caaec44
 ---&amp;gt; 1cb4c0f3e212
Removing intermediate container a6375caaec44
Successfully built 1cb4c0f3e212
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;An important note, here, is that the &lt;em&gt;engine&lt;/em&gt; does the build (&amp;ldquo;Sending
build context to Docker daemon&amp;rdquo;).  Basically the command will tar up
the current directory, send that to the engine, the engine does all
the hard work and creates the image.  It is &lt;em&gt;not&lt;/em&gt; done in your
current shell.&lt;/p&gt;

&lt;p&gt;We can see the results, and run the container:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello               latest              1cb4c0f3e212        4 seconds ago       849 kB

% docker run --rm hello
Hello, World
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;--rm&lt;/code&gt; flag means &amp;ldquo;clean up after running&amp;rdquo;.  We&amp;rsquo;ll see more about this
in later blog entries.&lt;/p&gt;

&lt;h2 id=&#34;what-does-the-container-image-look-like&#34;&gt;What does the container image look like?&lt;/h2&gt;

&lt;p&gt;So now we&amp;rsquo;ve built this container, what does it look like?&lt;/p&gt;

&lt;p&gt;We can pull the container from the engine and look at it&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% mkdir /tmp/container
% cd /tmp/container
% docker save hello | tar xvf -
1cb4c0f3e212f5abfb4b0b74d36a6ace8b7fad164b3e460d8cbf7fb1c3905270.json
59aef640ce511eadb6169072a6d8cefd95a3d1b14b73b92bd86fcb7e0b67618e/
59aef640ce511eadb6169072a6d8cefd95a3d1b14b73b92bd86fcb7e0b67618e/VERSION
59aef640ce511eadb6169072a6d8cefd95a3d1b14b73b92bd86fcb7e0b67618e/json
59aef640ce511eadb6169072a6d8cefd95a3d1b14b73b92bd86fcb7e0b67618e/layer.tar
manifest.json
tar: manifest.json: implausibly old time stamp 1970-01-01 00:00:00
repositories
tar: repositories: implausibly old time stamp 1970-01-01 00:00:00
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The content is in the layer tar file&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% tar tf 59aef640ce511eadb6169072a6d8cefd95a3d1b14b73b92bd86fcb7e0b67618e/layer.tar
hello
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;rsquo;s basically just a tar ball with meta data!&lt;/p&gt;

&lt;h2 id=&#34;why-did-i-build-that-with-static&#34;&gt;Why did I build that with -static?&lt;/h2&gt;

&lt;p&gt;In the above example I used &lt;code&gt;-static&lt;/code&gt; while compiling.  Let&amp;rsquo;s see
what happens if I don&amp;rsquo;t do that.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% gcc -o hello hello.c

% docker build -t hello-dynamic .
Sending build context to Docker daemon 12.29 kB
Step 1/3 : FROM scratch
 ---&amp;gt;
Step 2/3 : COPY hello /
 ---&amp;gt; b94d1686eec2
Removing intermediate container f5fdec11138e
Step 3/3 : CMD /hello
 ---&amp;gt; Running in bc887d4cc424
 ---&amp;gt; 5f13658614ea
Removing intermediate container bc887d4cc424
Successfully built 5f13658614ea

% docker run --rm hello-dynamic
standard_init_linux.go:178: exec user process caused &amp;quot;no such file or directory&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&amp;ldquo;No such file or directory&amp;rdquo; isn&amp;rsquo;t a helpful error message, but experience
with older technologies (&lt;code&gt;chroot&lt;/code&gt; environments) reminds me that we need
to include all the libraries we need inside the image as well.  Remember,
a container needs to include all the dependencies it needs!&lt;/p&gt;

&lt;p&gt;OK, we can work out what is needed, and update our build and &lt;code&gt;Dockerfile&lt;/code&gt;
to include what is necessary:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% ldd hello
        linux-vdso.so.1 =&amp;gt;  (0x00007ffca81c9000)
        libc.so.6 =&amp;gt; /lib64/libc.so.6 (0x00007fa02da4d000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fa02de22000)

% mkdir lib64

% cp /lib64/libc.so.6 /lib64/ld-linux-x86-64.so.2 lib64

% cat Dockerfile
FROM scratch
COPY hello /
COPY lib64/ /lib64/
CMD [&amp;quot;/hello&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you ever built an &amp;ldquo;anonymous FTP&amp;rdquo; chroot then this would feel familiar; all library dependencies need to be inside the container image.&lt;/p&gt;

&lt;p&gt;This time the container runs:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker build -t hello-dynamic .
Sending build context to Docker daemon 2.288 MB
Step 1/4 : FROM scratch
 ---&amp;gt;
Step 2/4 : COPY hello /
 ---&amp;gt; Using cache
 ---&amp;gt; b94d1686eec2
Step 3/4 : COPY lib64/ /lib64/
 ---&amp;gt; 280171c871b9
Removing intermediate container 3872e77dd215
Step 4/4 : CMD /hello
 ---&amp;gt; Running in fe399496bd09
 ---&amp;gt; 6d706ccc02fc
Removing intermediate container fe399496bd09
Successfully built 6d706ccc02fc

% docker run --rm hello-dynamic
Hello, World
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;what-does-this-new-container-look-like&#34;&gt;What does this new container look like?&lt;/h2&gt;

&lt;p&gt;We&amp;rsquo;d expect to see the 3 files inside the layer file.  Let&amp;rsquo;s look:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% mkdir /tmp/container
% cd /tmp/container
% docker save hello-dynamic | tar xvf -
10e6ef63539659eef459b5b0795ad1d91e44b4d3d6b5cf369f026cabbef333f4/
10e6ef63539659eef459b5b0795ad1d91e44b4d3d6b5cf369f026cabbef333f4/VERSION
10e6ef63539659eef459b5b0795ad1d91e44b4d3d6b5cf369f026cabbef333f4/json
10e6ef63539659eef459b5b0795ad1d91e44b4d3d6b5cf369f026cabbef333f4/layer.tar
1f5263a466b60441b1569ae0bf6d059f6a866d721bde8c8e795313116400fb4f/
1f5263a466b60441b1569ae0bf6d059f6a866d721bde8c8e795313116400fb4f/VERSION
1f5263a466b60441b1569ae0bf6d059f6a866d721bde8c8e795313116400fb4f/json
1f5263a466b60441b1569ae0bf6d059f6a866d721bde8c8e795313116400fb4f/layer.tar
6d706ccc02fc6c6ead9b6913b8bd21f15a34abcb09b5deb8e5407af5f4203f14.json
manifest.json
tar: manifest.json: implausibly old time stamp 1970-01-01 00:00:00
repositories
tar: repositories: implausibly old time stamp 1970-01-01 00:00:00
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Oh, hey, multiple layers!  Let&amp;rsquo;s look inside each layer:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% tar tf 10e6ef63539659eef459b5b0795ad1d91e44b4d3d6b5cf369f026cabbef333f4/layer.tar
hello

% tar tf 1f5263a466b60441b1569ae0bf6d059f6a866d721bde8c8e795313116400fb4f/layer.tar
lib64/
lib64/ld-linux-x86-64.so.2
lib64/libc.so.6
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So each COPY command created a new layer to the Docker image, which show up in the manifest file&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% jq &#39;.[] | [ .Layers ]&#39; &amp;lt; manifest.json
[
  [
    &amp;quot;10e6ef63539659eef459b5b0795ad1d91e44b4d3d6b5cf369f026cabbef333f4/layer.tar&amp;quot;,
    &amp;quot;1f5263a466b60441b1569ae0bf6d059f6a866d721bde8c8e795313116400fb4f/layer.tar&amp;quot;
  ]
]
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;this-is-hard-work-what-if-i-wanted-perl-or-php-or&#34;&gt;This is hard work!  What if I wanted perl or php or&amp;hellip;?&lt;/h2&gt;

&lt;p&gt;This working out of dependencies isn&amp;rsquo;t a good solution.  Each library may
have its own set of dependencies, and libraries that are optionally loaded
at run time (e.g. name resolver libraries) won&amp;rsquo;t get found.  So, instead
of starting from &lt;code&gt;scratch&lt;/code&gt; we can bring in a base OS image instead:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat Dockerfile
FROM debian:latest
COPY hello /
CMD [&amp;quot;/hello&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;FROM debian:latest&lt;/code&gt; line tells the engine to use an image of that
name as the base layer.  If the engine doesn&amp;rsquo;t know about this then
it will reach out to a &lt;em&gt;repository&lt;/em&gt; to find and pull the image (default:
docker.io).  This is done by the engine and the engine &lt;em&gt;can&lt;/em&gt; be configured
to use HTTP proxies (if necessary).  So if you don&amp;rsquo;t explicitly block
stuff then any developer can pull almost anything in.&lt;/p&gt;

&lt;p&gt;This layer now becomes the base on which our code gets copied.  The
build now runs pretty much as expected; we can see the engine doing
the &lt;code&gt;pull&lt;/code&gt; to get the necessary image.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker build -t hello-debian .
Sending build context to Docker daemon 12.29 kB
Step 1/3 : FROM debian:latest
latest: Pulling from library/debian
10a267c67f42: Pull complete
Digest: sha256:476959f29a17423a24a17716e058352ff6fbf13d8389e4a561c8ccc758245937
Status: Downloaded newer image for debian:latest
 ---&amp;gt; 3e83c23dba6a
Step 2/3 : COPY hello /
 ---&amp;gt; c76829938202
Removing intermediate container 78158e94a68c
Step 3/3 : CMD /hello
 ---&amp;gt; Running in 83c90a1cb1d8
 ---&amp;gt; 740546dadcc9
Removing intermediate container 83c90a1cb1d8
Successfully built 740546dadcc9

% docker run --rm hello-debian
Hello, World
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;size-and-complexity&#34;&gt;Size and complexity&lt;/h2&gt;

&lt;p&gt;This convenience doesn&amp;rsquo;t come for free, of course!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-debian        latest              740546dadcc9        3 minutes ago       124 MB
hello-dynamic       latest              6d706ccc02fc        17 hours ago        2.28 MB
hello               latest              1cb4c0f3e212        17 hours ago        849 kB
debian              latest              3e83c23dba6a        3 weeks ago         124 MB
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Our &amp;ldquo;Hello, World&amp;rdquo; application has grown from 849 Kbytes to a whopping 124Mbytes.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker save hello-debian | tar xf -
tar: manifest.json: implausibly old time stamp 1970-01-01 00:00:00
tar: repositories: implausibly old time stamp 1970-01-01 00:00:00

% for a in */layer.tar; do print -n &amp;quot;$a: &amp;quot; ; tar tf $a | wc -l ; done
7a83b1430fe3eaed26ecd9b011dcd885c6f04e45bee3205734fea8ce7382a01e/layer.tar: 1
a1ae6cd0978a7d90aea036f11679f31e1a3142b1f40030fb80d4c8748b0a6a01/layer.tar: 8259
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;rsquo;s also grown from 1 file to 8,260 files.&lt;/p&gt;

&lt;p&gt;But we no longer need to track dependencies.  Is this a win?  Well, from
a developer&amp;rsquo;s pespective, it most definitely is.&lt;/p&gt;

&lt;h2 id=&#34;security-concerns&#34;&gt;Security concerns&lt;/h2&gt;

&lt;p&gt;From a security perspective though&amp;hellip;  your application image now has a
complete(ish) copy of Debian inside it.  This is &lt;em&gt;hidden&lt;/em&gt; from your
traditional infrastructure operations team.  It may not even use a standard
OS used by your organisation!   If there&amp;rsquo;s a patch in the OS
layer then the &lt;em&gt;application&lt;/em&gt; team are now responsible for patching and
deploying the fixed containers.&lt;/p&gt;

&lt;p&gt;Will they be tracking these vulnerabilities?  How quickly would they
have fixed shellshock?  Or (in more advanced cases) Apache Struts?&lt;/p&gt;

&lt;h2 id=&#34;advanced-builds&#34;&gt;Advanced builds&lt;/h2&gt;

&lt;p&gt;If we&amp;rsquo;re pulling in upstream images we can use their packages as well&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat Dockerfile
FROM centos

RUN yum -y update
RUN yum -y install httpd

CMD [&amp;quot;/usr/sbin/httpd&amp;quot;,&amp;quot;-DFOREGROUND&amp;quot;]

% docker build -t web-server .
...[stuff happens]...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The RUN command can run any shell script, and creates a new layer.  In
this case I created two layers (one for &lt;code&gt;yum update&lt;/code&gt; and one for
&lt;code&gt;yum install&lt;/code&gt;).  I could have done a more complicated script such as
&lt;code&gt;yum update &amp;amp;&amp;amp; yum install&lt;/code&gt; and only created one layer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Exercise for those following at home: Extract the image (&lt;code&gt;docker save&lt;/code&gt;)
and look at the layers created.  Note that data in &lt;code&gt;/var/lib/yum&lt;/code&gt; and &lt;code&gt;/var/lib/rpm&lt;/code&gt; has also changed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;But we now have a web server!  Let&amp;rsquo;s give it a file to serve:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat web_base/index.html
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;Test&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
This is a test
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;

% docker run --rm -d -p 80:80 -v $PWD/web_base:/var/www/html \
-v /tmp/weblogs:/var/log/httpd web-server
63250d9d48bb784ac59b39d5c0254337384ee67026f27b144e2717ae0fe3b57b
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;-v&lt;/code&gt; flag maps the local directory to a volume inside the container.  In this case we mapped the HTML directory and the apache log directory&lt;/p&gt;

&lt;p&gt;This is one way we can pass configuration to a container and get log information out of a container&lt;/p&gt;

&lt;p&gt;Notice we didn&amp;rsquo;t write any special code!  This is standard apache running in a container&lt;/p&gt;

&lt;p&gt;And it works!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
63250d9d48bb        web-server          &amp;quot;/usr/sbin/httpd -...&amp;quot;   2 minutes ago       Up 2 minutes        0.0.0.0:80-&amp;gt;80/tcp   modest_shirley

% curl http://localhost
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;Test&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
This is a test
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;

% cat /tmp/weblogs/access_log
172.17.0.1 - - [18/Jun/2017:14:08:59 +0000] &amp;quot;GET / HTTP/1.1&amp;quot; 200 63 &amp;quot;-&amp;quot; &amp;quot;curl/7.29.0&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the &lt;code&gt;ps&lt;/code&gt; command we can see the port mapping.&lt;/p&gt;

&lt;p&gt;The name is randomly generated, but can be set by the &lt;code&gt;docker run&lt;/code&gt; comamnd line&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;In this blog we&amp;rsquo;ve taken a basic look at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Docker engine&lt;/li&gt;
&lt;li&gt;How to build a simple container

&lt;ul&gt;
&lt;li&gt;What the container looks like&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Library dependencies

&lt;ul&gt;
&lt;li&gt;Layers&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Pulling in external images&lt;/li&gt;
&lt;li&gt;Running almost anything at build time (&amp;ldquo;yum&amp;rdquo;)&lt;/li&gt;
&lt;li&gt;Mapping local directories into the container

&lt;ul&gt;
&lt;li&gt;Configuration files, log files&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We&amp;rsquo;ve also seen some security concerns around developers being able
to pull random files from anywhere into these containers, and it being
an opaque box to infrastructure operate.&lt;/p&gt;

&lt;p&gt;We can start to see some of the risks in running Docker instances.  These
also apply to vendor provided containers, and for similar reasons.  The
vendor becomes responsible for patching the contents of the container,
which &lt;em&gt;should&lt;/em&gt; mean more frequent releases (they not only need to fix
their application, they also need to fix the OS).  Do they?  Will your
teams have the time needed to run these new containers through test/qa/prod
release cycles?&lt;/p&gt;

&lt;p&gt;In later blog entries I&amp;rsquo;ll start to look inside a running container
and look at some ways we can detect intrusion and protect against it.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Introduction to web SSL certificates</title>
      <link>https://www.sweharris.org/post/2017-06-11-webcerts/</link>
      <pubDate>Sun, 11 Jun 2017 16:29:07 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-06-11-webcerts/</guid>
      <description>

&lt;p&gt;Last year I wrote about &lt;a href=&#34;https://www.sweharris.org/post/2016-12-04-letsencrypt/&#34;&gt;how I used Letsencrypt&lt;/a&gt;
to handle the SSL certificates for this site.  In this entry I&amp;rsquo;m going to
take a step back and discuss the basics of what an SSL certificate is and
the steps involved in managing them.  There&amp;rsquo;s a lot of jargon involved,
which can make this seem more complicated than it already is.&lt;/p&gt;

&lt;p&gt;Note that in this post I&amp;rsquo;m likely to use the words &amp;ldquo;SSL&amp;rdquo; and &amp;ldquo;TLS&amp;rdquo;
interchangeably.  TLS is the successor to SSL (in some respects you can
think of TLS1 as SSL4) and many of the same things apply.  The basics of
certificates are the same.  I started playing with SSL over 20 years ago,
and tend to use that term (even when I &lt;em&gt;should&lt;/em&gt; really use TLS).&lt;/p&gt;

&lt;p&gt;Note also you may see the phrase &amp;ldquo;X509 certificate&amp;rdquo; used in some
places.  The &lt;em&gt;format&lt;/em&gt; typically used to manage SSL certificates is
X509; you may say that an SSL cert is an X509 cert with the
&amp;ldquo;server authentication&amp;rdquo; attribute.  X509 certs may also be used elsewhere
(e.g. for code signing), but if you&amp;rsquo;re reading some SSL tutorial and
it tells you to do stuff with the X509 file then we&amp;rsquo;re talking about
the same thing.&lt;/p&gt;

&lt;p&gt;SSL certs can be present in various services (e.g. SMTPS, IMAPS, NNTPS)
but the most common use case most people see are for HTTPS (encrypted web
sites, like this one).  I&amp;rsquo;ll describe things in those terms, but the same
concepts apply.&lt;/p&gt;

&lt;h2 id=&#34;what-is-an-ssl-certificate-used-for&#34;&gt;What is an SSL certificate used for&lt;/h2&gt;

&lt;p&gt;An SSL cert does two things for you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identify the server&lt;/li&gt;
&lt;li&gt;Provides a means of performing public key encryption with the server&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So what this means is that when you go to &lt;a href=&#34;https://www.sweharris.org&#34;&gt;this site&lt;/a&gt;
your browser will be told &amp;ldquo;Hi, I&amp;rsquo;m www.sweharris.org!&amp;rdquo;, and will be given
a way of &lt;em&gt;verifying&lt;/em&gt; that the certificate is not lying to you.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s important to note that the certificate doesn&amp;rsquo;t tell you who runs the
site but we&amp;rsquo;ll see, later, how this can be handled.&lt;/p&gt;

&lt;h2 id=&#34;how-is-it-generated&#34;&gt;How is it generated&lt;/h2&gt;

&lt;p&gt;Modern tools such as &lt;a href=&#34;https://www.letsencrypt.org&#34;&gt;Letsencrypt&lt;/a&gt; can hide
all this from you, but it may be useful to know the underlying basics.&lt;/p&gt;

&lt;p&gt;We start off by generating a public/private key pair.  Typically, today,
this would be an RSA 2048 or 4096 bit key.  As with all public
key systems the &lt;em&gt;private&lt;/em&gt; key is the important part and should be kept
protected.&lt;/p&gt;

&lt;p&gt;We then create a &lt;em&gt;Certificate Signing Request&lt;/em&gt; (CSR).  This contains
the &lt;em&gt;public&lt;/em&gt; part of the key pair, along with some information about
the site.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;em&gt;common name&lt;/em&gt; (CN) of the site  (stored in the Subject field)&lt;/li&gt;
&lt;li&gt;Other names the website may use (Subject Alternate Names - SAN)&lt;/li&gt;
&lt;li&gt;(Optionally) other information such as the city/state/country or the name of the site owner (also stored in the Subject field)&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;signature&lt;/em&gt; for the request (typically SHA256 based).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, for example, this web site has&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    Public Key: (4096 bit RSA key)
       Subject: CN=www.sweharris.org
           SAN: DNS:www.sweharris.org, DNS: sweharris.org
     Signature: (SHA256 sig)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The certificate for &lt;code&gt;www.google.com&lt;/code&gt; has:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    Public Key: (2048 bit RSA key)
       Subject: C=US, ST=California, L=Mountain View, O=Google Inc, CN=www.google.com  
           SAN: DNS:www.google.com
     Signature: (SHA256 sig)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Other fields can be added to this request, but these are the minimum.&lt;/p&gt;

&lt;p&gt;This CSR is then sent to the &lt;em&gt;Certificate Authority&lt;/em&gt; (CA) for signing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;NOTE: As you can see, the CN field isn&amp;rsquo;t too well defined, whereas the
SAN field is better organised.  Recent versions of Chrome have started
to &lt;em&gt;require&lt;/em&gt; SAN entries and will only use those to validate the site.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;what-is-certificate-signing&#34;&gt;What is certificate signing&lt;/h2&gt;

&lt;p&gt;Once the CA receives the CSR it needs to validate the request is correct
(am I allowed to request a certificate for www.sweharris.org, or is this
a naughty person trying to pretend to be me).&lt;/p&gt;

&lt;p&gt;Once the CA is happy the request it takes the CSR adds various fields
(most importantly a serial number, a start/end date, its own Issuer field,
and for what purpose the certificate can be used for).  The result is
then cryptographically signed (basically a hash is taken of the data,
and encrypted with the CA&amp;rsquo;s own private key).  The result is returned
to the requester and is the certificate to be used.&lt;/p&gt;

&lt;p&gt;There are two common types of validation:&lt;/p&gt;

&lt;h3 id=&#34;domain-validation-dv&#34;&gt;Domain validation (DV)&lt;/h3&gt;

&lt;p&gt;This is the simplest and most basic form of checking.  Basically the CA
tries to verify the requester has some form of control over the domain.
This may be something like&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Put a file on the webserver at /my/check.html containing the string &amp;ldquo;wowzer&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Edit your DNS so you have a TXT record &amp;ldquo;check_this&amp;rdquo; with the string &amp;ldquo;foobar&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Read the email sent to webmaster and click on the link in it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It&amp;rsquo;s important to note that this doesn&amp;rsquo;t ask anything about the organisation
behind the request, just whether it has some control over the domain.  A
phishing organisation could register the DNS name sweharr1s.org and
request a cert for that.&lt;/p&gt;

&lt;p&gt;A DV site typically shows up in browsers with a green padlock, but not
much else.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;
&lt;img src=&#34;https://www.sweharris.org/images/sweharris_cert_header.png&#34; alt=&#34;mysite&#34; /&gt;
&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;The advantage of DV certificates is that the creation and signing can
be done very cheaply, or even automatically (which is how Letsencrypt
works).&lt;/p&gt;

&lt;h3 id=&#34;extended-validation-ev&#34;&gt;Extended validation (EV)&lt;/h3&gt;

&lt;p&gt;EV certs take a deeper approach to validating the request; the CA also
check the &lt;em&gt;owner&lt;/em&gt; claims.  So, for example, I might be able to get a DV
cert for &lt;code&gt;chas3.com&lt;/code&gt;, but I would not be able to get an EV cert saying
&amp;ldquo;this is owned by JPMorgan Chase&amp;rdquo;.  An EV cert is meant to help reduce
&lt;a href=&#34;https://en.wikipedia.org/wiki/Phishing&#34;&gt;phishing&lt;/a&gt; attacks by helping
the web user spot if an EV cert is in use.&lt;/p&gt;

&lt;p&gt;In a web browser the owner of an EV is typically presented:
&lt;center&gt;
&lt;img src=&#34;https://www.sweharris.org/images/chase_cert_header.png&#34; alt=&#34;chase&#34; /&gt;
&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;When you compare that to my DV cert you can see that we both have the
green padlock, showing the certs are good, but the Chase entry has more
details about the owner next to the padlock.&lt;/p&gt;

&lt;p&gt;EV certification takes more resources from the CA (typically people
are involved and it&amp;rsquo;s a multi-day affair and may require a registered
legal entity (e.g. a registered company name) in your country.&lt;/p&gt;

&lt;p&gt;The idea behind EV is that you can now get a level of trust of the
identity of the &lt;em&gt;organisation&lt;/em&gt; behind a web site, which can be very
important for a site such as a bank.  &amp;ldquo;JPMorgan Chase and Co run
this site and it is called www.chase.com&amp;rdquo; is a stronger message than
&amp;ldquo;this site is called www.chas3.com&amp;rdquo;.&lt;/p&gt;

&lt;h3 id=&#34;organisation-validated-ov&#34;&gt;Organisation Validated (OV)&lt;/h3&gt;

&lt;p&gt;This is somewhat of a middle layer between DV and EV.  In this setup
the owner of the site is still checked.  Originally this was meant to
be the &amp;ldquo;higher quality&amp;rdquo; certificate but there were no strict rules around
how this validation was performed (which is why the CA/Browser Forum - see
later - introduced EV).  That means there&amp;rsquo;s a level of assurance in the
owner of the domain, but it&amp;rsquo;s not necessarily as strong as that presented
by an EV cert.&lt;/p&gt;

&lt;p&gt;OV certificates include organisational details inside the certificate,
but these are rarely presented directly to the user by default.  Indeed,
the user may need to go digging to distinguish between DV and OV, so I&amp;rsquo;m
not sure if these provide any real benefit any more.&lt;/p&gt;

&lt;h2 id=&#34;how-does-your-browser-know-the-certificate-is-valid&#34;&gt;How does your browser know the certificate is valid?&lt;/h2&gt;

&lt;p&gt;This is where the CAs signature comes in.  You can use the CAs public
to verify the signature is accurate (calculate the signature yourself
and then use the public key to decrypt the one they provided; do they match?).&lt;/p&gt;

&lt;p&gt;The problem is where to get the CAs public key from?&lt;/p&gt;

&lt;p&gt;To solve this your operating system and web browser come with a set of
CA keys pre-installed.   For example, the Chromium browser on my Debian
desktop shows a lot of CAs, including:
&lt;center&gt;
&lt;img src=&#34;https://www.sweharris.org/images/cert_manager.png&#34; alt=&#34;certs&#34; /&gt;
&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;The sheer number of CAs can cause a problem; do you trust them all?
Inherently you do, even if you don&amp;rsquo;t know it!  Are you sure some random
CA won&amp;rsquo;t sign a certificate for your site?  Or allow some bad person pretend
to be your bank?  There&amp;rsquo;s a &lt;a href=&#34;https://cabforum.org/&#34;&gt;CA/Browser Forum&lt;/a&gt;
that tries to keep on top of this which, combined with &lt;a href=&#34;https://www.sweharris.org/post/2017-03-19-certificate_transparency/&#34;&gt;Certificate
Transparency&lt;/a&gt;, tries to keep
on top of the problem but it&amp;rsquo;s not clear if there is a good solution.&lt;/p&gt;

&lt;p&gt;One advantage of this model, though, is that an enterprise can create
their own &amp;ldquo;internal&amp;rdquo; CA; they just need to add the CA&amp;rsquo;s public key to
their corporate image (or deploy it using Microsoft group policies, or
similar) and their own internal created SSL certificates are trusted, which
can enable internal SSL encryption to happen without needing an external
CA.&lt;/p&gt;

&lt;h2 id=&#34;what-is-certificate-chaining&#34;&gt;What is certificate chaining&lt;/h2&gt;

&lt;p&gt;Typically the CA doesn&amp;rsquo;t sign requests with the &amp;ldquo;root&amp;rdquo; key that the
browser knows about.  It&amp;rsquo;s a lot of work to get new keys distributed
(it&amp;rsquo;s not just browsers but also other software, such as java, that is
impacted) so these keys are long lived (20 or 30 years, in some cases).
If they were stolen then there would be potential for false signings
for a long time.  So, instead, the root key is locked in a vault and
inaccessible.  Not so useful.  Instead an &lt;em&gt;intermediate&lt;/em&gt; certificate
(that has been signed by the root cert) is used to do the signing.
These may be shorter lived (say 5 years or less).&lt;/p&gt;

&lt;p&gt;The problem, now, is in telling the browser about this.  So instead of
the server just presenting the signed certificate from the CA it sends
both that cert &lt;em&gt;and&lt;/em&gt; the intermediate&amp;rsquo;s cert public key.&lt;/p&gt;

&lt;p&gt;The browser can check the intermediate cert is good because it knows
about the root cert.  Once it trusts the intermediate it can then
use this to check and trust the web servers certificate.&lt;/p&gt;

&lt;p&gt;So, for example, we can see the chain for www.google.com
&lt;center&gt;
&lt;img src=&#34;https://www.sweharris.org/images/google_chain.png&#34; alt=&#34;certs&#34; /&gt;
&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Here the website certificate has been signed by a Google CA, which
has been signed by GeoTrust&amp;hellip; and that is in the browser/OS certificate
store and is trust.  So the browser can verify the site is correct.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Certificate chaining mistakes are common in new SSL deployments, so
it&amp;rsquo;s definitely worth verifying you get this correct!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;what-happens-when-a-certificate-expires&#34;&gt;What happens when a certificate expires?&lt;/h2&gt;

&lt;p&gt;Essentially nothing &lt;em&gt;happens&lt;/em&gt;.  However web browsers will start to
complain.  As part of their validation process they check the &amp;ldquo;not before&amp;rdquo;
and &amp;ldquo;not after&amp;rdquo; dates inside the CA signed certificate and compares them
to the local time.  Once the certificate has expired then the browser will
no longer trust it and will give the user a nasty scary looking screen.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;
&lt;img src=&#34;https://www.sweharris.org/images/expired_cert.png&#34; alt=&#34;certs&#34; /&gt;
&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;If the user decided to click on through then they can still get to
your site, and it will still be encrypted&amp;hellip; but don&amp;rsquo;t do this.  Don&amp;rsquo;t
encourage users to ignore these warnings.  Make sure your cert is
renewed in time!&lt;/p&gt;

&lt;h2 id=&#34;what-happens-when-a-certificate-is-lost-stolen&#34;&gt;What happens when a certificate is &lt;del&gt;lost&lt;/del&gt; stolen?&lt;/h2&gt;

&lt;p&gt;It doesn&amp;rsquo;t matter if the signed cert is stolen; all that information
is public.  The important part is the &lt;em&gt;private&lt;/em&gt; key that we generated
all the way back at the beginning of this post while creating the CSR.
This private key is what is used to prove communication is to the server,
so if someone steals that then they can decrypt your data, or even
impersonate you.&lt;/p&gt;

&lt;p&gt;There are two ways a certificate can be revoked, and these are under
the control of the CA:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Certificate Revocation List (CRL).  In this version the CA posts a
complete list of revoked certificates.  The CRL URI is in a field
in the signed certificate so the client knows where to look.
&lt;br&gt;
e.g.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;        X509v3 CRL Distribution Points:

            Full Name:
              URI:http://sr.symcb.com/sr.crl
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The client must download this list and then check for the serial number of the
certificate to see if it has been revoked.  The Symantec list mentioned
here is currently 167K in size and contains 4700 entries so clients using
this approach may cache data.  (Of course expired certs may be removed
from the CRL, helping to keep the size down).&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Online Certificate Status Protocol (OCSP).  This version is more API
oriented; rather than downloading a complete CRL the web browser can
ask specifically for the state of the certificate.  Again the URL
is present in the signed certificate:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;        Authority Information Access:
            OCSP - URI:http://sr.symcd.com
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Entries typically have a validity time associated with them, to tell the
browser how long to cache the results for.
&lt;p&gt;
&lt;a href=&#34;https://community.letsencrypt.org/t/may-19-2017-ocsp-and-issuance-outage-postmortem/34922&#34;&gt;OCSP failures&lt;/a&gt; have been the cause of sites becoming unreachable
and have some privacy concerns, so a version called &lt;a href=&#34;https://en.wikipedia.org/wiki/OCSP_stapling&#34;&gt;OCSP stapling&lt;/a&gt;, where the web server presents a signed OCSP response.  &lt;a href=&#34;https://httpd.apache.org/docs/trunk/mod/mod_ssl.html#sslusestapling&#34;&gt;Apache documentation&lt;/a&gt; claims this doesn&amp;rsquo;t work properly for intermediate certs,
but standard OCSP caching may help, here.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Unfortunately, revocation checking isn&amp;rsquo;t necessarily reliable nor as well
performed as it should be.  For example, Chrome doesn&amp;rsquo;t do OCSP at all,
and &lt;a href=&#34;http://www.zdnet.com/article/chrome-does-certificate-revocation-better/&#34;&gt;claims to have its own method&lt;/a&gt;.  It&amp;rsquo;s purely a function of the client and
non-browser clients rarely perform all the validation (or, indeed, &lt;em&gt;any&lt;/em&gt;
validation) on the certificates.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;This was meant to be a brief introduction to some of the features of
an SSL certificate, but it grew a little large!  There&amp;rsquo;s a lot of features
available (and I didn&amp;rsquo;t even talk about client certs, mutual TLS, code signing
certs&amp;hellip;) and it can get a little complicated.&lt;/p&gt;

&lt;p&gt;Fortunately modern tools such as &lt;a href=&#34;https://www.letsencrypt.org&#34;&gt;Letsencrypt&lt;/a&gt;
handle most of this for you (it can handle the key generation, the CSR,
the Domain Validation, the chaining and the rotation when certificates
are due to expire&amp;hellip; magic!).  In an enterprise world, companies such
as &lt;a href=&#34;https://www.venafi.com&#34;&gt;Venafi&lt;/a&gt; can act as an interface to hide
the complexity, and integrate with your CA of choice.&lt;/p&gt;

&lt;p&gt;So, hopefully, most people won&amp;rsquo;t need to deal with these messy internals
so much.  But knowing about SSL certs and how they work for assigning
identity to a machine will help understand their limitations and what
considerations need to in any security model relying on them.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Data At Rest Encryption (DARE)</title>
      <link>https://www.sweharris.org/post/2017-06-04-encryption-rest/</link>
      <pubDate>Sun, 04 Jun 2017 16:24:09 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-06-04-encryption-rest/</guid>
      <description>

&lt;p&gt;I&amp;rsquo;ve previous written about &lt;a href=&#34;https://www.sweharris.org/post/2017-04-09-encryption_hashing/&#34;&gt;encryption and hashing&lt;/a&gt; and why things like customer passwords should never be encrypted.&lt;/p&gt;

&lt;p&gt;Sometimes, though, you need encryption because you need to get the raw
data back.&lt;/p&gt;

&lt;p&gt;Now you can apply encryption at different layers.  Some are easy; some
are hard.  What you need to be aware of, though, is what they protect
against.  There is no one-size-fits-all solution&lt;/p&gt;

&lt;h2 id=&#34;a-standard-app&#34;&gt;A standard app&lt;/h2&gt;

&lt;p&gt;In a common scenario we may have an application that writes data to a
database; that database persists data to disk.&lt;/p&gt;

&lt;h4 id=&#34;device-encryption&#34;&gt;Device encryption&lt;/h4&gt;

&lt;p&gt;Here we&amp;rsquo;re looking at things like encrypting the
whole hard disk.  This could be done via software (e.g
&lt;a href=&#34;https://en.wikipedia.org/wiki/BitLocker&#34;&gt;BitLocker&lt;/a&gt; on Windows,
&lt;a href=&#34;https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Security_Guide/sec-Encryption.html&#34;&gt;LUKS&lt;/a&gt;
on Linux) or via hardware (&lt;a href=&#34;https://en.wikipedia.org/wiki/Hardware-based_full_disk_encryption&#34;&gt;self encrypting drives&lt;/a&gt;
- SED).  The idea is that the storage mechanism itself is encrypted,
and the data is decrypted when read.  The key used to enable to
encrypt/decrypt cycle is typically entered at boot time; without the
right key then the data is unreadable.  For a laptop you would typically
need to enter the password at power up; for SED devices the key may be
negotiated via the hardware BIOS/TPM.&lt;/p&gt;

&lt;p&gt;This helps prevent against physical theft; eg if someone steals your laptop
then they can&amp;rsquo;t read your data without knowing the unlock password.  If
someone steals an SED device from your datacenter (or a site engineer
accidentally walks out with one after performing a replacement) then the
device won&amp;rsquo;t be able to talk to the motherboard to get the unlock key.&lt;/p&gt;

&lt;p&gt;This is the sort of encryption used on iPhones and newer Android devices,
and it&amp;rsquo;s important for the same reason that companies use BitLocker on
laptops; if the device is lost or stolen then the contents can be unreadable.&lt;/p&gt;

&lt;p&gt;Once the storage device is &amp;ldquo;unlocked&amp;rdquo; then reads and writes are encrypted
&lt;em&gt;transparently&lt;/em&gt; to the OS and applications.  They don&amp;rsquo;t need to care about
it.&lt;/p&gt;

&lt;p&gt;What it doesn&amp;rsquo;t protect against, though, is against data access once the
device has been unlocked.  So an SA on your Linux server will be able to
read all the data (the device decrypts it for them!), for example.&lt;/p&gt;

&lt;p&gt;This layer of encryption is, essentially, &lt;em&gt;transparent&lt;/em&gt; to higher levels
of the stack which makes it nice to implement, especially on mobile
devices.  Everything that runs on the machine pretty much runs unchanged.&lt;/p&gt;

&lt;p&gt;So be aware of the limitations: device level encryption can protect against
loss of the device but can not protect against attacks at the OS or higher.&lt;/p&gt;

&lt;h4 id=&#34;database-encryption&#34;&gt;Database encryption&lt;/h4&gt;

&lt;p&gt;So we can go up a level; we don&amp;rsquo;t want our SAs to be able to read our data.
Let&amp;rsquo;s encrypt at the database level, instead.  The common term for
this is &amp;ldquo;Transparent Data Encryption&amp;rdquo; (TDE).
&lt;a href=&#34;https://docs.oracle.com/cd/B19306_01/network.102/b14268/asotrans.htm&#34;&gt;Oracle&lt;/a&gt;,
&lt;a href=&#34;https://docs.microsoft.com/en-us/sql/relational-databases/security/encryption/transparent-data-encryption-tde&#34;&gt;Microsoft&lt;/a&gt; and
&lt;a href=&#34;https://www.mysql.com/products/enterprise/tde.html&#34;&gt;MySQL&lt;/a&gt; are
examples of this.&lt;/p&gt;

&lt;p&gt;Now the &lt;em&gt;database&lt;/em&gt; does the encryption/decryption.  Your SA trying to
read the datafiles will just see rubbish, but the application will be
able to run unchanged.  We&amp;rsquo;ve protected against the SA.&lt;/p&gt;

&lt;p&gt;What it doesn&amp;rsquo;t protect against, though, is the DBA.  The DBA can connect
to the database and read anything.  It also doesn&amp;rsquo;t protect against
the SA trying to get hold of the encryption keys or gain DBA privileges
(switch to the Oracle group?)&lt;/p&gt;

&lt;p&gt;This level is effectively transparent to the database users (hence
the TDE terminology), which makes it nice to implement (no application
code change is necessary).&lt;/p&gt;

&lt;p&gt;So be aware of the limitations: database level encryption can protect
from disk loss or for someone being able to read the raw data files,
but it doesn&amp;rsquo;t protect against authorized privileged users of the database
(DBAs) or people who can &lt;em&gt;become&lt;/em&gt; privileged users.&lt;/p&gt;

&lt;h4 id=&#34;application-level-encryption-ale&#34;&gt;Application level encryption (ALE)&lt;/h4&gt;

&lt;p&gt;So now we get into the application itself; the &lt;em&gt;app&lt;/em&gt; is modified to
encrypt the data.  You might use a tools from companies such as
&lt;a href=&#34;https://www.vormetric.com&#34;&gt;Vormetric&lt;/a&gt; or &lt;a href=&#34;https://www.voltage.com&#34;&gt;Voltage&lt;/a&gt;,
which can be configured to talk to a &lt;a href=&#34;https://en.wikipedia.org/wiki/Hardware_security_module&#34;&gt;HSM&lt;/a&gt;
to get encryption keys.&lt;/p&gt;

&lt;p&gt;At this stage the application can decide which columns to encrypt.  You
might want to encrypt a customer&amp;rsquo;s name and address, but not necessarily
the date of a purchase.&lt;/p&gt;

&lt;p&gt;ALE is the most intrusive into an application because the app needs to
be modified to perform the encryption.&lt;/p&gt;

&lt;p&gt;Depending on the type of data you may want to use &lt;a href=&#34;https://en.wikipedia.org/wiki/Format-preserving_encryption&#34;&gt;Format Preserving
Encryption&lt;/a&gt;
so the data &lt;em&gt;looks&lt;/em&gt; in the same format as the original (e.g. credit card
numbers), which will allow some applications to continue to work on
the encrypted data, rather than needing to decrypt it every time.
(This is a good use case, when storing data in the public cloud; if your
app can work on FPE data then the risk of exposure by running it in
the cloud is a lot smaller than having to decrypt it each time).&lt;/p&gt;

&lt;p&gt;Now neither the SA nor the DBA have direct access to the data, although
they still may be able to abuse privileges to get hold of the encryption
key or authentication tokens to talk to the HSM.&lt;/p&gt;

&lt;p&gt;Of course your application may still need to be able to decrypt the data
(how can you send an order if you can&amp;rsquo;t decrypt the name and address?),
which means that you are still at risk from rogue developers or errors
at the application layer, but you may be protected from a SQL injection type
attack because the resulting dataset would be encrypted&lt;/p&gt;

&lt;h2 id=&#34;what-about-cloud-storage&#34;&gt;What about cloud storage?&lt;/h2&gt;

&lt;p&gt;You need to think of &amp;ldquo;who has access? who can attack?&amp;rdquo;.  So let&amp;rsquo;s say
you&amp;rsquo;re storing stuff in Amazon S3 and decide to use server side encryption.
Accidentally you allow the buckets to be read by the world, but without
decryption.  So you&amp;rsquo;ve protected against &amp;ldquo;raw data theft&amp;rdquo; (compare to
disk leaving the data center).  But you haven&amp;rsquo;t protected against
theft by &amp;ldquo;authorized&amp;rdquo; users, because the S3 API will do the decryption
for you.  You&amp;rsquo;re &lt;em&gt;also&lt;/em&gt; vulnerable to admins of the Amazon account who
can modify the rules&amp;hellip;&lt;/p&gt;

&lt;p&gt;Similarly if you use EBS attached to the S3 instance and encrypt it with
LUKS then you may be safe from the admins, but the SAs of the VMs can
still access the data.  Of course if you&amp;rsquo;re doing hands off delivery and
don&amp;rsquo;t allow anyone to login then there may not &lt;em&gt;be&lt;/em&gt; any SAs :-)&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;I like to look at technology as a stack of things sitting on top of
each other.&lt;/p&gt;

&lt;p&gt;So your app sits on top of a database, which sits on top of an OS, which
sits on top of a machine.&lt;/p&gt;

&lt;p&gt;Encryption at different layers protects against attacks at that level
of the stack; SEDs can protect against &amp;ldquo;machine&amp;rdquo; attacks, but doesn&amp;rsquo;t
protect against higher levels of the stack.&lt;/p&gt;

&lt;p&gt;In a modern deployment you should consider device encryption as the lowest
level requirement, even inside a datacenter.  Disks &lt;em&gt;do&lt;/em&gt; walk, even with
the best of processes.  But just because you have this low level encryption
it does not mean you have &amp;ldquo;solved&amp;rdquo; the encryption problem.  You need to look
at your attack surface and pick a level that&amp;rsquo;s appropriate.&lt;/p&gt;

&lt;p&gt;Sorry, developers, just because you have an encrypted disk or database TDE
doesn&amp;rsquo;t mean you can avoid doing ALE!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Stuff changes; don&#39;t take things on faith, get the facts</title>
      <link>https://www.sweharris.org/post/2017-05-28-measure/</link>
      <pubDate>Sun, 28 May 2017 16:58:07 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-05-28-measure/</guid>
      <description>

&lt;p&gt;A number of years back I saw a mail thread around Java performance.  One
person made the claim that Java was slow; if you wanted performant
apps then write in a different language.  This matched my experience,
so I felt a little confirmation bias.  However the reply really made
me think; this may have been true 10 years ago (and, indeed, it&amp;rsquo;d been
over 10 years since I&amp;rsquo;d done any real Java) but modern techniques
meant that Java was perfectly fast.  The kicker was that, instead of
believing rumour and word-of-mouth ancient results, do the tests
yourself; &lt;em&gt;measure&lt;/em&gt; and get the facts.&lt;/p&gt;

&lt;h2 id=&#34;my-home-server-disks&#34;&gt;My home server disks&lt;/h2&gt;

&lt;p&gt;My home machine has mutated a few times over the years, and
suffers some &lt;a href=&#34;https://www.sweharris.org/post/2016-11-13-technical-debt/&#34;&gt;technical debt&lt;/a&gt; as a
result.&lt;/p&gt;

&lt;p&gt;Currently the disks are connected to a couple of SAS9211-8i controllers.
In theory these are PCIe 8x controllers but my motherboard has a 16x slot
and a 4x slot, so one card isn&amp;rsquo;t being used at full potential.  I&amp;rsquo;m using
the controllers in JBOD mode, with Linux mdraid to create the various
RAID options.  I prefer this because it means I&amp;rsquo;m not tied to specific
hardware and could migrate the disks to another setup, entirely, and
the kernel should autodetect and bring up the RAID automatically.&lt;/p&gt;

&lt;p&gt;This means the setup is currently on a CentOS 6 based system with
the cards and disks distributed over the two cards:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;16x slot:

&lt;ul&gt;
&lt;li&gt;2 Crucial CT512MX1 SSDs in a RAID 1&lt;/li&gt;
&lt;li&gt;4 Seagate ST2000 in a RAID 10&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;4x slot:

&lt;ul&gt;
&lt;li&gt;8 Seagate ST4000 in a RAID 6&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now I&amp;rsquo;d been taking it as an article of faith that the SSDs would be
fastest, with the RAID 10 being better than the RAID 6 for writes,
and the RAID 6 being better for reads.&lt;/p&gt;

&lt;p&gt;When I &lt;a href=&#34;https://www.sweharris.org/post/2016-11-27-home-machine&#34;&gt;built this&lt;/a&gt; I ran some
&lt;code&gt;hdparm -t&lt;/code&gt; tests on the RAID volumes and was surprised how
well the RAID 6 performed&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;The two SSDs  are in a RAID 1  and get 375 MB/sec
The 4*2Tbytes are in a RAID 10 and get 267 MB/sec
The 8*4Tbytes are in a RAID 6  and get 532 MB/sec
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This made me wonder how well they&amp;rsquo;d work in a more targeted
test.  Since EPEL has &lt;code&gt;bonnie++&lt;/code&gt; in the repository I chose that.
For each of the RAID volumes I picked an existing &lt;code&gt;ext3&lt;/code&gt; filesystem
to run the tests on.  This should give some form of &amp;ldquo;real world&amp;rdquo;
feel, since it wouldn&amp;rsquo;t be on newly created filesystems.&lt;/p&gt;

&lt;p&gt;I ran each test twice.&lt;/p&gt;

&lt;p&gt;The results (slightly edited for formatting) make interesting reading:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;           ------Sequential Output------   --Sequential Input- --Random-
           -Per Chr- --Block-- -Rewrite-   -Per Chr- --Block-- --Seeks--
Machine   K/sec %CP  K/sec %CP  K/sec %CP K/sec %CP K/sec  %CP  /sec %CP
Raid6       800  92 108776  14 103820  11  3276  76 606148  23 170.3   8
Raid6       784  91 108436  13 105046  11  3373  76 606068  23 172.2   8

Raid10      753  94 175905  21  91956   9  2700  76 227793  10 409.2  15
Raid10      745  91 170551  20  93408   9  3209  78 229931  10 531.6   7

Raid1 SSD   786  96 182078  21  97995  10  3685  84 236123  10 460.2  17
Raid1 SSD   796  95 173306  20  98546  10  3012  75 233678  11 470.9  16
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What seems clear is that for reading the ability to distribute load
over 8 disks gives a clear speed advantage when reading data blocks,
but at a CPU cost.  Sequential character reads don&amp;rsquo;t make a lot of
difference, so we may be seeing limiting factors of the kernel and CPU
and memory, rather than disk I/O here.  RAID 6 definitely loses for
random seeks, though!&lt;/p&gt;

&lt;p&gt;More interesting are the writes.  RAID 6 is definitely slower, but
surprisingly the SSD wasn&amp;rsquo;t noticeably faster than the spinning 2TB
disks.  These disks are &lt;em&gt;meant&lt;/em&gt; to be able to do 500MB/s, but I appear
to get real-world speeds of 180MB/s, only a little faster than the
2TB Seagates (and those values seem reasonable,
looking at &lt;a href=&#34;http://hdd.userbenchmark.com/Seagate-Barracuda-720014-2TB/Rating/1619&#34;&gt;this&lt;/a&gt;) chart.&lt;/p&gt;

&lt;p&gt;And why are the rewrites tipped the other way?&lt;/p&gt;

&lt;p&gt;At this point I&amp;rsquo;d almost consider moving all my data on the RAID 6
because I think that&amp;rsquo;d give the most balanced performance!  However,
performance isn&amp;rsquo;t the only design criteria; data risk (if a 4TB disk
failed would the array survive long enough to rebuild the lost disk?)
and data separation; I could turn off the RAID 6 and still keep 95% of my
functionality, just long term storage wouldn&amp;rsquo;t be available, so I could
run on a smaller machine if this motherboard died.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;This &amp;ldquo;get the facts&amp;rdquo; can apply to many things.  It becomes tempting to
measure &lt;em&gt;everything&lt;/em&gt; and try to apply change based on those numbers.  But
we can see, from this simple disk speed test, that numbers may not be
so clear and &lt;em&gt;what&lt;/em&gt; you measure can give you different results.  If I
only measure &amp;ldquo;block read&amp;rdquo; speed then I would just have everything on the
RAID 6 disks; that&amp;rsquo;s so much quicker!  But if I care about writing then
maybe the RAID 10.  Would I even care about the SSDs?  And there are
other factors (resiliency, recovery) to take into account.  Overly
optimising for one factor isn&amp;rsquo;t always the best idea, either!&lt;/p&gt;

&lt;p&gt;Technology changes; configurations can have impacts; optimisations (JIT
bytecode compilers) can add a whole new dimension.  What was an article
of faith 10 years ago may now hinder you and cause you to build slower
more complicated solutions.&lt;/p&gt;

&lt;p&gt;If possible you should try out various options early in the design process
and pick the one that gives you best results for your use case.  You need
the facts in order to make the best decision.  But don&amp;rsquo;t over-optimise
at the cost of other factors.  Decisions are not made in a vacuum.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Bottlenecks and SPOFs</title>
      <link>https://www.sweharris.org/post/2017-05-21-spof-bottleneck/</link>
      <pubDate>Sun, 21 May 2017 11:02:58 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-05-21-spof-bottleneck/</guid>
      <description>

&lt;p&gt;If you&amp;rsquo;ve ever built any enterprise level system you&amp;rsquo;ll be aware of the
needs of performance and resiliency.  You may do performance testing on
your application; you may have a backup server in a second data center;
you may even do regular &amp;ldquo;Disaster Recovery tests&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;And yet, despite all these efforts, your application fails in unexpected
ways or isn&amp;rsquo;t as resilient as you planned.  Your primary server dies,
the DR server doesn&amp;rsquo;t work properly.  Why is this?&lt;/p&gt;

&lt;h2 id=&#34;performance-tuning-and-hidden-bottlenecks&#34;&gt;Performance tuning and hidden bottlenecks&lt;/h2&gt;

&lt;p&gt;A few weeks back I upgraded my home internet connection to gigabit speeds.
The next day I found that my primary VM felt slow; commands were taking
a noticeable amount of time to run when they shouldn&amp;rsquo;t (eg a simple &lt;code&gt;ls&lt;/code&gt;).
Investigation showed that my machine (a quad core i5) was maxed out,
and a single process &lt;a href=&#34;https://rclone.org&#34;&gt;rclone&lt;/a&gt; was responsible.
My offsite backup was running (copying data to Amazon), and I &lt;em&gt;encrypt&lt;/em&gt;
my data while sending it.  By removing the network bottleneck I was now
hitting a CPU performance bottleneck.&lt;/p&gt;

&lt;p&gt;Now many applications have unexpected hidden bottlenecks as well.  A
common problem is when a service switches from a production data center
to a secondary; this second data center may have higher network latency
to their customers and this can impact performance in odd ways (using
perl &lt;code&gt;DBD::Oracle&lt;/code&gt; do a select of a million rows from a database 10ms
away vs 30ms away and spot the difference!).  Processing that may take
most of a night may now fail to complete before the next work day;
reporting deadlines could be missed, and this could have regulatory
implications and fines in some industries.&lt;/p&gt;

&lt;p&gt;This means that having a &amp;ldquo;DR&amp;rdquo; plan may not be sufficient.  You should
also have a &lt;em&gt;Sustained Resiliency&lt;/em&gt; plan; don&amp;rsquo;t just verify you can
shutdown your production database and spin it up in DR; keep it up
and running for a week or two to verify that downstream dependent
applications keep working and can meet their end-of-day, end-of-week
deadlines.&lt;/p&gt;

&lt;h2 id=&#34;single-points-of-failures&#34;&gt;Single Points of Failures&lt;/h2&gt;

&lt;p&gt;As part of our resilient design we also make choices on what services
can be made highly available (e.g. a cluster) vs redundant (e.g.
warm standby environment in a secondary location).  We may also accept
a single point of failure, based on risk factors and cost.&lt;/p&gt;

&lt;p&gt;For example, at home if my &lt;a href=&#34;https://www.sweharris.org/post/2017-05-07-home-grown-router/&#34;&gt;router&lt;/a&gt;
died then I could replace it with an openWRT based system, or even a
desktop with 2 ethernet cards.  It wouldn&amp;rsquo;t be as performant, but it
would work for a temporary basis.  Similarly if my main machine died I
have a spare that I could get working (it would be messy and the case
wouldn&amp;rsquo;t close&amp;hellip;).   But&amp;hellip; I only have Verizon FIOS.  If that dies then
I&amp;rsquo;m off the net (my friend hit this problem recently; his ONT failed).
Now I &lt;em&gt;could&lt;/em&gt; also get Cablevision as a secondary internet provider, but
this isn&amp;rsquo;t worth the monthly cost for me.  So I live with the SPOF.
The server this site is served from, though, does have a copy at a
second provider - &lt;a href=&#34;https://www.linode.com&#34;&gt;linode&lt;/a&gt; and &lt;a href=&#34;https://www.panix.com&#34;&gt;Panix&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another thing that may show up in a real DR scenario (as opposed to planned
ones) is an unexpected dependency.  Many DR tests are very fake in nature;
they have a planned sequence (close down production database, sync to DR,
bring up DR database, test application, switch back again).  This is all
clean and designed to minimise disruption to the production environment,
but it&amp;rsquo;s not really representative of a real failure mode.  What happens
if there&amp;rsquo;s a datacenter outage?  This isn&amp;rsquo;t &lt;em&gt;planned&lt;/em&gt;; you won&amp;rsquo;t be
working with a clean replicated database, you may have data-loss or
require a database recovery which can impact recovery times.&lt;/p&gt;

&lt;p&gt;Or you might find you have an unexpected SPOF dependency; is your DNS
managed from the primary datacenter so you can&amp;rsquo;t modify service entries
to point to your secondary?  Are all writes sent to a server in the
primary location?  Is your authentication service hosted there?&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://www.theregister.co.uk/2017/02/28/aws_is_awol_as_s3_goes_haywire/&#34;&gt;Amazon hit this&lt;/a&gt; in early 2017;
they found they had a massive dependency on S3 and this dependency impacted
not only many many other applications but also their own status site!  They
couldn&amp;rsquo;t update the status page to tell people about the outage because
it depended on S3.  Oops!&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;You might think that modern &lt;a href=&#34;https://12factor.net&#34;&gt;12-factor apps&lt;/a&gt;
might be more immune to these failures, but you&amp;rsquo;d be wrong.  You still
need to think about the underlying infrastructure (&amp;ldquo;the cloud is just
someone else&amp;rsquo;s computer&amp;rdquo;); deploy to multiple regions, ensure your
data is properly replicated, have a &lt;em&gt;sustained resiliency&lt;/em&gt; program,
and test worst case scenarios.  Even if your original architecture was
good, implementations mutate and grow beyond the initial design criteria.
What may have worked 2 years ago may not work now.&lt;/p&gt;

&lt;p&gt;Be aware of hidden SPOFs (could someone DDoS your DNS servers?  What would
happen if your &lt;a href=&#34;https://en.wikipedia.org/wiki/Domain_hijacking&#34;&gt;domain was hijacked&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;The cloud doesn&amp;rsquo;t solve your HA/DR/SR requirements; it just provides tools
to assist in building resilient solutions.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Building a home router</title>
      <link>https://www.sweharris.org/post/2017-05-07-home-grown-router/</link>
      <pubDate>Sun, 07 May 2017 13:50:18 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-05-07-home-grown-router/</guid>
      <description>

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;WARNING: technical content ahead!  There&amp;rsquo;s also a tonne of config files,
which make this page look longer than it really is, but hopefully they&amp;rsquo;ll
help other people who want to do similar work.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;For many years I&amp;rsquo;ve been using variations of the Linksys WRT54G.  I
first switched to this router when freeware ROMs became available; I&amp;rsquo;ve
used DD-WRT, Tomato, OpenWRT and others.  I love the flexibility it gives
me.  My current router is a TP-Link TL1043ND with OpenWRT.  It works well,
and the flexibility means it&amp;rsquo;s also configured as my OpenVPN endpoint,
HEnet IPv6 tunnel endpoint, dual SID WiFi access point&lt;/p&gt;

&lt;p&gt;However I have some problems with this setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Upgrades are painful. If there&amp;rsquo;s a bug in some core code (eg openvpn)
then the only real fix is to find the latest software and reflash; you
can&amp;rsquo;t just upgrade the individual packages, even if they were installed
as extras.  This has meant that my router may technically be vulnerable
to known issues.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Network speed. This week I upgraded my FIOS connection to gigabit
speeds; the TP-Link maxes out around 175Mbit/s and so is now the
bottleneck.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;It&amp;rsquo;s not exactly performant; the OpenVPN speed is horribly slow.  This
isn&amp;rsquo;t really a problem since I just use it as an admin channel between
my home network and my internet hosts, but it&amp;rsquo;d be nice to resolve.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Since I needed a newer faster router I decided to try and fix these
problems at the same time.  This, basically, meant building a real PC
with a real OS and configuring it as a router.  I could have looked at
something like &lt;a href=&#34;https://www.pfsense.org/&#34;&gt;pfsense&lt;/a&gt; but that&amp;rsquo;s a different
OS to manage.  I didn&amp;rsquo;t particularly need a pretty GUI, either.&lt;/p&gt;

&lt;p&gt;So I went with a CentOS 7 build.&lt;/p&gt;

&lt;h2 id=&#34;the-hardware&#34;&gt;The hardware&lt;/h2&gt;

&lt;p&gt;The nice thing about these WRT routers is they are &lt;em&gt;cheap&lt;/em&gt;.  Of course
there are tradeoffs (performance).  I wanted something in the same
ballpark and settled on a &lt;a href=&#34;https://www.pcengines.ch/apu2.htm&#34;&gt;PC Engines APU2&lt;/a&gt;
board.  They only had the 2Gb RAM model in stock when I ordered, but
that should be sufficient:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;System Board: $102.00
        Case: $ 10.00
   16Gb SATA: $ 14.40
   WiFi card: $ 19.00
    Antennas: $  4.20
      Cables: $  3.00
    Shipping: $ 14.30
              =======
              $166.90
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;rsquo;s in the right ballpark.  It&amp;rsquo;s a fanless system, so quiet, and just
runs from a DC power adapter (which I had available).  The one downside
is that the WiFi card can only work on 2.4 &lt;em&gt;or&lt;/em&gt; 5Ghz, not both at the same
time, but otherwise this is just about right.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&#34;https://www.sweharris.org/images/apu2.jpg&#34; alt=&#34;APU2&#34; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;The PC Engines team have a number of support files which allow you to
generate boot USB drives to allow you install your OS of choice, including
(in my case) CentOS 7.  And the machine has a serial console, making it
easy to remote manage.  You don&amp;rsquo;t need to plug a keyboard, mouse, monitor
in (indeed, there&amp;rsquo;s no VGA/HDMI output!)&lt;/p&gt;

&lt;h2 id=&#34;the-os&#34;&gt;The OS&lt;/h2&gt;

&lt;p&gt;I installed a pretty minimal CentOS 7 image on the machine.  Why C7?
Because that&amp;rsquo;s what the majority of my systems are based on.  It meant
I could use my standard backup, monitoring, patching, control processes.
I removed NetworkManager, firewalld, unnecessary firmware.  I added
the EPEL repo.  In particular I added&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;hostapd&lt;/code&gt; to be the Wifi AP manager&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bridge-utils&lt;/code&gt; to manage the bridging&lt;/li&gt;
&lt;li&gt;&lt;code&gt;iw&lt;/code&gt; and &lt;code&gt;wireless-tools&lt;/code&gt; to manage the WiFi&lt;/li&gt;
&lt;li&gt;&lt;code&gt;openvpn&lt;/code&gt; for the VPN endpoint&lt;/li&gt;
&lt;li&gt;&lt;code&gt;iptables-service&lt;/code&gt; to allow me to save/restore IPtable configurations&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dhcp&lt;/code&gt; and &lt;code&gt;dnsmasq&lt;/code&gt; to serve guest-wifi addresses&lt;/li&gt;
&lt;li&gt;&lt;code&gt;radvd&lt;/code&gt; for IPv6 routing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;basic-network-layout&#34;&gt;Basic network layout&lt;/h2&gt;

&lt;p&gt;I want to have 3 networks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;WAN&lt;/li&gt;
&lt;li&gt;LAN&lt;/li&gt;
&lt;li&gt;Guest-net&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To make rules easier to follow I created 3 bridges (br-wan, br-lan, br-guest).
I was then able to associate physical and logical devices to this.&lt;/p&gt;

&lt;p&gt;So, for example, in &lt;code&gt;/etc/sysconfig/network-scripts&lt;/code&gt; I could configure
the WAN port:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% cat ifcfg-br-wan
DEVICE=br-wan
TYPE=Bridge
ONBOOT=yes
BOOTPROTO=dhcp
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
PEERDNS=no

% cat ifcfg-enp2s0 
DEVICE=enp2s0
TYPE=Ethernet
ONBOOT=yes
BRIDGE=&amp;quot;br-wan&amp;quot;
NM_CONTROLLED=&amp;quot;no&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This puts the second ethernet port onto the WAN bridge and configures
it for DHCP, which is what my ISP uses.  I plug in the cable and&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% ip -4 addr show dev br-wan
13: br-wan: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP qlen 1000
    inet 173.54.110.200/24 brd 173.54.110.255 scope global dynamic br-wan
       valid_lft 4808sec preferred_lft 4808sec
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Perfect, the machine is now on the internet&amp;hellip; and succeptible to
being attacked.  Indeed, I saw one &lt;code&gt;ssh&lt;/code&gt; scan happen while I was building
this; I should have locked down traffic before I started, but I felt the
risk was low (only 1 account has password access and that has a hard
password).&lt;/p&gt;

&lt;p&gt;The LAN side can be similarly configured, but with a static IP:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cat ifcfg-br-lan
DEVICE=br-lan
TYPE=Bridge
ONBOOT=yes
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_AUTOCONF=no
IPV6ADDR=2001:470:1f07:dc4::1/64
BOOTPROTO=none
IPADDR=10.0.0.1
NETMASK=255.255.255.0
BROADCAST=10.0.0.255
NETWORK=10.0.0.0

$ cat ifcfg-enp1s0
DEVICE=enp1s0
TYPE=Ethernet
ONBOOT=yes
BRIDGE=&amp;quot;br-lan&amp;quot;
NM_CONTROLLED=&amp;quot;no&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note I&amp;rsquo;ve given this an IPv6 address as well.&lt;/p&gt;

&lt;p&gt;And br-guest is similarly static, but (at this point) with no
ethernet port assigned:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cat ifcfg-br-guest 
DEVICE=br-guest
TYPE=Bridge
ONBOOT=yes
BOOTPROTO=static
IPADDR=10.100.100.1
NETMASK=255.255.255.0
DEFROUTE=no
IPV4_FAILURE_FATAL=no
IPV6INIT=no
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The observant will have noticed that I haven&amp;rsquo;t mentioned WiFi - that
gets configured next!&lt;/p&gt;

&lt;h2 id=&#34;wifi&#34;&gt;WiFi&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;hostapd&lt;/code&gt; program creates the WiFi networks &lt;em&gt;and&lt;/em&gt; controls the
bridges the networks are connected to.  The WiFi card in this machine
can host multiple SSIDs at the same time.  In my case I defined two
networks (LAN and GUEST) with their own WPA passwords and associated
to the relevant networks.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cat /etc/hostapd/hostapd.conf
ctrl_interface=/var/run/hostapd
ctrl_interface_group=wheel

macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0

driver=nl80211

interface=wlp4s0
hw_mode=g
channel=1

ssid=LANSSID
ap_isolate=1
disassoc_low_ack=1
preamble=1
wmm_enabled=1
ignore_broadcast_ssid=0
uapsd_advertisement_enabled=1
wpa_passphrase=YOURNETWORKPASSWORD
auth_algs=1
wpa=2
wpa_pairwise=CCMP
bridge=br-lan
wpa_key_mgmt=WPA-PSK
okc=0
disable_pmksa_caching=1
bssid=04:f0:21:26:d3:7e

bss=wlp4s0_1
ssid=GUESTSSID
ap_isolate=1
disassoc_low_ack=1
preamble=1
wmm_enabled=1
ignore_broadcast_ssid=0
uapsd_advertisement_enabled=1
wpa_passphrase=YOURGUESTNETPASSWORD
auth_algs=1
wpa=2
wpa_pairwise=CCMP
bridge=br-guest
wpa_key_mgmt=WPA-PSK
okc=0
disable_pmksa_caching=1
bssid=04:f0:21:26:d3:7f
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This configures the &lt;code&gt;wlp4s0&lt;/code&gt; (WiFi card) interface but also creates a
second logical interface &lt;code&gt;wlp4s0_1&lt;/code&gt; for the guest network.&lt;/p&gt;

&lt;h2 id=&#34;bridge-results&#34;&gt;Bridge results&lt;/h2&gt;

&lt;p&gt;We can verify what interface is on what network quite simply.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% brctl show
bridge name     bridge id               STP enabled     interfaces
br-guest        8000.04f02126d37f       no              wlp4s0_1
br-lan          8000.000db9439ccc       no              enp1s0
                                                        wlp4s0
br-wan          8000.000db9439ccd       no              enp2s0
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;guestnet-dhcp-and-dns&#34;&gt;Guestnet DHCP and DNS&lt;/h2&gt;

&lt;p&gt;For my LAN I have an ISC DHCP and BIND setup running on another machine;
machines on the LAN network (whether cabled or wireless) will talk to
them; I don&amp;rsquo;t need to worry.  But guestnet users can&amp;rsquo;t reach these.  So
the router needs to provide these functions.&lt;/p&gt;

&lt;p&gt;The out-of-box configuration for &lt;code&gt;dnsmasq&lt;/code&gt; pretty much works just fine.
The only change I added was &lt;code&gt;no-hosts&lt;/code&gt; to prevent it looking up entries
in the &lt;code&gt;/etc/hosts&lt;/code&gt; file.  At the moment I&amp;rsquo;m letting it use the
DNS server list in &lt;code&gt;/etc/resolv.conf&lt;/code&gt; as the server to forward to
(ie my internal host) but I might reconfigure it to point to Google
instead.&lt;/p&gt;

&lt;p&gt;If I do that then I expect (untested!) the configuration to be&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;no-resolv
server=8.8.8.8
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This would allow me to use this router&amp;rsquo;s DNSmasq as a secondary DNS
for LAN usage.  (Food for thought).&lt;/p&gt;

&lt;p&gt;For DHCP I&amp;rsquo;m sticking with ISC &lt;code&gt;dhcpd&lt;/code&gt;, with a simple configuration:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ddns-update-style  none;

option option-128 code 128 = string;
option option-129 code 129 = text;
option option-221 code 221 = text;

subnet 10.100.100.0 netmask 255.255.255.0 {
  authoritative;
  option routers      10.100.100.1;
  option subnet-mask    255.255.255.0;
  option domain-name    &amp;quot;spuddy.org&amp;quot;;
  option domain-name-servers  10.100.100.1;
  default-lease-time 3600;
  max-lease-time 3600;
  range dynamic-bootp 10.100.100.10 10.100.100.200;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Basically, serve out addresses with a default route and DNS server.
Pretty simple!&lt;/p&gt;

&lt;h2 id=&#34;ipv6&#34;&gt;IPv6&lt;/h2&gt;

&lt;h3 id=&#34;setting-up-an-ipv6-tunnel&#34;&gt;Setting up an IPv6 tunnel&lt;/h3&gt;

&lt;p&gt;If have a &lt;a href=&#34;https://tunnelbroker.net/&#34;&gt;HEnet tunnel&lt;/a&gt; for my home IP
range.  This is pretty easy to set up with CentOS:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;DEVICE=sit1
BOOTPROTO=none
ONBOOT=yes
IPV6INIT=yes
IPV6TUNNELIPV4=IP_ADDRESS_OF_REMOTE_SERVER
IPV6ADDR=YOUR_ASSIGNED_IPv6 ENDPOINT
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;rsquo;s pretty much it.  As long as your IPv4 address is assigned at
HE.net then the tunnel comes up and runs.&lt;/p&gt;

&lt;p&gt;You can do this with a dynamic script that probes your external IP address
and then calls the tunnelbroker API:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;PASS=YOUR_PASSWORD
USERID=YOUR_USERNAME
GTUNID=YOUR_TUNNEL_ID
HOST=https://$USERID:$PASS@ipv4.tunnelbroker.net

newip=$1

# Check to see what the end point currently is
x=$(wget -q --no-check-certificate -O - $HOST/tunnelInfo.php?tid=$GTUNID | sed -n &#39;s/^.*&amp;lt;clientv4&amp;gt;\(.*\)&amp;lt;.*$/\1/p&#39;)

if [ &amp;quot;x$x&amp;quot; == &amp;quot;x$newip&amp;quot; ]
then
  echo Tunnel IP is already correct
  exit
fi

wget -q --no-check-certificate -O - &amp;quot;$HOST/nic/update?hostname=$GTUNID&amp;amp;myip=$newip&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With a script similar to this even if your IP address changes then you can
make sure the tunnel endpoint is updated and your IPv6 connection will
restore.&lt;/p&gt;

&lt;p&gt;(Hmm, I run that script from a host on my LAN; I wonder if I could make it
a triggered event; see the &amp;ldquo;reflection&amp;rdquo; section below on this)&lt;/p&gt;

&lt;h3 id=&#34;setting-up-radvd&#34;&gt;Setting up &lt;code&gt;radvd&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;In order for the rest of your network to see the IPv6 world we use &lt;code&gt;radvd&lt;/code&gt;.
This allows hosts to auto-discover their IPv6 network and default route.&lt;/p&gt;

&lt;p&gt;We just configure it on the LAN network:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cat /etc/radvd.conf 
interface br-lan
{
        AdvSendAdvert on;
        MinRtrAdvInterval 30;
        MaxRtrAdvInterval 100;
        prefix YOUR_IP_V6_NETWORK/64
        {
                AdvOnLink on;
                AdvAutonomous on;
                AdvRouterAddr off;
        };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In my case the IPv6 network is that from HE.net; 2001:470:1f07:dc4::/64
as matches the IPv6 address defined in &lt;code&gt;ifcfg-br-lan&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&#34;firewalls-and-routing&#34;&gt;Firewalls and routing&lt;/h2&gt;

&lt;p&gt;Now we have the &lt;em&gt;plumbing&lt;/em&gt; out of the way we can start to make the device
act like a router.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s make the kernel forward traffic first:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cat /etc/sysctl.d/forward.conf 
net.ipv4.ip_forward = 1
net.ipv4.conf.all.forwarding = 1
net.ipv6.conf.all.forwarding = 1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At this point your LAN and guest networks can see each other, and you should
be able to see your external (ISP provided) IP address.  But not much else
on IPv4.  You should have full internet access via IPv6&amp;hellip; and the rest
of the internet can see you, as well!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;iptables&lt;/code&gt; is used to configure both NAT and firewall rules; &lt;code&gt;ip6tables&lt;/code&gt;
is used to configure IPv6 firewall rules.  We don&amp;rsquo;t need NAT on a
routed IPv6 network.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s two ways of doing this; you can run the &lt;code&gt;iptables&lt;/code&gt; command to add
rules, or you can edit &lt;code&gt;/etc/sysconfig/iptables&lt;/code&gt; files directly.  If
you use the commands then run &lt;code&gt;service iptables save&lt;/code&gt; to update the
config file so the rules persist after a reboot.  If you edit the file
directory then run &lt;code&gt;service iptables reload&lt;/code&gt; to force them to be reloaded.&lt;/p&gt;

&lt;p&gt;I tend to do edit the file directly!&lt;/p&gt;

&lt;h3 id=&#34;ipv4-rules&#34;&gt;IPv4 rules&lt;/h3&gt;

&lt;p&gt;when looking at standard rules (INPUT/OUTPUT/FORWARD) we have to look
at them from the perspective of the router.  INPUT rules are those
that impact packets that are targetted at the router; OUTPUT rules are
those that originate from the router; FORWARD rules are those that
pass &lt;em&gt;through&lt;/em&gt; the router.  This gets important for NAT where the packet
targets the router&amp;rsquo;s external IP address.&lt;/p&gt;

&lt;p&gt;First we need to allow incoming traffic that corresponds to outgoing
connections (if you reach out on port 80 then you want to allow the
remote end to reply!).  We&amp;rsquo;ll add two basic rules to the 3 main filter
channels.  From the command line this would look like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
iptables -A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -m conntrack --ctstate INVALID -j DROP
iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate INVALID -j DROP
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You&amp;rsquo;ll see similar entries in the &lt;code&gt;*filter&lt;/code&gt; section of the config
file.&lt;/p&gt;

&lt;p&gt;Now we want to allow some specifics.  The LAN needs to see the WAN,
for example.  We can add some more INPUT rules:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-A INPUT -i lo -j ACCEPT
-A INPUT -i br-lan -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -p tcp -m tcp --dport 12345 -j ACCEPT
-A INPUT -i br-guest -j guest_reflection
-A INPUT -j REJECT --reject-with icmp-port-unreachable
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can see, now, why I created these bridge devices.  It becomes
pretty clear what networks rules apply to!  We&amp;rsquo;ll talk about the
&amp;ldquo;reflection&amp;rdquo; rule later.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;--dport 12345&lt;/code&gt; is where I run my OpenVPN server.  This allows
the remote machines to access it.&lt;/p&gt;

&lt;p&gt;Forwarding is similar:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-A FORWARD -i br-lan -j ACCEPT
-A FORWARD -i tun0 -j ACCEPT
-A FORWARD -i br-wan -m conntrack --ctstate DNAT -j ACCEPT
-A FORWARD -i br-guest -o br-wan -j ACCEPT
-A FORWARD -i br-guest -j guest_reflection
-A FORWARD -j REJECT --reject-with icmp-port-unreachable
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;br-wan&lt;/code&gt; rule is important when we get to port forwarding.  We
also only allow the guest network to see the WAN; it can no longer
reach your LAN machines.&lt;/p&gt;

&lt;p&gt;The output chain doesn&amp;rsquo;t have any special requirements; we allow any
packet originating from the router to be sent out.&lt;/p&gt;

&lt;p&gt;So far so good.  But you still can&amp;rsquo;t see the outside world from the
LAN.  So now we get to the NAT table.  This is configured with
&lt;code&gt;iptables -t nat&lt;/code&gt;, or by entries in the &lt;code&gt;*nat&lt;/code&gt; section of the config
file.&lt;/p&gt;

&lt;p&gt;With NAT we have INPUT, OUTPUT, PREROUTING and POSTROUTING sections.&lt;/p&gt;

&lt;p&gt;The first step is  (remember, if from the command line to add &lt;code&gt;-t nat&lt;/code&gt;)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-A POSTROUTING -o br-wan -j MASQUERADE
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is the magic that allows outgoing communication.  Every machine
on your LAN and guest networks should now be able to see servers on
the internet.&lt;/p&gt;

&lt;p&gt;Many people (me included!) also want to allow some services internally
to be visible externally.  For example, I run my own IMAPS server which
I have my phone configured to talk to.  We need to allow this traffic
through:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-A PREROUTING -i br-wan -p tcp -m tcp --dport 12346 -j DNAT --to-destination 10.0.0.137:993
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This tells the router that anything arriving from the WAN targeting port 12346
should be redirected to the internal server 10.0.0.137 on the IMAPS port.&lt;/p&gt;

&lt;p&gt;You can define a series of ports; eg for bittorrent I have&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-A PREROUTING -i br-wan -p tcp -m tcp --dport 6881:6999 -j DNAT --to-destination 10.0.0.137:6881-6999
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These work in conjunction with the earlier FOWARDING DNAT rule I mentioned
to let the traffic through.&lt;/p&gt;

&lt;h3 id=&#34;ipv6-rules&#34;&gt;IPv6 rules&lt;/h3&gt;

&lt;p&gt;Because there&amp;rsquo;s no NAT needed here we can have simpler rules.  I just allow
my external servers to access the internal machines, and nothing else.
That makes for a very trivial set of rules in &lt;code&gt;/etc/sysconfig/ip6tables&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -i lo -j ACCEPT
-A INPUT -i br-lan -j ACCEPT
-A INPUT -p ipv6-icmp -j ACCEPT
-A INPUT -s ip:6:of::HOST1/128 -j ACCEPT
-A INPUT -s ip:6:of::HOST2/128 -j ACCEPT
-A INPUT -s ip:6:of::HOST3/128 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp6-adm-prohibited
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -m conntrack --ctstate INVALID -j DROP
-A FORWARD -i br-lan -j ACCEPT
-A FORWARD -s ip:6:of::HOST1/128 -j ACCEPT
-A FORWARD -s ip:6:of::HOST2/128 -j ACCEPT
-A FORWARD -s ip:6:of::HOST3/128 -j ACCEPT
-A FORWARD -j REJECT --reject-with icmp6-adm-prohibited
-A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -m conntrack --ctstate INVALID -j DROP
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As with IPv4, the INPUT rules allow those hosts to access the router
directly, the FORWARD rules allow it to access machines behind the router
on my LAN.&lt;/p&gt;

&lt;h2 id=&#34;reflection&#34;&gt;Reflection&lt;/h2&gt;

&lt;p&gt;So far we now have a working router.  We can reach the internet and allow
the internet to reach into our network.  But there&amp;rsquo;s one tiny gotcha.
Which is an odd edge-case that you may not care about&amp;hellip;&lt;/p&gt;

&lt;p&gt;Access from your internal network (LAN, guestnet) to your &lt;em&gt;external&lt;/em&gt;
IP address will not work!  That&amp;rsquo;s because the traffic to those external
ports doesn&amp;rsquo;t come in from br-wan and so isn&amp;rsquo;t rewritten.  Now OpenWRT
creates a series of additional rules called &amp;ldquo;reflection&amp;rdquo; rules.  They
take the packet and &lt;em&gt;rewrite it&lt;/em&gt; so it looks like it comes from the
router, and then sends it back in to the LAN.  It&amp;rsquo;s a kludge, but it
works.&lt;/p&gt;

&lt;p&gt;In the NAT section I added two rules:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-A PREROUTING -s 10.0.0.0/8 -p tcp -m tcp -j reflection_pre
-A POSTROUTING -s 10.0.0.0/8 -p tcp -m tcp -j reflection_post
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now this allows us to reflect traffic originating from any internal
IP address (LAN, guestnet) by creating rules in the new chains.&lt;/p&gt;

&lt;p&gt;The problem is that these rules need to refer to the router&amp;rsquo;s external
IP address, and this can change.  So I added a hook into dhclient&amp;rsquo;s
configuration, which gets run whenever an IP address is associated:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cat /etc/dhcp/dhclient.d/reflect.sh
#!/bin/bash

I=&amp;quot;/sbin/iptables&amp;quot;
N=&amp;quot;$I -t nat&amp;quot;

get_ip()
{
  /sbin/ip -4 addr show dev $1 | sed -n &#39;s/^\s*inet \(.*\)\/.*/\1/p&#39;
}

LAN_ADDR=$(get_ip br-lan)
LAN=${LAN_ADDR%.*}.0/24
GUEST_ADDR=$(get_ip br-guest)
GUEST=${GUEST_ADDR%.*}.0/24
ALL_LAN=${LAN_ADDR%.*}.0/8

reflect()
{
  $I -A guest_reflection -s $ALL_LAN -d $1/32 -p tcp -m tcp --dport $(echo $2 | tr - :) -j ACCEPT

  $N -A reflection_post -s $ALL_LAN -d $1/32 -p tcp -m tcp --dport $(echo $2 | tr - :) -j SNAT --to-source $LAN_ADDR
  $N -A reflection_pre -s $ALL_LAN -d $new_ip_address/32 -p tcp -m tcp --dport $(echo $3 | tr - :) -j DNAT --to-destination $ip:$i_port
}

reflect_restore()
{
  if [ &amp;quot;$interface&amp;quot; = &amp;quot;br-wan&amp;quot; -a -z &amp;quot;$new_ip_address&amp;quot; ]
  then
    $N -N reflection_post 2&amp;gt; /dev/null
    $N -N reflection_pre  2&amp;gt; /dev/null
    $N -F reflection_post
    $N -F reflection_pre
    $I -N guest_reflection 2&amp;gt; /dev/null
    $I -F guest_reflection
  fi
}

reflect_config()
{
  if [ &amp;quot;$interface&amp;quot; = &amp;quot;br-wan&amp;quot; -a -n &amp;quot;$new_ip_address&amp;quot; -a &amp;quot;$new_ip_address&amp;quot; != &amp;quot;$old_ip_address&amp;quot; ]
  then
    $N -N reflection_post 2&amp;gt; /dev/null
    $N -N reflection_pre  2&amp;gt; /dev/null
    $N -F reflection_post
    $N -F reflection_pre
    $I -N guest_reflection 2&amp;gt; /dev/null
    $I -F guest_reflection

    $I -L -t nat -n | sed -n &#39;s/^DNAT.*tcp dpts*:\(.*\) to:\(.*\):\(.*\)/\1 \2 \3/p&#39; | while read e_port ip i_port
    do
      reflect $ip $i_port $e_port
    done
  fi
  $N -A reflection_post  -j RETURN
  $N -A reflection_pre   -j RETURN
  $I -A guest_reflection -j RETURN
}

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now what this does is look at the existing port forwarding rules
you&amp;rsquo;ve defined and then builds the necessary forwarding and NATting
rules.  So, for example, for the IMAPS port I can now see:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# iptables -n -L guest_reflection -v | grep 993
    0     0 ACCEPT     tcp  --  *      *       10.0.0.0/8           10.0.0.137           tcp dpt:993

# iptables -t nat -n -L reflection_pre -v | grep 993  
    0     0 DNAT       tcp  --  *      *       10.0.0.0/8           173.54.110.200       tcp dpt:12346 to:10.0.0.137:993

# iptables -t nat -n -L reflection_post -v | grep 993
    0     0 SNAT       tcp  --  *      *       10.0.0.0/8           10.0.0.137           tcp dpt:993 to:10.0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;final-configuration&#34;&gt;Final configuration:&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;# cat /etc/sysconfig/iptables
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:guest_reflection - [0:0]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -i lo -j ACCEPT
-A INPUT -i br-lan -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -p tcp -m tcp --dport 12345 -j ACCEPT
-A INPUT -i br-guest -j guest_reflection
-A INPUT -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -m conntrack --ctstate INVALID -j DROP
-A FORWARD -i br-lan -j ACCEPT
-A FORWARD -i tun0 -j ACCEPT
-A FORWARD -i br-wan -m conntrack --ctstate DNAT -j ACCEPT
-A FORWARD -i br-guest -o br-wan -j ACCEPT
-A FORWARD -i br-guest -j guest_reflection
-A FORWARD -j REJECT --reject-with icmp-port-unreachable
-A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -m conntrack --ctstate INVALID -j DROP
COMMIT
*nat
:PREROUTING ACCEPT [4:2876]
:INPUT ACCEPT [1:60]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:reflection_post - [0:0]
:reflection_pre - [0:0]
-A PREROUTING -i br-wan -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.2:80
-A PREROUTING -i br-wan -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.0.0.2:443
-A PREROUTING -i br-wan -p tcp -m tcp --dport 12346 -j DNAT --to-destination 10.0.0.137:993
-A PREROUTING -i br-wan -p tcp -m tcp --dport 6881:6999 -j DNAT --to-destination 10.0.0.137:6881-6999
-A PREROUTING -s 10.0.0.0/8 -p tcp -m tcp -j reflection_pre
-A POSTROUTING -s 10.0.0.0/8 -p tcp -m tcp -j reflection_post
-A POSTROUTING -o br-wan -j MASQUERADE
COMMIT

# cat /etc/sysconfig/ip6tables
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -i lo -j ACCEPT
-A INPUT -i br-lan -j ACCEPT
-A INPUT -p ipv6-icmp -j ACCEPT
-A INPUT -s ip:6:of::HOST1/128 -j ACCEPT
-A INPUT -s ip:6:of::HOST2/128 -j ACCEPT
-A INPUT -s ip:6:of::HOST3/128 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp6-adm-prohibited
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -m conntrack --ctstate INVALID -j DROP
-A FORWARD -i br-lan -j ACCEPT
-A FORWARD -s ip:6:of::HOST1/128 -j ACCEPT
-A FORWARD -s ip:6:of::HOST2/128 -j ACCEPT
-A FORWARD -s ip:6:of::HOST3/128 -j ACCEPT
-A FORWARD -j REJECT --reject-with icmp6-adm-prohibited
-A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -m conntrack --ctstate INVALID -j DROP
COMMIT
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;That took me around a day to build.  It doesn&amp;rsquo;t have a pretty GUI, it
doesn&amp;rsquo;t give me speed graphs or track usage.  It&amp;rsquo;s a very basic router.
Which is what I want.  I could add stuff like bandwidth graphs
(which might be interesting) by monitoring packets per minute.  They&amp;rsquo;re
&amp;ldquo;day 2&amp;rdquo; deliverables.&lt;/p&gt;

&lt;p&gt;My &amp;ldquo;day 1&amp;rdquo; was to build a router to replace my TP-Link and that was
capable of making better use of my gigabit link.  And I think I&amp;rsquo;ve mostly
done this.  It&amp;rsquo;s actually hard to tell, because my &lt;em&gt;desktop&lt;/em&gt; only has
a 100Mbit ethernet card in it so sites like &lt;a href=&#34;https://speedtest.net&#34;&gt;speedtest.net&lt;/a&gt; or &lt;a href=&#34;https://fast.com&#34;&gt;fast.com&lt;/a&gt; just tell me the speed my desktop
can handle!&lt;/p&gt;

&lt;p&gt;For the past few years I&amp;rsquo;ve been doing a regular &lt;code&gt;wget&lt;/code&gt; of a 100Mbyte file
from &lt;a href=&#34;http://cachefly.cachefly.net/100mb.test&#34;&gt;http://cachefly.cachefly.net/100mb.test&lt;/a&gt; but this now takes around
1 second and so the startup cost and latency become a determining factor
in the speed calculation.  I&amp;rsquo;m getting speeds around 760Mbit/s, but
would a larger file give better results!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;2017-05-07 14:50:02 (95.2 MB/s) - `/dev/null&#39; saved [104857600/104857600]
2017-05-07 15:05:02 (78.6 MB/s) - `/dev/null&#39; saved [104857600/104857600]
2017-05-07 15:20:02 (88.1 MB/s) - `/dev/null&#39; saved [104857600/104857600]
2017-05-07 15:35:02 (93.0 MB/s) - `/dev/null&#39; saved [104857600/104857600]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Similarly hitting other sites may give slower results because the
bandwidth across the internet could be the limiting factor.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s funny how local and remote infrastructure can now be the limiting
factor in testing speeds; previously the link to the ISP was the bottleneck.&lt;/p&gt;

&lt;p&gt;This showed up nicely in my morning backups; every Sunday I do a level 0
dump and then put an encrypted copy into my Amazon Cloud Drive.  Last
week that took almost 4 hours to upload 100G.  Today it took around 30
minutes, which means I was uploading at around 480Mbit/s.  And there the
limiting factor might have been the CPU &amp;lsquo;cos the process was using 380%
CPU to do the encryption, on my 4-core machine!&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s fast enough for me, anyway ;-)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Cloud Inventory</title>
      <link>https://www.sweharris.org/post/2017-04-30-cloud-inventory/</link>
      <pubDate>Sun, 30 Apr 2017 16:16:58 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-04-30-cloud-inventory/</guid>
      <description>

&lt;p&gt;One of the golden rules of IT security is that you need to maintain an
accurate inventory of your assets.  After all, if you don&amp;rsquo;t know what
you have then how you can secure it?  This may cover a list of physical
devices (servers, routers, firewalls), virtual machines, software&amp;hellip;
An &amp;ldquo;asset&amp;rdquo; is an extremely flexible term and you need to look at it from
various viewpoints to ensure you have good knowledge of your environment.&lt;/p&gt;

&lt;p&gt;Traditionally many of the tools we use to track this stuff are based
around a relatively static concept of machine persistency; if it takes
months to get tin onto the datacenter floor and then it&amp;rsquo;ll stay there
for 3 or more years then it makes sense to track physical assets in
that way.  Similarly if you build a VM and it stays around for a year
and runs a known application then we can use that VM as the basis for
an inventory record.  We can create tools that use the OS as the core
record and scan the machine (e.g. &lt;code&gt;ssh&lt;/code&gt; in) and discover relationships
(child VMs; OS version; software running; communications between servers;
etc) and automatically build out the inventory.  This is good standard
enterprise IT management.&lt;/p&gt;

&lt;p&gt;The cloud, though, can change this.  I can spin up a server in under
a minute, run my application for 2 hours, then shut it down again.
Tomorrow I can spin up another copy (with a new machine identity,
new IP address, etc).  The machine isn&amp;rsquo;t up long enough to be scanned,
and even if we could then the records would be stale and useless.&lt;/p&gt;

&lt;p&gt;So we need to rethink &lt;em&gt;how&lt;/em&gt; we deal with inventory in a cloud world.&lt;/p&gt;

&lt;h2 id=&#34;iaas&#34;&gt;IaaS&lt;/h2&gt;

&lt;p&gt;The first thing people typically think of, when considering cloud, is the
IaaS model.  Spin up an AWS VPC, create networks, VMs, install your app.
We&amp;rsquo;re in the cloud!  And this is fine.  You&amp;rsquo;re basically treating the
cloud as an outsourced data center, with the assets being an extension
of your core environment.  In this scenario your existing tools and
processes may well be sufficient.&lt;/p&gt;

&lt;p&gt;However a primary feature of an IaaS is that it can be a lot more dynamic
than that.  There&amp;rsquo;s an API to let you build new assets and these are
available almost immediately.  I could run a script that builds a new VPC,
creates a three tier network architecture, installs VMs, deploys my app.
Within minutes I have a full stack.&lt;/p&gt;

&lt;p&gt;This can lead to a &lt;a href=&#34;https://www.sweharris.org/post/2016-05-02-shadow-it/&#34;&gt;shadow IT&lt;/a&gt; problem, so
it becomes very important to control IaaS services.  Central IT should
provide the tools and the gateway services to the cloud and not allow
direct administrative access.&lt;/p&gt;

&lt;p&gt;This can also be used to solve the &amp;ldquo;need to scan&amp;rdquo; nature of existing
systems; your tooling can &lt;em&gt;tag&lt;/em&gt; the data by requiring this to be specified
up front (&amp;ldquo;I&amp;rsquo;m building 3 VMs with RedHat 7 to run application XYZ and
it needs to listen on port 443 and speak to database ABC&amp;rdquo;).  You have
the data needed for your inventory, up front!&lt;/p&gt;

&lt;p&gt;The same can be true for other sorts of infrastructure (networking, WAFs,
firewalls, storage).  If you must permit this level of administrative
access to the cloud provider then ensure there&amp;rsquo;s an &lt;em&gt;audit trail&lt;/em&gt; of
activity (e.g. AWS CloudTrail) that can be used to track the API calls
and maintain the inventory information, accordingly.&lt;/p&gt;

&lt;p&gt;However we&amp;rsquo;re not quite finished&amp;hellip; a lot of inventories are point
in time snapshots; &amp;ldquo;this is what we have &lt;em&gt;now&lt;/em&gt;&amp;rdquo;.  Unfortunately
a data breach may not be detected for quite a while (I&amp;rsquo;ve see &lt;a href=&#34;https://www.infosecurity-magazine.com/news/hackers-spend-over-200-days-inside/&#34;&gt;200
days&lt;/a&gt;
thrown around a lot).  Since your cloud server may have been shut down,
IP address re-used for another application, and a new instance created
elsewhere, we need the ability to &amp;ldquo;time travel&amp;rdquo;; maintain an audit trail
to allow us to recreate the state of the inventory at whatever time we
care about.&lt;/p&gt;

&lt;p&gt;And, bonus!  This also helps speed up delivery of &lt;em&gt;internal&lt;/em&gt; IaaS
services.&lt;/p&gt;

&lt;h2 id=&#34;paas&#34;&gt;PaaS&lt;/h2&gt;

&lt;p&gt;In some respects an off-premise PaaS provider is probably easier to
manage than an IaaS; PaaS engagements are typically more &amp;ldquo;heavy weight&amp;rdquo;
than just spinning up a few VMs, and the teams using them are more likely
to follow corporate processes around vendor management (especially
if the team wants a VPN into the PaaS environment), and this can help
ensure the application inventory is correctly maintained.  At this point
we can&amp;rsquo;t create an &amp;ldquo;application to host&amp;rdquo; mapping, because there is no
fixed host, but we can easily see how the PaaS provider becomes an
equivalent parent entity.&lt;/p&gt;

&lt;p&gt;Of course some teams may bypass the controls (another Shadow IT issue),
especially where the PaaS is directly reachable and management via https.
Some of these concerns can be addressed in a similar way to SaaS, which
we&amp;rsquo;ll get to in a moment.&lt;/p&gt;

&lt;p&gt;An on-premise PaaS can be a challenge for existing processes to
handle.  It&amp;rsquo;s tempting to treat this similar to an off-prem solution
(&amp;ldquo;my application runs on the inhouse PaaS&amp;rdquo;), but we lose some of the
ability to determine impact of a breach.  Common post-breach investigation
processes use the inventory to determine application scope impact, but
with a PaaS almost any application in the environment could be co-located
on the same physical machine at the time an application was broken into.
Inventory and audit trails don&amp;rsquo;t help so much here because elastic
applications, especially 12 factor applications, are highly dynamic
inside a PaaS environment.  Yes, this also impacts off-prem PaaS,
but we&amp;rsquo;re accepting those are opaque boxes; with an on-prem PaaS we
have the ability to take the lid off the box&amp;hellip; and this could hamper
us!&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;d love to hear from any DFIR experts on how they handle (or plan to
handle) PaaS breaches; the best I&amp;rsquo;ve heard, so far, is &amp;ldquo;comprehensive
audit logs of everything that happens&amp;rdquo;).  Please, feed back welcome!&lt;/p&gt;

&lt;h2 id=&#34;saas&#34;&gt;SaaS&lt;/h2&gt;

&lt;p&gt;Now we come to the scariest part of the cloud,
mostly because your organisation &lt;del&gt;may be&lt;/del&gt; are using
SaaS services without your knowledge.  &lt;a href=&#34;https://twitter.com/jwgoerlich/status/858106541626576897&#34;&gt;Wolf Goerlich
claims&lt;/a&gt;
that your average organisation uses 928 cloud services.  There&amp;rsquo;s also
a claim that CISOs reckon they only use 40 cloud apps.  Now there may
a discrepancy between &amp;ldquo;cloud app&amp;rdquo; and &amp;ldquo;cloud service&amp;rdquo; accounting for
this massive gap but, even so, 928 is &lt;em&gt;a lot&lt;/em&gt;, and  most of these will
be SaaS offerings.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;re not talking about your centrally managed service (e.g. the corporate
Office365, or corporate Google Apps); those we have pretty good control
over and can track their use and understand them as assets.&lt;/p&gt;

&lt;p&gt;The problem is the &lt;em&gt;unmanaged&lt;/em&gt; services.  This is because many of these
SaaS offerings are just ad-hoc web sites that people use without thinking.
&amp;ldquo;I want to pretty format my perl code; ah, here&amp;rsquo;s a web site; let&amp;rsquo;s
cut&amp;rsquo;n&amp;rsquo;paste into that form&amp;hellip;&amp;rdquo;&lt;/p&gt;

&lt;p&gt;Effectively this is almost all &amp;ldquo;shadow IT&amp;rdquo;, and one that&amp;rsquo;s hard to
identify.&lt;/p&gt;

&lt;p&gt;You might wonder why that is a problem&amp;hellip; well, that web site now has
a copy of your code.  Do they keep it?  What terms and conditions were
on that site?  Many of them may claim ownership of the data submitted;
has your developer now given away that code, just for the benefit of
having it nicely formatted?&lt;/p&gt;

&lt;p&gt;Even if the T&amp;amp;Cs are good, has the site ever been breached?  How can
you be sure there isn&amp;rsquo;t a bad guy &lt;em&gt;on&lt;/em&gt; that service stealing data?&lt;/p&gt;

&lt;p&gt;Then there&amp;rsquo;s third party repository services; developers
may pull down modules or libraries from docker, or
nodejs, or CPAN or&amp;hellip;  These services may not be reliable
(&lt;a href=&#34;https://www.theregister.co.uk/2016/03/23/npm_left_pad_chaos/&#34;&gt;leftpad&lt;/a&gt;
anyone?), or have rogue code added, and can lead to non-repeatable builds.&lt;/p&gt;

&lt;p&gt;How can you manage this if you don&amp;rsquo;t even know what is in use?&lt;/p&gt;

&lt;p&gt;The first step is to identify what your teams are doing; what 928
services are being accessed.  Then identify which of these may be
considered high risk (eg T&amp;amp;Cs that you don&amp;rsquo;t like; poor reputation)
and then start blocking them at your border.  You do force people
to go via proxies, don&amp;rsquo;t you?&lt;/p&gt;

&lt;p&gt;This starts to sound like a lot of work and is likely an area worth
purchasing a service to handle; these can take your proxy logs and identify
who is accessing what, whether it&amp;rsquo;s mostly downloads or if there are
large uploads (which could identify data exfiltration), and provide
reports on your risk posture.  (And this can also help with the shadow IT
PaaS issue, mentioned earlier).&lt;/p&gt;

&lt;p&gt;Ultimately you may wish to create &lt;em&gt;inhouse&lt;/em&gt; alternatives; if you find
lots of people hitting code formatting sites then create your own!  Create
your own code repository service that has curated library/code modules
so you&amp;rsquo;re not dependent on external services.  Perhaps find a service
provider that does what the adhoc service does and enter into a managed
agreement.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s no one size fits all solution to managing a cloud inventory.
For managed services this can be
done via central IT tooling (IaaS) or identified service agreements
(SaaS); we need to change our technology processes to handle the more
dynamic nature of the environments, but we can deal with this in various
ways (e.g. dedicate a VPC to an application? Then it doesn&amp;rsquo;t matter so
much about VM spinup/spindown; all VMs inside that VPC are dedicated to
the app)&lt;/p&gt;

&lt;p&gt;The bigger gap is the unmanaged SaaS footprint.  The first step is
&lt;em&gt;identification&lt;/em&gt;.  The second is control.  This can be made easier
with strong &lt;em&gt;egress&lt;/em&gt; controls on your environment, forcing traffic
to go through choke and monitoring points.  You want to do this for
Data Loss Prevention, malware scanning, blocking phishing sites and
so on; the same infrastructure can be used to detect and limit
risking SaaS usage&amp;hellip; and to keep an inventory of &lt;em&gt;what&lt;/em&gt; SaaS services
are in use!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Persistent Applications</title>
      <link>https://www.sweharris.org/post/2017-04-23-persistence/</link>
      <pubDate>Sun, 23 Apr 2017 16:54:18 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-04-23-persistence/</guid>
      <description>

&lt;p&gt;&lt;a href=&#34;https://www.sweharris.org/post/2016-07-28-persistency/&#34;&gt;A while ago&lt;/a&gt; I wrote about some of the
technology basics that can be used for data persistency.  Apparently
this is becoming a big issue, so I&amp;rsquo;m revisiting this from another
direction.&lt;/p&gt;

&lt;h2 id=&#34;why-does-this-matter&#34;&gt;Why does this matter?&lt;/h2&gt;

&lt;p&gt;In essence, an application is a method of changing data from one state
to another; &amp;ldquo;I charge $100 to my credit card&amp;rdquo; fires off a
number of applications that result in my account being debited, and the
merchant being credited.  Similarly when my employer pays me a million
bucks (hey, it &lt;em&gt;could&lt;/em&gt; happen!) there&amp;rsquo;s another set of changes.&lt;/p&gt;

&lt;p&gt;At the end of the day, a large proportion of applications operate
on some form of persistent data.&lt;/p&gt;

&lt;h2 id=&#34;persistence-on-non-persistent-http&#34;&gt;persistence on non-persistent HTTP.&lt;/h2&gt;

&lt;p&gt;Web developers are used to dealing with non-persistency.  After all,
every HTTP request is a unique connection.  Developers learned to deal
with this.&lt;/p&gt;

&lt;p&gt;In the very early days it was done by the construct
of hidden fields in a form.  Each step in a multi-step process resulted
in the web page, itself, persisting the state from the previous steps.&lt;/p&gt;

&lt;p&gt;When cookies came along, some of this information was stored in the
cookie.  And then the concept of a session ID came along, with data
persisted on the server and the client just identifying the session.
The languages grew to help and hide this complexity (eg PHP session IDs).&lt;/p&gt;

&lt;p&gt;When we expanded to multiple servers and load balancers the load balancer
learned how to interpret the session headers and direct traffic to the
same node.&lt;/p&gt;

&lt;p&gt;Today this type of persistency over a non-persistent transport is
considered normal.  We know the failure modes (e.g. server reboots)
and the smart developer can handle this state.&lt;/p&gt;

&lt;h2 id=&#34;non-persistent-containers&#34;&gt;Non-persistent containers&lt;/h2&gt;

&lt;p&gt;This web development model nicely grows into the modern container world.
Containers can easily have a temporary writeable overly &lt;code&gt;/tmp&lt;/code&gt; and
so your existing PHP app can maintain its state database for the lifetime
of the container.  We may reboot containers more frequently, though, so
a smart developer might use a distributed store such as &lt;code&gt;etcd&lt;/code&gt;; now it
doesn&amp;rsquo;t matter &lt;em&gt;what&lt;/em&gt; container processes the request, it has access to
the transaction state.  This small change in development actually makes
life &lt;em&gt;easier&lt;/em&gt;; the load balancer doesn&amp;rsquo;t need to understand state because
any container instance is good and so the least loaded instance can be used.&lt;/p&gt;

&lt;h2 id=&#34;non-web-apps-lift-and-shift&#34;&gt;Non-web apps; Lift and shift&lt;/h2&gt;

&lt;p&gt;The world isn&amp;rsquo;t so clean cut for non-web apps.  A number of these
apps are based inherently on the concept of a persistent infrastructure
layer.  This may require a code change, or else using the &amp;ldquo;machine
container&amp;rdquo; pattern aka &amp;ldquo;container as a lightweight VM&amp;rdquo;.  With a small
amount of effort the app may be rewriteable to work with an attached
persistent store, or to use an external persistence layer (database,
S3 store, something else).  The lift-and-shift approach gives least
benefits of the container model; you might want to reconsider &lt;em&gt;why&lt;/em&gt;
you want to containerize this app.&lt;/p&gt;

&lt;h2 id=&#34;databases&#34;&gt;Databases&lt;/h2&gt;

&lt;p&gt;A database is just a special case of a non-web app.  We could add a
persistent backend store (the equivalent of a &lt;code&gt;-v&lt;/code&gt; flag with docker)
to the container spin up, and treat it as a cluster build.  We can
then spin containers and the new image will reconnect to the existing
backend store and act as if it was a recovering database rejoining the
cluster&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Not everything needs to be placed in a container; is it the right technology
solution?  However, containers are &lt;em&gt;flexible&lt;/em&gt;.  There&amp;rsquo;s more than one way
to use them.  A PaaS, such as CloudFoundry or Apprenda, pushes for the 12
factor approach of development.  This gets a lot of headlines.  But it&amp;rsquo;s
not the only approach.  An existing web app can normally be easily ported
to an immutable container model (just with a writeable &lt;code&gt;/tmp&lt;/code&gt;).  A small
amount of rework can allow a more traditional app to work.  Or we can
use the &amp;ldquo;lightweight VM&amp;rdquo; approach and persist data.&lt;/p&gt;

&lt;p&gt;I find the &amp;ldquo;containers, containers, containers&amp;rdquo; mantra to be a little
offputting.  For decades I&amp;rsquo;ve maintained &amp;ldquo;use the right technology for
the job&amp;rdquo;, whether that&amp;rsquo;s a Windows machines or a Linux machine or even
a mainframe from the dinosaur pool (they have their uses!).  Similarly,
physical, virtual, container&amp;hellip; and the type of container model; there
is no one size fits all solution.  Pick what is right for your use
case.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Multifactor Authentication</title>
      <link>https://www.sweharris.org/post/2017-04-16-twofactor/</link>
      <pubDate>Sun, 16 Apr 2017 15:35:49 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-04-16-twofactor/</guid>
      <description>

&lt;p&gt;We&amp;rsquo;re all used to using passwords as an authenticator.  However, passwords
have a number of problems.  In particular people tend to re-use them on
other sites (so if one website was broken into the password used there
may also work on another site).  Also passwords are susceptible to
replay attacks (even if you force a password change every 90 days, there&amp;rsquo;s
still a large window of time where a stolen password can be used).&lt;/p&gt;

&lt;p&gt;To mitigate this risk, a &lt;em&gt;second&lt;/em&gt; factor may be used.&lt;/p&gt;

&lt;h2 id=&#34;what-is-multi-factor-authentication&#34;&gt;What is multi-factor authentication.&lt;/h2&gt;

&lt;p&gt;Typically we look at authentication tokens as being classed in one of
three ways.  Collequially these are termed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Something you know.  Typically this is a password&lt;/li&gt;
&lt;li&gt;Something you have.  Maybe a physical token of some form&lt;/li&gt;
&lt;li&gt;Something you are.  This is form of biometric, such as a fingerprint&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These are sometimes jokingly referred to as &amp;ldquo;something you&amp;rsquo;ve forgotten;
something you&amp;rsquo;ve lost; something you&amp;rsquo;ve had chopped of&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Multi-factor authentication is where 2 or more &lt;em&gt;different&lt;/em&gt; factors are
used.  The &amp;ldquo;different&amp;rdquo; part is important.  If, for example, we used
two passwords (two &amp;ldquo;something you know&amp;rdquo; factors) then we are not any
stronger than if we forced one larger password.&lt;/p&gt;

&lt;p&gt;e.g. if password1 was &amp;ldquo;hello&amp;rdquo; and password2 was &amp;ldquo;there&amp;rdquo; then we have the
same as if we only had &amp;ldquo;hellothere&amp;rdquo; as the password.  Indeed, depending
on the implementation, it may be &lt;em&gt;weaker&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;You probably already use two factor authentication in your every day
life; each time you go to the ATM to withdraw cash you are presenting
two factors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Something you know (the PIN)&lt;/li&gt;
&lt;li&gt;Something you have (the card you enter into the machine).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;two-factor-autentication-2fa&#34;&gt;Two Factor Autentication (2FA)&lt;/h2&gt;

&lt;p&gt;Here you present two factors to the system.  Both of these factors are
checked, and if you&amp;rsquo;ve entered them correctly then you are let in.&lt;/p&gt;

&lt;p&gt;Critically, for 2FA, if you get either factor wrong then you are not told
&lt;em&gt;what&lt;/em&gt; factor is wrong.&lt;/p&gt;

&lt;h3 id=&#34;weaker-2fa&#34;&gt;Weaker 2FA&lt;/h3&gt;

&lt;p&gt;This is very similar to 2FA, but the two authenticators are checked
separately and you are told what one is wrong.  This is weaker than
2FA because each factor can be attacked separately.&lt;/p&gt;

&lt;p&gt;An example of this might be a web site where you are asked to enter
your password.  If you get your password correct then you are asked
to enter a PIN, but if you get the password wrong then you are told
to re-enter the password.  You can keep on attacking the password
until you are asked for a PIN; once you get the PIN prompt you know
the password is correct.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;To complicate things slightly, sites such as the AWS web console
ask for passwords and PINs separately, but they always ask for the
PIN whether you get the password correct or not, so this is, potentially,
strong 2FA.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;A common strong form of &amp;ldquo;something you have&amp;rdquo; is an RSA SecurID token.
&lt;center&gt;&lt;img src=&#34;https://www.sweharris.org/images/RSA-SecurID.png&#34; alt=&#34;RSA SecurID&#34; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;This device generates a number based on the current time and a secret
unique to the device.  It&amp;rsquo;s a string One Time Password (OTP) generator,
and is one of the most common &amp;ldquo;something you have&amp;rdquo; tokens.  Unfortunately
each company would typically require a unique RSA token and they need
replacing every few years, so you could end up carrying a lot of these
around.  To try and solve this problem there&amp;rsquo;s now software versions
of these keys (&amp;ldquo;soft token&amp;rdquo;) that may be tied to a device (e.g. using
the phone device ID) and require a PIN to unlock, but they &lt;em&gt;could&lt;/em&gt; be
stolen&amp;hellip;&lt;/p&gt;

&lt;p&gt;One &amp;ldquo;something you have&amp;rdquo; token I like the idea of is the &lt;a href=&#34;https://www.yubico.com/product/fido-u2f-security-key/&#34;&gt;YubiKey FIDO U2F&lt;/a&gt;.
&lt;center&gt;&lt;img src=&#34;https://www.sweharris.org/images/YubiKey.png&#34; alt=&#34;U2F&#34; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;This uses public key crypto in a clever way, to allow the same key to
be used on multiple sites and is really cheap.  Unfortunately client
side support is poor at the moment and worse, from my perspective, many
organisations are locking down USB ports (for good reason) and so making
use of these devices hard to introduce.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not so much of a fan of biometrics (&amp;ldquo;something you are&amp;rdquo;).  Fingerprints
are the most common, but some voice response systems are now attempting
voice recognition as a second factor, and retina scan systems also exist.
The problem I have with these is that they&amp;rsquo;re hard to revoke.  What happens
if your fingerprint gets stolen (you leave a million copies lieing around
every day!); you can&amp;rsquo;t really &lt;em&gt;change&lt;/em&gt; it!  It may be good enough to unlock your phone, but I wouldn&amp;rsquo;t use it as a single factor.&lt;/p&gt;

&lt;h2 id=&#34;two-step-verification-2sv&#34;&gt;Two step verification (2SV)&lt;/h2&gt;

&lt;p&gt;2SV is very similar to 2FA in that it asks for two authenticators.
In this case, though, the second authenticator is typically a OTP
transmitted
to you out of band.  A common example is the first time you login to
your bank web site from a new machine (or new browser); it might want
to send you a one time number via SMS to your phone that you need to
type into the website.&lt;/p&gt;

&lt;p&gt;Superficially, this looks like 2FA.  You need to have your phone to
receive it, surely?&lt;/p&gt;

&lt;p&gt;The problem is in that assumption, that you need to have the phone to
use the OTP.  You don&amp;rsquo;t; it could have been intercepted in transit,
or you might have entered it into a phishing site, or you set up your
phone so that SMS messages are diverted to a mailbox and just protected
by a password&amp;hellip;&lt;/p&gt;

&lt;p&gt;Effectively this form of authenticator is just a complicated form of
&amp;ldquo;something you know&amp;rdquo;.&lt;/p&gt;

&lt;h2 id=&#34;factor-strength&#34;&gt;Factor strength.&lt;/h2&gt;

&lt;p&gt;We&amp;rsquo;ve all seen websites that tell you rules for setting up a password.
This is based on the idea of making this factor &amp;ldquo;strong&amp;rdquo;.  After all,
a password that&amp;rsquo;s 50 characters long and written in emoji is stronger
than &amp;ldquo;hello&amp;rdquo;&amp;hellip; right?  Unfortunately many of these rules forget that
humans have to remember the password, and could be counter-productive.&lt;/p&gt;

&lt;p&gt;However the concept of the strength of a factor is important.  Multi-factor
authentication requires strong factors; but &lt;em&gt;strong&lt;/em&gt; is relative to the
use case.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s take PINs on an ATM card; that may only be 4 digits long, which
sounds really weak!  But in this use case the card may be rejected
(or even &lt;em&gt;retained&lt;/em&gt; by the machine) after 3 failed attempts.  So our
theoretically 10,000 entries has a 1 in 3,333 chance of being guessed.
That seems small, but it&amp;rsquo;s actually pretty good.  If we increased
the minimum PIN length to 6 we may be 100 times stronger, but now its
a lot harder for people to remember and so there&amp;rsquo;s a greater chance
that it&amp;rsquo;ll be written down and kept in the wallet along with the card.&lt;/p&gt;

&lt;p&gt;On the other hand, 4 digit PINs may not be suitable for a OTP sent as
part of a 2SV process and we don&amp;rsquo;t need to remember this for a long
time, so longer 8 digit PINs may be acceptable.&lt;/p&gt;

&lt;p&gt;The use case is important in determining the strength of a factor.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;A good MFA solution can strengthen the security of an environment;
even a 2SV solution (e.g. &lt;a href=&#34;https://support.google.com/accounts/answer/1066447?hl=en&#34;&gt;Google Authenticator 2SV&lt;/a&gt;) is much better than just requiring
a password.  I use Google Authenticator on &lt;a href=&#34;https://www.sweharris.org/post/2013-09-26-googleauth/&#34;&gt;my own servers&lt;/a&gt; if coming from an untrusted source.&lt;/p&gt;

&lt;p&gt;A large enterprise should require 2FA for staff entering their network
from the internet (eg setting up VPNs, or remote desktop).  For an
individual you may wish to setup 2SV on your email account (especially
since password reset emails are sent to them!).  For your retro-computing
web forum, though, you may not want to go to the effort.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;d like to see FIDO U2F get more adoption; &lt;a href=&#34;https://bugzilla.mozilla.org/show_bug.cgi?id=1065729&#34;&gt;Firefox doesn&amp;rsquo;t seem to
have it yet&lt;/a&gt;,
but it looks like more vendors &lt;a href=&#34;https://www.yubico.com/2016/07/over-a-dozen-services-supporting-fido-u2f/&#34;&gt;are planning it&lt;/a&gt;.  It&amp;rsquo;s a cheap, simple
solution to the &amp;ldquo;something you have&amp;rdquo; problem.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Encryption vs Hashing</title>
      <link>https://www.sweharris.org/post/2017-04-09-encryption_hashing/</link>
      <pubDate>Sun, 09 Apr 2017 17:51:36 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-04-09-encryption_hashing/</guid>
      <description>

&lt;p&gt;Let&amp;rsquo;s say you run an ecommerce web site.  As part of this people create
accounts.  Naturally those accounts have passwords.  Do you encrypt those
passwords before storing them in the database?&lt;/p&gt;

&lt;p&gt;All you people who put your hands up and answered yes&amp;hellip; put them down;
you&amp;rsquo;re wrong.  You should &lt;em&gt;hash&lt;/em&gt; the data instead.  This may sound like
a &amp;ldquo;tomato/tomato&amp;rdquo; thing, but it&amp;rsquo;s not.&lt;/p&gt;

&lt;p&gt;Encryption and hashing may both be &lt;em&gt;cryptographic&lt;/em&gt; in nature, but there&amp;rsquo;s a subtle difference between them.&lt;/p&gt;

&lt;h1 id=&#34;encryption&#34;&gt;Encryption&lt;/h1&gt;

&lt;p&gt;Encryption is the act of taking a plain text message and encoding it.
This process is &lt;em&gt;reversible&lt;/em&gt;; someone with the right knowledge could
take the cipher text (as the encoded data is known) and decrypt it back
to the original plain text.&lt;/p&gt;

&lt;p&gt;An early example that is sometimes taught to school kids is the &lt;a href=&#34;https://en.wikipedia.org/wiki/Caesar_cipher&#34;&gt;&amp;ldquo;Caesar
Cipher&amp;rdquo;&lt;/a&gt;.  Old usenet nerds may know of a special case of this; &amp;ldquo;ROT 13&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;With the Caesar cipher a number is picked, and the characters moved
forward that many.  So, for example, if the number was &amp;ldquo;3&amp;rdquo; then we would
move &amp;ldquo;A&amp;rdquo;-&amp;gt;&amp;ldquo;D&amp;rdquo;, &amp;ldquo;B&amp;rdquo;-&amp;gt;&amp;ldquo;E&amp;rdquo;, &amp;hellip; &amp;ldquo;X&amp;rdquo;-&amp;gt;&amp;ldquo;A&amp;rdquo;, &amp;ldquo;Y&amp;rdquo;-&amp;gt;&amp;ldquo;B&amp;rdquo;, &amp;ldquo;Z&amp;rdquo;-&amp;gt;&amp;ldquo;C&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;In this scenario the plain-text &amp;ldquo;HELLO THERE&amp;rdquo; would become &amp;ldquo;KHOOR WKHUH&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;To decrypt that string you would need to know the magic number (&amp;ldquo;3&amp;rdquo;), and
then rotate &lt;em&gt;backwards&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Now that&amp;rsquo;s a pretty simple cipher, and you wouldn&amp;rsquo;t use it in the real
world!&lt;/p&gt;

&lt;p&gt;Today you would use algorithms such as AES256 to encrypt the data, which
is the &lt;a href=&#34;https://en.wikipedia.org/wiki/Advanced_Encryption_Standard&#34;&gt;AES&lt;/a&gt;
algorithm with 256bit key sizes.&lt;/p&gt;

&lt;h2 id=&#34;use-cases&#34;&gt;Use cases&lt;/h2&gt;

&lt;p&gt;Typically encryption is used when the original plain text
needs to be protected &lt;em&gt;and&lt;/em&gt; be recoverable.  A &lt;a href=&#34;https://en.wikipedia.org/wiki/Password_manager&#34;&gt;password
manager&lt;/a&gt; would use
encryption to protect my passwords from being stolen.  Only someone
knowing the encryption key (me!) would be able to decode the values and
get my password back.&lt;/p&gt;

&lt;h2 id=&#34;symmetrical-vs-asymmetrical&#34;&gt;Symmetrical vs asymmetrical.&lt;/h2&gt;

&lt;p&gt;Algorithms such as AES are considered &lt;em&gt;symmetric&lt;/em&gt; because the same key
is used to encrypt and decrypt the data.  If you wanted to share data
with someone else then they also need to know this key.  Thus the key
is a &lt;em&gt;shared secret&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Asymmetrical encryption uses two different keys, which have a relationship
to each other.  A common one is the &lt;a href=&#34;https://simple.wikipedia.org/wiki/RSA_(algorithm%29) which is based on some clever facts around
prime numbers.  We typically call one of these keys the _public_ key, and
the other one the _private_ key (hence another name for this is&#34; title=&#34;public key
cryptography&#34;&gt;RSA algorithm&lt;/a&gt;.  The public key is used to encrypt the data.  It normally
doesn&amp;rsquo;t matter that the public key is known (hence the name).  The data
can only be decrypted if the private key is known.  This is the basis
for SSL/TLS encryption used on the internet.&lt;/p&gt;

&lt;h2 id=&#34;symmetric-and-asymmetric-working-together&#34;&gt;Symmetric and Asymmetric working together&lt;/h2&gt;

&lt;p&gt;Many asymmetric algorithms are slow and not always suitable for large
chunks of data.  RSA, for example, can&amp;rsquo;t encrypt data larger than
the key size.  In situations where we want asymmetric (e.g. the web)
what we can do is pick a random key and use a faster symmetric solution
for the data.  We use the slower RSA system to encrypt that random key,
and both the encrypted key and the encrypted data are sent to the other
person.  Using their private key they can decrypt the random value and
then use that to decrypt the main data.&lt;/p&gt;

&lt;h2 id=&#34;salting&#34;&gt;Salting&lt;/h2&gt;

&lt;p&gt;One problem with many cryptographic schemes is that the same plain-text
will lead to the same cipher text.  This means that an evil person looking
at the messages might be able to see patterns; if the word &amp;ldquo;OK&amp;rdquo; is
encrypted the same way each time then that evil person can make a guess.&lt;/p&gt;

&lt;p&gt;To avoid this a &lt;em&gt;salt&lt;/em&gt; value can be prepended to the plain-text before
encrypting.  This salt can be random; it really doesn&amp;rsquo;t matter what
it is.  Now the same plain text (&amp;ldquo;OK&amp;rdquo;) is made into a different message
each time, and so the encrypted data is different each time.&lt;/p&gt;

&lt;h1 id=&#34;hashing&#34;&gt;Hashing&lt;/h1&gt;

&lt;p&gt;So if we need to use encryption to get the data back, why did I say encryption
was wrong for storing customer passwords at the beginning of this post?&lt;/p&gt;

&lt;p&gt;Hashing is a &lt;em&gt;one way&lt;/em&gt; function.  The idea is to come up with a piece
of data that represents the original text.  In this scenario the
plain text is converted to a hash value.&lt;/p&gt;

&lt;p&gt;A simple case, if we said that &amp;ldquo;A&amp;rdquo;=1, &amp;ldquo;B&amp;rdquo;=2, &amp;ldquo;C&amp;rdquo;=3&amp;hellip; then we could
define a simple hash of just adding up the values.  Now the word
&amp;ldquo;HELLO&amp;rdquo; would be hashed as 52 ( 8+5+12+12+15 ).&lt;/p&gt;

&lt;p&gt;There is no way of getting back from &amp;ldquo;52&amp;rdquo; to the original plain text,
which is why these are called &amp;ldquo;one way&amp;rdquo; or &amp;ldquo;trap door&amp;rdquo; functions.&lt;/p&gt;

&lt;h2 id=&#34;use-cases-1&#34;&gt;Use cases&lt;/h2&gt;

&lt;p&gt;There are some common use cases for file integrity and checking.
For example, if I have a file I could generate a hash value for it.
Now at any point in the future I could re-compute the hash of file; if the hash
value is the same then I can be confident the file has not changed.
Similarly if I send you a copy of the file then you can compute the hash
and if it matches my copy then you can be confident you&amp;rsquo;ve received the
file.&lt;/p&gt;

&lt;p&gt;The other main use case are for passwords.  We don&amp;rsquo;t actually need to
store the customer password in our database; we can store the hash value.  Now
when the customer wants to login, we can calculate the hash of their
input; if it matches what we have saved we can be confident they entered
the right password.&lt;/p&gt;

&lt;h2 id=&#34;collisions&#34;&gt;Collisions&lt;/h2&gt;

&lt;p&gt;Now in the use cases I said &amp;ldquo;confident&amp;rdquo;&amp;hellip;&lt;/p&gt;

&lt;p&gt;The earlier hash algorithm is &lt;em&gt;bad&lt;/em&gt; and many strings would cause the same
result (&amp;ldquo;OHELL&amp;rdquo; would also give 52).  But if we pick a good hash then
we can give a probability of how likely it is for someone to enter
a different value that collides.  For example, the &lt;code&gt;md5&lt;/code&gt; algorithm
returns a 128bit number, which means that the chances of two pieces of
plain text colliding are 2&lt;sup&gt;-128&lt;/sup&gt;. If you had 2&lt;sup&gt;64&lt;/sup&gt;
pieces of plain-text then you might expect to find a collision; a very small chance indeed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Unfortunately, the &lt;code&gt;md5&lt;/code&gt; algorithm has a number of weaknesses, so
it&amp;rsquo;s no longer considered a strong hash.  Don&amp;rsquo;t use it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;With the right algorithm (eg SHA256) the risk of collision is considered
so tiny that the chance of someone entering the wrong password on a login
screen and getting the right hash is so vanishingly small that we can
ignore it.&lt;/p&gt;

&lt;h2 id=&#34;salting-1&#34;&gt;Salting&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s another problem with hashing, though.&lt;/p&gt;

&lt;p&gt;If I manage to get a copy of your hash file then I could try and guess
what plain text was used to generate the hash.  This is relatively
simple for password files because people tend to pick easy to remember
passwords.  I could simply &lt;em&gt;brute force&lt;/em&gt; attempt a lot of passwords
and see what ones match.  But there&amp;rsquo;s a simpler way; since the hash
has to be consistent for a given plain text we could precompute all
the common passwords and store the results.  The result is called a
&lt;a href=&#34;https://en.wikipedia.org/wiki/Rainbow_table&#34;&gt;rainbow table&lt;/a&gt;.  Sure,
they can be large but storage is cheap.&lt;/p&gt;

&lt;p&gt;Now, with a rainbow table, converting from the hash back to a password
is as simple a looking up the hash value.&lt;/p&gt;

&lt;p&gt;To make this harder we can use a &lt;em&gt;salt&lt;/em&gt; value.  This is randomly chosen
each time.  For SHA256 this salt is 16 characters, resulting in the
same plain text being hashed in one of 2&lt;sup&gt;96&lt;/sup&gt; different ways.
This can make rainbow tables impractical, and require the
attacker to use brute force.&lt;/p&gt;

&lt;p&gt;Now modern GPUs can make &lt;a href=&#34;https://www.troyhunt.com/our-password-hashing-has-no-clothes/&#34;&gt;brute force attacks fast&lt;/a&gt; - over 4.7 &lt;em&gt;billion&lt;/em&gt; md5s per second!
Even SHA-1 is fast; it may take hours per password&amp;hellip; but that&amp;rsquo;s not
much money on an AWS-GPU cluster for a determined attacker!&lt;/p&gt;

&lt;p&gt;Fortunately new algorithms (eg &lt;a href=&#34;https://en.wikipedia.org/wiki/Bcrypt&#34;&gt;bcrypt&lt;/a&gt;
and &lt;a href=&#34;https://en.wikipedia.org/wiki/PBKDF2&#34;&gt;PBKDF2&lt;/a&gt;) have been designed
to be slow to calculate.  It doesn&amp;rsquo;t matter if it takes your login page
an extra second to calculate the hash; it won&amp;rsquo;t do it very often!  But
slowing down brute force attacks can make them impractically expensive&amp;hellip;
today.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Update August 2020:  PBKDF2 is no longer a recommend cipher.  It&amp;rsquo;s weak-ish against GPU and ASIC attacks, which is the same sort of kit bitcoin miners use.  Instead the recommendation is to use &lt;a href=&#34;https://en.wikipedia.org/wiki/Argon2&#34;&gt;Argon2&lt;/a&gt; or &lt;a href=&#34;https://en.wikipedia.org/wiki/Scrypt&#34;&gt;scrypt&lt;/a&gt;.   This is a space that keeps changing as we learn more.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;

&lt;p&gt;So if hash files and salts are not resilient to brute force attacks,
why did I recommend hashing for customer password files?  Simply because
&lt;em&gt;encryption&lt;/em&gt; requires the server to have a copy of the decryption key
available (unless you have a &lt;a href=&#34;https://www.sweharris.org/post/2016-09-13-hsm/&#34;&gt;HSM&lt;/a&gt;), so theft
of an encrypted password file would also likely lead to theft of the
decryption key, making it even easier for the attacker.&lt;/p&gt;

&lt;p&gt;When you don&amp;rsquo;t need to recover the plain text, hashing is normally always
a better solution.  Just remember to pick a good algorithm that&amp;rsquo;s resistant
to brute force attacks!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Role Based Access Control</title>
      <link>https://www.sweharris.org/post/2017-04-02-rbac/</link>
      <pubDate>Sun, 02 Apr 2017 15:14:14 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-04-02-rbac/</guid>
      <description>

&lt;p&gt;Identity and Access Management (IAM) historically consists of the three A&amp;rsquo;s&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication

&lt;ul&gt;
&lt;li&gt;What acccount is being accessed?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Authorization

&lt;ul&gt;
&lt;li&gt;Is this account allowed access to this machine?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Access Control

&lt;ul&gt;
&lt;li&gt;What resources are you allowed to use?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Companies spend a lot of time and effort on the Authentication side
of the problem.  Single signon solutions for web apps, Active Directory
for servers (even Unix machines), OAuth for federated access to external
resources, 2 Factor for privileged access&amp;hellip;  there&amp;rsquo;s a lot of solutions
around and many companies know what they should be doing, here.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Well, small caveat&amp;hellip; we&amp;rsquo;re pretty good at centrally managed
&lt;em&gt;infrastructure&lt;/em&gt;, but there&amp;rsquo;s a tendancy for application developers
to try and introduce their own authentication store because it makes
their life easier; keep an eye out for that!  It will cause problems
down the line; when Harry leaves the company have you found &lt;em&gt;all&lt;/em&gt; the
places his account may be stored?  Do all these places follow your
controls around password management?  Do they follow properly audited
access processes?  And so on&amp;hellip;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;why-do-we-need-rbac&#34;&gt;Why do we need RBAC&lt;/h2&gt;

&lt;p&gt;The problem starts to happen when we look at Authorization and Access
Control.  There&amp;rsquo;s a tendency to grant access on an individual basis,
so you end up with &amp;ldquo;Tom can login to Servers 1,2,3,4; Dick can login
to Servers 1,2,3; Harry can login to Servers 1,2,4&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;On the face of it, this looks OK&amp;hellip; each person has the access they
need to do their job, and no more.&lt;/p&gt;

&lt;p&gt;But do they?  Tom, Dick and Harry are all colleagues; they work together.
Tom has called in sick and Dick is covering&amp;hellip; except Dick can&amp;rsquo;t login
to Server 4.  Oops!&lt;/p&gt;

&lt;p&gt;When Fred joins the team, what servers should he have access to?  One
&amp;ldquo;work-around&amp;rdquo; is to copy the access of someone else in the team (who?)
but this can still break when the company gets Server 5; who gets access
to that?&lt;/p&gt;

&lt;p&gt;This problem gets massively worse as the number of servers and number of
people grow.&lt;/p&gt;

&lt;h2 id=&#34;rbac&#34;&gt;RBAC&lt;/h2&gt;

&lt;p&gt;There were some hints in the previous section on how this can be solved;
we can define &lt;em&gt;roles&lt;/em&gt;.  &amp;ldquo;This is the SA team&amp;rdquo;; &amp;ldquo;The SA team can login
to Servers 1,2,3,4&amp;rdquo;; &amp;ldquo;Tom, Dick and Harry are SAs&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;We end up with a simple configuration:&lt;/p&gt;

&lt;p&gt;Role Description&lt;br&gt;
  Role Members&lt;br&gt;
  Role Permissions&lt;br&gt;&lt;/p&gt;

&lt;p&gt;When Fred joins the team he gets added to the &amp;ldquo;SA team&amp;rdquo; membership and,
magically, he has access to the servers he needs.&lt;/p&gt;

&lt;p&gt;People can also be in more than one role.  This tends to happen when
people move roles or have multiple responsibilities; for example some
may be a developer for application A &lt;em&gt;and&lt;/em&gt; application B; he would be
in both of those roles at the same time.&lt;/p&gt;

&lt;h2 id=&#34;servers-have-roles-too&#34;&gt;Servers have roles too!&lt;/h2&gt;

&lt;p&gt;The previous section mentioned &amp;ldquo;SA team can login to Servers 1,2,3,4&amp;rdquo;.
Imagine we also had &amp;ldquo;DBA team can login to Servers 1,2,3,4&amp;rdquo;.  When Server 5
comes along we need to work out all these rules and add the server to it.&lt;/p&gt;

&lt;p&gt;Instead we can say
  &amp;ldquo;This is a Unix Server&amp;rdquo;
  &amp;ldquo;This is a Server for Application A&amp;rdquo;
  &amp;ldquo;This is an Oracle Server&amp;rdquo;&lt;/p&gt;

&lt;p&gt;These are, effectively, roles for servers.  So now when Server 5 arrives
we can add it to the correct roles based on what it is going to be used
for.&lt;/p&gt;

&lt;h2 id=&#34;results&#34;&gt;Results&lt;/h2&gt;

&lt;p&gt;Now we can have rules that say things like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;          &amp;quot;Corporate Unix SAs&amp;quot; &amp;quot;can login to&amp;quot;     &amp;quot;All Unix machines&amp;quot;
          &amp;quot;Corporate Unix SAs&amp;quot; &amp;quot;can NOT login to&amp;quot; &amp;quot;Application A Machines&amp;quot;
           &amp;quot;Application A SAs&amp;quot; &amp;quot;can login to&amp;quot;     &amp;quot;Application A Machines&amp;quot;
    &amp;quot;Application A Developers&amp;quot; &amp;quot;can login to&amp;quot;     &amp;quot;App A Dev machines&amp;quot;
                 &amp;quot;Oracle DBAs&amp;quot; &amp;quot;can login to&amp;quot;     &amp;quot;Oracle servers&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;rsquo;s a pretty simple list.   We can extend this to access controls on
the machine as well; eg&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;quot;Application A SAs&amp;quot; &amp;quot;can run as root&amp;quot; &amp;quot;/bin/ls&amp;quot; &amp;quot;on Application A Machines&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;implementation&#34;&gt;Implementation&lt;/h2&gt;

&lt;p&gt;This is where things get a little harder.  From a technology perspective,
a role maps quite nicely into a group.  In the &lt;a href=&#34;https://www.sweharris.org/post/2016-04-16-unix-iam-history/&#34;&gt;old Unix days&lt;/a&gt; we had Netgroups to control this sort of thing.  With
Active Directory, security groups.  Or you may want to bring in third party
tooling to help manage this.&lt;/p&gt;

&lt;p&gt;The problem is in &lt;em&gt;defining&lt;/em&gt; the roles.  And you will get this wrong.
Everyone does!&lt;/p&gt;

&lt;p&gt;There is a temptation to minimise disruption when going from a disorganised
authorisations model to an RBAC one; we can attempt to &lt;em&gt;discover&lt;/em&gt; roles,
based on actual activity, perhaps role up via the HR database to a consistent
manager.  Tools exist to try and assist in this data analysis and third
party organisations are willing to provide professional services to assist
in this (for a fee, of course!).&lt;/p&gt;

&lt;p&gt;Alternatively you may want to &amp;ldquo;start fresh&amp;rdquo; and build a parallel structure
to your existing AAA solution, define the roles and then migrate servers
into it (e.g. application by application).  This can take more time, but
may result in a cleaner structure; we haven&amp;rsquo;t discovered roles; we&amp;rsquo;ve
defined them.&lt;/p&gt;

&lt;p&gt;Either way there&amp;rsquo;s a transition period and a testing period.  You won&amp;rsquo;t
do this in one weekend!&lt;/p&gt;

&lt;h2 id=&#34;other-benefits-of-rbac-auditing&#34;&gt;Other benefits of RBAC; auditing!&lt;/h2&gt;

&lt;p&gt;If you&amp;rsquo;re in a controlled environment with external audit constraints
then a typical question asked is &amp;ldquo;who can login to your application
servers, and why?&amp;rdquo;&lt;/p&gt;

&lt;p&gt;RBAC makes this easier to understand&amp;hellip;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My server is a &amp;ldquo;Unix machine&amp;rdquo; - Unix SAs can login to them.&lt;/li&gt;
&lt;li&gt;My server is a &amp;ldquo;Database server&amp;rdquo; - DBAs can login to them.&lt;/li&gt;
&lt;li&gt;My server runs Application A in production - AppA support can login to them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we can look into these groups and get the list of people.&lt;/p&gt;

&lt;p&gt;If the auditor asks &amp;ldquo;Why can Harry login this server&amp;rdquo; we can say &amp;ldquo;Harry
is a Unix SA; Unix SAs can login to my servers&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;It becomes very easy to explain to auditors the who and why.  And the
results are consistent; there&amp;rsquo;s no &amp;ldquo;Why can Tom login to server 4, but
Dick can&amp;rsquo;t?&amp;rdquo;&lt;/p&gt;

&lt;h2 id=&#34;beyond-rbac-abac&#34;&gt;Beyond RBAC - ABAC&lt;/h2&gt;

&lt;p&gt;RBAC is a simple model, but it requires role maintenance.  When someone
joins the company we need to have him added to roles; when someone
changes job we need to verify their new roles; we typically need regular
recertification that roles are still accurate.&lt;/p&gt;

&lt;p&gt;Attribute Based Access Control (ABAC), on the other hand, grants access
based on things we know about.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Tom is based in New York
Tom has job code 12345
Tom is a US Citizen
Tom has passed enhanced vetting
Tom reports to John
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With ABAC we can write rules based on those things:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;People who are based in the USA *AND*
       who are US Citizens or Green Card holders *AND*
       passed enhanced vetting *AND*
       have job code 12345
Can access Unix servers THAT
           are running government applications *AND*
           are running Oracle
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;rsquo;s one complicated rule!  But now it&amp;rsquo;s pretty much self-supporting;
all the information comes from upstream systems (e.g. the HR database,
the CMDB).  When Tom changes role, his job code changes and so he
automatically loses access.  Of course we rely on good data from those
upstream systems&amp;hellip;&lt;/p&gt;

&lt;p&gt;Now very few systems currently support ABAC; they&amp;rsquo;re group based and
thus RBAC.  It&amp;rsquo;s not uncommon to have batch jobs that run regularly and
try to build RBAC groups out of ABAC rules.  This isn&amp;rsquo;t as clean as
a full ABAC solution, but it allows you to write rules in an ABAC
manner while still working with RBAC technologies.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;It&amp;rsquo;s surprising, to me, how many organisations are still at the &amp;ldquo;unique
access rights&amp;rdquo; stage.  It just makes life hard, and there&amp;rsquo;s no consistency
of access and control.&lt;/p&gt;

&lt;p&gt;RBAC requires a management layer to process it properly, but when this has
been achieved then it becomes a lot easier to manage and control access in
an environment.&lt;/p&gt;

&lt;p&gt;Of course, if you only have one security boundary (everyone can access everything)
then such a process is just unnecessary overhead!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Lessons from a pentest run</title>
      <link>https://www.sweharris.org/post/2017-03-25-pentest/</link>
      <pubDate>Sat, 25 Mar 2017 15:06:47 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-03-25-pentest/</guid>
      <description>

&lt;p&gt;Over on Twitter, &lt;a href=&#34;https://twitter.com/TinkerSec&#34;&gt;@TinkerSec&lt;/a&gt; live tweeted
a pentest and created a &lt;a href=&#34;https://twitter.com/i/moments/845292659480690688&#34;&gt;moment thread&lt;/a&gt; of it.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s fascinating reading, and well worth reading.  Even non-technical
people should be able to get something out of this.  I like that it&amp;rsquo;s
a form of insider attack (industrial espionage by a newly hired employee?
disgruntled employee? vendor allowed unaccompanied access?) rather than
an external attack.&lt;/p&gt;

&lt;p&gt;One of the things that typically comes out of an event like this is a
series of action items.  I could imagine the following bullet points
on some powerpoint somewhere&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User education; remind them to never give out passwords or 2FA numbers to anyone.  Possible training course?&lt;/li&gt;
&lt;li&gt;USB lockdown; disable storage devices totally except for people on an exception list&lt;/li&gt;
&lt;li&gt;Time based One Time Passwords for IT infrastructure accounts&lt;/li&gt;
&lt;li&gt;Review all devices checking for disk encryption&lt;/li&gt;
&lt;li&gt;Lock support areas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You get the idea.  A nice solid list of action items that all sound
reasonable.&lt;/p&gt;

&lt;p&gt;The problem with such lists is that they end up focusing on one attack
path and closing that down.  We can see how Tinker changed tactics during
his test; one path is blocked, so try another.  If we shut down the path
he eventually used, would another one be found (block USB storage; use
a &lt;a href=&#34;https://hakshop.com/products/usb-rubber-ducky-deluxe&#34;&gt;rubber ducky&lt;/a&gt;
instead?).&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Aside&lt;/em&gt;: many Virtual Desktop (VDI) solutions provide some level of
control here; e.g. if you log out of your VDI session then the VM
is destroyed and next login is on a newly created VM, which makes
unquoted path attacks harder (your code doesn&amp;rsquo;t persist between
logins).  Similarly thin desktops typically don&amp;rsquo;t allow random USB
devices access (which I find annoying; it means I can&amp;rsquo;t use
&lt;a href=&#34;https://www.yubico.com/products/yubikey-hardware/fido-u2f-security-key/&#34;&gt;Ubikey U2F&lt;/a&gt; devices for 2FA).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is not to say that &lt;em&gt;prevention&lt;/em&gt; is a bad thing; it can raise the
bar and require smarter attackers.  It can prevent accidental data
breaches (e.g. someone copies important data to a USB stick, loses
it on the train) but you can always go too far down the rabbit hole
and end up doing the equivalent of &lt;a href=&#34;http://www.businessinsider.com/us-ally-used-3-million-dollar-patriot-missile-to-shoot-down-a-200-dollar-drone-2017-3&#34;&gt;destroying a $200 drone with a $3mm
missile&lt;/a&gt;.
Your time, effort and money may be better spent elsewhere.&lt;/p&gt;

&lt;p&gt;One such area is in &lt;em&gt;detection&lt;/em&gt;.  And, indeed, this is ultimately what
caught this attack; anomalous behaviour on a desktop (base64 encoded
powershell, of all things) led to the compromised machine being isolated
and security called.&lt;/p&gt;

&lt;p&gt;Intrusion Detection Systems (IDS) are the partners of IPS (Prevention).
They can highlight where IPS has been circumvented or avoided.  It
can take place in many places (network demarcation points such as
firewalls, routers; endpoints such as desktops and servers; central
infrastructure tools such as scanners and integrity monitors).  It should
even exist at the application layer (anomalous activity).&lt;/p&gt;

&lt;p&gt;IDS work better the more data they have so it is common to start feeding
logs into a central Security Operations Center (SOC).  A common form is
just to log everything to Splunk, and then let the SOC deal with it.&lt;/p&gt;

&lt;p&gt;But an IDS is pointless if there&amp;rsquo;s no knowledge behind the data.  A
tonne of data streams results in just noise.  We need to know what is
normal behaviour; what is expected; what &lt;em&gt;thresholds&lt;/em&gt; are normal (we expect
50 failed logins a minute from a user population of 10,000; if we see 500
then there&amp;rsquo;s odd stuff happening).  This requires data modelling.  Tools
exist to try and &amp;ldquo;self-learn&amp;rdquo; baseline activity, but these may sometimes
get confused and learn the wrong thing.  So teams onboarding to the SOC
must work to ensure their data is understood as information.  The SOC
needs to be aware of all their datastreams and potentially how the interact
in order to gain &lt;em&gt;knowledge&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;And then, finally, once suspicious activity has occured we need the ability
to take action.  Isolating a rogue device is good, but may not be viable
everywhere (&amp;ldquo;our IDS detected suspicious activity from server X, so we shut
down the network port&amp;hellip; oh, did we just break our primary trading platform
for 2 hours at the cost of $$$$?  Let me pack up my desk&amp;hellip;&amp;ldquo;) so the
response needs to be tuned to the type of activity and risk to the company.&lt;/p&gt;

&lt;p&gt;As we saw with IPS, there will always be gaps in coverage.  A common
refrain is &amp;ldquo;red teams have it easy; we have to close every security gap
but they just need to find one.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;Tinker turns this on its head; &amp;ldquo;Blue Team has it easy. All they need to
do is find ONE IoC. Red Team? We have to be perfect in every attack to
not get caught.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;As with IPS, IDS coverage won&amp;rsquo;t perfect.  Things will slip through.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Using tools and processes are an essential part of preventing an attacker
from succeeding in the first place.  However many responses to a break
are focused on the immediate issue.  To use an ITIL term; they are
&lt;em&gt;incident response&lt;/em&gt; focused, rather then &lt;em&gt;problem management&lt;/em&gt; focused.
Of course no one likes having a known vulnerability, so we will try
and close that gap, but sometimes we need to look at the bigger picture.&lt;/p&gt;

&lt;p&gt;First rule of security: your system &lt;em&gt;will&lt;/em&gt; be broken into.  So let&amp;rsquo;s
also focus on setting up tripwires and alarm bells.  A bank vault is
hard to break into (IPS), but we also have alarms that ring (IDS).
Detecting a breach is just as important as preventing them in the
first place.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Phishing and Certificate Transparency</title>
      <link>https://www.sweharris.org/post/2017-03-19-certificate_transparency/</link>
      <pubDate>Sun, 19 Mar 2017 13:23:00 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-03-19-certificate_transparency/</guid>
      <description>

&lt;p&gt;Many people are at a large risk of a &lt;a href=&#34;https://en.wikipedia.org/wiki/Phishing&#34;&gt;phishing attack&lt;/a&gt;.  In this scenario the person may receive an email that
&lt;em&gt;looks&lt;/em&gt; like it came from a legitimate source (e.g. their bank) and
encourages them to click a link that presents them with their bank login
page.  The user then attempts to login&amp;hellip;&lt;/p&gt;

&lt;p&gt;Except that site &lt;em&gt;isn&amp;rsquo;t&lt;/em&gt; their banking site.  It&amp;rsquo;s a mockup that looks
like the real one.  And they&amp;rsquo;ve now told their banking password to the
attacker.&lt;/p&gt;

&lt;p&gt;A variant on this, called &lt;em&gt;Spear Phishing&lt;/em&gt;, is specifically targetted
at a company; e.g. the website might look like an intranet login page,
and now the attacker has gained credentials to the company network; a situation
made worse by SSO solutions; that password may be the same password used
to login to your Windows desktop!&lt;/p&gt;

&lt;p&gt;Related to this (and playing into this) is &lt;a href=&#34;https://en.wikipedia.org/wiki/Typosquatting&#34;&gt;Typo Squatting&lt;/a&gt;; the bad website might be called &lt;code&gt;paypale.com&lt;/code&gt;,
for example.  Or &lt;code&gt;paipal.com&lt;/code&gt; or &lt;code&gt;paypa1.com&lt;/code&gt; or&amp;hellip;   the ways the
URL can be made to look similar to the original are unlimited.  They
need not even be that smart; &lt;code&gt;paypal_com.example.com&lt;/code&gt;?&lt;/p&gt;

&lt;h2 id=&#34;ssl-as-a-mitigation-or-not&#34;&gt;SSL as a mitigation&amp;hellip; or not!&lt;/h2&gt;

&lt;p&gt;In the early days of SSL it was very hard to get a certificate; you had
to prove to the Certificate Authority (CA) who you were, and there were checks
in place to prevent bad certificates from being issued.  We also wanted
to encourage people to only enter sensitive data, such as credit card
numbers, to an SSL encrypted site.  So we taught people to look for the
&amp;ldquo;green padlock&amp;rdquo;.  If there was no padlock then it is not safe.&lt;/p&gt;

&lt;p&gt;And this kinda worked, for a while.  The difficulty in getting a cert
meant that a green padlock was a level of trust.  And so this advice
mutated and started to be understood as &amp;ldquo;green padlock means it is safe&amp;rdquo;.
Which is &lt;em&gt;not&lt;/em&gt; quite the same thing.&lt;/p&gt;

&lt;p&gt;With &lt;a href=&#34;https://www.sweharris.org/post/2016-12-04-letsencrypt/&#34;&gt;automated &lt;em&gt;free&lt;/em&gt; certificates&lt;/a&gt;, such as those
from &lt;a href=&#34;https://letsencrypt.org&#34;&gt;LetsEncrypt&lt;/a&gt; I could request and get
a certificate for &lt;code&gt;www.paypal.com.sweharris.org&lt;/code&gt;.  In this scenario
a phisher could send potential victimes to a site that has the green
padlock.&lt;/p&gt;

&lt;p&gt;People learned the wrong lesson from the green padlock.&lt;/p&gt;

&lt;p&gt;Now there are some things we can do to help teach people (many companies
use services such as &lt;a href=&#34;https://phishme.com/&#34;&gt;PhishMe&lt;/a&gt; to run training
and test scenarios.  The use of &lt;a href=&#34;https://www.troyhunt.com/journey-to-an-extended-validation-certificate/&#34;&gt;Extended Validation Certificates&lt;/a&gt; can help
highlight good sites.  And, of course, teach people to not click links
and carefully inspect URLs before entering data.&lt;/p&gt;

&lt;p&gt;But even the best of people make mistakes.  I may have been phished once,
but the second after I realised this I changed the password on the account.
If it can happen to me then it can happen to anyone.&lt;/p&gt;

&lt;p&gt;Ideally, of course, CAs wouldn&amp;rsquo;t release certs for well known domains
(what legitimate reason do I have for &lt;code&gt;paypal.com.sweharris.org&lt;/code&gt;?)
but given the sheer number of sites in question (banks, other financial
institutions, government sites, commerce sites&amp;hellip;) and the typosquatting
and obfuscation problem, this is not really practical.&lt;/p&gt;

&lt;p&gt;The consequence of making it easy for the &amp;lsquo;good guys&amp;rsquo; to get SSL certs
means that it&amp;rsquo;s also easy for the &lt;em&gt;bad&lt;/em&gt; guys to get them as well.&lt;/p&gt;

&lt;p&gt;So what can companies do to protect their customers?&lt;/p&gt;

&lt;h2 id=&#34;certificate-transparency&#34;&gt;Certificate Transparency&lt;/h2&gt;

&lt;p&gt;Certificate Transparency (CT) came about as a result of a number
of errors made by CAs, such as mistakenly providing a cert for
a domain they shouldn&amp;rsquo;t have done, or a &lt;a href=&#34;https://www.wired.com/2011/03/comodo-compromise/&#34;&gt;hacker compromising a CA
partner&lt;/a&gt; to gain certs
for &lt;code&gt;google.com&lt;/code&gt; and similar.&lt;/p&gt;

&lt;p&gt;With CT every certificate issued is logged to a number of log services
by the CA, and those logs are open to the public.&lt;/p&gt;

&lt;p&gt;One easy to view site is &lt;a href=&#34;https://crt.sh&#34;&gt;crt.sh&lt;/a&gt;.  This is an easy to
use service.  You can enter the domain name you care about and get a list
of all the certs issued.&lt;/p&gt;

&lt;p&gt;For example, the certificates for this site:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.sweharris.org/images/crt_sh.png&#34; alt=&#34;sweharris.org certs&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Hmm, interesting&amp;hellip; why did I request a new cert on 2017/1/29, just 5
days after the previous one?  Digging deeper I can see that&amp;rsquo;s because
I added this site as a SAN entry to my default (non-SNI aware) cert.&lt;/p&gt;

&lt;h2 id=&#34;automation&#34;&gt;Automation&lt;/h2&gt;

&lt;p&gt;Of course these sorts of logs are fine for &amp;ldquo;eyes on glass&amp;rdquo; monitoring
but larger companies don&amp;rsquo;t want manual processing; automation is the
key.  Fortunately there are APIs available as well.  Symantec run a
log that produces nice JSON output that is easy to call.&lt;/p&gt;

&lt;p&gt;eg the call for this site would be:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;https://cryptoreport.websecurity.symantec.com/chainTester/webservice/ctsearch/search?keyword=sweharris.org
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A typical entry might look like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;      {
        &amp;quot;documentId&amp;quot;: &amp;quot;q1SpPQpqDh6nQoKQW5sl5CjPNbwBlMY6F7LE1K7vakQ=&amp;quot;,
        &amp;quot;serialNumber&amp;quot;: &amp;quot;03483b8d546d95fe3c1726b5f68eb5b9533a&amp;quot;,
        &amp;quot;commonName&amp;quot;: &amp;quot;www.sweharris.org&amp;quot;,
        &amp;quot;notAfter&amp;quot;: &amp;quot;2017-Feb-10&amp;quot;,
        &amp;quot;notBefore&amp;quot;: &amp;quot;2016-Nov-12&amp;quot;,
        &amp;quot;organization&amp;quot;: &amp;quot;&amp;quot;,
        &amp;quot;issuerCommonName&amp;quot;: &amp;quot;Let&#39;s Encrypt Authority X3&amp;quot;,
        &amp;quot;issuerOrganization&amp;quot;: &amp;quot;Let&#39;s Encrypt&amp;quot;,
        &amp;quot;subjectAlternativeNames&amp;quot;: [
          &amp;quot;sweharris.org&amp;quot;,
          &amp;quot;www.sweharris.org&amp;quot;
        ],
        &amp;quot;issuer&amp;quot;: &amp;quot;Let&#39;s Encrypt Authority X3&amp;quot;
      },
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It now becomes possible for a company to automate checking of CT logs
and compare them to their request system.  Any log entry that shows up
that doesn&amp;rsquo;t match a request can be flagged to the Security Operations
Center (SOC) for followup and investigation with the CA.&lt;/p&gt;

&lt;p&gt;Companies can also be proactive.  They can look for re-use of their
name elsewhere (so Paypal could search for any cert that has &lt;code&gt;paypal&lt;/code&gt;
in it).  They can also look for common typosquatted variations (although,
as previously noted, this isn&amp;rsquo;t a complete answer).  This can help
mitigate some of the phishing attacks attacks.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;CT logs are one way that a company can protect their customers from a
number of phishing attacks.  It&amp;rsquo;s not perfect, but it has benefits.&lt;/p&gt;

&lt;p&gt;Enterprise key management solutions may offer the ability to search
CT logs as part of their solution; if you&amp;rsquo;re looking at such a solution
then ask the vendor what they do about CT logs, and how integrated it is
in their solution.  They may even run their own CT log server!&lt;/p&gt;

&lt;p&gt;Other tools, such as CAA DNS records (a method of telling CAs which ones
are authorised to create keys) and &lt;a href=&#34;https://en.wikipedia.org/wiki/HTTP_Public_Key_Pinning&#34;&gt;HPKP&lt;/a&gt; to pin known good keys into the browser can also help
out with rogue certificate issuance (Comodo would refuse to issue a
cert for your domain if your CAA records says that only letsencrypt is
allowed!) but CT logs are a way of verifying what has been issued.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Offsite Backups in the cloud</title>
      <link>https://www.sweharris.org/post/2017-03-12-amazon-cloud-drive/</link>
      <pubDate>Sun, 12 Mar 2017 15:26:18 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-03-12-amazon-cloud-drive/</guid>
      <description>

&lt;p&gt;Part of any good backup strategy is to ensure a copy of your backup is
stored in a secondary location, so that if there is a major outage (datacenter
failure, office burns down, whatever) there is a copy of your data stored
elsewhere.  After all, what use is a backup if it gets destroyed at the
same time as the original?&lt;/p&gt;

&lt;p&gt;A large enterprise may do cross-datacenter backups, or stream them to a
&amp;ldquo;bunker&amp;rdquo;; smaller business may physically transfer media to a storage
location (in my first job &lt;em&gt;mumble&lt;/em&gt; years ago, the finance director would
take the weekly full-backup tapes to her house so we had at most 1 week of
data loss).&lt;/p&gt;

&lt;p&gt;With the internet now being so fast (my home connection is faster than my
LAN was 10 years ago!) offsite storage in the cloud is now a feasible
option, and a number of businesses have started up around this concept
allowing anyone, even home users, to have an offsite backup  (e.g.
Crashplan, Carbonite, Backblaze).  Many of these solutions require
an agent to be installed on your machine and it will &amp;ldquo;live&amp;rdquo; detect
changes and upload them to the cloud storage, which is nice.&lt;/p&gt;

&lt;p&gt;These services are priced in a number of ways (e.g. fixed price,
or per Terabyte).  They may even allow you to &amp;ldquo;bring your own storage&amp;rdquo;
(e.g. backup to an Amazon S3 pool you control).  You should also be
aware of network transfer charges.&lt;/p&gt;

&lt;h2 id=&#34;the-diy-solution&#34;&gt;The DIY solution&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;m an old-school Unix guy and do old-school backup solutions.  So each
server has a nightly job that does a dump (level 0 on Sunday, level 1 on
Monday, etc).  For my remote servers I &lt;code&gt;rsync&lt;/code&gt; the data back to my home
machine.  I have an LVM on here that stores all the backups for the past
2 weeks.   This works fine for data restores, but would be vulnerable
to my house burning down (for example); backups of my home machine and
the original data are in the same location.&lt;/p&gt;

&lt;p&gt;Until recently I had a physical server colocated in Canada and would
copy my files to that machine.  However I cancelled this service (it was
just too expensive and I didn&amp;rsquo;t need a full server; my existing virtual
machines did the job I needed) and started looking for an alternative
way for handling offsite files.&lt;/p&gt;

&lt;p&gt;I had spotted that Amazon now have a &lt;a href=&#34;https://www.amazon.com/clouddrive/&#34;&gt;Cloud
Drive&lt;/a&gt;.  What makes this service
attractive is that the $60/year option is unlimited.  I&amp;rsquo;ve read that
people have stored over 100Tbytes of data here.  Options such as Google
Drive charge $20/100Gb/Yr (or $100/Tb/yr) so if you store over 300Gb of
data then Amazon is cheaper.  Similarly Dropbox is $100/Tb/yr.  This makes
Amazon nice from a pricing perspective, but it&amp;rsquo;s not necessarily so well
supported as other options (eg Backblaze have dedicated customer support
for their backup/restore solutions and can even ship you a drive with your
data on&amp;hellip; for a fee, of course!).&lt;/p&gt;

&lt;p&gt;Now Amazon Cloud Drive (ACD) has agents for Windows and Mac but, of course,
not for Linux or Unix in general.  Fortunately people have coded to the ACD
API, and provided solutions such as &lt;a href=&#34;https://github.com/yadayada/acd_cli&#34;&gt;acd_cli&lt;/a&gt; or &lt;a href=&#34;http://rclone.org/&#34;&gt;rclone&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rclone&lt;/code&gt; looked attactive to me; it can act like &lt;code&gt;rsync&lt;/code&gt; but for Amazon
(and other) cloud drives.
In addition it can also &lt;em&gt;encrypt&lt;/em&gt; the data sent to the cloud which,
to me, is pretty important; I don&amp;rsquo;t want to become a statistic like
&lt;a href=&#34;https://www.troyhunt.com/the-capgemini-leak-of-michael-page-data-via-publicly-facing-database-backup/&#34;&gt;Capgemini&lt;/a&gt; and expose my backups to the world!&lt;/p&gt;

&lt;h2 id=&#34;rclone-configuration&#34;&gt;rclone configuration&lt;/h2&gt;

&lt;p&gt;Once I&amp;rsquo;d signed up for ACD (oh, hey, 3 month free trial so if this doesn&amp;rsquo;t
work out then I can cancel it!) it was pretty simple to configure &lt;code&gt;rclone&lt;/code&gt;
to talk to Amazon.  The &lt;code&gt;rclone config&lt;/code&gt; comamnd steps you through the
process (even on headless servers) and builds the config file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[Amazon]
type = amazon cloud drive
client_id = 
client_secret = 
token = {&amp;quot;access_token&amp;quot;:&amp;quot;***&amp;quot;,&amp;quot;token_type&amp;quot;:&amp;quot;bearer&amp;quot;,&amp;quot;refresh_token&amp;quot;:&amp;quot;***&amp;quot;, &amp;quot;expiry&amp;quot;:&amp;quot;***&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;rsquo;s all there is to it.  So now we can work directly from the
comamnd line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ rclone mkdir Amazon:foo
$ rclone copy ~/.profile Amazon:foo
2017/03/12 16:08:25 amazon drive root &#39;foo&#39;: Waiting for checks to finish
2017/03/12 16:08:25 amazon drive root &#39;foo&#39;: Waiting for transfers to finish
2017/03/12 16:08:26 
Transferred:   1.714 kBytes (1.715 kBytes/s)
Errors:                 0
Checks:                 0
Transferred:            1
Elapsed time:       900ms
$ rclone ls Amazon:foo
     1755 .profile
$ rclone delete Amazon:foo/.profile
2017/03/12 16:08:41 Waiting for deletions to finish
$ rclone rmdir Amazon:foo
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is pretty easy!  And, of course, the files are visible from a web browser.&lt;/p&gt;

&lt;h2 id=&#34;encryption&#34;&gt;Encryption&lt;/h2&gt;

&lt;p&gt;So far this data isn&amp;rsquo;t encrypted, so now we need to create an encrypted area.
The nice part of this is that you pick a subdirectory and specify that for
encryption.  Again &lt;code&gt;rclone config&lt;/code&gt; can build this for you; the resulting
config section looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[backups]
type = crypt
remote = Amazon:Backups
filename_encryption = off
password = **THATWOULDBETELLING*
password2 = **THATWOULDBETELLING*
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;remote&lt;/code&gt; line tells &lt;code&gt;rclone&lt;/code&gt; to use the &lt;code&gt;Backups&lt;/code&gt; directory on the
previously created &lt;code&gt;Amazon&lt;/code&gt; setup.&lt;/p&gt;

&lt;p&gt;An interesting line is &lt;code&gt;filename_encryption&lt;/code&gt;.  This can be &lt;code&gt;off&lt;/code&gt; or &lt;code&gt;standard&lt;/code&gt;.
In &lt;code&gt;off&lt;/code&gt; mode the &lt;em&gt;filename&lt;/em&gt; appears unchanged (well, &lt;code&gt;.bin&lt;/code&gt; gets added to
the end). In &lt;code&gt;standard&lt;/code&gt; mode the filename also gets encrypted.  For my
backups I didn&amp;rsquo;t care if people saw &lt;code&gt;linode/20170312.root.0.gz.bin&lt;/code&gt; as
the filename, and it makes it easy to see what is there via the web.&lt;/p&gt;

&lt;p&gt;I can now do &lt;code&gt;rclone copy /BACKUPS backups:&lt;/code&gt; and the program will recursively
copy all my data up.&lt;/p&gt;

&lt;p&gt;My home connection is a FIOS 75Mbit/s link.  Uploading averaged around 60Mbit/s,
so it took a while to upload 320Gb of data, but I left it overnight and it
worked.&lt;/p&gt;

&lt;p&gt;So now let&amp;rsquo;s see how this looks:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ rclone ls Amazon:Backups/linode/linode | sort -k+2 | head -3
     6358 20170223._datadisk.4.gz.bin
 80846055 20170223._news.4.gz.bin
     4214 20170223.log.bin

$ rclone ls backups:linode/linode | sort -k+2 | head -3       
     6310 20170223._datadisk.4.gz
 80826279 20170223._news.4.gz
     4166 20170223.log
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can see the filesizes are larger when looking at the raw data; that&amp;rsquo;s
part of the encryption overhead.&lt;/p&gt;

&lt;h3 id=&#34;verify&#34;&gt;Verify&lt;/h3&gt;

&lt;p&gt;Of course a backup isn&amp;rsquo;t any good if you can&amp;rsquo;t restore from it, so I
also tried downloading all the data as well.  I created another temporary
LVM and then restored all the data backup&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ rclone copy backups: .

[...]

Transferred:   341.269 GBytes (9.703 MBytes/s)
Errors:                 0
Checks:                 0
Transferred:          706
Elapsed time:  10h0m17.2s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That looks good!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ diff -r . /BACKUPS
Only in /BACKUP/: lost+found
Only in /BACKUP/penfold: 20170226._FastData.0.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;rsquo;s interesting&amp;hellip;  we learn two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Empty directories are not copied over&lt;/li&gt;
&lt;li&gt;Amazon has a &lt;em&gt;maximum&lt;/em&gt; filesystem limit; currently this is 50Gb.  Any file
larger than this won&amp;rsquo;t be copied.&lt;br /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The second entry has meant I&amp;rsquo;ve modified my backup software slightly; it now
splits the data files every 10Gb to ensure they&amp;rsquo;re small enough.&lt;/p&gt;

&lt;p&gt;But other than that, the data I got back was identical to the data I sent
up.&lt;/p&gt;

&lt;h3 id=&#34;worst-case-scenario&#34;&gt;Worst case scenario&lt;/h3&gt;

&lt;p&gt;When I wrote, earlier, about &lt;a href=&#34;https://www.sweharris.org/post/2016-12-11-backup-restore/&#34;&gt;backups&lt;/a&gt;
I mentioned the need to be aware of what software you need to perform
a recover.&lt;/p&gt;

&lt;p&gt;In this case I need two files; the &lt;code&gt;rclone&lt;/code&gt; binary and the &lt;code&gt;$HOME/.rclone.conf&lt;/code&gt;
configuration.  Now the binary I can store in the Amazon drive as well; if
I need it then I can download it via a web browser.&lt;/p&gt;

&lt;p&gt;More critically is the configuration file; this contains the encryption
strings for my data, and so I don&amp;rsquo;t want this easily visible.  So this
file I stored in my password manager (&lt;code&gt;lastpass&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;So now all I need to bootstrap my recover process is a web browser and
knowledge of the &lt;code&gt;lastpass&lt;/code&gt; password.&lt;/p&gt;

&lt;h3 id=&#34;simplified-restore&#34;&gt;Simplified restore&lt;/h3&gt;

&lt;p&gt;In the above tests I copied all the files back before comparing.  However,
&lt;code&gt;rclone&lt;/code&gt; also has experimental FUSE support for mounting.  It works best
for reading.  So now I could do:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo /bin/fusermount -u /mnt/Amazon
[1] +  Done                    sudo rclone mount backups: /mnt/Amazon &amp;amp;
$ 
$ sudo rclone mount backups: /mnt/Amazon &amp;amp;
[1]     29086
$ sudo diff /BACKUP/linode/linode/20170312.log /mnt/Amazon/linode/linode
$ sudo /bin/fusermount -u /mnt/Amazon                                         
[1] +  Done                    sudo rclone mount backups: /mnt/Amazon &amp;amp;
$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Direct access to the files without a lot of temporary storage needed!
Which might be important after a disaster, if I&amp;rsquo;m short of disk space :-)&lt;/p&gt;

&lt;h2 id=&#34;behaviour-change&#34;&gt;Behaviour change&lt;/h2&gt;

&lt;h3 id=&#34;media-storage&#34;&gt;Media storage&lt;/h3&gt;

&lt;p&gt;Unlimited storage has a few other benefits as well.  I have ripped all
my CDs to FLAC format.  That&amp;rsquo;s another 300Gb or so.  If my system
died I&amp;rsquo;d be annoyed to have to re-rip all the CDs (which may not be
available after a fire).  But with unlimited storage&amp;hellip;&lt;/p&gt;

&lt;p&gt;In this case I don&amp;rsquo;t want Amazon to see the filenames, just in case
they have some automated scanning tool looking for potentially pirated
content (I do own these CDs, but would an automation tool know that?).&lt;/p&gt;

&lt;p&gt;In this case the config entry looks like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[flac]
type = crypt
remote = Amazon:My_CDs
filename_encryption = standard
password = *IWONTTELL*
password2 = *IWONTTELL*
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now I can &lt;code&gt;rclone sync&lt;/code&gt; my FLAC files up.  Encrypted filenames look a
little odd:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ rclone ls Amazon:My_CDs | head -3
 30038497 c87a5pke85pd9ev7gp52aftecj8eokp19p2gn900pkkdb9ngr4n0/042hle8jn609itgohdh0q4gt6q7b3smbndn1cfjkklnsm2qm5l06u7au2ufme7jgne1oc8c7b68j4oarc9ebgks6faufrdeel3qv5j0
 32853891 c87a5pke85pd9ev7gp52aftecj8eokp19p2gn900pkkdb9ngr4n0/p705nk3k7j9ns64ki3bf7go7c8jq9q439j2avlcu6ipbpi4qvjmg
 23424207 c87a5pke85pd9ev7gp52aftecj8eokp19p2gn900pkkdb9ngr4n0/bf8e4mj9d7184f3021mdhbgua876d40stfa18ao5kfjl2sinaie805qc12r86f1jc32flct9ova8i
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again I verified the data I uploaded looked correct.&lt;/p&gt;

&lt;p&gt;Amazon now claims I&amp;rsquo;m using 650Gb of storage.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m now thinking whether I should also upload my ripped DVDs as well.  I
don&amp;rsquo;t see why not&amp;hellip;&lt;/p&gt;

&lt;h3 id=&#34;unlimited-backups&#34;&gt;Unlimited backups&lt;/h3&gt;

&lt;p&gt;Previously my backups retained only 14 days of history.  The overnight
process would delete files over that age, to keep disk usage in check.&lt;/p&gt;

&lt;p&gt;But with unlimited storage I could start keeping offsite backups for
months, if not years.&lt;/p&gt;

&lt;p&gt;This also helps with any possible ransomware issue; if something did
encrypt my local files &lt;em&gt;and&lt;/em&gt; corrupted the backups but kept the sync
process unbroken then the last 14 days of offsite backups might get
broken, but older files won&amp;rsquo;t show locally and so won&amp;rsquo;t be touched.
Annoying but not critical.&lt;/p&gt;

&lt;h2 id=&#34;automation&#34;&gt;Automation&lt;/h2&gt;

&lt;p&gt;With the backups and music now available, I can automate the offsite
copying as part of the overnight job:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/bin/ksh -p

rc()
{
  echo
  cd /$1 || exit
  /home/sweh/bin/rclone --stats=0 --max-size=40000M --config /home/sweh/.rclone.conf $2 . $3:
}

rc /BACKUP copy backups
rc /Media/audio sync flac
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note the the backup uses &lt;code&gt;copy&lt;/code&gt; (so new files get copied up, old files get
left) but the music uses &lt;code&gt;sync&lt;/code&gt;; if I sell or otherwise get rid of a CD
then I delete the flac files and the offsite copy will also get deleted.&lt;/p&gt;

&lt;p&gt;Today was Sunday, so a level 0 backup.  The output from the job reports
that it took just over 4 hours to upload all the backups:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;2017/03/12 12:46:51 Encrypted amazon drive root &#39;Backups&#39;: Waiting for checks to
 finish
2017/03/12 12:46:51 Encrypted amazon drive root &#39;Backups&#39;: Waiting for transfers
 to finish
2017/03/12 13:56:15
Transferred:   117.701 GBytes (7.795 MBytes/s)
Errors:                 0
Checks:               650                                   
Transferred:           48    
Elapsed time:  4h17m41.2s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The daily incremental typically takes under 7 minutes.&lt;/p&gt;

&lt;h2 id=&#34;limitations&#34;&gt;Limitations&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;rclone&lt;/code&gt; and ACD have some limitations.  These are what I&amp;rsquo;ve hit, so far:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;No files larger than 50Gb&lt;/li&gt;
&lt;li&gt;Empty directories are not copied&lt;/li&gt;
&lt;li&gt;Symbolic links aren&amp;rsquo;t copied  (the latest DEV version has an option to &lt;em&gt;follow&lt;/em&gt; links, but can&amp;rsquo;t copy the link itself)&lt;/li&gt;
&lt;li&gt;Large filenames (eg over 160chars) break if using filename encryption&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Cloud storage for offsite backups are now a viable technology&amp;hellip; if you
have a fast enough internet connection.  Beware of hidden costs in your
tool of choice and make sure you can recover from a complete failure of
your hardware.&lt;/p&gt;

&lt;p&gt;In my case &lt;code&gt;rclone&lt;/code&gt; and ACD make a good scriptable solution.&lt;/p&gt;

&lt;p&gt;There is now no reason for home users to not have offsite solutions, just
like large enterprises!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Abusing LD_PRELOAD for fun and profit</title>
      <link>https://www.sweharris.org/post/2017-03-05-ld-preload/</link>
      <pubDate>Sun, 05 Mar 2017 18:10:03 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-03-05-ld-preload/</guid>
      <description>

&lt;p&gt;The &lt;a href=&#34;https://en.wikipedia.org/wiki/Executable_and_Linkable_Format&#34;&gt;ELF format&lt;/a&gt;
is pretty common across various unix versions, having superseded previous
binary formats such as &lt;a href=&#34;https://en.wikipedia.org/wiki/A.out&#34;&gt;a.out&lt;/a&gt; and
&lt;a href=&#34;https://en.wikipedia.org/wiki/COFF&#34;&gt;COFF&lt;/a&gt;.  Pretty much, today, if you
see a unix binary then it&amp;rsquo;s probably ELF format.&lt;/p&gt;

&lt;p&gt;One of features of the ELF format is that the run time linker can be
smart about how it resolves dependencies, and this smartness can be
tuned.  A typical tuning many people know is the &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt; variable, which
can be used to add new directories to be searched for the needed libraries.&lt;/p&gt;

&lt;p&gt;Another one, the focus of this entry, is &lt;code&gt;LD_PRELOAD&lt;/code&gt;.  This can
be used to &lt;em&gt;force&lt;/em&gt; a library to be loaded and this can be used to
alter the way the standard libc calls are processed.&lt;/p&gt;

&lt;p&gt;This entry may get a little more technical than normal for this blog; I
just felt the need to post some code!  I&amp;rsquo;ll present three unusual
use cases:&lt;/p&gt;

&lt;h2 id=&#34;the-snowflake&#34;&gt;The snowflake&lt;/h2&gt;

&lt;p&gt;In small companies or self-managed departments we typically have usernames
that are easy to use.  So my login may be &lt;code&gt;sweh&lt;/code&gt; or &lt;code&gt;sweharris&lt;/code&gt; or
&lt;code&gt;stephen&lt;/code&gt; or similar.   This is nice for humans, and makes it easy; an
&lt;code&gt;ls&lt;/code&gt; or a &lt;code&gt;ps&lt;/code&gt; will show the username and the human looking at it will
know what person is really being referenced.  Unfortunately this isn&amp;rsquo;t
scalable (what if you have two people named &amp;ldquo;Stephen&amp;rdquo;).  Larger companies
tend to give people &lt;em&gt;generated&lt;/em&gt; names.  The login name may be random
or refer to the employee ID.  Now &lt;code&gt;xyz123ab&lt;/code&gt; or &lt;code&gt;x123456&lt;/code&gt; doesn&amp;rsquo;t
really help.&lt;/p&gt;

&lt;p&gt;I had to deal with a manager who ran servers that were being migrated
from &amp;ldquo;self-managed&amp;rdquo; into the corporate management tool.  Of course this
meant the &amp;ldquo;fred&amp;rdquo; account now had to become &amp;ldquo;z987654&amp;rdquo; and he was angry.
He demanded to be a unique and special snowflake and keep human friendly
names.  We weren&amp;rsquo;t going to do this, but it gave me an idea for a joke.
I could create a &lt;code&gt;snowflake.so&lt;/code&gt; library that could be pre-loaded.  It
would override the normal &lt;code&gt;getpwuid()&lt;/code&gt; call and &lt;em&gt;rewrite&lt;/em&gt; the results.&lt;/p&gt;

&lt;p&gt;Ultimately, after the Managing Director told him to shut up, he gave
up.&lt;/p&gt;

&lt;p&gt;Now a full version of the code had configuration files, but here is a
simple variant; it will replace the current user&amp;rsquo;s username with a
variable:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-C&#34;&gt;/* This routine intercepts getwpuid()
 * It will call the original, and if the called
 * uid == getuid() and $OVERRIDE_USER is set then
 * replaces the username with $OVERRIDE_USER
 *
 * gcc -o getpwuid_modify.so -fPIC -shared getpwuid_modify.c -ldl
 * export LD_PRELOAD=$PWD/getpwuid_modify.so
 * export OVERRIDE_USER=&amp;quot;dummy_username&amp;quot;
 * run the app
 * unset LD_PRELOAD
 */

#define _GNU_SOURCE
#include &amp;lt;sys/types.h&amp;gt;
#include &amp;lt;pwd.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;dlfcn.h&amp;gt;

struct passwd *getpwuid(uid_t uid)
{
  static void * (*func)();
  static uid_t my_uid;
  static char *override;
  struct passwd *p;

  if(!func)
  {
    func = (void *(*)()) dlsym(RTLD_NEXT, &amp;quot;getpwuid&amp;quot;);
    my_uid = getuid();
    override = getenv(&amp;quot;OVERRIDE_USER&amp;quot;);
  }

  p=func(uid);
  if (p &amp;amp;&amp;amp; uid == my_uid &amp;amp;&amp;amp; override)
    p-&amp;gt;pw_name=override;

  return(p);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What this code does is intercept the &lt;code&gt;getpwuid&lt;/code&gt; function.  It then looks
for the &lt;em&gt;original&lt;/em&gt; function and calls that, then manipulates the result.&lt;/p&gt;

&lt;p&gt;To the calling program we just get a different string:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-C&#34;&gt;$ gcc -o getpwuid_modify.so -fPIC -shared getpwuid_modify.c -ldl
$ export LD_PRELOAD=$PWD/getpwuid_modify.so
$ whoami
sweh
$ OVERRIDE_USER=root whoami
root
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let&amp;rsquo;s hope there&amp;rsquo;s no programs that test the result of &lt;code&gt;whoami&lt;/code&gt; to
determine what functions are allowed!&lt;/p&gt;

&lt;h2 id=&#34;shifting-time&#34;&gt;Shifting time&lt;/h2&gt;

&lt;p&gt;Recently, on twitter, a friend asked if there was a good way of setting
his computer clock 5 minutes fast.  I guess he&amp;rsquo;s one of these people who
needs his alarm to start 5 minutes early.  Now you don&amp;rsquo;t want to play with
the system clock because NTP would fight you.   The &lt;em&gt;normal&lt;/em&gt; way would be
to create your own unique tzdata entry (easily based off your local timezone).
This will work for most people because their TZ rules don&amp;rsquo;t change often.&lt;/p&gt;

&lt;p&gt;Or you can cheat and override the library calls :-)&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-C&#34;&gt;/* This routine intercepts time() and clock_gettime() adds 300 seconds.
 *
 * gcc -o time_modify.so -fPIC -shared time_modify.c -ldl
 * export LD_PRELOAD=$PWD/time_modify.so
 * run the app
 * unset LD_PRELOAD
 */

#define _GNU_SOURCE
#include &amp;lt;sys/types.h&amp;gt;
#include &amp;lt;time.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;dlfcn.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;

time_t time(time_t *tloc)
{
  static time_t (*func)();
  time_t t;

  if(!func)
  {
    func = (time_t (*)()) dlsym(RTLD_NEXT, &amp;quot;time&amp;quot;);
  }

  t=func(tloc) + 300;
  if (tloc) *tloc=t;

  return(t);
}

int clock_gettime(clockid_t clk_id, struct timespec *tp)
{
  static int i;
  static int (*func)();

  if(!func)
  {
    func = (int (*)()) dlsym(RTLD_NEXT, &amp;quot;clock_gettime&amp;quot;);
  }

  i=func(clk_id,tp);
  tp-&amp;gt;tv_sec += 300;

  return(i);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can see the code logic is very very similar and that multiple functions
can be overridden.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-C&#34;&gt;$ date ; LD_PRELOAD=$PWD/time_modify.so date
Sun Mar  5 18:48:05 EST 2017
Sun Mar  5 18:53:05 EST 2017
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I think he eventually went with timezone creation; it&amp;rsquo;s pretty easy for
America/New_York :-)&lt;/p&gt;

&lt;h2 id=&#34;overcoming-license-restrictions&#34;&gt;Overcoming license restrictions&lt;/h2&gt;

&lt;p&gt;This one was big in the 90s.  Sun SPARC servers had an NVRAM chip, and
each host had a unique &lt;code&gt;hostid&lt;/code&gt; value.  Some licensed software had a
license file that was based on this hostid.  If you tried to run it on
another machine then it&amp;rsquo;d fail to start.&lt;/p&gt;

&lt;p&gt;A number of solutions were available for this, including reprogramming
the NVRAM, but a common one was to use LD_PRELOAD.&lt;/p&gt;

&lt;p&gt;In this case the code is a lot simpler; we don&amp;rsquo;t need to call out to
the original routine or do anything conditional; just return the number
we want.
(the compile sequence is different here; it&amp;rsquo;s for Solaris)&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-C&#34;&gt;long gethostid(void) {
 return 0x12345678;
}

$ gcc -fPIC -c newhostid.c
$ gcc -shared -o newhostid.so newhostid.o
$ export LD_PRELOAD=/tmp/newhostid.so
$ /usr/bin/hostid
12345678
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course this was &lt;em&gt;never&lt;/em&gt; used to allow license keys to be reused on
multiple servers at the same time.  Oh no, that would be wrong&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;LD_PRELOAD&lt;/code&gt; isn&amp;rsquo;t really something I&amp;rsquo;d recommend for production
quality code.  I can see it being useful during development (&amp;ldquo;I want to
test this new function without rebuilding a whole library&amp;rdquo;) and, as can
be seen, it can be used to circumvent some forms of protection.  But I
wouldn&amp;rsquo;t consider it supportable!&lt;/p&gt;

&lt;p&gt;And, no, you can&amp;rsquo;t use it against &lt;em&gt;setuid&lt;/em&gt; programs; the linker ignores
these variables in this case.  You can&amp;rsquo;t make &lt;code&gt;su&lt;/code&gt; give you a root
shell by overriding library calls :-)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Can you control the entry points to your network?</title>
      <link>https://www.sweharris.org/post/2017-02-20-entry-points/</link>
      <pubDate>Mon, 20 Feb 2017 19:12:53 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-02-20-entry-points/</guid>
      <description>

&lt;p&gt;One of the major threats that companies are concerned about is
&amp;ldquo;insider threat&amp;rdquo;.  According to some Data Breach Incident Response (DBIR)
analyses, insider threat may be the 2nd or 3rd major reason for data
loss.  It&amp;rsquo;s interesting to note that the insider threat is way down in
the actual number of incidents, but they count for a larger number of
successful data loss incidents because the insider knows where the
data is, may have legitimate access to the data, and may know the
controls that need to be bypassed to exfiltrate it.  &lt;a href=&#34;https://en.wikipedia.org/wiki/Edward_Snowden&#34;&gt;Snowden&lt;/a&gt; may be the most well known of these types
of incidents, especially in the US.&lt;/p&gt;

&lt;p&gt;Related to this is the &lt;em&gt;ex&lt;/em&gt;-Insider.  Someone who used to work for
you and no longer does.  They also know where the data is, what controls
you have, and may know passwords to access the data.  When someone
leaves, can you be sure that their access to data has been revoked?&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;http://www.theregister.co.uk/2017/02/18/it_admin_/&#34;&gt;A recent story&lt;/a&gt;
can highlight what happens if a privileged insider is let go, but
his access not fully revoked.&lt;/p&gt;

&lt;p&gt;So how can we defend against this sort of malicious ex-Insider?&lt;/p&gt;

&lt;h2 id=&#34;network-access&#34;&gt;Network access&lt;/h2&gt;

&lt;p&gt;If you can&amp;rsquo;t get access to the network in the first place then it&amp;rsquo;s
a lot harder to attack servers and services!&lt;/p&gt;

&lt;p&gt;This person gained access via a VPN.  It&amp;rsquo;s not stated, but looking at
the &lt;a href=&#34;https://regmedia.co.uk/2017/02/18/johnson_indictment.pdf&#34;&gt;indictment&lt;/a&gt;
it seems as if this person had a company Cisco Linksys router; likely
this was preconfigured to connect to the corporate VPN automatically,
and this was disabled&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lesson: Ensure all remote access solutions for an ex-Insider are
terminated immediately.  If this is a user based VPN where the user
needs to enter their username and credentials then ensure those credentials
are terminated; if this is a device based VPN then ensure the device&amp;rsquo;s
access is revoked.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now a truly malicious person could have planned ahead and created their
own backdoor network; eg a process on a server that makes outgoing tunnel
requests via the web proxy, or a piece of software installed on a secretary&amp;rsquo;s
desktop, or even a small device that plugs into the network (these can be
so small now that they can plug in to a desktop port, and the real desktop
PC plugged into that, and if you&amp;rsquo;re not looking carefully then you&amp;rsquo;ll never
spot it).  There are lots of ways that remote access malware can work; your
malicious ex-Insider could use any of these.&lt;/p&gt;

&lt;p&gt;So although we can control the front door, we can&amp;rsquo;t always determine if
there&amp;rsquo;s a rogue backdoor.  So we need further protection&lt;/p&gt;

&lt;h2 id=&#34;connecting-to-a-server&#34;&gt;Connecting to a server&lt;/h2&gt;

&lt;h3 id=&#34;personal-accounts&#34;&gt;Personal accounts&lt;/h3&gt;

&lt;p&gt;Typically you need to provide a credential to login to a server!  If &amp;ldquo;Jim&amp;rdquo;
wants to login, he&amp;rsquo;ll normally login with the &amp;ldquo;jim&amp;rdquo; account.  So we need
to make sure that Jim&amp;rsquo;s account is deleted.  Many regulatory authorities
use the word &amp;ldquo;immediately&amp;rdquo;, but in practice this may be triggered by
the HR system and processed in batch overnight.  However you need to have
a manual process to perform emergency removals just in case that batch
process is too slow.   This, of course, means you need a good Identity
and Access Management (I&amp;amp;AM) program.  Whether you use Active Directory (and
hook your Unix machines into that) or LDAP or even distributed password
files, doesn&amp;rsquo;t matter; you need to manage them&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lesson: Delete ex-Insider personal accounts ASAP&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;shared-accounts&#34;&gt;Shared accounts&lt;/h3&gt;

&lt;p&gt;Even if you delete Jim&amp;rsquo;s account, does he know the passwords for any
other accounts?  Does he know the &lt;code&gt;root&lt;/code&gt; account password?  You better
change that.  What about the &lt;code&gt;oracle&lt;/code&gt; account?  &lt;code&gt;sybase&lt;/code&gt;?  The account
your application runs under?  Your &lt;em&gt;router&lt;/em&gt; admin passwords?&lt;/p&gt;

&lt;p&gt;These non-human &amp;ldquo;functional&amp;rdquo; accounts are a common weak point.  They&amp;rsquo;re
all privileged accounts, but the password is commonly shared amongst
team members.  If you have a good I&amp;amp;AM program then you may be able
to change these passwords&amp;hellip; but are you sure you know where they all live?&lt;/p&gt;

&lt;p&gt;Ideally these accounts should have passwords stored in a &lt;em&gt;password vault&lt;/em&gt;,
requiring a &amp;ldquo;break glass&amp;rdquo; process if any human ever needs to know them;
this process will change the password within a few hours of a human being
told what it is.&lt;/p&gt;

&lt;p&gt;Alternatively a &amp;ldquo;privileged access&amp;rdquo; gateway may be used; this can use
the vault to automatically log a user in (using the user&amp;rsquo;s own 2FA
credentials) and audit their activity.  Now no human ever needs to know
the password.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lesson: Stop sharing passwords for functional accounts.  Use a good
privileged access management program to ensure that the ex-Insider&amp;rsquo;s
knowledge expires quickly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;alternate-credentials&#34;&gt;Alternate credentials&lt;/h3&gt;

&lt;p&gt;Not all login access is done via passwords.  A common alternative is
to use &lt;a href=&#34;https://www.sweharris.org/post/2016-09-05-sshkeys/&#34;&gt;SSH public key authentication&lt;/a&gt;.  This
brings in a new set of challenges.  Our malicious ex-Insider may have
planned ahead and added &lt;em&gt;his&lt;/em&gt; keys to another person&amp;rsquo;s account.  Now,
when Jim is terminated, he can use these keys to login as Harry.  As
far as the system is concerned, this &lt;em&gt;is&lt;/em&gt; Harry.  Deleting Jim&amp;rsquo;s account
doesn&amp;rsquo;t help, now!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lesson: Ensure any alternate authentication tokens are properly managed.
If you&amp;rsquo;re using SSH public keys then you may want to look into a key
manager solution to ensure that &amp;ldquo;rogue&amp;rdquo; keys haven&amp;rsquo;t been added.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;local-rogue-accounts&#34;&gt;Local &amp;ldquo;rogue&amp;rdquo; accounts&lt;/h3&gt;

&lt;p&gt;Related to rogue credentials, we may also have rogue accounts!  It&amp;rsquo;s not
too unusual for a lazy SA to create a second privileged account (&amp;ldquo;jimroot&amp;rdquo;)
which he can access, bypassing the privileged access management system.
They justify this to themselves as an efficiency gain (it is!) but it
shouldn&amp;rsquo;t be allowed.  However our malicious ex-Insider may also have
planned ahead and created some of these accounts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lesson: A full I&amp;amp;AM system must also be able to track and audit any
local accounts created outside of the central tool.  They should be
handled appropriately (deleted? disabled? brought into central control?)
and shouldn&amp;rsquo;t be allowed to be kept uncontested.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;control-systems&#34;&gt;Control systems&lt;/h2&gt;

&lt;p&gt;Typically environments also have non-PC/non-server environments.  You may
have IP telephony; your door access systems may be network connected; your
building temperature control systems may be networked; your industrial
control systems may be networked (see &lt;a href=&#34;https://en.wikipedia.org/wiki/Stuxnet&#34;&gt;Stuxnet&lt;/a&gt;).  Many of these systems can&amp;rsquo;t be controlled the same way as
your servers and desktops; they&amp;rsquo;re not smart enough to hook into centralised
systems or may have low-entry PINs that are shared.  Such systems should
be &lt;em&gt;firewalled&lt;/em&gt; off from the main network and protected by strong &amp;ldquo;jumphost&amp;rdquo;
servers, which may require 2FA to ensure the authenticating user has permission
to access the device (and also log their activity)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lesson: Weaker devices should be network segregated and protected.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve only covered a small subset things that can be, and should be,
controlled.  By focusing on this area (I&amp;amp;AM, Privileged access, jumphosts)
we can mitigate a lot of the risk of an ex-Insider.  At the same time
we&amp;rsquo;re also mitigating the risk of a &lt;em&gt;current&lt;/em&gt; insider attack because we&amp;rsquo;re
handling privileged access at the same time!&lt;/p&gt;

&lt;p&gt;This isn&amp;rsquo;t to say we shouldn&amp;rsquo;t also have additional controls in place
around server changes (stop a malicious insider from planting bad code),
network access controls, external gateway monitoring (web proxies; DNS
servers; etc).  There&amp;rsquo;s a lot that can be done there as well.&lt;/p&gt;

&lt;p&gt;The number one control is to stop an attacker from getting a foothold on
your network at all.  However if that does happen (and it &lt;em&gt;will&lt;/em&gt; happen)
then we can make sure that we have secondary controls, such as proper
I&amp;amp;AM systems, to limit the attack - especially from an ex-Insider.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Managing the cloud management layer</title>
      <link>https://www.sweharris.org/post/2017-02-13-cloud-management-layer/</link>
      <pubDate>Mon, 13 Feb 2017 14:12:32 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-02-13-cloud-management-layer/</guid>
      <description>&lt;p&gt;A typical cloud engagement has a &lt;em&gt;dual responsibility&lt;/em&gt; model.  There&amp;rsquo;s
stuff that can be considered &amp;ldquo;below the line&amp;rdquo; and is the responsibility
of the cloud service provider (CSP) and there&amp;rsquo;s stuff above the line,
which is the responsibility of the customer.&lt;/p&gt;

&lt;p&gt;Amazon have a &lt;a href=&#34;https://aws.amazon.com/compliance/shared-responsibility-model/&#34;&gt;good example&lt;/a&gt; for their IaaS:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href=/images/NewSharedResponsibilityModel.png&gt;&lt;img src=/images/NewSharedResponsibilityModel.png width=516px height=263px border=1&gt;&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Where the line lives will depend on the type of engagement; the higher
up the abstraction tree (IaaS-&amp;gt;PaaS-&amp;gt;SaaS) the more the CSP has responsibility.&lt;/p&gt;

&lt;p&gt;But there&amp;rsquo;s a part of this that is frequently &lt;em&gt;missed&lt;/em&gt;, and that&amp;rsquo;s the
line itself.  This line is typically where the CSP exposes controls to
the customer (&amp;ldquo;self service&amp;rdquo; is part of the cloud model).  For Amazon
this may be the console where you can spin up a new VPC, new VMs, change
firewall rules, modify VPC-VPC communication and so on.&lt;/p&gt;

&lt;p&gt;This is clearly critical for a secure cloud offering.  What use is there
in defining a firewall if the console can be used to create a new VM with
a connection to the internet and bypass this firewall?&lt;/p&gt;

&lt;p&gt;We need to manage the management layer.  Otherwise this layer can
be used to bypass controls and create a shadow IT environment.&lt;/p&gt;

&lt;p&gt;What this means will depend on your organisations stance and controls;
is an audit and reporting control (detective) sufficient or do you want
pro-active automated control over the management layer?  Can your CSP
provide the automation you need?&lt;/p&gt;

&lt;p&gt;For an enterprise we may need to consider some questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who has access to this management layer (privileged access)&lt;/li&gt;
&lt;li&gt;Who has access to resources (end users)&lt;/li&gt;
&lt;li&gt;Who logged in?&lt;/li&gt;
&lt;li&gt;Who failed to login?&lt;/li&gt;
&lt;li&gt;What activities were performed&lt;/li&gt;
&lt;li&gt;What is the current configuration state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You&amp;rsquo;ll note these are the same sort of questions that an application
control process would also ask; that&amp;rsquo;s not a surprise!  We&amp;rsquo;re managing
the cloud management layer the same as an app :-)&lt;/p&gt;

&lt;p&gt;Some of these may be managed by Federation (can your existing authentication
solution federate out of your datacenter?), or via synchronisation (hourly
job that compares what users have permission to who &lt;em&gt;should&lt;/em&gt; have permission),
or (worst case) by a human eyeballing a screen.&lt;/p&gt;

&lt;p&gt;Can your log infrastructure be reachable from the CSP (maybe a gateway
service)?  Can events be streamed into it, or pulled programmatically?&lt;/p&gt;

&lt;p&gt;The breadth of the controls made available by the cloud service provider
and how well we can integrate with them will impact the risk assessment
of the cloud engagement; it is meaningless to have a locked down server
inside an IaaS if we can disable all the controls through a weakly
secured management plane!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Big bugs have lesser bugs</title>
      <link>https://www.sweharris.org/post/2017-02-05-bigbugs/</link>
      <pubDate>Sun, 05 Feb 2017 18:57:05 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-02-05-bigbugs/</guid>
      <description>

&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/The_Siphonaptera&#34;&gt;The Siphonaptera&lt;/a&gt; has
various versions.  The version I learned as a kid goes:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    Big bugs have little bugs,
    Upon their backs to bite &#39;em,
    And little bugs have lesser bugs,
    and so, ad infinitum.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We make use of this fact a lot in computer security; a breach of the OS
can impact the security of the application.&lt;/p&gt;

&lt;p&gt;We could even build a simple dependency list:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    The security of the application depends on
    The security of the operating system depends on
    The security of the hypervisor depends on
    The security of the virtualisation environment depends on
    The security of the automation tool...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course, in reality the dependency list is a highly branching tree;
the app may depend on multiple different things in order to be secure,
such as the source code repository, the build environment, the single
signon solution&amp;hellip;&lt;/p&gt;

&lt;p&gt;This seems obvious; if I can break into the central management tool
then I can use that to break into VMs and from there impact the app.&lt;/p&gt;

&lt;h2 id=&#34;bidirectional&#34;&gt;Bidirectional&lt;/h2&gt;

&lt;p&gt;We also have some awareness that the list isn&amp;rsquo;t one way.  We know about
remote code execution and privileged escalation attacks, so we can
&lt;em&gt;also&lt;/em&gt; say:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;   The security of the operating system depends on
   The security of the application
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A problem comes in when we have a large difference in organisational
security boundaries.  A broken app allowing privileged access to the OS is
annoying, but it&amp;rsquo;s still (normally) only the app that&amp;rsquo;s directly impacted.&lt;/p&gt;

&lt;p&gt;However when there&amp;rsquo;s a higher level structures in place then we may have
multiple applications impacted; a hypervisor bug may allow an application
in one OS to impact a different application in a different OS.&lt;/p&gt;

&lt;p&gt;It gets even worse; a bug in the hypervisor management layer (e.g. the
VMware agents feeding into VSphere or VCOps) could cause a bug in an
application leading to impact &lt;em&gt;every&lt;/em&gt; server in the enterprise.&lt;/p&gt;

&lt;p&gt;We saw a variation of this, &lt;a href=&#34;https://www.computest.nl/advisories/CT-2017-0109_Ansible.txt&#34;&gt;recently&lt;/a&gt;.  An &lt;code&gt;ansible&lt;/code&gt; bug allowed a
compromised machine to run commands on the &lt;em&gt;controller&lt;/em&gt; node.  And,
of course, the controller typically has access to every machine managed
by &lt;code&gt;ansible&lt;/code&gt;, including &lt;code&gt;root&lt;/code&gt; access on those machines.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;   The security of the application depends on
   The security of the operating system depends on
   The security of the hypervisor depends on
   The security of the automation depends on
   The security of the hypervisor depends on
   The security of the operating system depends on
   The security of the application
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With all the branches!&lt;/p&gt;

&lt;h2 id=&#34;assessments&#34;&gt;Assessments&lt;/h2&gt;

&lt;p&gt;When we do application risk assessments we tend to focus on the app and
the OS that runs it.  We don&amp;rsquo;t look at the automation environment, the
authentication tool, the hypervisor management because these are &amp;ldquo;the same&amp;rdquo;
across app deployments in an enterprise, so not worth testing hundreds of
times over.&lt;/p&gt;

&lt;p&gt;This can lead to a gap; we need to ensure these tools are properly covered
and managed.  If you pay for an external team to pen-test your app then
it may be a good thing to resist the temptation to limit their scope; let
them try and break the higher level constructs that your app depends on.
You might learn something new; something a real attacker could use against
you!&lt;/p&gt;

&lt;p&gt;At the very least ensure your tooling is fully patched and that bugs
found against them are evaluated as having company wide impact.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Make it easy to use</title>
      <link>https://www.sweharris.org/post/2017-01-23-make-it-easy/</link>
      <pubDate>Mon, 23 Jan 2017 19:18:30 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-01-23-make-it-easy/</guid>
      <description>

&lt;p&gt;There is a temptation in computer security circles to aim for the perfect.
After all, we know that if there &lt;em&gt;is&lt;/em&gt; a hole then it will be found and
will be exploited.  So we tend to build (hopefully! &lt;em&gt;ahem&lt;/em&gt; OpenSSL) secure
products that will withstand attacks&amp;hellip; and then fail at usability&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s take a brief travel through&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;unix-naming-services&#34;&gt;Unix naming services&lt;/h2&gt;

&lt;h3 id=&#34;nis&#34;&gt;NIS&lt;/h3&gt;

&lt;p&gt;In the long distant past (the 1980s), Sun Microsystems created a system
called NIS (Network Information Services)&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:1&#34;&gt;&lt;a rel=&#34;footnote&#34; href=&#34;#fn:1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.  This was a massive step
forward for large computer networks; it allowed a central password &amp;ldquo;map&amp;rdquo;
rather than needing to distribute it to every computer; it provided a
central control point (change one file and every client machine picks it
up).  Today this is expected, but in the 80s it was new and clever.&lt;/p&gt;

&lt;p&gt;As time went on, though, we realised things weren&amp;rsquo;t as nice as we&amp;rsquo;d like.
People like &lt;a href=&#34;https://twitter.com/alecmuffett&#34;&gt;Alex Muffett&lt;/a&gt; created
fast &lt;a href=&#34;https://en.wikipedia.org/wiki/Crack_%28password_software%29&#34;&gt;crack&lt;/a&gt;
routines.  NIS exposed the raw &lt;code&gt;crypt&lt;/code&gt; strings and so people could take
them and off-line attack and steal passwords.  You didn&amp;rsquo;t even need to
have a login to steal this information; just access to the network.&lt;/p&gt;

&lt;p&gt;Further, NIS was inherently based on network trust; someone on your
network could fake a NIS server and convince your machine to talk to them;
now they can login to your machine and become root.  There were some small
attempts to increase NIS security but, really, it was a security nightmare.&lt;/p&gt;

&lt;h3 id=&#34;nis-1&#34;&gt;NIS+&lt;/h3&gt;

&lt;p&gt;So Sun next created NIS+.  This solved many of the problems with NIS;
servers had keys so the communication could be trusted; data could be
protected (no more &lt;code&gt;crypt&lt;/code&gt; string exposure); it even allowed for hierarchies
of servers, so tree based definitions could be created (eg at the top level
we could have SA accounts valid everywhere; the chemistry department could
run their own account system and only chemistry servers would know about
those accounts).&lt;/p&gt;

&lt;p&gt;Nice!  Well, not so much.&lt;/p&gt;

&lt;p&gt;The problem with NIS+ was that the &lt;em&gt;management&lt;/em&gt; of it was horrendous.
For a headache, look at the procedure to change the &lt;a href=&#34;http://www.eng.auburn.edu/users/rayh/solaris/NIS+_FAQ.html#*3.7&#34;&gt;root server&amp;rsquo;s IP
address&lt;/a&gt;.
There are 9 primary steps, each with multiple sub-steps, including a &amp;ldquo;wait
12 hours&amp;rdquo; period.  WTF?&lt;/p&gt;

&lt;p&gt;Running NIS+ at scale was just too complicated for many organisations.
They stuck with NIS.  The insecure, broken solution.  Because it worked
for them.&lt;/p&gt;

&lt;p&gt;NIS+ was so bad that by the time Solaris 9 came out, mention of it had
been dropped from the official Sun training courses.  NIS was still
mentioned; LDAP was the primary focus.  But NIS+ had been dropped totally.&lt;/p&gt;

&lt;h3 id=&#34;compare-to-microsoft-nt-domains&#34;&gt;Compare to Microsoft NT Domains&lt;/h3&gt;

&lt;p&gt;If you look at the old NT domain model you&amp;rsquo;ll see a lot of similarities
between this and the NIS+ model.  After all, they&amp;rsquo;re trying to solve
similar problems.  The difference, though, is in &lt;em&gt;usability&lt;/em&gt;.  Let&amp;rsquo;s
take the &amp;lsquo;change primary server IP address&amp;rsquo; problem, from before.  With NT
this is pretty simple; any replica can be promoted to become a primary.
NT cheats; every domain server (primary or replica) shares the same
identity, so it&amp;rsquo;s easy to move the primary around.&lt;/p&gt;

&lt;p&gt;NT has its own problems (mostly due to backward compatability - LANMAN
hashes!)  but it was massively easier to manage.&lt;/p&gt;

&lt;p&gt;NIS+ lack of &amp;ldquo;ease of use&amp;rdquo; lead to failure for adoption.  NT pretty
GUIs made it easy to use.&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:2&#34;&gt;&lt;a rel=&#34;footnote&#34; href=&#34;#fn:2&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h2 id=&#34;today-s-fight&#34;&gt;Today&amp;rsquo;s fight&lt;/h2&gt;

&lt;p&gt;The fight, as I type, is the same as last week; &lt;a href=&#34;https://www.whatsapp.com/&#34;&gt;WhatsApp&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To summarise, the &lt;a href=&#34;https://en.wiktionary.org/wiki/Grauniad&#34;&gt;Grauniad&lt;/a&gt;
wrote an article about how WhatsApp had a &lt;a href=&#34;https://www.theguardian.com/technology/2017/jan/13/whatsapp-backdoor-allows-snooping-on-encrypted-messages&#34;&gt;security
backdoor&lt;/a&gt;.
The security world went mad, with claims, counter-claims,
rhetoric, demands to opensource the software, or use the
&lt;a href=&#34;https://signal.org/&#34;&gt;Signal&lt;/a&gt; software.&lt;/p&gt;

&lt;p&gt;Why is this important?  Well, WhatsApp is meant to provide E2E (End To
End) encryption of messages.  Only the sending and receiving devices
get to see the plain text.  If someone manages to attack anywhere in
the path (eg the central server) then they still can&amp;rsquo;t read the messages.
So, clearly, a backdoor that breaks E2E is important.&lt;/p&gt;

&lt;p&gt;The reality is that the backdoor isn&amp;rsquo;t anything of the sort; it&amp;rsquo;s
a usability trade-off.  Under specific circumstances (essentially;
the receiver gets a new phone and generates a new key) the sender will
automatically re-encrypt the message and send it.  An alert is provided
to the user.  With Signal the user is prompted about the change and
given the option to re-encrypt.&lt;/p&gt;

&lt;p&gt;What is the risk?  Only unsent messages are retransmitted.  And there&amp;rsquo;s
limited attack points; primarily the central servers and the recipients
mobile network (de-register the legitimate device, register your own
device, receive messages!).  The latter is a potentially legitimate
attack vector in some countries, with tight crack-downs on dissent.&lt;/p&gt;

&lt;p&gt;The &amp;ldquo;perfect security&amp;rdquo; team claim the Signal approach is better, but
don&amp;rsquo;t take into account user experience (&amp;ldquo;resend?  Sure, I know Fred
gets a new burner phone every week to avoid security forces&amp;rdquo;).  The
WhatsApp team believe that the vaste majority (99%) of rekeys will
be due to standard &amp;ldquo;new phone&amp;rdquo; purchases.&lt;/p&gt;

&lt;p&gt;So here we have a usability vs perfect security trade off.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;&amp;ldquo;100% secure or go home&amp;rdquo; is a very binary view of the world.  Now for a
megabank or a government (or a target of a major government) then such
a posture might be true.  After all, who knows what compute resources
the NSA can bring to bear on you :-)&lt;/p&gt;

&lt;p&gt;But, really, most people don&amp;rsquo;t &lt;em&gt;need&lt;/em&gt; perfect security; they just need
&amp;ldquo;good enough&amp;rdquo; security.  If you&amp;rsquo;re in a risky situation then this XKCD
is your bigger risk than an attack against a theoretical weakness.
&lt;center&gt;
&lt;a href=https://xkcd.com/538/&gt;&lt;img src=/images/xkcd-security.png&gt;&lt;/a&gt;
&lt;/center&gt;
If you &lt;em&gt;do&lt;/em&gt; need perfect security in your communication then maybe
Signal is the way to go; if you just need &amp;lsquo;good enough&amp;rsquo; then WhatsApp
will work.&lt;/p&gt;

&lt;p&gt;Both are a gazillion times better than SMS, which is what happened before!&lt;/p&gt;

&lt;p&gt;As my girlfriend frequently reminds me, &lt;a href=&#34;https://en.wikipedia.org/wiki/Perfect_is_the_enemy_of_good&#34;&gt;don&amp;rsquo;t let the perfect be the enemy of the good&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;footnotes&#34;&gt;

&lt;hr /&gt;

&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;Originally &amp;ldquo;Yellow Pages&amp;rdquo; until British Telecom sued for trademark infringement; this is why the commands still begin &lt;code&gt;yp&lt;/code&gt; - e.g. &lt;code&gt;ypcat&lt;/code&gt;
 &lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:1&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;Yes yes, there are other reasons why NT beat NIS+; desktop integration being a major one.  But it was massively easier to manage an NT domain than a NIS+ one.
 &lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:2&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Stop, step back, take a minute, slow down</title>
      <link>https://www.sweharris.org/post/2017-01-16-slowdown/</link>
      <pubDate>Mon, 16 Jan 2017 21:52:51 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-01-16-slowdown/</guid>
      <description>

&lt;p&gt;There&amp;rsquo;s an old comment; &amp;ldquo;A Lie Can Travel Halfway Around the World While the Truth Is Putting On Its Shoes&amp;rdquo;.  This came from a pre-internet world.  Today
a lie can travel around the world in seconds.&lt;/p&gt;

&lt;h2 id=&#34;personal-annecdote&#34;&gt;Personal annecdote&lt;/h2&gt;

&lt;p&gt;Last year I &lt;a href=&#34;https://www.sweharris.org/post/2016-02-10-break-mbr/&#34;&gt;broke the MBR on every hard disk&lt;/a&gt;
on my home server.  I was panicing.  I really didn&amp;rsquo;t want to rebuild
and restore from backup, and then re-rip all my DVDs; such a time
sink!  So I stopped; stepped away from the keyboard; got a (decaf)
coffee.  Took the time to think.&lt;/p&gt;

&lt;p&gt;By taking a minute, slowing down, I was able to think about the problem
and come to a solution that saved me a &lt;em&gt;tonne&lt;/em&gt; of time and effort (and,
effectively, zero downtime except for one reboot).&lt;/p&gt;

&lt;h2 id=&#34;real-world-incidents&#34;&gt;Real world incidents&lt;/h2&gt;

&lt;p&gt;An incident happens; in American it&amp;rsquo;s probably a shooting.  It could have
been the Christmas truck incident in Germany.  Or Benghazi.  Or 9&amp;#47;11.
Immediately twitter and facebook are aflame with theories and stories.
But we don&amp;rsquo;t actually know what&amp;rsquo;s happening; the facts are still being
investigated.  Stop; step back, take a minute, slow down.  Wait a few
days and see what the investigation reports.  The truth probably isn&amp;rsquo;t
what you read on social media.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s even an infographic&amp;hellip;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.sweharris.org/images/breaking-news.jpg&#34; alt=&#34;break-news&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;infosec-stories&#34;&gt;Infosec stories&lt;/h2&gt;

&lt;p&gt;Last week the &lt;a href=&#34;https://en.wiktionary.org/wiki/Grauniad&#34;&gt;Grauniad&lt;/a&gt;
wrote an article about how the world&amp;rsquo;s leading secure
communication app, &lt;a href=&#34;https://www.whatsapp.com/&#34;&gt;WhatsApp&lt;/a&gt;, had a &lt;a href=&#34;https://www.theguardian.com/technology/2017/jan/13/whatsapp-backdoor-allows-snooping-on-encrypted-messages&#34;&gt;security
backdoor&lt;/a&gt;
The security world went mad, with claims, counter-claims,
rhetoric, demands to opensource the software, or use the
&lt;a href=&#34;https://signal.org/&#34;&gt;Signal&lt;/a&gt; software.&lt;/p&gt;

&lt;p&gt;Stop; step back, take a minute, slow down.&lt;/p&gt;

&lt;p&gt;The &amp;ldquo;day two&amp;rdquo; story shows that this isn&amp;rsquo;t a &lt;em&gt;backdoor&lt;/em&gt; (which has a specific
meaning).  It&amp;rsquo;s a compromise between usability and security.  Was it the
right compromise?  Maybe not.  But it&amp;rsquo;s not a backdoor.  The world isn&amp;rsquo;t
ending, the WhatsApp servers can&amp;rsquo;t read your stuff, the FBI can&amp;rsquo;t get a
warrant to read your messages.&lt;/p&gt;

&lt;h2 id=&#34;corporate-environments&#34;&gt;Corporate environments&lt;/h2&gt;

&lt;p&gt;Your company has just been breached (it &lt;em&gt;will&lt;/em&gt; happen).  You&amp;rsquo;ve done a
thorough incident response and decided &amp;ldquo;XYZ technology wasn&amp;rsquo;t good enough&amp;rdquo;.
Perhaps it was that an SA&amp;rsquo;s laptop got infected with a key logger (AntiVirus
software wasn&amp;rsquo;t good enough), or a web site leaked credentials (inadequate
scanning).&lt;/p&gt;

&lt;p&gt;A common response is &amp;ldquo;XYZ wasn&amp;rsquo;t good enough; let&amp;rsquo;s replace it with ABC&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Stop; step back, take a minute, slow down.&lt;/p&gt;

&lt;p&gt;The &amp;ldquo;day two&amp;rdquo; story is that
what you&amp;rsquo;ve got is probably as good as what you&amp;rsquo;re proposing.  ABC may
have detected &lt;em&gt;this&lt;/em&gt; issue, but it may not detect another issue that XYZ
has been protecting you from.  The problem may actually lay elsewhere
(an underlying assumption that you&amp;rsquo;d repeat with the new technology).&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;It&amp;rsquo;s easy to fall into the &lt;a href=&#34;https://en.wikipedia.org/wiki/Politician&#39;s_syllogism&#34;&gt;Politician&amp;rsquo;s syllogism&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We must do something&lt;/li&gt;
&lt;li&gt;This is something&lt;/li&gt;
&lt;li&gt;Therefore, we must do this.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Whether this is in response to an external event (shooting, bombing), or
an internal issue (something broke) or even a personal issue (argument
with your Significant Other), there&amp;rsquo;s a rush to try and &lt;em&gt;fix&lt;/em&gt; things.&lt;/p&gt;

&lt;p&gt;Stop; step back, take a minute, slow down.&lt;/p&gt;

&lt;p&gt;Make sure you&amp;rsquo;ve got the correct information and the right analysis;
the situation may not be what you think it is.  By stepping back and
taking that extra time you might save yourself a lot of time and effort
and avoid replacing a working system with one with new and different
oddities.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The Itsy Bitsy Security Spider</title>
      <link>https://www.sweharris.org/post/2017-01-08-spider/</link>
      <pubDate>Sun, 08 Jan 2017 22:47:50 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-01-08-spider/</guid>
      <description>

&lt;p&gt;Sometimes we can learn a lot from nursery rhymes; I&amp;rsquo;ve previously shown how &lt;a href=&#34;https://www.sweharris.org/post/2016-07-07-bucket/&#34;&gt;A Hole In My Bucket&lt;/a&gt; can teach us about understanding
problems and how this can lead to security issues.&lt;/p&gt;

&lt;p&gt;The Itsy Bitsy Spider can also teach us&amp;hellip;&lt;/p&gt;

&lt;p&gt;So what is the story of the spider?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Spider starts to do something productive
Event happens that destroys the progress
Spider starts over to do something productive
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But what we don&amp;rsquo;t see, here, is the spider &lt;em&gt;learning&lt;/em&gt; from the event.  It
has fixed target (climbing the water spout) and is focused on achieving
that goal.&lt;/p&gt;

&lt;p&gt;Now we see similar &amp;ldquo;event happens&amp;rdquo; in our lives.&lt;/p&gt;

&lt;h2 id=&#34;management-change&#34;&gt;Management change&lt;/h2&gt;

&lt;p&gt;A common one in large
enterprise environments is a change in management.  The new hierarchy
want to stamp their authority on their department and so will pick on
something and force change; they throw away the old and replace it with
their favourite technology.&lt;/p&gt;

&lt;p&gt;Except technology isn&amp;rsquo;t the whole of the problem space.  Technology is
&lt;em&gt;easy&lt;/em&gt;; it&amp;rsquo;s process and controls that are hard.&lt;/p&gt;

&lt;p&gt;So the incoming management tree might demand a replacement of product X
with product Y.  The engineering teams will work out how to get product
Y working in the company; they&amp;rsquo;ll replicate existing data models, process
workflows, user interfaces (request/approval/re-certification/etc).&lt;/p&gt;

&lt;p&gt;And at the end of the day we&amp;rsquo;ll have all the existing problems replicated
into the new system.&lt;/p&gt;

&lt;p&gt;New management will have washed the spider out of the spout, but then
engineering climb up it exactly the same as before.  Nothing has been
learned, nothing has been improved.&lt;/p&gt;

&lt;h2 id=&#34;external-attack&#34;&gt;External attack&lt;/h2&gt;

&lt;p&gt;This rainstorm is the one we all dread.  We know it &lt;em&gt;will&lt;/em&gt; happen&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:1&#34;&gt;&lt;a rel=&#34;footnote&#34; href=&#34;#fn:1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
and try to limit the consequences.&lt;/p&gt;

&lt;p&gt;So we build a solution; we have defence in depth; we have overlapping
controls and processes; we have so much stuff running on machines that
we chew up more resources &lt;em&gt;monitoring&lt;/em&gt; than we do on the actual work of
the company.   And we still get hacked.&lt;/p&gt;

&lt;p&gt;As part of the incident response management goes into a panic, bring in
consultants to analyse the existing solution.  These consultants will
spend months interviewing people and writing reports&amp;hellip; that match their
existing preconceptions and recommend installing new solution.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;re back in the same boat as before; technology change but not addressing
the real problem.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;What we&amp;rsquo;re really talking about, here, is a variation of &amp;ldquo;group think&amp;rdquo;.
The company has a set of processes and standards to be followed and any
new technology will be forced into that viewpoint.  A rainstorm may
force a change of technology but we&amp;rsquo;ll just rebuild in the same pattern.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s hard, but sometimes you need to think outside the box and come up
with new &lt;em&gt;ideas&lt;/em&gt;, rather than just new technology.&lt;/p&gt;

&lt;p&gt;Next up: Humpty Dumpty can be put back together again.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34;&gt;

&lt;hr /&gt;

&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;You &lt;em&gt;will&lt;/em&gt; be hacked.
 &lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:1&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Always Listening Devices</title>
      <link>https://www.sweharris.org/post/2017-01-02-always-listening/</link>
      <pubDate>Mon, 02 Jan 2017 13:22:58 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2017-01-02-always-listening/</guid>
      <description>

&lt;p&gt;Recently we heard news that the police had &lt;a href=&#34;http://www.theregister.co.uk/2016/12/28/us_cops_seek_amazon_echo_data_for_murder_inquiry/&#34;&gt;requested Alexa recordings&lt;/a&gt; to assist with a murder enquiry.  The victim had an Amazon Echo and the
police feel there&amp;rsquo;s useful data to be obtained.&lt;/p&gt;

&lt;p&gt;This leads to speculation about what sort of information is recorded by
these devices, and how secure are they?&lt;/p&gt;

&lt;h2 id=&#34;what-type-of-devices-are-we-talking-about&#34;&gt;What type of devices are we talking about?&lt;/h2&gt;

&lt;p&gt;There are a number of devices out there these days which you can talk
to, to request things.  These include Apple&amp;rsquo;s &amp;ldquo;Siri&amp;rdquo;, Google&amp;rsquo;s nameless
&amp;ldquo;Assistant&amp;rdquo;, Amazon&amp;rsquo;s &amp;ldquo;Alexa&amp;rdquo; and Microsoft&amp;rsquo;s &amp;ldquo;Cortana&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Some of these require you to press a button to wake them up, but others
are always listening for a &amp;ldquo;wake word&amp;rdquo;.  Here you might say &amp;ldquo;Hey Siri,
what&amp;rsquo;s the weather?&amp;ldquo;.  The device hears the magic word &amp;ldquo;Hey Siri&amp;rdquo; and
then works out what you said and acts accordingly.&lt;/p&gt;

&lt;p&gt;These devices come in varied form factors; any modern smart phone likely
has an assistant which may be voice activated (and may be enabled by
default; there may be switches to turn it off or convert it to activate
in limited cases); your smart watch may have it (my Motorola 360 will
listen for &amp;ldquo;OK Google&amp;rdquo; but only when the watch is active; so raise your
arm to wake it up and talk to it); your laptop may have it (macOS Sierra
has Siri, but requires a button press to activate); tablets may have
it; and, of course, the new &amp;ldquo;hot&amp;rdquo; items of Amazon Echo and Google Home,
which are designed to sit in your house and listen to you.&lt;/p&gt;

&lt;h2 id=&#34;how-do-they-work&#34;&gt;How do they work?&lt;/h2&gt;

&lt;p&gt;These devices don&amp;rsquo;t typically process your voice commands locally.
They just don&amp;rsquo;t have the processing power or storage to understand
natural language commands.  Instead they are always listening to you for
the wake word.  These are generally fixed or (as with Samsung&amp;rsquo;s attempt)
trainable.  This processing is done locally.&lt;/p&gt;

&lt;p&gt;Once the magic word is said then the device will start streaming data to
the service provider, along with a small buffer of data from before the
command (Amazon claim &amp;ldquo;a fraction of a second&amp;rdquo; in their &lt;a href=&#34;https://www.amazon.com/gp/help/customer/display.html?ie=UTF8&amp;amp;nodeId=201602230&#34;&gt;FAQ&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The cloud service now has a copy of your voice recording, can attempt to
parse it, and respond accordingly.  Because the activity is parsed remotely
it can be made smarter and updated and new commands added just by the
provider updating their servers; no remote update is needed.  New &amp;ldquo;skills&amp;rdquo;
can be added at any time.&lt;/p&gt;

&lt;h2 id=&#34;amazon-echo-in-practice&#34;&gt;Amazon Echo in practice&lt;/h2&gt;

&lt;p&gt;I received an Echo as a present so, of course, I started to network sniff
to see what it was doing.  Excluding DHCP/ARP and other normal local
traffic, a few things stood out.&lt;/p&gt;

&lt;p&gt;Every 30 seconds I saw a UDP packet of 159 bytes being sent out to some
ec2 instance on port 33434.  This might be the
&lt;a href=&#34;https://developer.amazon.com/device-messaging&#34;&gt;Amazon Device Messaging&lt;/a&gt; (ADM)
which implies a remote command &lt;em&gt;might&lt;/em&gt; be able to wake up your Echo up.&lt;/p&gt;

&lt;p&gt;Every 30 seconds, HTTPS traffic to an Amazon IP address (205.251.242.52 in
my sample) of 41 bytes.  This would seem to be another polling mechanism.&lt;/p&gt;

&lt;p&gt;NTP traffic to various places&lt;/p&gt;

&lt;p&gt;Infrequent ping traffic to the default gateway, the DNS server I listed
in DHCP &lt;em&gt;and&lt;/em&gt; Google and OpenDNS DNS servers, followed by DNS lookups for
&lt;code&gt;www.example.org&lt;/code&gt; and a HTTP attempt to the result.  This is possibly
a connectivity attempt to verify the WiFi connection is still working
properly.&lt;/p&gt;

&lt;p&gt;A small communication with &lt;code&gt;device-metrics-us.amazon.com&lt;/code&gt;.  Hmm!&lt;/p&gt;

&lt;p&gt;And that&amp;rsquo;s all I saw when the Echo was idle.&lt;/p&gt;

&lt;p&gt;When I spoke the activity word then I started to see a lot of https
traffic to the same Amazon IP address previously mentioned.  So perhaps
the 30 seconds polling test mentioned earlier may just be a &amp;ldquo;is the
remote end still there?&amp;rdquo; test, to allow for quicker sending of data.
After the conversation had completed then the traffic resumed back to
idle levels.&lt;/p&gt;

&lt;p&gt;I also tested streaming of music (&amp;ldquo;Alexa play 80s pop&amp;rdquo;).  What was interesting,
here, was that the song appears to be buffered locally; I could see a LOT
of https traffic (from a cloudfront server) which then stopped.  So it&amp;rsquo;s
clear the Echo has enough memory to store a 4 minute song locally.&lt;/p&gt;

&lt;h2 id=&#34;what-are-the-risks&#34;&gt;What are the risks?&lt;/h2&gt;

&lt;p&gt;Based on the above data, the risk would appear to be small.  Let&amp;rsquo;s look
at it:&lt;/p&gt;

&lt;h3 id=&#34;amazon-etc-store-your-voice-recordings&#34;&gt;Amazon etc store your voice recordings&lt;/h3&gt;

&lt;p&gt;They do this to help train your device to your voice (or so they claim).
In theory this now creates a record of all your requests and so could
become subject to a subpoena.  Even &lt;em&gt;if&lt;/em&gt; you trust Amazon/Google/whoever
will they fight for you to keep this data out of the hands of the police?&lt;/p&gt;

&lt;h3 id=&#34;how-much-do-they-send-before-the-magic-word&#34;&gt;How much do they send before the magic word?&lt;/h3&gt;

&lt;p&gt;We only have their word that a fraction of a second is sent prior to the
magic word.  They might lie.&lt;/p&gt;

&lt;h3 id=&#34;activity-may-change&#34;&gt;Activity may change&lt;/h3&gt;

&lt;p&gt;What I record is how Echo works &lt;em&gt;today&lt;/em&gt;.  I have no doubt that Amazon can
force a firmware update to devices as necessary.  So some of the protections
we see (e.g. the LED ring lighting up to show streaming) might disappear.
Could the Feds demand a version of the firmware that would record and
stream permanently without a visual indicator?  How many of the protections
are software and how many are hardwired?&lt;/p&gt;

&lt;h3 id=&#34;attacks-against-the-device&#34;&gt;Attacks against the device&lt;/h3&gt;

&lt;p&gt;A simple &lt;code&gt;nmap&lt;/code&gt; of the device shows no listening ports, so an attacker on
your local network (remotely by a router exploit!) do not &lt;em&gt;appear&lt;/em&gt; to have
an attack vector this way.  This leaves custom skills.  Now these are
processed remotely on a remote server; the amount of data sent back is
primarily limited to a &amp;ldquo;speech&amp;rdquo; text channel or to an audio channel.  If
there was a bug in the codec or text-to-speech modules then an attacker
might gain access that way, but it requires you to have enabled their
skill.&lt;/p&gt;

&lt;h2 id=&#34;other-risks&#34;&gt;Other risks&lt;/h2&gt;

&lt;h3 id=&#34;attacks-against-the-account&#34;&gt;Attacks against the account&lt;/h3&gt;

&lt;p&gt;This, in my mind, is more likely&amp;hellip; your voice recordings and enabled
skills are all controled via the &lt;a href=&#34;https://alexa.amazon.com&#34;&gt;Alexa&lt;/a&gt; site,
and this is protected by your normal Amazon password.  Is that secure?
The data you&amp;rsquo;re now protecting has extended beyond your purchase history
and ability to buy stuff, but to voice recordings and command histories.&lt;/p&gt;

&lt;h3 id=&#34;inappropriate-use&#34;&gt;Inappropriate use&lt;/h3&gt;

&lt;p&gt;There&amp;rsquo;s a second class of risk relating to inappropriate use of these
types of device (why would you link it to your bank account when there
are no &lt;em&gt;voice&lt;/em&gt; level controls?  Anyone in your house could ask for the
same information).  This includes the built-in &amp;ldquo;buy stuff from Amazon&amp;rdquo;
skill, so &lt;em&gt;turn that off&lt;/em&gt;!  But that&amp;rsquo;s another blog post :-)&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Everyone has to make their own risk assessment of these devices.  Based on
what I&amp;rsquo;ve observed and tested, I don&amp;rsquo;t think the Amazon Echo creates a
large exposure.  Although the device may be &amp;ldquo;always listening&amp;rdquo; it
doesn&amp;rsquo;t send data until the magic word is spoken.  I&amp;rsquo;ve seen a twitter
joke about Orwell&amp;rsquo;s 1984 along the lines of &amp;ldquo;we didn&amp;rsquo;t need to have
enforced surveillance, we brought it into our own homes&amp;rdquo;, but I don&amp;rsquo;t
think this is accurate.  These devices aren&amp;rsquo;t streaming 24x7, but only
on demand.&lt;/p&gt;

&lt;p&gt;So why did the police demand recordings in the murder case?  I don&amp;rsquo;t
know, but what if the victim had said &amp;ldquo;Alexa, Fred is killing me!&amp;rdquo;
while he was being murdered?  That would be recorded and could be
relevant information :-)&lt;/p&gt;

&lt;p&gt;Personally, until I find out otherwise, I feel the Echo device is not
a large risk&amp;hellip; as long as I don&amp;rsquo;t connect it to personal data sources
(no, Alexa, you won&amp;rsquo;t get access to my bank account!).&lt;/p&gt;

&lt;h2 id=&#34;but-what-about-laptops&#34;&gt;But what about laptops?&lt;/h2&gt;

&lt;p&gt;A common recommendation for laptop owners is to cover your camera
(and block the microphone) when you&amp;rsquo;re not using them.  You can buy
camera shutters that can be stuck over the camera, allowing you to
slide open/closed as needed.  Why is this different to an &amp;ldquo;always
listening&amp;rdquo; device?&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s a matter of attack vectors. Earlier I showed that there&amp;rsquo;s no open
ports on an Echo; an attacker can&amp;rsquo;t break into it so easily.  However a laptop
is possibly running Windows or macOS, is used to read emails or surf the
web and is at a much greater risk of malware being installed which could
then access the camera or microphone.  The Echo, being an appliance device,
has fewer malware insertion vectors (I won&amp;rsquo;t say &lt;em&gt;none&lt;/em&gt; because everything
has bugs) and so doesn&amp;rsquo;t present the same risk surface.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>SSH keeps disconnecting</title>
      <link>https://www.sweharris.org/post/2016-12-24-ssh-disconnect/</link>
      <pubDate>Sat, 24 Dec 2016 21:16:52 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-12-24-ssh-disconnect/</guid>
      <description>

&lt;p&gt;This blog post is of a more practical nature, and may be of use for
people at home who ssh into servers and then come back later to find
their session disconnected.  It &lt;em&gt;might&lt;/em&gt; also help some people in
offices with nasty firewalls!&lt;/p&gt;

&lt;p&gt;Basically the scenario goes something like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ssh into a server&lt;/li&gt;
&lt;li&gt;lock your screen, go away for a few hours&lt;/li&gt;
&lt;li&gt;come back, unlock your screen&lt;/li&gt;
&lt;li&gt;ssh session has been disconnected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So how does this happen, and what can we do to stop it?&lt;/p&gt;

&lt;h2 id=&#34;network-address-translation-nat&#34;&gt;Network Address Translation (NAT)&lt;/h2&gt;

&lt;p&gt;The first thing we need to be aware of is how most home router work.  When
you connect to a standard home consumer ISP they give you one IP address&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:1&#34;&gt;&lt;a rel=&#34;footnote&#34; href=&#34;#fn:1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Now every device you have &lt;em&gt;including&lt;/em&gt; the router needs an IP address.  Your
desktop, your laptop, your cellphone, your games console, your iPad&amp;hellip;  if
you go around your house and look at the number of devices you&amp;rsquo;ve connected
to your WiFi (or plugged in with a cable into the router) then you might be
surprised.  I counted at least 20 devices in my house; there may be more!&lt;/p&gt;

&lt;p&gt;So the router needs to work hard in how it lets all those devices share
the same IP address.  It does this by creating a local network on your
WiFi/LAN and devices get their addresses from that.  So your laptop may
get 192.168.1.10, your cellphone might get 192.168.1.11, your iPad maybe
192.168.1.24 and so on.&lt;/p&gt;

&lt;p&gt;Where this gets clever is that the router then &amp;ldquo;changes&amp;rdquo; the address
whenever any of your devices talks to the internet.  So lets say your
iPad hits this web site.  Your iPad is 192.168.1.24 and wants to talk
to my server.  When the traffic gets to the router it will &lt;em&gt;translate&lt;/em&gt;
the first address into the external address provided by your ISP.  So now
your iPad can talk to my server.&lt;/p&gt;

&lt;p&gt;The problem is that the router needs to remember that it&amp;rsquo;s done this, so
that when my server replies then it knows to send the response back to
the iPad and not to your desktop or your phone.  The router needs to keep
a &lt;em&gt;connection table&lt;/em&gt; in memory of all the address translations it is
doing.&lt;/p&gt;

&lt;h2 id=&#34;dropping-connections&#34;&gt;Dropping connections&lt;/h2&gt;

&lt;p&gt;There are a number of problems with NAT, but two are relevant here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The memory in a router is small; if too many connections are made
then it might have to drop some traffic (I saw this with the older
Verizon FIOS ActionTec routers; it only had a small NAT table).&lt;/li&gt;
&lt;li&gt;Connections might break messily; the router needs to have a way of
cleaning up the connection table entries for dead connections.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is normally solved by having a timer associated with each entry;
&amp;ldquo;when did we last see a packet?&amp;rdquo;.  If the table gets full and a new entry
needs to be created then the oldest connection could be dropped and closed
down.  Similarly if the connection is too old (&amp;ldquo;we haven&amp;rsquo;t seen a packet
for over 2 hours&amp;rdquo;) then the router might consider this a dead connection
and drop it.  Some routers are even more aggressive and may drop connections
after 30 minutes or even sooner!&lt;/p&gt;

&lt;p&gt;This second case is where we start to see idle sessions get dropped.  Because
the ssh session hasn&amp;rsquo;t sent any traffic in a few hours the router thinks
it is a dead session and will close it.&lt;/p&gt;

&lt;h2 id=&#34;keepalive&#34;&gt;KeepAlive&lt;/h2&gt;

&lt;p&gt;The standard workaround for this sort of problem is to make sure the
router never thinks your connection is idle; send &amp;ldquo;fake traffic&amp;rdquo; at
regular intervals.  In computer jargon this is called &amp;ldquo;keep alive&amp;rdquo;
traffic; we&amp;rsquo;re sending it just to keep the connection alive.&lt;/p&gt;

&lt;p&gt;Now the first thing someone notices when reading the &lt;code&gt;ssh&lt;/code&gt; manual page
is something called &lt;code&gt;TCPKeepAlive&lt;/code&gt;.  Hey, that sounds good!  It turns
on keep alive packets at the TCP layer!  Unfortunately&amp;hellip; not.  TCP
KeepAlive packets weren&amp;rsquo;t designed to handle intermediate router drops;
they&amp;rsquo;re more there to keep the local socket alive and detect if the remote
server has gone away (and so drop the connection).  The traffic is frequently
sent at a much lower frequency than the router needs, and so it doesn&amp;rsquo;t
prevent the connection being dropped.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ssh&lt;/code&gt; authors noticed this and in version 2 of the protocol (there&amp;rsquo;s
a 99.99% chance you &lt;em&gt;are&lt;/em&gt; using SSH2; SSH1 has known security issues and
has been turned off almost everywhere) they added a &amp;ldquo;No Operation&amp;rdquo; (NOOP)
message type.  This can be used as a simple Keep Alive packet.&lt;/p&gt;

&lt;p&gt;How you turn this on depends on your client.&lt;/p&gt;

&lt;h4 id=&#34;unix-and-macos&#34;&gt;Unix (and MacOS)&lt;/h4&gt;

&lt;p&gt;In your &lt;code&gt;$HOME/.ssh/config&lt;/code&gt; file you can turn on KeepAlive with the following
commands:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Host *
  ServerAliveInterval 600
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This tells the ssh client that if it hasn&amp;rsquo;t received a message from the
server within 600 seconds then send a NOOP message to it, to get a response.
This works pretty well at making the router think the connection is still
busy and so don&amp;rsquo;t drop it as idle.  Nicely this packet is only sent if
you are idle, so it doesn&amp;rsquo;t cause any extra traffic on active sessions.&lt;/p&gt;

&lt;p&gt;Depending on how aggressive your router is, you may need a smaller number.&lt;/p&gt;

&lt;h4 id=&#34;windows-using-putty&#34;&gt;Windows, using putty&lt;/h4&gt;

&lt;p&gt;&lt;a href=&#34;http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html&#34;&gt;putty&lt;/a&gt;
is a pretty good Windows ssh client.  It&amp;rsquo;s the one I use when forced to
use windows!  It also has the ability to send keepalives, which can be
found on the &lt;em&gt;Connection&lt;/em&gt; section of the connection menu:
&lt;center&gt;
&lt;img src=&#34;https://www.sweharris.org/images/putty.png&#34; alt=&#34;putty&#34; /&gt;
&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;You can enter a timeout here, and save it as part of your connection profile.&lt;/p&gt;

&lt;h4 id=&#34;others&#34;&gt;Others&lt;/h4&gt;

&lt;p&gt;If you have a favourite ssh client with keepalive ability built in then feel
free to drop me a note in the comments!&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;NAT is nasty and some of the compromises it causes can cause longer running
idle sessions to break.   This doesn&amp;rsquo;t really impact most users because
typical activity (eg web surfing) uses short-lived connections.  But for
long lived (eg ssh) sessions that can be idle for a long time then we may
see disruption.&lt;/p&gt;

&lt;p&gt;We can work around this at the application level by sending application layer
keepalive traffic.  Many ssh clients have this ability built in.&lt;/p&gt;

&lt;p&gt;Connection dropping isn&amp;rsquo;t &lt;em&gt;solely&lt;/em&gt; caused by NAT, but it is a common
cause, especially for people initiating connections from home with
an ISP provided router.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34;&gt;

&lt;hr /&gt;

&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;Not always, but if you&amp;rsquo;ve requested more than one address then you should know enough to realise this is a simplification.
 &lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:1&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Backup and restore</title>
      <link>https://www.sweharris.org/post/2016-12-11-backup-restore/</link>
      <pubDate>Sun, 11 Dec 2016 20:44:25 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-12-11-backup-restore/</guid>
      <description>

&lt;h2 id=&#34;have-you-tested-your-backups-recently&#34;&gt;Have you tested your backups recently?&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;m sure you&amp;rsquo;ve heard that phrase before.  And then thought &amp;ldquo;Hmm, yeah,
I should do that&amp;rdquo;.  If you remember, you&amp;rsquo;ll stick a tape in the drive
and fire up your software, and restore a dozen files to a temporary
location.  Success!  You&amp;rsquo;ve proven your backups can be recovered.&lt;/p&gt;

&lt;p&gt;Or have you?&lt;/p&gt;

&lt;p&gt;What would you do if your server was destroyed?  Do you require
specialist software to recover that backup?  Do you still have the
install media?  The license keys?&lt;/p&gt;

&lt;p&gt;What would you do if the datacenter caught fire and you had to rebuild
from scratch?  (Assuming you ship your backups offsite&amp;hellip;)&lt;/p&gt;

&lt;p&gt;Or had everything encrypted by malware&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;sf-mta&#34;&gt;SF MTA&lt;/h2&gt;

&lt;p&gt;In November 2016 the San Francisco
Municipal Transportation Agency got &lt;a href=&#34;http://www.sfexaminer.com/hacked-appears-muni-stations-fare-payment-system-crashes/&#34;&gt;hit by
ransomware&lt;/a&gt;.
It encrypted a lot of their files.  They were unable to run the terminals to
allow passengers to buy tickets, and were forced to allow free travel.&lt;/p&gt;

&lt;p&gt;Now in many of these cases the victim ends up paying up to get the decryption
keys to recover their data.  But the SF MTA didn&amp;rsquo;t do that; they went to
their backup tapes and restored everything they needed.&lt;/p&gt;

&lt;h2 id=&#34;document-test&#34;&gt;Document, test&lt;/h2&gt;

&lt;p&gt;When you are in a disaster recovery situation you need to have standard
processes and procedures fully documented.  How do you restore data?  How
do you recall tapes back from offsite?  Do you &lt;em&gt;know&lt;/em&gt; what tapes to
recall (hint: the tape inventory may have been encrypted!).&lt;/p&gt;

&lt;p&gt;Simple procedures that you &lt;em&gt;test&lt;/em&gt; are critical.  Assume a worst case
scenario and work out how you would recover from that.  Note problems
that arise during the tests and update your procedures.&lt;/p&gt;

&lt;h2 id=&#34;protect-the-backups&#34;&gt;Protect the backups&lt;/h2&gt;

&lt;p&gt;Many backup systems leave data &amp;ldquo;on line&amp;rdquo;, especially those that backup to
a remote disk.  If these backups can be modified then they could &lt;em&gt;also&lt;/em&gt;
be encrypted.  A backup is useless if you can&amp;rsquo;t read the data.&lt;/p&gt;

&lt;p&gt;These backups contain pretty much all your data.  They should be
treated as highly confidential data.  If you have PII (Personally Identifiable Information) in that backup then you need to treat it the same as any other
PII data.  This may mean it needs to be encrypted&amp;hellip; in which case you
now have encryption key management problems (not so &amp;ldquo;simple procedures&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;You also need to be careful where and how you store your backups; again
in November Michael Page, a UK based recruiting firm, had &lt;a href=&#34;https://www.troyhunt.com/the-capgemini-leak-of-michael-page-data-via-publicly-facing-database-backup/&#34;&gt;their data
leaked&lt;/a&gt;.
These were SQL backups from a service run by Capgemini.  Somehow
production quality data was placed on a development server, and exposed.&lt;/p&gt;

&lt;h2 id=&#34;personal-anecdote&#34;&gt;Personal anecdote&lt;/h2&gt;

&lt;p&gt;I have a very simple process for my backups; it may not be efficient,
it may waste disk space&amp;hellip; but it&amp;rsquo;s &lt;em&gt;simple&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I use the native OS backup software.  So for ext[234] disks I use the
&lt;code&gt;dump&lt;/code&gt; command; for xfs disks I use &lt;code&gt;xfsdump&lt;/code&gt; (and when I ran SunOS
or Solaris I used their &lt;code&gt;dump&lt;/code&gt; commands).&lt;/p&gt;

&lt;p&gt;On a Sunday I run a level 0 backup; that&amp;rsquo;s everything.  On Monday I
do a level 1; on Tuesday a level 2&amp;hellip;  so each day has an increment
on the previous day.&lt;/p&gt;

&lt;p&gt;These backups are then &amp;lsquo;rsync&amp;rsquo;d offsite to a second server.  If the
worst happens then I could build a machine and boot it from a DVD and
then restore all the data over the network back to the disks (no special
software dependencies!  It&amp;rsquo;s part of the standard OS).  I have a simple
process; restore the latest level 0 then all the incrementals.&lt;/p&gt;

&lt;p&gt;I got to do this for real, once.  I was in Newark Airport, ssh&amp;rsquo;d home
to read my mail, when I hard crashed the server (known issue; if I
ran &lt;code&gt;X&lt;/code&gt; twice then it hard crashed).  Damn; I wasn&amp;rsquo;t going to be home
for 2 weeks!  All my mail and stuff would queue up on my external
machines, but&amp;hellip; &lt;em&gt;grump&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I had a brain-wave; I had a second machine where I was playing around
with virtualization&amp;hellip; could I recover the broken machine into a VM
from the backups?  I fired up a new VM, custom configuration for disk
sizes and then restored the data.  Got on the plane while the restore
was running.  When I got to the hotel I finished up the process and
rebooted&amp;hellip; and it worked!&lt;/p&gt;

&lt;p&gt;Indeed it worked so well that when I finally got home and rebooted the
physical server all I did was transfer over the few files that had
changed since the backup run and then shut it down.  I&amp;rsquo;ve been running
via VM ever since.  The old physical machine is sitting under a table,
just in case I need hardware in an emergency :-)&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Backups are no good if they can&amp;rsquo;t be used to restore your servers back
to operational state.  This means &lt;em&gt;test&lt;/em&gt; your processes, including any
steps necessary to get your backup/restore software working again.&lt;/p&gt;

&lt;p&gt;Protect your backups, both from tampering and from being leaked.&lt;/p&gt;

&lt;p&gt;Don&amp;rsquo;t expect everything to work first time; and don&amp;rsquo;t be surprised
if restores take longer than you expect!  (One off-site DR test my
company ran ended up with the windows server restores taking 2 days
when they only planned for 4 hours; good lesson to learn!)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Using Letsencrypt for TLS</title>
      <link>https://www.sweharris.org/post/2016-12-04-letsencrypt/</link>
      <pubDate>Sun, 04 Dec 2016 14:42:33 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-12-04-letsencrypt/</guid>
      <description>

&lt;p&gt;In previous posts I pointed out &lt;a href=&#34;https://www.sweharris.org/post/2016-05-31-secure-webserver/&#34;&gt;why TLS is important&lt;/a&gt;, how to configure Apache to &lt;a href=&#34;https://www.sweharris.org/post/2016-10-16-ssl-score/&#34;&gt;score an A+&lt;/a&gt;
and how to &lt;a href=&#34;https://www.sweharris.org/post/2016-10-23-headers/&#34;&gt;tune HTTP headers&lt;/a&gt;.  All this is
dependent on &lt;em&gt;getting&lt;/em&gt; an SSL cert.&lt;/p&gt;

&lt;h2 id=&#34;some-jargon-explained&#34;&gt;Some jargon explained&lt;/h2&gt;

&lt;p&gt;Before we delve into a &amp;ldquo;how to&amp;rdquo;, some basic jargon should be explained:&lt;/p&gt;

&lt;h3 id=&#34;ssl-tls&#34;&gt;SSL/TLS&lt;/h3&gt;

&lt;p&gt;TLS (&amp;ldquo;Transport Layer Security&amp;rdquo;) is the successor to SSL (&amp;ldquo;Secure
Socket Layer&amp;rdquo;).  SSL was created by Netscape in the mid 90s (I remember
installing &amp;ldquo;Netscape Commerce Server&amp;rdquo; in 1996).  When you hear people
talk about SSL and TLS they pretty much use the terms interchangeably.
You can think of it as a progression SSL2, SSL3, TLS1.0, TLS1.1, TLS1.2
with each version better than the previous.&lt;/p&gt;

&lt;p&gt;SSL/TLS is what makes the connection to the server secure.&lt;/p&gt;

&lt;h3 id=&#34;ssl-certificate&#34;&gt;SSL Certificate&lt;/h3&gt;

&lt;p&gt;This is a file you place on your server and this basically says
&amp;ldquo;&lt;em&gt;I am server x.y.z&lt;/em&gt;&amp;rdquo;.  The server for this website says &amp;ldquo;&lt;em&gt;I am server
www.sweharris.org&lt;/em&gt;&amp;rdquo;.  There are other things this certificate can say
(&amp;rdquo;&lt;em&gt;I can also be called sweharris.org&lt;/em&gt;&amp;rdquo;).  Different certificates can
also be used for other reasons (e.g. signing code), but I won&amp;rsquo;t go into
that here.&lt;/p&gt;

&lt;p&gt;The SSL certificate is &lt;em&gt;signed&lt;/em&gt; by a trusted party (the &amp;ldquo;Certificate
Authority&amp;rdquo; - CA), so when your browser goes to a web site it can verify the
certificate is valid.  Your browser has a list of CAs that the browser
creator trusts.  If I tried to create a certificate for &amp;ldquo;google.com&amp;rdquo;
then no CA would sign it, and your browser would say &amp;ldquo;Nope!&amp;rdquo;&lt;/p&gt;

&lt;h3 id=&#34;domain-validation&#34;&gt;Domain Validation&lt;/h3&gt;

&lt;p&gt;In order to get a certificate signed the CA needs to know that you &lt;em&gt;are&lt;/em&gt;
who you claim you are.  &amp;ldquo;Domain Validation&amp;rdquo; (DV) is the weakest and easiest
method of validating ownership.  This may be done by sending an email to
a standard address (eg &lt;code&gt;postmaster&lt;/code&gt; or &lt;code&gt;hostmaster&lt;/code&gt;).  It might be done
by requiring you to put a specific file on the web server.  Or changing
a DNS entry&amp;hellip;   the idea is to require the requester to prove they have
access to a controlled resource associated with the domain.&lt;/p&gt;

&lt;p&gt;This techique is used elsewhere; e.g. if you put your website into
Google Webmaster Tools then it will require you to put a specific entry
on your server (eg &lt;code&gt;/googleSOMESTRING.html&lt;/code&gt;).  If you want to use
Google Apps for your mail then it may want a DNS entry (eg &lt;code&gt;googleSOMESTRING   IN      CNAME   google.com.&lt;/code&gt;).   These are both &amp;ldquo;domain validation&amp;rdquo; examples.&lt;/p&gt;

&lt;h3 id=&#34;extended-verification&#34;&gt;Extended Verification&lt;/h3&gt;

&lt;p&gt;Extended Validation (EV) certs take a deeper approach to validating
the request; they also check the &lt;em&gt;owner&lt;/em&gt; claims.  So, for example, I
might be able to get a DV cert for &lt;code&gt;chas3.com&lt;/code&gt;, but I would not be able
to get an EV cert saying &amp;ldquo;this is owned by JPMorgan Chase&amp;rdquo;.  An EV
cert is meant to help reduce &lt;a href=&#34;https://en.wikipedia.org/wiki/Phishing&#34;&gt;phishing&lt;/a&gt;
attacks by helping the web user spot if an EV cert is in use.&lt;/p&gt;

&lt;p&gt;Compare my site to Chase&amp;rsquo;s:
&lt;center&gt;
&lt;img src=&#34;https://www.sweharris.org/images/sweharris_cert_header.png&#34; alt=&#34;mysite&#34; /&gt;
&lt;br&gt;
&lt;img src=&#34;https://www.sweharris.org/images/chase_cert_header.png&#34; alt=&#34;chase&#34; /&gt;
&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;We both have the green padlock, showing the cert&amp;rsquo;s are good, but the
Chase entry has more details about the owner next to the padlock.&lt;/p&gt;

&lt;p&gt;For a site like mine a DV cert is sufficient.  You need to decide
if you want a DV or EV for your site.&lt;/p&gt;

&lt;h2 id=&#34;getting-a-cheap-cert&#34;&gt;Getting a cheap cert&lt;/h2&gt;

&lt;p&gt;When I first started out in 1996 getting a cert was a hard tedious
process.  We had to fax (fax!) details to one of the very few CAs
that were around, and it took weeks to get the cert.  Painful.  It
was effectively an EV process, long before such a thing really existed.&lt;/p&gt;

&lt;p&gt;As time went on the DV process became easier to get, but they still cost
money.  It wasn&amp;rsquo;t really worth it for most people.&lt;/p&gt;

&lt;p&gt;In 2012 I noticed that StartCom were providing &lt;em&gt;free&lt;/em&gt; DV certs, under
the brand StartSSL.  This was an Israeli company and their CA was
a common one.  It made sense.&lt;/p&gt;

&lt;p&gt;The StartSSl process was pretty painful.  It was totally manual and
involved using a web site with cut&amp;rsquo;n&amp;rsquo;paste.  The DV process expired after
30 days so every renewal required revalidation.  But it was free, and
I only had 7 certs with them, so I could jump through the hoops every
so often.&lt;/p&gt;

&lt;p&gt;Unfortunately, it&amp;rsquo;s not clear &lt;a href=&#34;http://www.percya.com/2016/09/startcom-operated-solely-in-china.html&#34;&gt;if StartSSL is still trustworth&lt;/a&gt;, and may now
&lt;a href=&#34;https://pierrekim.github.io/blog/2016-02-16-why-i-stopped-using-startssl-because-of-qihoo-360.html&#34;&gt;operate from China&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;letsencrypt&#34;&gt;Letsencrypt&lt;/h2&gt;

&lt;p&gt;Fortunately &lt;a href=&#34;https://www.letsencrypt.org&#34;&gt;Letsencrypt&lt;/a&gt; started up.  Their
goal was to &lt;em&gt;automate&lt;/em&gt; a lot of the manual steps, while still providing
free DV certs.  They even provide a client so you can basically say
&amp;ldquo;encrypt my site&amp;rdquo; and their software will create the necessary cert files,
do the DV process (stick a file on the server), retrieve the signed
result, reconfigure your webserver daemon and, boom, in seconds your site
is now SSL enabled.  The certificate is only valid for 90 days, but that&amp;rsquo;s
not a problem; the same software can automatically renew the cert before
it expires.&lt;/p&gt;

&lt;p&gt;Very impressive.&lt;/p&gt;

&lt;p&gt;Unfortuntately it doesn&amp;rsquo;t work for me.  My site is replicated across
multiple providers (one copy at Linode in Texas; one copy at Panix in
New York; one copy at OVH in Canada).  I manage content on my home machine
and &lt;code&gt;rsync&lt;/code&gt; the results out.  I also manage the webserver configurations
via &lt;code&gt;ansible&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If I ran their client on one machine then I&amp;rsquo;d have to copy the resulting
certs to the other two&amp;hellip; it&amp;rsquo;s doable, but messy.&lt;/p&gt;

&lt;p&gt;However there was another way of doing the DV certification, and that&amp;rsquo;s
via DNS.  Now my DNS is &lt;em&gt;also&lt;/em&gt; replicated (hidden primary server at home;
public primary at the three sites).  So this means I could do the cert
DV validation via DNS from my home machine, then push the resulting cert
out to the web servers via &lt;code&gt;ansible&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The original Letsencrypt client couldn&amp;rsquo;t do DNS validation, but
&lt;a href=&#34;https://github.com/lukas2511&#34;&gt;Lukas Schaur&lt;/a&gt; created an alternative
shell based client called &lt;a href=&#34;https://github.com/lukas2511/dehydrated&#34;&gt;deydrated&lt;/a&gt;.
This is a much simpler program, but allowed DNS mode to be used, and had
a call out so I could modify how the DNS change ran.&lt;/p&gt;

&lt;h2 id=&#34;how-it-works&#34;&gt;How it works&lt;/h2&gt;

&lt;p&gt;Last week one of my certs needed renewing, so I went through the renew
process:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd etc/localnet/Letsencrypt/
$ ./refresh
 + Valid till Dec  6 23:35:00 2016 GMT (Less than 8 days). Renewing!
 + Signing domains...
 + Generating private key...
 + Generating signing request...
 + Requesting challenge for linode.spuddy.org...
 + Responding to challenge for linode.spuddy.org...
 + Challenge is valid!
 + Requesting certificate...
 + Done!
 + Creating fullchain.pem...
/home/sweh/etc/localnet/PlayBooks/Files/Postfix/Per-host/linode
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;refresh&lt;/code&gt; command calls &lt;code&gt;./dehydrated -c&lt;/code&gt; to do all the hard work
of talking to the Letsencrypt servers.  It noticed that the &lt;code&gt;linode&lt;/code&gt;
cert needed renewing, and got a new signed cert.  My script then
compared all the managed certs and copied any changed ones into the
ansible tree.  In this case the single cert for the linode Postfix
server (also used by INN) was updated.&lt;/p&gt;

&lt;p&gt;Since a change was done I could then use ansible to push it out:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd ../PlayBooks/
$ ansible-playbook -l linode postfix-inn.yml 

PLAY [Set up postfix config on mail servers] ********************************** 

[...]

TASK: [send machine specific certs] ******************************************* 
changed: [linode] =&amp;gt; (item=privkey.pem)
changed: [linode] =&amp;gt; (item=fullchain.pem)

NOTIFIED: [restart postfix] *************************************************** 
changed: [linode]

PLAY [Set up INN] ************************************************************* 

[...]

TASK: [send INN privkey] ****************************************************** 
changed: [linode]

TASK: [send INN cert chain] *************************************************** 
changed: [linode]

[...]

PLAY RECAP ******************************************************************** 
linode                     : ok=21   changed=4    unreachable=0    failed=0   
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;rsquo;s it!  I can also verify the new certs are in place and working&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd ../Letsencrypt
$ ./check_remote nntp linode.spuddy.org
             linode.spuddy.org NNTP: OK notAfter=Feb 27 16:31:00 2017 GMT
$ ./check_remote smtp linode.openvpn linode.spuddy.org
             linode.spuddy.org SMTP: OK notAfter=Feb 27 16:31:00 2017 GMT
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;how-to-know-when-to-renew-a-cert&#34;&gt;How to know when to renew a cert&lt;/h2&gt;

&lt;p&gt;It would be bad to allow a cert to expire, so you need ample warning of
when a cert needs to be refreshed.  Because of the tree used by the
&lt;code&gt;dehydrated&lt;/code&gt; code is consistent this is very easy to script:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/bin/ksh -p

# Warn if cert will expire in this many days
let DAYS=${DAYS:-7}
let warn=DAYS*86400

typeset -R25 h
bad=&amp;quot;&amp;quot;

cd /home/sweh/etc/localnet/Letsencrypt/certs || exit
for a in */cert.pem
do
  b=$(openssl x509 -checkend $warn -in $a)
  if [ &amp;quot;x$b&amp;quot; = &amp;quot;xCertificate will expire&amp;quot; ]
  then
    b=$(openssl x509 -noout -dates -in $a | sed -n &#39;s/^notAfter=//p&#39;)
    h=${a%/*}
    bad=&amp;quot;$bad\nletsencrypt $h: $b&amp;quot;
  fi
done

if [ -n &amp;quot;$bad&amp;quot; ]
then
  print Following certificate expiration dates:
  print &amp;quot;$bad&amp;quot;
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So I can now see what certs are due to expire:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ checkssl
$ DAYS=20 checkssl
$ DAYS=25 checkssl
Following certificate expiration dates:

letsencrypt           bofh.spuddy.org: Dec 28 23:46:00 2016 GMT
letsencrypt        gallery.spuddy.org: Dec 28 23:47:00 2016 GMT
letsencrypt          games.spuddy.org: Dec 28 23:47:00 2016 GMT
letsencrypt           home.spuddy.org: Dec 28 23:47:00 2016 GMT
letsencrypt       mercury7.spuddy.org: Dec 28 23:48:00 2016 GMT
letsencrypt     panix-news.spuddy.org: Dec 28 23:48:00 2016 GMT
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is easy to put into a &lt;code&gt;cron&lt;/code&gt; job.  Indeed&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;1 1 * * * /home/sweh/bin/checkssl
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the morning I can refresh any certs necessary while drinking my
coffee :-)&lt;/p&gt;

&lt;h2 id=&#34;automation&#34;&gt;Automation&lt;/h2&gt;

&lt;p&gt;So far I&amp;rsquo;ve only automated 90% of the job.  I still have to run the
&lt;code&gt;refresh&lt;/code&gt; and &lt;code&gt;ansible-playbook&lt;/code&gt; commands.  Partly this is because
it&amp;rsquo;s so easy, partly because it gives me positive feedback (I know
the work was done and the push successful), but mostly because this
is &amp;ldquo;good enough&amp;rdquo; for my use case.&lt;/p&gt;

&lt;p&gt;When I started using this process I would occassionally get errors with
the DV step; I&amp;rsquo;m not sure if that was due to DNS propagation issues
or caching at the LetsEncrypt side or something else.  I haven&amp;rsquo;t had a
problem for quite a while now, but I like to keep my eye on it.&lt;/p&gt;

&lt;p&gt;But we can see, quite easily, how a daily &amp;ldquo;refresh/push&amp;rdquo; process could
be created so the overnight &amp;ldquo;checkssl&amp;rdquo; job could become a &amp;ldquo;check and
refresh&amp;rdquo; job.&lt;/p&gt;

&lt;p&gt;Currently I have 12 certificates managed this way, and it takes less
than 5 minutes a month to manage.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Where DV certs are sufficient, a tooling around Letsencrypt is perfectly
adequate and sensible.  It can even be used for internal web sites, as long
as DNS challenge/response can be handled.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s little excuse to not use SSL on web sites any more!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>LXD and machine containers</title>
      <link>https://www.sweharris.org/post/2016-11-27-lxd-machine-container/</link>
      <pubDate>Sun, 27 Nov 2016 16:31:00 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-11-27-lxd-machine-container/</guid>
      <description>

&lt;p&gt;A few months back I was invited to an &lt;a href=&#34;https://rfgex.com&#34;&gt;RFG Exchange&lt;/a&gt;
Rounds taping, on containers.  There were a number of big name vendors
there.  I got invited as an end user with opinions :-)&lt;/p&gt;

&lt;p&gt;The published segment is on &lt;a href=&#34;https://www.youtube.com/watch?v=9ajuFXgcbD4&#34;&gt;youtube&lt;/a&gt; under the &lt;a href=&#34;https://www.youtube.com/channel/UCcjW0Br67wEYc5o6EcgdvCA&#34;&gt;RFG Exchange&lt;/a&gt; channel.&lt;/p&gt;

&lt;p&gt;Unknown to me, Mark Shuttleworth (Canonical, Ubuntu) was a &amp;ldquo;headline act&amp;rdquo;
at this taping and I got to hear some of what he had to say, in particular
around the Ubuntu &amp;ldquo;LXD&amp;rdquo; implementation of containers.  I&amp;rsquo;m not convinced
he&amp;rsquo;s going in the right direction and I pulled what my girlfriend calls
&amp;ldquo;sceptical face&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;
&lt;img src=&#34;https://www.sweharris.org/images/RFGex/sceptical.png&#34; alt=&#34;Sceptical face&#34; /&gt;
&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Beyond the problem of &amp;ldquo;machine containers&amp;rdquo; (which are, basically, the
&lt;a href=&#34;https://www.sweharris.org/post/2016-08-15-container-as-vm/&#34;&gt;&amp;ldquo;container as a VM&amp;rdquo;&lt;/a&gt; model, and which
is specifically promoted by LXD), I have a real problem with how he
sees machine containers being used.  This is typified by the segment starting
at &lt;a href=&#34;https://www.youtube.com/watch?v=9ajuFXgcbD4&amp;amp;t=2m&#34;&gt;2 minutes&lt;/a&gt;; we can
take an 1990&amp;rsquo;s Linux install and run it unchanged inside a machine container.
It&amp;rsquo;s very possible that this would work.  I ran old 90&amp;rsquo;s compiled
executables for many years; the Linux kernel is pretty good at backwards
compatibility in this way.
(I doubt a real old &lt;code&gt;a.out&lt;/code&gt; format system would run, but it&amp;rsquo;s likely an
&lt;code&gt;ELF&lt;/code&gt; system should&amp;hellip; albeit with some kernel warnings about deprecated
syscalls).&lt;/p&gt;

&lt;p&gt;The discussion (which doesn&amp;rsquo;t appear to be in this video, unless I&amp;rsquo;ve
missed it) also touched on &amp;ldquo;run anything&amp;rdquo;, with Mark saying that,
absolutely, this is a supported use case.&lt;/p&gt;

&lt;p&gt;The problem is &amp;ldquo;just because you can, doesn&amp;rsquo;t mean you should&amp;rdquo;.  The
&amp;ldquo;run anything&amp;rdquo; model leads to &lt;a href=&#34;https://www.sweharris.org/post/2016-04-02-container-security/&#34;&gt;Wild West&lt;/a&gt;
deployments.&lt;/p&gt;

&lt;p&gt;In an enterprise environment we spend many many hours in standardising
our setup.  We force a standardised operating system (RedHat or Ubuntu LTS
or SUSE, typically, for stability).  We force a common identity and access
management (I&amp;amp;AM) solution.  We have a standardised software stack deployed as
part of the build (monitoring, backup, scanning, privileged control&amp;hellip;).&lt;/p&gt;

&lt;p&gt;We don&amp;rsquo;t &lt;em&gt;want&lt;/em&gt; people running anything they like.  I don&amp;rsquo;t want the
introduction of Debian installs inside a machine container inside my
RedHat or Ubuntu environment.  Yes, LXD supports this; RedHat modified
Docker supports this; I could even wrapper generic Docker to do this.
But this way leads to insecurity.&lt;/p&gt;

&lt;h2 id=&#34;software-delivery&#34;&gt;Software delivery&lt;/h2&gt;

&lt;p&gt;I was at a cloud forum last week and a software vendor asked &amp;ldquo;do you
want me to provide my software in the form of a container&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;No, really, I don&amp;rsquo;t.  If this container allows for access to the OS
(eg via SSH) then I need to &lt;em&gt;control&lt;/em&gt; that access, which means it&amp;rsquo;s
got to be integrated with my I&amp;amp;AM processes and with my monitoring
processes.  If there&amp;rsquo;s persistent data then I need to back it up.  The
whole of the control stack that I&amp;rsquo;ve optimised for my chosen OS needs
to run in that container.&lt;/p&gt;

&lt;p&gt;The only time I would accept a containerized application is if it was
a true appliance.  An immutable image that is configured via external
data (eg from the &lt;code&gt;docker run&lt;/code&gt; command line) to point to external
resources.  Now a container may be a suitable deployment mechanism.&lt;/p&gt;

&lt;p&gt;But don&amp;rsquo;t give me a full machine container and expect me to run it as
a virtual machine.  I never accepted VMware images for this reason; containers
don&amp;rsquo;t change the security stance.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;As I&amp;rsquo;ve written before, machine containers are perfectly valid use of
container technology.  But if you treat a container as a VM then you
must &lt;em&gt;run&lt;/em&gt; it as a VM.  This means full integration into your control
stack.  You don&amp;rsquo;t (shouldn&amp;rsquo;t!) let anyone start up a VM on your network
with any OS they like in it; you shouldn&amp;rsquo;t let anyone start a machine
container with untrusted unknown content.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Building my home server</title>
      <link>https://www.sweharris.org/post/2016-11-27-home-machine/</link>
      <pubDate>Sun, 27 Nov 2016 13:06:29 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-11-27-home-machine/</guid>
      <description>&lt;p&gt;A couple of weeks back I got a new case for my PC.  Previously I
was using a generic mini-tower and then had an external 8-disk tower
(&lt;a href=&#34;http://www.sansdigital.com/towerraid/tr8mb.html&#34;&gt;Sans Digital TR8MB&lt;/a&gt;)
connected via an eSATA concentrator (4 disks per channel).&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s been working OK for years but every so often the controller
would reset (especially under write loads); no data lost but annoying.
Also after a power reset (eg a failure, or maintenace) then frequently
one or two disks (slot 2 in both halves!!) weren&amp;rsquo;t always detected and
needed reseating and re-adding to the RAID6 (yay for write-intent bitmaps,
so recovery is quick!).&lt;/p&gt;

&lt;p&gt;I spotted the &lt;a href=&#34;http://www.newegg.com/Product/Product.aspx?Item=N82E16811235039&#34;&gt;Zalman MS800&lt;/a&gt;
tower.  This has 10 bays.  Not enough; I have 12x3.5 disks
and 2x2.5 SSDs.  But I&amp;rsquo;d previously bought some &lt;a href=&#34;http://www.newegg.com/Product/Product.aspx?Item=N82E16816132037&#34;&gt;5.25-&amp;gt;3.5
adapters&lt;/a&gt;
that let you put 4x3.5 disk into 3x5.25 space (1 was using one of them in
the old case, and the other 2 were emergency backups incase the external
tower broke).&lt;/p&gt;

&lt;p&gt;So 9 of the slots could fit 12 disks and the 10th slot could contain
both SSDs.  And, hey, it was only $60 (down to $40 if I can be bothered
to fill in the rebate card).&lt;/p&gt;

&lt;p&gt;This would also mean I needed some better controllers; the old SiL eSATA
card that came with the old disk tower wouldn&amp;rsquo;t work for the internal
disks, so I bought 2 LSI 9211-8 cards; that&amp;rsquo;d give me 16 channels; more
than enough (in theory I could have just used one card, the
&lt;a href=&#34;http://www.newegg.com/Product/Product.aspx?Item=N82E16813157181&#34;&gt;motherboard&lt;/a&gt; has 5*SATA-3Gbps ports which might have been suitable).  My existing 650W
PSU should be sufficient to handle all of this&amp;hellip;&lt;/p&gt;

&lt;p&gt;Quite amazingly it worked!  I needed to fiddle with the boot stuff a
fair bit but I think it&amp;rsquo;ll now boot unattended if necessary :-)&lt;/p&gt;

&lt;p&gt;Speeds are faster than before.  Now I get (using &lt;code&gt;hdparm -t&lt;/code&gt;)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;         SSD: 375MB/sec  (I got 226 using internal ports)
2Tbyte disks: 133MB/sec
4Tbyte disks: 145MB/sec  (I was getting 125 using the old eSATA card)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The raw disk speeds don&amp;rsquo;t look that much better (in particular the
2Tbyte disks don&amp;rsquo;t show any real change).  But what about RAID
performance?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;The two SSDs  are in a RAID 1  and get 375 MB/sec
The 4*2Tbytes are in a RAID 10 and get 267 MB/sec
The 8*4Tbytes are in a RAID 6  and get 532 MB/sec
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Heh, we can definitely see the benefit of load distribution for reads!
This last number is much higher than the old eSATA card because there&amp;rsquo;s
no contention on the port concentrator.  Big win!  And that&amp;rsquo;s what I&amp;rsquo;d
hoped for.&lt;/p&gt;

&lt;p&gt;Each of the disk adapters has its own fan (120mm).  The case has two
fans (there&amp;rsquo;s also a way of adding a fan internally if necessary, but I
didn&amp;rsquo;t use that).&lt;/p&gt;

&lt;p&gt;So how hot does this monster run?  Most of the time it&amp;rsquo;s idle-ish, just
running a couple of VMs plus &amp;ldquo;management&amp;rdquo; stuff (DNS, DHCP, NTP etc).&lt;/p&gt;

&lt;p&gt;LM-sensors tells me:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Core 0:      +39.0 C  (high = +83.0 C, crit = +99.0 C)
Core 1:      +35.0 C  (high = +83.0 C, crit = +99.0 C)
Core 2:      +39.0 C  (high = +83.0 C, crit = +99.0 C)
Core 3:      +34.0 C  (high = +83.0 C, crit = +99.0 C)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, that&amp;rsquo;s maybe a little high for an idling machine but it&amp;rsquo;s well
within tolerance.  I&amp;rsquo;m happy with that.&lt;/p&gt;

&lt;p&gt;The disks are interesting; the SMART output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/dev/sda: 194 Temperature_Celsius ... 30
/dev/sdb: 194 Temperature_Celsius ... 30
/dev/sdc: 194 Temperature_Celsius ... 27
/dev/sdd: 194 Temperature_Celsius ... 28
/dev/sde: 194 Temperature_Celsius ... 28
/dev/sdf: 194 Temperature_Celsius ... 28
/dev/sdg: 194 Temperature_Celsius ... 27
/dev/sdh: 194 Temperature_Celsius ... 28
/dev/sdi: 194 Temperature_Celsius ... 28
/dev/sdj: 194 Temperature_Celsius ... 28
/dev/sdk: 194 Temperature_Celsius ... 28
/dev/sdl: 194 Temperature_Celsius ... 27
/dev/sdm: 194 Temperature_Celsius ... 28
/dev/sdn: 194 Temperature_Celsius ... 28
/dev/sdo: 194 Temperature_Celsius ... 40
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The two SSDs run slightly hotter than the spinning rust! And the last
disk (sdo) is a 1Tbyte disk sitting in an external cradle and just
exposed to ambient air for cooling.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s quite impressive how much difference fans can make :-)  The
external disk is hotter than the internal disks, and even more fun the
spinning rust runs cooler than the SSDs; the SSDS don&amp;rsquo;t have any forced
air-flow whereas the disks have those 120mm fans drawing air over them.&lt;/p&gt;

&lt;p&gt;(Heh, the UPS also claims power load is now down to 23%; previously it
was 25% with the external drive bay).&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/new-case.jpg&#34; alt=&#34;New case&#34;&gt;
&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title>Intel Clear Containers</title>
      <link>https://www.sweharris.org/post/2016-11-21-clear-containers/</link>
      <pubDate>Mon, 21 Nov 2016 20:11:13 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-11-21-clear-containers/</guid>
      <description>

&lt;h2 id=&#34;containers-aren-t-secure-but-neither-are-vms&#34;&gt;Containers aren&amp;rsquo;t secure&amp;hellip; but neither are VMs&lt;/h2&gt;

&lt;p&gt;An argument I sometimes here is that large companies (especially financial
companies) can&amp;rsquo;t deploy containers to production because they&amp;rsquo;re too risky.
The people making this argument focus on the fact that the Linux kernel
is only a &lt;em&gt;software&lt;/em&gt; segregation of resources.  They compare this to
virtual machines, where the CPU can enforce segregation (eg with VT-x).&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not convinced they&amp;rsquo;re right.  It sounds very very similar to the
arguments about VMs a decade ago.  It also misses out on the hypervisor,
itself, being software.  This hypervisor runs in privileged mode and
is accessible from the client (eg network drivers, block device drivers,
paravirt drivers).  VT-x instructions can help with some low level
primitives and segregation, but even that&amp;rsquo;s not perfect (oops, rowhammer!).&lt;/p&gt;

&lt;p&gt;Will there be bugs in the Linux kernel that&amp;rsquo;ll enable one container to
break out?  Sure!  But they&amp;rsquo;ll be found and patched.  And hypervisors
aren&amp;rsquo;t bug free.  As of time of writing there&amp;rsquo;s yet another critical Xen
bug meaning one of my public VMs will need to be rebooted as my service
provider patches their servers.&lt;/p&gt;

&lt;h2 id=&#34;intel-clear-containers&#34;&gt;Intel Clear Containers&lt;/h2&gt;

&lt;p&gt;So Intel took this concern and ran &lt;a href=&#34;https://www.sweharris.org/Intel_Clear_Containers.pdf&#34;&gt;with it&lt;/a&gt; (pdf).&lt;/p&gt;

&lt;p&gt;Essentially they created a &amp;ldquo;one container per VM&amp;rdquo; solution and optimised
the VM.  The hypervisor layer is a stripped down and optimised KVM/QEMU
solution.  Each VM then runs on a minimal Linux OS (&amp;ldquo;Clear Linux&amp;rdquo;) that&amp;rsquo;s been
optimised for this work (fast boot times, minimal drivers, optimised for
running a container).&lt;/p&gt;

&lt;p&gt;So now we have VT-x protections between containers, because there are no
containers sharing the same kernel.  To make this solution more transparent
they have created a &amp;ldquo;docker runtime&amp;rdquo; plugin, so Clear Containers can be
managed as if they were normal docker containers (eg Swarm, Kubernettes).&lt;/p&gt;

&lt;p&gt;They&amp;rsquo;ve also worked with CoreOS and the OCI for compatibility with those
layers.&lt;/p&gt;

&lt;h2 id=&#34;but-is-this-necessary&#34;&gt;But is this necessary?&lt;/h2&gt;

&lt;p&gt;Many of the risks of a shared kernel can be mitigated simply by not
running containers as root (eg unprivileged Docker containers; the default)
or by running a PaaS (eg CloudFoundry or Apprenda).&lt;/p&gt;

&lt;p&gt;Clear Containers are more heavy-weight than a pure container-in-shared-kernel
model and wouldn&amp;rsquo;t be a suitable replacement for low level container calls
(eg &lt;code&gt;clone()&lt;/code&gt; with &lt;code&gt;CLONE_NEWPID&lt;/code&gt; and similar flags).  But they&amp;rsquo;re faster
than building a traditional VM.&lt;/p&gt;

&lt;p&gt;In this respect they may be a competitor for Canonical&amp;rsquo;s &lt;a href=&#34;https://www.ubuntu.com/cloud/lxd&#34;&gt;LXD
solution&lt;/a&gt;, or perhaps VMware&amp;rsquo;s &lt;a href=&#34;http://blogs.vmware.com/PowerCLI/2015/08/vmware-instant-clone-now-fingertips-new-powercli-extensions-fling.html&#34;&gt;Instant
Clone&lt;/a&gt;.
Intel Clear Containters allow you to create a longer running container
solutions packaged inside a docker container wrapper and gaining
the protections of VT-x via the &amp;ldquo;one container per VM&amp;rdquo; model.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not convinced there&amp;rsquo;s a good use case&amp;hellip; but then I&amp;rsquo;m not convinced
by the &amp;ldquo;container as lightweight VM&amp;rdquo; use case, either :-)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Technical Debt</title>
      <link>https://www.sweharris.org/post/2016-11-13-technical-debt/</link>
      <pubDate>Sun, 13 Nov 2016 21:22:33 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-11-13-technical-debt/</guid>
      <description>

&lt;h2 id=&#34;my-home-server&#34;&gt;My home server&lt;/h2&gt;

&lt;p&gt;I was doing an upgrade on my home &amp;ldquo;server&amp;rdquo; today, and it made me realise
that design choices I&amp;rsquo;d made 10 years still impact how I build this machine
today.&lt;/p&gt;

&lt;p&gt;In 2005 I got 3*300Gb Maxtor drives.  I ran them in a RAID 5; that gave
me 600Gb of usable space.  It worked well.&lt;/p&gt;

&lt;p&gt;In 2007 I upgraded the machine to 500Gb disks.  This required additional
SATA controllers, so I got enough to allow new and old disks to be
plugged in at the same time (cables galore).  I copied the data over.
But the &amp;ldquo;architecture&amp;rdquo; was roughly the same.&lt;/p&gt;

&lt;p&gt;I bought a new PC, moved the disks.  I got an external disk array (8 bays)
using an eSata concentrator.  Switched to 5*1Tb disks.  Replaced the PC
(quad core!), upgraded the memory, switch to 2Tb disks, switch to 4Tb disks.&lt;/p&gt;

&lt;p&gt;Today I bought a new case that could handle 10 5.25&amp;rdquo; drives, and put in
3 &amp;ldquo;4*3.25 bays in a 3 bay space&amp;rdquo; in them.  Used some SAS controllers.&lt;/p&gt;

&lt;p&gt;So today I have 4*2Tb in a raid 10, 8*4Tb in a raid 6 and 2*500Gb SSD in
raid 1.&lt;/p&gt;

&lt;p&gt;But the design choice was set 10 years ago.  Just because I picked Linux
mdraid, and &lt;a href=&#34;https://www.sweharris.org/post/2012-03-04-virtualization-allchange/&#34;&gt;KVM&lt;/a&gt; for virtualisation a few years later.&lt;/p&gt;

&lt;p&gt;This means I can&amp;rsquo;t easily switch to another OS base.  I&amp;rsquo;d actually
like to try out SmartOS because it has Solaris based ZFS, which strikes
me as a lot better way to handle this level of storage.  But how do I
migrate 24Tb of data, without buying another 8 disks?&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s technical debt; I &lt;em&gt;could&lt;/em&gt; overcome this buy spending money (basically
buy a whole new machine, with all the disks and controllers).  It might
even be a good thing (I could upgrade from my old 2010 based Core i5 750
machine to something more modern).  But it&amp;rsquo;s a lot of money.&lt;/p&gt;

&lt;p&gt;Instead I&amp;rsquo;ve been spending smaller chunks of money to do incremental
upgrades of my existing machine.  Most likely my next upgrade will be a
new motherboard, memory, CPU&amp;hellip; which will go into the existing case with
the existing disks and existing controllers.  I can&amp;rsquo;t easily switch to
a newer better solution.&lt;/p&gt;

&lt;h2 id=&#34;software-development&#34;&gt;Software development&lt;/h2&gt;

&lt;p&gt;So what does all the above have to do with software development?&lt;/p&gt;

&lt;p&gt;We also have technical debt here; we&amp;rsquo;ve built processes and procedures.
We may have switched from waterfall to agile (and done it badly, abusing
the &amp;ldquo;scrum&amp;rdquo; approach because the larger organisation is still waterfall
oriented).  We&amp;rsquo;ve added test driven design methodologies.  We&amp;rsquo;ve done
peer programming, extreme programming&amp;hellip;&lt;/p&gt;

&lt;p&gt;But they all focus on small aspects of the overall picture.  We&amp;rsquo;re still
looking at deploying operating systems, databases, software.  We may have
support and change management constraints.&lt;/p&gt;

&lt;p&gt;This technical debt is stopping us from using new technologies better;
in particular cloud computing.&lt;/p&gt;

&lt;p&gt;The number of times I&amp;rsquo;ve heard &lt;a href=&#34;https://www.sweharris.org/post/2016-08-08-lift_and_shift/&#34;&gt;lift and shift&lt;/a&gt; when talking about moving
to the cloud is scary.  All you&amp;rsquo;re doing, here, is &amp;ldquo;outsourcing the
datacenter&amp;rdquo;.  You&amp;rsquo;re not making use of new technologies, you&amp;rsquo;re just
replicating existing structures.  This means you&amp;rsquo;re going to need to
have a DR solution, HA data replication, testing, failover.  You&amp;rsquo;re
still needing to patch systems, have reboot and maintenance windows.
People still login and su/sudo.&lt;/p&gt;

&lt;p&gt;This isn&amp;rsquo;t cloud computing; this is traditional computing on virtual
servers stored off premise.&lt;/p&gt;

&lt;p&gt;Just like my &amp;ldquo;duplicate and rebuild from scratch&amp;rdquo; home server we may need
to do the same with our software.  Build with a &lt;a href=&#34;http://12factor.net&#34;&gt;12 factor&lt;/a&gt; focus.  Design
for failure.  Scale horizontally.  Design for hands-off compute, automated
deployment, stateless applications, attached storage.&lt;/p&gt;

&lt;p&gt;Now we can start to make use of the new technologies.  We don&amp;rsquo;t need a
DR solution because the design, itself, is resilient.  We don&amp;rsquo;t do
failover testing because there &lt;em&gt;is&lt;/em&gt; no failover.  We don&amp;rsquo;t need to patch
the OS; we redeploy&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s a lot of benefits to be gained from re-factoring your app, your
infrastructure.  However getting there isn&amp;rsquo;t necessarily cheap.  We&amp;rsquo;ve
a tonne of historical restrictions to overcome (design, architecture,
process, support).  We could spend a whole year rewriting our code to
the new paradigm, which is time not being spent improving the product.&lt;/p&gt;

&lt;p&gt;Can you afford to do this?  Can you afford &lt;em&gt;not&lt;/em&gt; to do this?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Docker in production</title>
      <link>https://www.sweharris.org/post/2016-11-06-docker-in-production/</link>
      <pubDate>Sun, 06 Nov 2016 15:31:12 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-11-06-docker-in-production/</guid>
      <description>

&lt;p&gt;In previous posts, and even at Cloud Expo, I&amp;rsquo;ve been
pushing the idea that it&amp;rsquo;s the &lt;a href=&#34;https://www.sweharris.org/post/2016-06-13-cloudexpo/&#34;&gt;process that matters, not the
technology&lt;/a&gt; when it comes to container security.
I&amp;rsquo;ve tried not to make claims that at tied to a specific solution,
although I have made a few posts using &lt;a href=&#34;https://www.sweharris.org/tags/docker/&#34;&gt;docker&lt;/a&gt; as a basis.&lt;/p&gt;

&lt;p&gt;I was recently asked my thoughts on &lt;a href=&#34;https://thehftguy.wordpress.com/2016/11/01/docker-in-production-an-history-of-failure/&#34;&gt;Docker in Production: A History of Failure
&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Basically they can be boiled down to &amp;ldquo;it&amp;rsquo;s new; if you ride the bleeding
edge you might get cut&amp;rdquo;.  Which we all know.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s some lessons we can take away from that rant, though.  Indeed
some of the mistakes and lessons come out in the comments.  None of them
are security related, but they all have impact on the resiliency of
the deployments.&lt;/p&gt;

&lt;h2 id=&#34;quickly-moving-technology-may-change-in-incompatible-ways&#34;&gt;Quickly moving technology may change in incompatible ways&lt;/h2&gt;

&lt;p&gt;One reason for the popularity of RedHat Enterprise Linux and for Ubuntu LTS
in large companies is simply due to the compatibility and stability of the
releases.  You can stick with RedHat 6 for 7 years and not worry (too much!)
about patches and enhancements breaking things.  Docker, as a technology,
is closer to Fedora than RHEL.  It&amp;rsquo;s evolving and changing and improving
very quickly.  Each release is getting better&amp;hellip; but we don&amp;rsquo;t have
compatibility guarantees.&lt;/p&gt;

&lt;h2 id=&#34;tooling-doesn-t-always-exist&#34;&gt;Tooling doesn&amp;rsquo;t always exist&lt;/h2&gt;

&lt;p&gt;Again, this is new technology.  You may need to invent and create stuff,
especially for you local specific requirements.  There&amp;rsquo;s nothing specific
to Docker, here.  Systems engineering has always had a &amp;ldquo;invent stuff&amp;rdquo;
role.  That&amp;rsquo;s the fun and why I work in technology infrastructure teams,
rather than doing application development.&lt;/p&gt;

&lt;h2 id=&#34;containers-aren-t-meant-to-be-persistent-but-can-be&#34;&gt;Containers aren&amp;rsquo;t meant to be persistent&amp;hellip; but can be!&lt;/h2&gt;

&lt;p&gt;In an ideal world a container based application
should not have persistency and treat storage as a service to be attached.
But&amp;hellip; &lt;a href=&#34;https://www.sweharris.org/post/2016-07-28-persistency/&#34;&gt;as previously written&lt;/a&gt;, you &lt;em&gt;can&lt;/em&gt;
attach persistent storage to your containers.  Docker even produces a
number of options.  You &lt;em&gt;can&lt;/em&gt; make a database run inside a docker container,
but should you?&lt;/p&gt;

&lt;h2 id=&#34;don-t-blindly-sync-repositories&#34;&gt;Don&amp;rsquo;t blindly sync repositories&lt;/h2&gt;

&lt;p&gt;You might think that synchronising an external repo to something internal
is a good thing; after all, it reduces dependencies on external services
and means your build process can continue even if the remote service
is unavailable.  Well&amp;hellip; yes, but that&amp;rsquo;s not the whole story.  Your
internal repo should be &lt;em&gt;curated&lt;/em&gt;.  Don&amp;rsquo;t just blindly sync trees.  The
&amp;ldquo;npm leftpad&amp;rdquo; issue, the docker signing key issue&amp;hellip; both of these would
propagate into an internal server if you blindly sync.  You also haven&amp;rsquo;t
added any security or repeatability to your process&lt;/p&gt;

&lt;h2 id=&#34;not-all-tasks-are-suitable-for-containers&#34;&gt;Not all tasks are suitable for containers&lt;/h2&gt;

&lt;p&gt;If your server is running 100% on your application then putting it into
a container won&amp;rsquo;t let you run on that machine.  If your application
hasn&amp;rsquo;t been developed for horizontal scalability then spinning up 10
containers won&amp;rsquo;t give you more capacity.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;It may not make sense to run your database server in a docker world;
it may not make sense to run your low-latency app in a container (the
people I&amp;rsquo;ve worked with won&amp;rsquo;t even use VMs; it must be physical with
specific CPUs with known cache-coherency properties; there must be no
disk I/O etc etc); it may not make sense to run your LDAP infra that
maxes out all CPU cores in a container&amp;hellip;&lt;/p&gt;

&lt;p&gt;Containers should only be one tool in the toolbox; it&amp;rsquo;s not the be-all
solution.&lt;/p&gt;

&lt;p&gt;Personally, I like the PaaS approach to containers
(eg &lt;a href=&#34;https://pivotal.io/platform&#34;&gt;Cloud Foundry&lt;/a&gt; or &lt;a href=&#34;http://www.apprenda.com&#34;&gt;Apprenda&lt;/a&gt;); this can hide a lot of the rawness and can provide a more friendly
solution&amp;hellip; but at the expense of flexibility.  It can encourage the
use of &lt;a href=&#34;http://www.12factor.net&#34;&gt;12 factor apps&lt;/a&gt;, horizontal scalability
and use of attached services.&lt;/p&gt;

&lt;p&gt;But if you do want to use Docker, then go into it with your eyes open;
be aware of the risks; be aware that the technology is changing quickly.&lt;/p&gt;

&lt;p&gt;And I&amp;rsquo;ll leave you with a &amp;ldquo;Downfall&amp;rdquo; parody, in which &lt;a href=&#34;https://www.youtube.com/watch?v=PivpCKEiQOQ&#34;&gt;Hitler talks about
using Docker in production&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Using SSH certificates</title>
      <link>https://www.sweharris.org/post/2016-10-30-ssh-certs/</link>
      <pubDate>Sun, 30 Oct 2016 09:31:20 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-10-30-ssh-certs/</guid>
      <description>

&lt;p&gt;In previous articles I&amp;rsquo;ve explained &lt;a href=&#34;https://www.sweharris.org/post/2016-09-05-sshkeys/&#34;&gt;how to use traditional SSH keys&lt;/a&gt;
and why connecting to a wrong server &lt;a href=&#34;https://www.sweharris.org/post/2016-09-18-ssh-password-exposure/&#34;&gt;could expose your password&lt;/a&gt;.  I was reminded of a newer form of authentication
supported by OpenSSH; CA keys.&lt;/p&gt;

&lt;p&gt;The CA key model is closer to how SSL certs work; you have an authority
that is trusted by the servers and clients, and a set of signed keys.&lt;/p&gt;

&lt;h2 id=&#34;creating-the-ca-key&#34;&gt;Creating the CA key&lt;/h2&gt;

&lt;p&gt;Creating a certificate authority key is pretty much the same as creating
any other key&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ mkdir ssh-ca
$ cd ssh-ca
$ ssh-keygen -f server_ca
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in server_ca.
Your public key has been saved in server_ca.pub.
The key fingerprint is:
04:f2:60:0a:89:c0:66:2d:1c:a9:da:ca:11:60:59:bf sweh@test1.spuddy.org
The key&#39;s randomart image is:
+--[ RSA 2048]----+
|Bo*.+ .          |
|+@ +.+ .         |
|* o  .. .        |
|..    ..         |
|...  E  S        |
|...              |
|...              |
|..               |
|                 |
+-----------------+
$ ls -l
total 8
-rw------- 1 sweh sweh 1766 Oct 30 09:30 server_ca
-rw-r--r-- 1 sweh sweh  403 Oct 30 09:30 server_ca.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;creating-and-using-signed-host-keys&#34;&gt;Creating and using signed host keys&lt;/h2&gt;

&lt;p&gt;Now we can start using this key to sign our host&amp;rsquo;s key.  This host is
&lt;code&gt;test1.spuddy.org&lt;/code&gt;.  We use &lt;code&gt;ssh-keygen&lt;/code&gt; (which has grown massively
from its origins!) with the &lt;code&gt;-h&lt;/code&gt; flag to indicate &amp;ldquo;host key&amp;rdquo;.  Because
it&amp;rsquo;s a certificate it can have an expiration date associated with it (&lt;code&gt;-V&lt;/code&gt;)
flag; in this case 52 weeks.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo ssh-keygen -s server_ca -I key_for_test1 -h -n test1.spuddy.org -V +52w /etc/ssh/ssh_host_rsa_key.pub
Enter passphrase: 
Signed host key /etc/ssh/ssh_host_rsa_key-cert.pub: id &amp;quot;key_for_test1&amp;quot; serial 0 for test1.spuddy.org valid from 2016-10-30T09:43:00 to 2017-10-29T09:44:13
$ ls -l /etc/ssh/ssh_host_rsa_key-cert*    
-rw-r--r-- 1 root root 1332 Oct 30 09:44 /etc/ssh/ssh_host_rsa_key-cert.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We now need to tell the server to offer this certificate.  In your &lt;code&gt;sshd_config&lt;/code&gt; file you need the line&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now the client also needs to be told about the CA.  It does this my
adding the CA&amp;rsquo;s public key into the known hosts file.  This can be
the clients&amp;rsquo;s global entry:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cat /etc/ssh/ssh_known_hosts
@cert-authority *.spuddy.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/jf9ZrH1qtVB6Gxo31bPA77WGuJ92jb9EaWNp+ht9j+s5+ZLLUm8RM1+T8vBow54IF0uavv/YLcchKIa6vmZdKmMJU5HF6SEdplGqDMDdvd+6U/cm/NQbmS0uTsLQBnCh4zptJJKeC1lc9IOCMwnz1oVA6rGdUc09rZMIDYyW2QpeFArgye5Yi57OWGJl+61QeqBMoAy/hytrYbGXYQsra5c5+PpYdPn2MbXzXY5dLf4H9usyhB+xzx8iAk5Sym4HBL6DnTnOzKAXL5fkI9XKiS3u7Hb1+7CSc0gOYoEFS+8L8kZ5iAqK5kkA0ekQO8DhzPEyZnecqx9n1C6UVb5D sweh@test1.spuddy.org
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now let&amp;rsquo;s see if this works.  I have no known hosts file of my own:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cat .ssh/known*
cat: .ssh/known*: No such file or directory
$ ssh test1.spuddy.org
sweh@test1.spuddy.org&#39;s password: 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Hey, it didn&amp;rsquo;t ask me to accept the key!&lt;/p&gt;

&lt;p&gt;Now I deliberately &lt;em&gt;mis-signed&lt;/em&gt; the key for &lt;code&gt;test2&lt;/code&gt;.  I specified &lt;code&gt;-n badkey.spuddy.org&lt;/code&gt; instead of &lt;code&gt;-n test2.spuddy.org&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What happens now?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh test2.spuddy.org
Certificate invalid: name is not a listed principal
The authenticity of host &#39;test2.spuddy.org (10.0.0.159)&#39; can&#39;t be established.
RSA key fingerprint is 58:45:95:16:c0:98:aa:5f:68:99:36:38:66:18:79:80.
Are you sure you want to continue connecting (yes/no)? 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Nice, it warns that the certificate doesn&amp;rsquo;t match and then falls back
to letting you accept the key.  Let&amp;rsquo;s fix the cert and try again:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh test2.spuddy.org
sweh@test2.spuddy.org&#39;s password: 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Better!&lt;/p&gt;

&lt;h2 id=&#34;client-keys&#34;&gt;Client keys&lt;/h2&gt;

&lt;p&gt;Now how can we use CA keys to &lt;em&gt;login&lt;/em&gt; to the server.  This is very
similar to signing host keys, but without the &lt;code&gt;-h&lt;/code&gt; flag, and we specify
the username this key is valid for.&lt;/p&gt;

&lt;p&gt;First I&amp;rsquo;ll generate my ssh key and then sign it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/sweh/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/sweh/.ssh/id_rsa.
Your public key has been saved in /home/sweh/.ssh/id_rsa.pub.
The key fingerprint is:
60:a7:fe:05:7a:7d:d6:ba:fe:2e:e8:05:66:36:fa:61 sweh@test1.spuddy.org
The key&#39;s randomart image is:
+--[ RSA 2048]----+
|                 |
|                 |
|      o .        |
|     . +         |
|      . S *      |
|     . . B o .   |
|      o o E.+ .  |
|       o +.=..   |
|        ..o.+=o  |
+-----------------+
$ ssh-keygen -s ssh-ca/server_ca -I user_sweh -n sweh -V +52w .ssh/id_rsa.pub
Enter passphrase:
Signed user key .ssh/id_rsa-cert.pub: id &amp;quot;user_sweh&amp;quot; serial 0 for sweh valid from 2016-10-30T10:14:00 to 2017-10-29T10:15:01
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We need to configure the server to accept signed keys; the CA&amp;rsquo;s public
key needs to be accessible and &lt;code&gt;sshd_config&lt;/code&gt; needs an extra line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TrustedUserCAKeys /etc/ssh/server_ca.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now let&amp;rsquo;s try:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh test2.spuddy.org
Enter passphrase for key &#39;/home/sweh/.ssh/id_rsa&#39;: 

test2$ cat .ssh/authorized_keys     
cat: .ssh/authorized_keys: No such file or directory
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It let me in!&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;/var/log/secure&lt;/code&gt; I can see:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Oct 30 10:19:17 test2 sshd[1967]: Accepted publickey for sweh from 10.0.0.158 port 38092 ssh2: RSA-CERT ID user_sweh (serial 0) CA RSA 04:f2:60:0a:89:c0:66:2d:1c:a9:da:ca:11:60:59:bf
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This also works with &lt;code&gt;ssh-agent&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ eval `ssh-agent`
Agent pid 2286
$ ssh-add
Enter passphrase for /home/sweh/.ssh/id_rsa: 
Identity added: /home/sweh/.ssh/id_rsa (/home/sweh/.ssh/id_rsa)
Certificate added: /home/sweh/.ssh/id_rsa-cert.pub (user_sweh)
$ ssh test2.spuddy.org echo hello
hello
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Signed host keys can help in avoiding need to maintain a track of host
keys, and so can solve the &amp;ldquo;initial trust&amp;rdquo; issue problem.  It can also
solve the &amp;ldquo;host rebuild&amp;rdquo; issue.  However an automation system to sign these
keys when a server is built is essential for this to work.&lt;/p&gt;

&lt;p&gt;Similarly we don&amp;rsquo;t need to distribute &lt;code&gt;authorized_keys&lt;/code&gt; files if the user
can present a signed certificate.  This requires a request system (preferably
self-service) where the user can present their public key and get a signed
result.&lt;/p&gt;

&lt;p&gt;Certificate authentication isn&amp;rsquo;t supported by all clients; you can
expect it in OpenSSH 6.2 onwards, and companies such as RedHat may
have backported it to older versions.  However desktop based ssh clients
such as putty may not support it.&lt;/p&gt;

&lt;p&gt;Certificate authentication isn&amp;rsquo;t as flexible as standard key based
authentication in that we don&amp;rsquo;t have an &lt;code&gt;authorized_keys&lt;/code&gt; entry to add
restrictions (&lt;code&gt;from=&lt;/code&gt;, &lt;code&gt;command=&lt;/code&gt;, etc) but it can solve a number
of problems, particularly around host key management and distributing of
&lt;code&gt;authorized_keys&lt;/code&gt; files for human accounts; build a new server, get the
host key signed and automatically we have a trust and an authentication
process working.&lt;/p&gt;

&lt;p&gt;We just need the workflows to do the signing :-)&lt;/p&gt;

&lt;h2 id=&#34;update&#34;&gt;Update&lt;/h2&gt;

&lt;p&gt;Based on blog posts and emails (thank you!) there&amp;rsquo;s a &lt;a href=&#34;https://www.sweharris.org/post/2022-02-06-ssh-certs-again/&#34;&gt;follow up post&lt;/a&gt;
which goes into some more detail on the advanced use of certificates, including
multiple principals and additional restrictions.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Security Headers on HTTP requests</title>
      <link>https://www.sweharris.org/post/2016-10-23-headers/</link>
      <pubDate>Sun, 23 Oct 2016 11:45:43 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-10-23-headers/</guid>
      <description>

&lt;p&gt;Modern web browsers have a number of settings to help protect your site
from attack.  You turn them on by use of various header lines in your
HTTP responses.  Now when I first read about them I thought they were
not useful; a basic rule for client-server computing is &amp;ldquo;don&amp;rsquo;t trust the
client&amp;rdquo;.  An attacker can bypass any rules you try to enforce client side.&lt;/p&gt;

&lt;p&gt;But then I read what they do and realised that they are primary to help
protect the &lt;em&gt;client&lt;/em&gt; and, as a consequence, protect your site from being
hijacked.  For example, if you can define exactly where javascript can
be run from then an attacker will find it harder to inject rogue scripts
and steal credentials.  We can help stop XSS attacks.&lt;/p&gt;

&lt;p&gt;What these headers do is stop the legitimate normal user of your site
being used as an attack vector.  This makes them an import part of the
controls surface of your web presence.  You still need to make sure your
app isn&amp;rsquo;t vulnerable to SQL injection, buffer overflow and everything
else; these headers (mostly) protect against a third-party attack.&lt;/p&gt;

&lt;h2 id=&#34;what-header-values-are-available&#34;&gt;What header values are available?&lt;/h2&gt;

&lt;p&gt;Fortunately, &lt;a href=&#34;https://www.scotthelme.co.uk/&#34;&gt;Scott Helme&lt;/a&gt; has done an
excellent series of posts that describe the headers.  I won&amp;rsquo;t repeat
all of his work, but I will summarise and link to the relevant pages.
They&amp;rsquo;re well worth reading.&lt;/p&gt;

&lt;h3 id=&#34;server-https-scotthelme-co-uk-hardening-your-http-response-headers-server&#34;&gt;&lt;a href=&#34;https://scotthelme.co.uk/hardening-your-http-response-headers/#server&#34;&gt;Server&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;This one is simple to understand; if you report the version of the software
you&amp;rsquo;re using then attackers can easily determine what vulnerabilities
may be present.  Knowing you run Apache 1.2.3 gives a lot more information
to attackers then if you reported &amp;ldquo;FooBarBaz&amp;rdquo;.&lt;/p&gt;

&lt;h3 id=&#34;strict-transport-security-https-scotthelme-co-uk-hsts-the-missing-link-in-tls&#34;&gt;&lt;a href=&#34;https://scotthelme.co.uk/hsts-the-missing-link-in-tls/&#34;&gt;Strict-Transport-Security&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;This tells the client to always use https for your site.  It can cache
this value so even if the user types in a non-https address the browser
will automatically switch to the TLS version.&lt;/p&gt;

&lt;h3 id=&#34;x-content-type-options-https-scotthelme-co-uk-hardening-your-http-response-headers-x-content-type-options&#34;&gt;&lt;a href=&#34;https://scotthelme.co.uk/hardening-your-http-response-headers/#x-content-type-options&#34;&gt;X-Content-Type-Options&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;This one really shouldn&amp;rsquo;t be needed, but is due to Microsoft being
too clever.  When you send a file via a https connection you include a
content-type header.  This should be used to help the browser decide what
to do with it.  But Internet Explorer ignores this and looks at the data
itself; if it looks like a word document then it&amp;rsquo;ll open it in word, even
if the content-type says differently.   This header allows you to turn off
that feature.&lt;/p&gt;

&lt;h3 id=&#34;x-xss-protection-https-scotthelme-co-uk-hardening-your-http-response-headers-x-xss-protection&#34;&gt;&lt;a href=&#34;https://scotthelme.co.uk/hardening-your-http-response-headers/#x-xss-protection&#34;&gt;X-XSS-Protection&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Modern web browsers have a level of built in protection to stop cross-site
scripting.  This header turns it on.&lt;/p&gt;

&lt;h3 id=&#34;x-frame-options-https-scotthelme-co-uk-hardening-your-http-response-headers-x-frame-options&#34;&gt;&lt;a href=&#34;https://scotthelme.co.uk/hardening-your-http-response-headers/#x-frame-options&#34;&gt;X-Frame-Options&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;When I first came across this it annoyed me.  It stopped me from using
my own &amp;lsquo;bookmarks&amp;rsquo; frame.  For the past 20 years my home page was a framed
site; on the left were my normal bookmarks and on the right was where the
content loaded.  Very very old school.  X-Frame-Options stopped this working
on sites like Dilbert or GPF.  Grrr.  But it has a good rationale; it
stops a site from being embedded in a frame and so can protect against
click-jacking.  Grump.&lt;/p&gt;

&lt;h3 id=&#34;public-key-pins-https-scotthelme-co-uk-hpkp-http-public-key-pinning&#34;&gt;&lt;a href=&#34;https://scotthelme.co.uk/hpkp-http-public-key-pinning/&#34;&gt;Public-Key-Pins&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;This allows you to restrict what SSL certificates can claim to be you.
For example, if you know you will always get a cert from &lt;a href=&#34;https://letsencrypt.org/&#34;&gt;Lets Encrypt&lt;/a&gt; then you can flag this.  In this way you can help
protect against a rogue CA also releasing a cert under your name.  We&amp;rsquo;ve
seen this happen before.&lt;/p&gt;

&lt;h3 id=&#34;content-security-policy-https-scotthelme-co-uk-content-security-policy-an-introduction&#34;&gt;&lt;a href=&#34;https://scotthelme.co.uk/content-security-policy-an-introduction/&#34;&gt;Content-Security-Policy&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;This is a biggie and important protection and is easily misconfigured
and can break your site.  And, indeed, first time I hit Scott&amp;rsquo;s site
it wasn&amp;rsquo;t working properly because site changes weren&amp;rsquo;t being properly
reflected in the policy.&lt;/p&gt;

&lt;p&gt;It can also stop you from doing stuff; e.g. I can&amp;rsquo;t embed YouTube videos
on this site because the policy I wrote locks it down very tightly.&lt;/p&gt;

&lt;p&gt;You will spend most of your time on this entry and will have to do the
most testing.&lt;/p&gt;

&lt;h2 id=&#34;my-configuration&#34;&gt;My configuration&lt;/h2&gt;

&lt;p&gt;Because I use Apache I can&amp;rsquo;t turn off the whole Server header, but I can
remove the version number.  But I can do pretty well for the rest:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ServerSignature Off

Header set Strict-Transport-Security &amp;quot;max-age=31536000; includeSubdomains&amp;quot;
Header set X-Content-Type-Options &amp;quot;nosniff&amp;quot;
Header set X-XSS-Protection &amp;quot;1; mode=block&amp;quot;
Header set X-Frame-Options &amp;quot;SAMEORIGIN&amp;quot;
Header set Content-Security-Policy &amp;quot;default-src &#39;self&#39; &#39;unsafe-inline&#39; &#39;unsafe-eval&#39; disqus.com *.disqus.com; style-src &#39;self&#39; *.googleapis.com *.gstatic.com &#39;unsafe-inline&#39;; font-src &#39;self&#39; *.gstatic.com&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;testing&#34;&gt;Testing&lt;/h2&gt;

&lt;p&gt;Scott has also created a site for you to be able to test your setup.
Just go to &lt;a href=&#34;https://securityheaders.io&#34;&gt;https://securityheaders.io&lt;/a&gt;, enter your site name and get an
almost immediate response.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.sweharris.org/images/securityheaders.png&#34; alt=&#34;Results&#34; /&gt;&lt;/p&gt;

&lt;p&gt;I don&amp;rsquo;t have my cert pinned at the moment.  You can also note that I
have a warning for the CSP; I allow &amp;lsquo;unsafe-inline&amp;rsquo;.  So my configuration
isn&amp;rsquo;t necessarily safe, but because I&amp;rsquo;m forcing SSL then the chances of
an attacker injecting rogue scripts isn&amp;rsquo;t really any different to trusting
&lt;code&gt;self&lt;/code&gt; and having the code loaded from an external page.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Most of these headers can be turned on without any impact on your app;
forcing TLS, turning off content-type sniffing, turning on XSS protections
and frame clickjacking protectings are mostly safe (not 100% because a
site may trip things and need workarounds).   CSP is the hard one, but
definitely worth spending time on.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Scoring an A&#43; for SSL/TLS</title>
      <link>https://www.sweharris.org/post/2016-10-16-ssl-score/</link>
      <pubDate>Sun, 16 Oct 2016 16:02:28 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-10-16-ssl-score/</guid>
      <description>

&lt;p&gt;&lt;img src=&#34;https://www.sweharris.org/images/ssl-a-plus.jpg&#34; alt=&#34;A+&#34; /&gt;&lt;/p&gt;

&lt;p&gt;(Side note: in this post I&amp;rsquo;m going to use TLS and SSL interchangably.
To all intents and purposes you can think of TLS as the successor to
SSL; most libraries do both).&lt;/p&gt;

&lt;p&gt;You can think of security as a stack.  Each layer of the stack needs to
be secure in order for the whole thing to be secure.  Or, alternatively,
you can think of it as a chain; the whole thing is only as strong as
the weakest link.&lt;/p&gt;

&lt;p&gt;No matter how you look at it, you need to ensure that every part of the
environment is good.&lt;/p&gt;

&lt;p&gt;In previous posts I&amp;rsquo;ve talked about static code analysis, and system
scanning.  This can help make sure your program hasn&amp;rsquo;t any obvious gaps,
and that you&amp;rsquo;re not running a bad alternate path.&lt;/p&gt;

&lt;p&gt;Now let&amp;rsquo;s look at protecting the data between you and your users.
Typically we do this with SSL.  So
you get your certificate and click the &amp;ldquo;turn on SSL&amp;rdquo; option and you&amp;rsquo;re
done; right?&lt;/p&gt;

&lt;p&gt;Unfortunately not.  SSL has a long and not so clean history.  There have
been both implementation bugs and logic issues.  &amp;ldquo;Heartbleed&amp;rdquo;, &amp;ldquo;BEAST&amp;rdquo;,
&amp;ldquo;POODLE&amp;rdquo;&amp;hellip; at one point it seemed that an issue was found in SSL every
other week.&lt;/p&gt;

&lt;p&gt;Further, something that was considered strong 10 years ago isn&amp;rsquo;t strong today
(RC4 codes).  And new and better methods of protecting data now exist
(elliptical curve, forward secrecy).&lt;/p&gt;

&lt;p&gt;So we may need to tune your SSL setup as well.  Turn off weak settings,
add new configurations.&lt;/p&gt;

&lt;p&gt;The problem is in how to know if you&amp;rsquo;ve done a good job?&lt;/p&gt;

&lt;h2 id=&#34;testing&#34;&gt;Testing&lt;/h2&gt;

&lt;p&gt;Fortunately there&amp;rsquo;s a very useful web site run by Qualys: &lt;a href=&#34;https://www.ssllabs.com/ssltest/&#34;&gt;https://www.ssllabs.com/ssltest/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will run through your site, testing for common failure modes.
It&amp;rsquo;ll try common bugs, weak settings and even provide a good summary of
how well your site will work with common browsers.  It takes somewhere
around 90-120 seconds to run.&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://www.sweharris.org/SSL_Server_Test_www.sweharris.pdf&#34;&gt;My site&lt;/a&gt; (PDF) scores an A+ on
these tests and it flags some compatibility issues.&lt;/p&gt;

&lt;p&gt;e.g. &amp;ldquo;This site works only in browsers with SNI support.&amp;rdquo;   That&amp;rsquo;s because
I present a different SSL certificate for each virtual host, and for this
to work we need the SSL &amp;ldquo;Server Name Indication&amp;rdquo; extention.  Pretty much
every common browser supports this these days.&lt;/p&gt;

&lt;p&gt;If we go down further into the report it tells me the Android 2.3.7, IE6,
IE8, Java 6 don&amp;rsquo;t support SNI.  I can live with that!&lt;/p&gt;

&lt;p&gt;Further it tells me that IE6 and IE8 just won&amp;rsquo;t work with my site because
of other settings.  Do I care?  According to a &lt;a href=&#34;https://www.netm
arketshare.com/browser-market-share.aspx?qprid=2&amp;amp;qpcustomd=0&#34;&gt;browser market share report&lt;/a&gt; IE8 is under 4%
of usage.  I can live with that.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.sweharris.org/images/OpenVAS/vas_scan_8.png&#34; alt=&#34;Browser breakdown&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;my-settings&#34;&gt;My settings&lt;/h2&gt;

&lt;p&gt;I use Apache with OpenSSL, which allows you to specify the protocols and
cipher suites.  The first is to ensure SSLv2 and SSLv3 are turned off.
Then we can pick the ciphers we want:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;SSLProtocol all -SSLv2 -SSLv3
SSLHonorCipherOrder on

SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:HIGH:!EDH-RSA-DES-CBC3-SHA:!DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;These settings aren&amp;rsquo;t necessarily the best.  I could tighten it up if I
don&amp;rsquo;t care about compatibility with older tools (java6 and java7 might
be easy to discard).&lt;/p&gt;

&lt;p&gt;These settings are also not always going to be fixed; a few months back
I did not have &lt;code&gt;!EDH-RSA-DES-CBC3-SHA:!DES-CBC3-SHA&lt;/code&gt; in the Cipher suite
because these &lt;em&gt;used&lt;/em&gt; to be considered good.  It&amp;rsquo;s worth reviewing the
results of the SSLlabs test on a regular basis.  And definitely after
a new vulnerability has been exposed.&lt;/p&gt;

&lt;p&gt;Getting an A or an A+ is easy, and is an essential part of the complete
security solution &lt;a href=&#34;https://www.sweharris.org/post/2016-05-31-secure-webserver/&#34;&gt;for your web site&lt;/a&gt;.
There are many good reasons to do it!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Deep scanning your deployment</title>
      <link>https://www.sweharris.org/post/2016-10-09-deep-scanning/</link>
      <pubDate>Sun, 09 Oct 2016 09:02:20 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-10-09-deep-scanning/</guid>
      <description>

&lt;p&gt;In &lt;a href=&#34;https://www.sweharris.org/post/2016-10-02-auto-scanning/&#34;&gt;my previous post&lt;/a&gt; I wrote about some
automation of static and dynamic scanning as part of the software delivery
pipeline.&lt;/p&gt;

&lt;p&gt;However nothing stays the same; we find new vulnerabilities or configurations
are broken or stuff previously considered secure is now weak (64bit ciphers
can be broken, for example).&lt;/p&gt;

&lt;p&gt;So as well as doing your scans during the development cycle we &lt;em&gt;also&lt;/em&gt; need
to do repeated scans of deployed infrastructure; &lt;em&gt;espcially&lt;/em&gt; if it&amp;rsquo;s
externally facing (but internal facing services may still be at risk from
the tens of thousands of desktops in your organisation).&lt;/p&gt;

&lt;p&gt;In this spirit I decided to scan this server using &lt;a href=&#34;http://www.openvas.org&#34;&gt;OpenVAS&lt;/a&gt; and that was installed as part of the the &lt;a href=&#34;https://www.kali.org/&#34;&gt;Kali Linux&lt;/a&gt; build.  OpenVAS can also call other tools (eg Nikto, that I mentioned
previously).&lt;/p&gt;

&lt;p&gt;Now I&amp;rsquo;d done this back in May and got a single &amp;ldquo;low level&amp;rdquo; message about
TCP timestamps, so I didn&amp;rsquo;t expect to see anything new.

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/OpenVAS/vas_scan_1a.png&#34; alt=&#34;Timestamps&#34;&gt;
&lt;/div&gt;
&lt;/p&gt;

&lt;p&gt;So let&amp;rsquo;s do a run:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/OpenVAS/vas_scan_1.png&#34; alt=&#34;First run&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Well, damn!  That&amp;rsquo;s not right!  I get an A+ on &lt;a href=&#34;https://www.ssllabs.com/ssltest/&#34;&gt;ssllabs tests&lt;/a&gt; (more on that in a later post).  What&amp;rsquo;s going on?&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/OpenVAS/vas_scan_1b.png&#34; alt=&#34;SSL protocols&#34;&gt;
&lt;/div&gt;



&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/OpenVAS/vas_scan_1c.png&#34; alt=&#34;Weak ciphers&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Oh&amp;hellip; port 563?  That&amp;rsquo;s NNTPS.  Oh!  I&amp;rsquo;d recently installed an SSL news
server on this machine!  And it seems the defaults aren&amp;rsquo;t so secure.&lt;/p&gt;

&lt;p&gt;So I dig into the manual page to work out how to disable SSLv2, SSLv3
and also to set the cipher suite to match that of my apache server.&lt;/p&gt;

&lt;p&gt;At the same time I told OpenVAS to update its libraries of known threats
and issues.  A scanner with an stale database isn&amp;rsquo;t really much use, and
OpenVAS has an update mechanism, with advisories being fed from DFN-CERT.
This is pretty impressive, all the more so that it&amp;rsquo;s free.&lt;/p&gt;

&lt;p&gt;So, problem solved, right?&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/OpenVAS/vas_scan_2.png&#34; alt=&#34;Second run&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Damnit!  Now my web server is also being flagged!  And a new DH issue.
Interestingly the TCP Timestamp issue has gone away; maybe that was no
longer really considered a problem.  Evaluations change.&lt;/p&gt;

&lt;p&gt;So what is weak&amp;hellip;

&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/OpenVAS/vas_scan_2a.png&#34; alt=&#34;More weak ciphers&#34;&gt;
&lt;/div&gt;
&lt;/p&gt;

&lt;p&gt;Now this is annoying.  The values reported here &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; match the config
entries used by OpenSSL.&lt;/p&gt;

&lt;p&gt;Are these weak?  The &lt;code&gt;nmap -p 443 hostname --script +ssl-enum-ciphers&lt;/code&gt;
routine reports those entries in the output and considers them strong.
As we&amp;rsquo;ve seen, though; evaluations can change.  This is why a scanning
tool needs update abilities.  I&amp;rsquo;m more likely to believe the OpenVAS
&amp;ldquo;weak&amp;rdquo; report as being newer and more accurate than the builtin &lt;code&gt;nmap&lt;/code&gt;
rules that RedHat won&amp;rsquo;t have updated in forever.&lt;/p&gt;

&lt;p&gt;Now my SSL configuration included entries that mentioned DES:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ECDHE-RSA-DES-CBC3-SHA
EDH-RSA-DES-CBC3-SHA
DES-CBC3-SHA
!DES
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This was to allow IE6 to talk to my site.  But let&amp;rsquo;s remove the three entries
and run again.  Same result!  Still an error.&lt;/p&gt;

&lt;p&gt;Some more digging and it seems that the bad entries were brought in with
the &lt;code&gt;HIGH&lt;/code&gt; setting.  So now we needed&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;HIGH
!EDH-RSA-DES-CBC3-SHA
!DES-CBC3-SHA
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;ECDHE&lt;/code&gt; entry I&amp;rsquo;d previously removed wasn&amp;rsquo;t at fault.  That&amp;rsquo;s elliptical
curve.   If only the output of the &amp;ldquo;weak ciphers&amp;rdquo; test and the configuration
options matched!&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/OpenVAS/vas_scan_3.png&#34; alt=&#34;Third run&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Woohoo!  Now all the cipher problems have been solved.&lt;/p&gt;

&lt;p&gt;Umm, there&amp;rsquo;s a downside to this.  IE6 and IE8 can no longer reach my
site.  Do I care?  According to a &lt;a href=&#34;https://www.netmarketshare.com/browser-market-share.aspx?qprid=2&amp;amp;qpcustomd=0&#34;&gt;browser market share report&lt;/a&gt; IE8 is under 4%
of usage.  I can live with that.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/OpenVAS/vas_scan_8.png&#34; alt=&#34;Browser breakdown&#34;&gt;
&lt;/div&gt;


&lt;p&gt;But what about this DH issue?  I looked into the server code and it &lt;em&gt;seems&lt;/em&gt;
to respond with different key sizes depending on the block size.  I&amp;rsquo;m not
sure the code is correct, but I&amp;rsquo;m not an SSL expert here.  However this is
a &amp;ldquo;low value&amp;rdquo; service; the data transported is passed in clear text on port
119 and the username/passwords used to access this server may also be used
in plain text on 119.  So I took the decision to &amp;ldquo;accept the risk&amp;rdquo; and
entered an override for my servers for this issue on this port, reducing
the severity to &amp;ldquo;Log&amp;rdquo;&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/OpenVAS/vas_scan_7.png&#34; alt=&#34;DH&#34;&gt;
&lt;/div&gt;


&lt;p&gt;The final result is a score of zero!  Yay!&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/OpenVAS/vas_scan_4.png&#34; alt=&#34;Final result&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Notice those 36 log entries.  Now some of these may be worth looking at.&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/OpenVAS/vas_scan_5.png&#34; alt=&#34;Log entries&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Here&amp;rsquo;s our override, as a log entry.  There&amp;rsquo;s also an entry claiming HSTS
isn&amp;rsquo;t present.  Which is a lie!  So let&amp;rsquo;s look at this:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/OpenVAS/vas_scan_6.png&#34; alt=&#34;HSTS&#34;&gt;
&lt;/div&gt;


&lt;p&gt;Ah!  This is a response to a &amp;lsquo;bad request&amp;rsquo; and it doesn&amp;rsquo;t see the HSTS
header.  But a &lt;em&gt;real&lt;/em&gt; request does:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ wget -O /dev/null --server-response https://www.sweharris.org/ 2&amp;gt;&amp;amp;1 | grep Stri
  Strict-Transport-Security: max-age=31536000; includeSubdomains
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So we can see this is a false positive; I get an &lt;code&gt;A&lt;/code&gt; rating for header
security at &lt;a href=&#34;https://securityheaders.io/&#34;&gt;securityheaders.io&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;lessons-learned&#34;&gt;Lessons Learned&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Keep scanning servers deployed to production; even if the app doesn&amp;rsquo;t
change something else might&lt;/li&gt;
&lt;li&gt;Keep your scanning tool databases up to date!&lt;/li&gt;
&lt;li&gt;Different tools may report different evaluations for the same issue&lt;/li&gt;
&lt;li&gt;Configuration parameters don&amp;rsquo;t match reported items&lt;/li&gt;
&lt;li&gt;Sometimes you have to accept losing customers (IE8?) to be secure&lt;/li&gt;
&lt;li&gt;Sometimes you can just accept the insecurity risk.  That&amp;rsquo;s why we have &amp;ldquo;risk management&amp;rdquo; teams!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OpenVAS is a &lt;em&gt;noisy&lt;/em&gt; scan (it flooded my Apache logs with probe attempts,
caused multiple ssh failures, triggered firewall protection rules).  In an
enterprise environment you might want to allow-list the traffic from your
scanning servers so they don&amp;rsquo;t trigger SOC alerts and don&amp;rsquo;t flood out real
alerting traffic.  But despite this a full vulnerability scan is useful.&lt;/p&gt;

&lt;p&gt;It definitely alerted me to a weakness on my server that I wasn&amp;rsquo;t aware of!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Scanning your code</title>
      <link>https://www.sweharris.org/post/2016-10-02-auto-scanning/</link>
      <pubDate>Sun, 02 Oct 2016 19:53:09 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-10-02-auto-scanning/</guid>
      <description>

&lt;p&gt;In many organisations an automated scan of an application is done before
it&amp;rsquo;s allowed to &amp;ldquo;go live&amp;rdquo;, especially if the app is external facing.&lt;/p&gt;

&lt;p&gt;There are typically two types of scan:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Static Scan&lt;/li&gt;
&lt;li&gt;Dynamic Scan&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&#34;static-scan&#34;&gt;Static scan&lt;/h3&gt;

&lt;p&gt;A static scan is commonly a &lt;em&gt;source code&lt;/em&gt; scan.  It will analyse code
for many common failure modes.  If you&amp;rsquo;re writing C code then it&amp;rsquo;ll
flag on common buffer overflow patterns.  If you&amp;rsquo;re writing Java with
database connectors it&amp;rsquo;ll flag on common password exposure patterns.  This
is a first line of defense.  If you can do this quickly enough then it
might even be part of your code commit path; eg a &lt;code&gt;git merge&lt;/code&gt; must pass
static scanning before it can be accepted, and can be a &lt;em&gt;triggered&lt;/em&gt;
event.&lt;/p&gt;

&lt;p&gt;Static scan&amp;rsquo;s aren&amp;rsquo;t perfect, of course.  Nothing is!  It can miss some
cases, and can false-positive on other cases (requiring work-arounds).
So a static scan isn&amp;rsquo;t a replacement for a code review (which can also
look at the code &lt;em&gt;logic&lt;/em&gt; to see if it does the right thing), but is
complementary.&lt;/p&gt;

&lt;p&gt;Static analysis was one reason for a massive increase in security of
opensource projects by pro-actively flagging potential risks.&lt;/p&gt;

&lt;h3 id=&#34;dynamic-scan&#34;&gt;Dynamic scan&lt;/h3&gt;

&lt;p&gt;A dynamic scan actually tests the component while it&amp;rsquo;s running.  For a
web site (the most common form of publically exposed application) it can
automatically discover execution paths and fuzz input fields and try to
present bad data.  Dynamic scanning can only test the code paths it
knows about (or discovers).  Stuff hidden behind authentication must
be special cased.  And it &lt;em&gt;could&lt;/em&gt; potentially caused bad behaviour to
happen; it could trigger a little Bobby Tables event,
so be very careful about scanning production systems!&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href=&#34;https://xkcd.com/327/&#34;&gt;&lt;img src=&#34;https://www.sweharris.org/images/xkcd-exploits_of_a_mom.png&#34; alt=&#34;Exploits of a Mom&#34;&gt;&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;h3 id=&#34;common-scanning&#34;&gt;Common scanning&lt;/h3&gt;

&lt;p&gt;A common practice is to combine both types of scan.  A static scan is
typically quick and can be done frequently.  A dynamic scan may take
hours, and so may not be done every time.&lt;/p&gt;

&lt;p&gt;So a common workflow may be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developer codes, tests stuff out in a local instance&lt;/li&gt;
&lt;li&gt;Developer commits   &lt;em&gt;Potential static scan here&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Pull request&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Code review&lt;/li&gt;
&lt;li&gt;Code merge &lt;em&gt;Static scan here&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So far work has been done purely in development; no production code has
been pushed.  The developer is allowed to develop and test their code with
minimal interruption.  It&amp;rsquo;s only when code is &amp;ldquo;ready&amp;rdquo; that scanning occurs.&lt;/p&gt;

&lt;p&gt;Now depending on your environment and production controls things may get
more complication.  Let&amp;rsquo;s assume a &amp;ldquo;merge&amp;rdquo; then triggers a &amp;ldquo;QA&amp;rdquo; or &amp;ldquo;UAT&amp;rdquo;
build.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Merge fires off &amp;ldquo;Jenkins&amp;rdquo; process&lt;/li&gt;
&lt;li&gt;Jenkins stands up a test environment&lt;/li&gt;
&lt;li&gt;Static scan occurs&lt;/li&gt;
&lt;li&gt;Merge successful only if the scan is successful.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Depending on the size of complexity of the app this scan could take hours.
One advantage to micro-services is that each app has a small footprint
and so the scan should be a lot quicker.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s important for a developer to not try and &lt;em&gt;hide&lt;/em&gt; code paths.  &amp;ldquo;Oh this
scanning tool stops me from working, so I&amp;rsquo;ll hide stuff so it never sees
it&amp;rdquo;&amp;hellip;  We all have the desire to do things quicker and know we&amp;rsquo;re smarter
than &amp;ldquo;the system&amp;rdquo;, but going down this path &lt;em&gt;will&lt;/em&gt; lead to bugs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Side bar: There&amp;rsquo;s the standard open-source comment; &amp;ldquo;with sufficient eyes,
all bugs are shallow&amp;rdquo;.  There&amp;rsquo;s a corollary to this; &amp;ldquo;with sufficient
people using your program all bugs will be exploited&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&#34;scanning-this-site-and-false-positives&#34;&gt;Scanning this site and false positives&lt;/h3&gt;

&lt;p&gt;Now this site is pretty simple.  I use &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt; to
generate static web pages.  That means there&amp;rsquo;s no CGI to be exploited;
no database connections to be abuse.  It&amp;rsquo;s plain and simple.&lt;/p&gt;

&lt;p&gt;But does that mean a scan of the site would be clean?  Is the Apache
server configured correctly?  Have I added some bad CGI to the static
area of the site?  Have I made another mistake somewhere?&lt;/p&gt;

&lt;p&gt;The &lt;a href=&#34;https://www.kali.org/&#34;&gt;Kali Linux&lt;/a&gt; distribution includes a tool called
&lt;a href=&#34;https://cirt.net/nikto2&#34;&gt;Nikto&lt;/a&gt; (no bonus points for knowing where the
name comes from).  This is a web scanner that can check for a few thousand
known issues on a web server.  It&amp;rsquo;s &lt;em&gt;not&lt;/em&gt; a full host scan (doesn&amp;rsquo;t check
for other open ports, for example).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;WARNING: Nikto is not a stealth tool; if you use this against someone&amp;rsquo;s
site then they &lt;strong&gt;WILL&lt;/strong&gt; know.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Given how my site is built, I wouldn&amp;rsquo;t expect it to find any issues.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s see!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;+ Server: Apache
+ Server leaks inodes via ETags, header found with file /, fields: 0x44af 0x533833f94c500 
+ Multiple index files found: /index.xml, /index.html
+ The Content-Encoding header is set to &amp;quot;deflate&amp;quot; this may mean that the server is vulnerable to the BREACH attack.
+ Allowed HTTP Methods: POST, OPTIONS, GET, HEAD 
+ OSVDB-3092: /sitemap.xml: This gives a nice listing of the site content.
+ OSVDB-3268: /icons/: Directory indexing found.
+ OSVDB-3233: /icons/README: Apache default file found.
+ 8328 requests: 0 error(s) and 7 item(s) reported on remote host
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Interesting, it found 7 items to flag on.&lt;/p&gt;

&lt;p&gt;Except if we look closer, these are not necessarily issues.  Is the &amp;ldquo;inode
number&amp;rdquo; something we need to care about?  I don&amp;rsquo;t think so.  The &lt;code&gt;sitemap.xml&lt;/code&gt;
file is deliberately there to allow search engines to find stuff.  The
&lt;code&gt;/icons&lt;/code&gt; directory is the apache standard&amp;hellip; is there a risk to having
this exposed?&lt;/p&gt;

&lt;p&gt;So even a &amp;ldquo;clean&amp;rdquo; site may have issues according to the scanning tool,
even though it really doesn&amp;rsquo;t.  (At least I assume it doesn&amp;rsquo;t!  My
evaluation may be wrong&amp;hellip;)&lt;/p&gt;

&lt;p&gt;It takes a human to filter out these
false positives.  If you&amp;rsquo;re going to put this as part of your CI/CD pipeline
then make sure you&amp;rsquo;ve filtered out the noise first!&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Static and Dynamic scanning tools are complementary.  They both have
strengths and weaknesses.  Both should be used.  Even if your code is
never exposed to the internet it&amp;rsquo;s worth doing it, to help protect from
the &lt;em&gt;insider threat&lt;/em&gt; and also to mitigate against an attacker with a
foothold from being able to exploit your server.&lt;/p&gt;

&lt;p&gt;They do not replace humans (e.g. code review processes) but can help
protect against common failure modes.&lt;/p&gt;

&lt;h2 id=&#34;additional&#34;&gt;ADDITIONAL&lt;/h2&gt;

&lt;p&gt;2016/10/13 The ever interesting Wolf Goerlich, as part of his &amp;ldquo;Stuck in
traffic&amp;rdquo; vlog, also points out another limitation of scanning tools;
they don&amp;rsquo;t handle malicious insiders writing bad code (and, by extension,
and intruder able to get into the source code repo and make updates).
You still need humans in the loop (e.g. code review processes), whether
it&amp;rsquo;s to test for code logic or malicious activities.  You should
&lt;a href=&#34;https://www.youtube.com/watch?v=XP-ArpOVywc&#34;&gt;watch Wolf&amp;rsquo;s vlog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Kerberos keytab management</title>
      <link>https://www.sweharris.org/post/2016-09-24-keytabs/</link>
      <pubDate>Sat, 24 Sep 2016 18:36:41 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-09-24-keytabs/</guid>
      <description>

&lt;p&gt;In an earlier blog I wrote that &lt;a href=&#34;https://www.sweharris.org/post/2016-09-05-sshkeys/&#34;&gt;SSH keys need to be managed&lt;/a&gt;.  It&amp;rsquo;s important!&lt;/p&gt;

&lt;p&gt;In the comments I was asked about keytabs.  I felt this such a good question
that it deserved it&amp;rsquo;s own blog entry.&lt;/p&gt;

&lt;h2 id=&#34;the-basics-of-kerberos-auth&#34;&gt;The basics of Kerberos auth&lt;/h2&gt;

&lt;p&gt;In essence, kerberos is a &amp;ldquo;ticket based&amp;rdquo; authentication scheme.  You start
by requesting a TGT (&amp;ldquo;Ticket granting ticket&amp;rdquo;).  This, typically, is where
you enter your password.  This TGT is then used to request service tickets
to access resources.  There&amp;rsquo;s a &lt;a href=&#34;http://www.kerberos.org/software/adminkerberos.pdf&#34;&gt;description&lt;/a&gt; which goes into a lot more detail, but is pretty
readable.&lt;/p&gt;

&lt;p&gt;Now all of this is pretty invisible and runs under the covers; the user
never needs to see any of this.  Indeed, Windows Active Directory is kerberos
based!&lt;/p&gt;

&lt;p&gt;So let&amp;rsquo;s see this in action:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh sweh@kclient
sweh@kclient&#39;s password: 

kclient$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So far that looks just the same as any other login!  But if we look
deeper&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;kclient$ klist
Ticket cache: FILE:/tmp/krb5cc_500_WfoXRC1791
Default principal: sweh@SPUDDY.ORG

Valid starting     Expires            Service principal
09/24/16 18:46:08  09/25/16 18:46:08  krbtgt/SPUDDY.ORG@SPUDDY.ORG
        renew until 09/24/16 18:46:08
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I have a TGT associated with my login.  That was all transparent.  And
I can use this to login to other machines&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;kclient$ ssh kdc
kdc$ exit
Connection to kdc closed.
kclient$ klist
Ticket cache: FILE:/tmp/krb5cc_500_WfoXRC1791
Default principal: sweh@SPUDDY.ORG

Valid starting     Expires            Service principal
09/24/16 18:46:08  09/25/16 18:46:08  krbtgt/SPUDDY.ORG@SPUDDY.ORG
        renew until 09/24/16 18:46:08
09/24/16 18:47:56  09/25/16 18:46:08  host/kdc.spuddy.org@SPUDDY.ORG
        renew until 09/24/16 18:46:08
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, it didn&amp;rsquo;t ask me for my password&amp;hellip; and now I can see there&amp;rsquo;s
a service ticket for that host.&lt;/p&gt;

&lt;p&gt;So Kerberos can give us a form of &amp;ldquo;single sign on&amp;rdquo; (I only had to enter
my password the once), and it&amp;rsquo;s all nice and transparent.&lt;/p&gt;

&lt;h2 id=&#34;what-is-a-keytab&#34;&gt;What is a keytab?&lt;/h2&gt;

&lt;p&gt;Everything so far has depended on being able to enter my password to
get that initial TGT.  This is fine for humans, but for automated processes
(e.g. oracle wanting to &lt;code&gt;scp&lt;/code&gt; files between servers) then it&amp;rsquo;s not very
useful.&lt;/p&gt;

&lt;p&gt;So we have the ability to use a &lt;em&gt;keytab&lt;/em&gt; file to get that initial key.&lt;/p&gt;

&lt;p&gt;In my test environment I created a &lt;code&gt;user1&lt;/code&gt; and extracted that user&amp;rsquo;s
key into a keytab file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ kadmin -p sweh/admin
Authenticating as principal sweh/admin with password.
Password for sweh/admin@SPUDDY.ORG: 
kadmin:  ktadd -k user1.keytab user1@SPUDDY.ORG
...lines deleted...
kadmin: exit
$ ls -l user1.keytab 
-rw------- 1 sweh sweh 666 Sep 24 18:53 user1.keytab
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we can use this to login to kerberos:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ kinit -k -t user1.keytab user1@SPUDDY.ORG
$ klist
Ticket cache: FILE:/tmp/krb5cc_500_WfoXRC1791
Default principal: user1@SPUDDY.ORG

Valid starting     Expires            Service principal
09/24/16 18:55:29  09/25/16 18:55:29  krbtgt/SPUDDY.ORG@SPUDDY.ORG
        renew until 09/24/16 18:55:29
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can see that we didn&amp;rsquo;t get asked for a password, and the &amp;ldquo;Default
principal&amp;rdquo; line mentions user1.  As far as the kerberos infrastructure
is concerned, I now &lt;em&gt;am&lt;/em&gt; user1 and can use this to ticket to login as
him:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh user1@kclient
Last login: Sat Sep 24 18:56:39 2016 from kclient.spuddy.org
[user1@kclient ~]$ exit
logout
Connection to kclient closed.
$ klist
Ticket cache: FILE:/tmp/krb5cc_500_WfoXRC1791
Default principal: user1@SPUDDY.ORG

Valid starting     Expires            Service principal
09/24/16 18:55:29  09/25/16 18:55:29  krbtgt/SPUDDY.ORG@SPUDDY.ORG
        renew until 09/24/16 18:55:29
09/24/16 18:56:39  09/25/16 18:55:29  host/kclient.spuddy.org@SPUDDY.ORG
        renew until 09/24/16 18:55:29
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So we can see that these keytab files are as powerful as a passphrase-less
ssh private key.&lt;/p&gt;

&lt;p&gt;In some respects they are &lt;em&gt;more&lt;/em&gt; powerful than ssh keys, because there&amp;rsquo;s
no server side restrictions that can be applied; with ssh public key
authentication the public key needs to be placed on the host for it to
be usable, and we can limit where the private key can be used (&amp;ldquo;from=&amp;rdquo;)
and what it can do (&amp;ldquo;command=&amp;rdquo;).  With kerberos authentication we can
login to any server where this ticket is valid (pretty much anywhere
the account exists) and get a shell.&lt;/p&gt;

&lt;p&gt;So it becomes critically important that keytab entries of this type are
closely managed.  Maybe they should be put into an equivalent of a password
vault and only pulled &amp;ldquo;as needed&amp;rdquo; by the application?  Or, at least,
placed into a locked directory where no one except the app can reach it.&lt;/p&gt;

&lt;p&gt;This is one reason why NIST recommends &lt;a href=&#34;http://nvlpubs.nist.gov/nistpubs/ir/2015/NIST.IR.7966.pdf&#34;&gt;SSH keys over
kerberos&lt;/a&gt;
in many cases.&lt;/p&gt;

&lt;h2 id=&#34;service-keytabs&#34;&gt;Service keytabs&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s a second form of keytab file; these are &lt;em&gt;service&lt;/em&gt; entries and are
typically of the form &lt;code&gt;service/FQDN@domain&lt;/code&gt;.  Your kerberos host probably
already has one in &lt;code&gt;/etc/krb5.keytab&lt;/code&gt; for the &lt;code&gt;host&lt;/code&gt; service&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-rw------- 1 root root 448 Sep 24 18:21 /etc/krb5.keytab
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You may have noticed the &lt;code&gt;host/kclient.spuddy.org&lt;/code&gt; entries in the &lt;code&gt;klist&lt;/code&gt;
entries above&amp;hellip; that&amp;rsquo;s as a result of this type of service.&lt;/p&gt;

&lt;p&gt;If you want to do kerberos authentication for web sites you would
create a &lt;code&gt;HTTP&lt;/code&gt; service principal and then that keytab file would be
used by the web server to verify incoming requests.&lt;/p&gt;

&lt;p&gt;Now these keytab entries are used to verify the service you&amp;rsquo;re talking to
&lt;em&gt;is&lt;/em&gt; the service you expect to talk to.  In a way they are comparable to
the ssh host keys or SSL certificate, but each service has their own key.
Because of this identity assertion these keytab files should also be
carefully managed.&lt;/p&gt;

&lt;h2 id=&#34;k5login-and-k5users-files&#34;&gt;k5login and k5users files&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s one final &amp;ldquo;gotcha&amp;rdquo; with kerberos; it allows one user to trust
another.  In &lt;code&gt;$HOME/.k5login&lt;/code&gt; you can list other kerberos principals that
are allowed to login to this account.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;user2&lt;/code&gt; has the following entry:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo cat ~user2/.k5login
user1@SPUDDY.ORG
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now this means that if I have a &lt;code&gt;user1&lt;/code&gt; TGT I can login as user2!  We&amp;rsquo;ll
re-use the keytab file from earlier&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ kinit -k -t user1.keytab user1@SPUDDY.ORG
$ ssh user2@kclient
Last login: Sat Sep 24 18:25:45 2016 from kclient.spuddy.org
[user2@kclient ~]$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this respect the &lt;code&gt;.k5login&lt;/code&gt; file is close to the ssh &lt;code&gt;authorized_keys&lt;/code&gt;
file; if I could add my login to &lt;code&gt;~oracle/.k5login&lt;/code&gt; then I can login
as oracle without needing a password.&lt;/p&gt;

&lt;p&gt;And, of course, we have NFS weaknesses if the user home directory is on
an NFS server&amp;hellip;&lt;/p&gt;

&lt;p&gt;Worse, this file &lt;em&gt;also&lt;/em&gt; works with &lt;code&gt;ksu&lt;/code&gt;&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ kinit -k -t user1.keytab user1@SPUDDY.ORG
$ ksu root
Authenticated user1@SPUDDY.ORG
Account root: authorization for user1@SPUDDY.ORG successful
Changing uid to root (0)
[root@kclient sweh]# cat /root/.k5login 
user1@SPUDDY.ORG
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Also note that &lt;code&gt;ksu&lt;/code&gt; will &lt;em&gt;also&lt;/em&gt; work with &lt;code&gt;.k5users&lt;/code&gt;, which is similar
but allows for restrictions on the command.  Do a &lt;code&gt;man ksu&lt;/code&gt; for
details.&lt;/p&gt;

&lt;p&gt;So just as how with ssh you need to set the &lt;code&gt;AuthorizedKeysFile&lt;/code&gt; file
entry, in &lt;code&gt;/etc/krb5.conf&lt;/code&gt; you should set &lt;code&gt;k5login_directory&lt;/code&gt; directory
to something users can not modify themselves, and then have a management
tool to control them, just as you would control ssh public keys.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not sure this is fully supported, though.  I&amp;rsquo;ve had marginal results
(ssh works properly, &lt;code&gt;ksu&lt;/code&gt; doesn&amp;rsquo;t?).  So you may want to verify this
change actually works the way you want and if it doesn&amp;rsquo;t then create some
form of detective control to see if a &lt;code&gt;.k5login&lt;/code&gt; or &lt;code&gt;.k5users&lt;/code&gt; file has
been created.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Unless you have a specific need for kerberos (eg a kerberised file system
where you need a ticket to access data), I&amp;rsquo;m not a fan.&lt;/p&gt;

&lt;p&gt;We can see that for &amp;ldquo;service accounts&amp;rdquo; we have a keytab management
problem to be resolved.&lt;/p&gt;

&lt;p&gt;For human accounts there&amp;rsquo;s a tendancy to use Active Directory as the source
of kerberos tickets, but I&amp;rsquo;ve &lt;a href=&#34;https://www.sweharris.org/post/2016-05-16-no-sso/&#34;&gt;previously written&lt;/a&gt;
why I think this is a bad idea.&lt;/p&gt;

&lt;p&gt;But if you &lt;em&gt;do&lt;/em&gt; want to go down the kerberos path (and it may be reasonable
for application servers, such as web servers) then we need to manage keytabs.&lt;/p&gt;

&lt;p&gt;If you&amp;rsquo;re looking at a key management solution (e.g. one that manages SSL
certs) then it&amp;rsquo;s worth seeing if it can &lt;em&gt;also&lt;/em&gt; manage SSH keys &lt;em&gt;and&lt;/em&gt; kerberos
keytabs.   It&amp;rsquo;s almost the same problem&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>SSH Password exposure</title>
      <link>https://www.sweharris.org/post/2016-09-18-ssh-password-exposure/</link>
      <pubDate>Sun, 18 Sep 2016 11:53:14 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-09-18-ssh-password-exposure/</guid>
      <description>

&lt;p&gt;Over on the Unix/Linux Stackexchange someone asked if ssh&amp;rsquo;ing to the wrong
machine could cause their password to be exposed.&lt;/p&gt;

&lt;p&gt;I answered &lt;a href=&#34;http://unix.stackexchange.com/questions/309938/is-your-ssh-password-revealed-when-you-attempt-to-connect-to-the-wrong-server/309940#309940&#34;&gt;&amp;ldquo;yes&amp;rdquo;&lt;/a&gt;&amp;hellip;
and was surprised to see the answer get over 140 upvotes.&lt;/p&gt;

&lt;h2 id=&#34;demonstration&#34;&gt;Demonstration&lt;/h2&gt;

&lt;p&gt;So it seems as if there&amp;rsquo;s some interest in this.  I decided to demonstrate
this risk in a short practical session.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s start with a generic CentOS 7 install.  It&amp;rsquo;s got nothing special on
it.&lt;/p&gt;

&lt;p&gt;We want to replace &lt;code&gt;sshd&lt;/code&gt; with a modified one that has a &lt;em&gt;one line&lt;/em&gt;
change:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;*** openssh-7.3p1.orig/auth-passwd.c    Wed Jul 27 18:54:27 2016
--- openssh-7.3p1/auth-passwd.c Sat Sep 17 19:34:41 2016
***************
*** 84,89 ****
--- 84,90 ----
  auth_password(Authctxt *authctxt, const char *password)
  {
        struct passwd * pw = authctxt-&amp;gt;pw;
+       logit(&amp;quot;User %s Password %s&amp;quot;,pw-&amp;gt;pw_name,password);
        int result, ok = authctxt-&amp;gt;valid;
  #if defined(USE_SHADOW) &amp;amp;&amp;amp; defined(HAS_SHADOW_EXPIRE)
        static int expire_checked = 0;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We build this and copy the sshd over the top of the original.&lt;/p&gt;

&lt;p&gt;So let&amp;rsquo;s try and login to this server:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;
    % ssh -l fred test1
    fred@test1&#39;s password: 
    Permission denied, please try again.
    fred@test1&#39;s password: 
    Permission denied, please try again.
    fred@test1&#39;s password: 
    Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now on the server, we can see lines in &lt;code&gt;/var/log/secure&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    Sep 17 19:36:33 test1 sshd[3597]: User fred Password test
    Sep 17 19:36:34 test1 sshd[3597]: User fred Password test2
    Sep 17 19:36:36 test1 sshd[3597]: User fred Password test3
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;They are the three passwords I entered!&lt;/p&gt;

&lt;p&gt;Now if the user doesn&amp;rsquo;t exist on the server we get &lt;code&gt;NOUSER&lt;/code&gt; as the username,
which isn&amp;rsquo;t helpful.  Fortunately other lines retain the data:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    Sep 17 19:40:38 test1 sshd[3601]: User NOUSER Password hello
    Sep 17 19:40:38 test1 sshd[3601]: Failed password for invalid user fred2 from 10.0.0.137 port 42746 ssh2
    Sep 17 19:40:39 test1 sshd[3601]: User NOUSER Password there
    Sep 17 19:40:39 test1 sshd[3601]: Failed password for invalid user fred2 from 10.0.0.137 port 42746 ssh2
    Sep 17 19:40:40 test1 sshd[3601]: User NOUSER Password eevryone
    Sep 17 19:40:40 test1 sshd[3601]: Failed password for invalid user fred2 from 10.0.0.137 port 42746 ssh2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So there&amp;rsquo;s still sufficient data to pick up all the usernames and passwords
being attempted.  And the connecting user is none the wiser that their
password might have just been stolen&lt;/p&gt;

&lt;h2 id=&#34;is-this-paranoia&#34;&gt;Is this paranoia?&lt;/h2&gt;

&lt;p&gt;Everything you do on a server is inherently dependent on trust on the SA
on that server.  They could keyboard sniff, or look in your process address
space or impersonate you or&amp;hellip;&lt;/p&gt;

&lt;p&gt;So if we have an inherent trust on the SA, why is this whole &amp;ldquo;steal password
via ssh&amp;rdquo; question a big deal?&lt;/p&gt;

&lt;p&gt;Firstly, an attempt to login to the &lt;em&gt;wrong&lt;/em&gt; machine can expose your
credentials.  Now it&amp;rsquo;s not an SA on your machine you&amp;rsquo;re shown your password
to, it&amp;rsquo;s some other admin who you may never have heard of.&lt;/p&gt;

&lt;p&gt;Secondly, credentials get re-used; especially in a large enterprise where
there may be a centralised LDAP server or other service.  Federation or
even direct integration between systems (Unix talking to Active Directory)
could let you cross environments.  A single typo in a hostname could
leak your password to many other systems an attacker.&lt;/p&gt;

&lt;h2 id=&#34;mitigation&#34;&gt;Mitigation&lt;/h2&gt;

&lt;p&gt;The primary mitigation is to &lt;em&gt;never&lt;/em&gt; use passwords.  The problem with
password based authentication is that the remote server has to have the
plain text available so that it can encrypt it according to the values in
&lt;code&gt;/etc/shadow&lt;/code&gt;, or for PAM based authentication, or&amp;hellip;   this means the
server process is in an inherent position of trust.&lt;/p&gt;

&lt;p&gt;If you use ssh public key authentication, or kerberos authentication
then your password is never passed to the server.  The attacker will never
see it.&lt;/p&gt;

&lt;p&gt;You can force this in your &lt;code&gt;.ssh/config&lt;/code&gt; file by ensuring that only
the preferred authentication mechanisms are permitted&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Host *
  PreferredAuthentications publickey
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You probably want to take other precautions even if you are logging into
the right server; e.g. disable agent forwarding so the remote SA can&amp;rsquo;t
abuse your agent; e.g. don&amp;rsquo;t request kerberos ticket forwarding so there&amp;rsquo;s
no kerberos ticket on the server for the remote SA to abuse.&lt;/p&gt;

&lt;p&gt;Secondary mitigation is to be very careful about the &lt;code&gt;known_hosts&lt;/code&gt; values.
If you suddenly get prompted to accept a key then it&amp;rsquo;s likely you&amp;rsquo;re
talking to a server you&amp;rsquo;ve never spoken to before.  BEWARE!   Of course
this doesn&amp;rsquo;t help if it&amp;rsquo;s the first time you&amp;rsquo;re logging in&amp;hellip;&lt;/p&gt;

&lt;p&gt;You can create &amp;lsquo;shortcuts&amp;rsquo; for yourself; eg in &lt;code&gt;.ssh/config&lt;/code&gt; you can create
entries such as&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Host myhost
  Server some.long.domain.name
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now &lt;code&gt;ssh myhost&lt;/code&gt; will go to the right place, and be less likely to typo.&lt;/p&gt;

&lt;h2 id=&#34;conclusions&#34;&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;&amp;ldquo;Passwords bad, m&amp;rsquo;kay?&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ve known for a long time that passwords are a terrible means of
authentication.  Mostly we&amp;rsquo;ve been saying that because they&amp;rsquo;re something
that &lt;em&gt;humans&lt;/em&gt; have to remember, and this makes them brute-forcable.  Add
in the bad practices, to which &lt;a href=&#34;https://nakedsecurity.sophos.com/2016/08/18/nists-new-password-rules-what-you-need-to-know/&#34;&gt;NIST have finally said &amp;ldquo;stop doing that!&amp;rdquo;&lt;/a&gt;, and we have a headache.&lt;/p&gt;

&lt;p&gt;But on top of this, we can see that passwords are bad from a purely technically perspective.&lt;/p&gt;

&lt;p&gt;The problem with public key authentication is that the keys need to be
properly managed.  I cover this in &lt;a href=&#34;https://www.sweharris.org/post/2016-09-05-sshkeys/&#34;&gt;more detail&lt;/a&gt;
but the essence is that you need a trusted &amp;ldquo;out of band&amp;rdquo; method of
ensuring your public keys are distributed to servers you&amp;rsquo;re allowed to
access, and management of host keys becomes complicated (especially in
a dynamic re-build environment).&lt;/p&gt;

&lt;p&gt;For my own machines I only use ssh public keys; my &amp;ldquo;build&amp;rdquo; process copies
my keys so they&amp;rsquo;re already present.  I never expose my password like that.
But while this may work for individuals it definitely doesn&amp;rsquo;t scale for
SMEs, let alone larger companies.  Imagine doing that for 50,000 servers
and 10,000 people.&lt;/p&gt;

&lt;p&gt;So we &lt;em&gt;need&lt;/em&gt; a management solution for these keys.  It&amp;rsquo;s the only way
we can scale, be dynamic, and &lt;em&gt;stop&lt;/em&gt; passwords from being used.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>HSMs, what are they good for?</title>
      <link>https://www.sweharris.org/post/2016-09-13-hsm/</link>
      <pubDate>Tue, 13 Sep 2016 08:51:07 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-09-13-hsm/</guid>
      <description>

&lt;h2 id=&#34;what-is-a-hsm&#34;&gt;What is a HSM?&lt;/h2&gt;

&lt;p&gt;A &lt;a href=&#34;https://en.wikipedia.org/wiki/Hardware_security_module&#34;&gt;HSM&lt;/a&gt; is a hardware
device that can perform cryptographic functions in a &amp;ldquo;secure&amp;rdquo; manner.&lt;/p&gt;

&lt;p&gt;The idea is that you can load your private key into a HSM and be sure that
it&amp;rsquo;s safe from theft.  Anyone tries to physical access the device and it&amp;rsquo;ll
wipe (or literally burn) the data.  So encryption or signing of data can
be trusted because only the HSM has the key needed to do the crypto.&lt;/p&gt;

&lt;p&gt;So, for example, there are modules for Oracle to allow for transparent
data encryption to happen via a HSM.  There are certificate authorities
that have their root key in a HSM.  International money transfer or
trading may be signed and verified by HSMs.&lt;/p&gt;

&lt;p&gt;Basically, HSMs are a big thing.&lt;/p&gt;

&lt;h2 id=&#34;the-problem&#34;&gt;The problem&lt;/h2&gt;

&lt;p&gt;But the problem I have isn&amp;rsquo;t with the HSM, itself, but in how they are
accessed.&lt;/p&gt;

&lt;p&gt;Take a standard network based HSM.  There are two standard ways a client
machine can access the HSM:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;IP based.  The server is &amp;ldquo;trusted&amp;rdquo; by the HSM to make requests.
(an on-machine HSM card is really just a variation of this; we use the
local hardware bus rather than the network).&lt;/li&gt;
&lt;li&gt;Authentication based.  The server authenticates to the HSM (eg with an X509 cert) in order to make requests.
There may be variations of #2 (eg symmetric encryption) but it&amp;rsquo;s all &amp;ldquo;private
data&amp;rdquo; based.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This second method is becoming more common with dynamic resources.
Think &amp;ldquo;cloud&amp;rdquo;; you might spin up 10 servers and get assigned IP addresses,
then shut down 3 of them, then spin up 5 more with different addresses.
At this point you can&amp;rsquo;t use IP address as a basis of trust, so we use
an authentication protocol instead.&lt;/p&gt;

&lt;h2 id=&#34;attack-paths&#34;&gt;Attack paths&lt;/h2&gt;

&lt;p&gt;An IP based trust to the HSM is naturally exposed to any system administrator
on the machine.  Or any attacker that manages to get remote code executition.
They can directly call the HSM since they&amp;rsquo;re coming from a forged source.&lt;/p&gt;

&lt;p&gt;An authentication based approach runs the risk of the credential
being stolen.  Either via an exploit in the app or OS, or via whatever
mechanism is used to provide credentials to the app.  In this scenario
the attacker may be able to make calls to the HSM from any machine on
the trusted network.&lt;/p&gt;

&lt;p&gt;In both of these scenarios the attacker can now call the HSM and have it
perform the necessary calculations using the stolen access.&lt;/p&gt;

&lt;h2 id=&#34;where-hsms-are-useful&#34;&gt;Where HSMs are useful&lt;/h2&gt;

&lt;p&gt;I can think of two ways that HSMs are useful&amp;hellip; and these come into play
once you have already been attacked.&lt;/p&gt;

&lt;p&gt;So, assume your attacker has got an RCE to a trusted machine or has
managed to steal an authentication credential.&lt;/p&gt;

&lt;p&gt;At this point you can revoke access to the HSM from the bad machine,
or revoke the bad credential.  Now the attacker no longer has access to
the HSM and thus to the private key.  They can no longer forge requests
or decrypt data.&lt;/p&gt;

&lt;p&gt;Without a HSM the attacker may be able to steal the primary keys and
so continue bad activity offline (forge requests, decrypt exfiltrated
encrypted data), but with a HSM their access to the keys have been
revoked.  Sure, this stops your app from running&amp;hellip; but you probably
want that, anyway!&lt;/p&gt;

&lt;p&gt;This makes it easier to limit the scope of intrusion and to recover
from it (fix the vulnerability in the code, build a new machine, create
new trusts, create new credentials), rather than having to revoke the
primary encryption keys, re-encrypt any data, ensure any counter-parties
are aware the key is no longer valid&amp;hellip;&lt;/p&gt;

&lt;p&gt;Sure, there&amp;rsquo;s still clean up and rollback type activities to be done after
an intrusion but at least the key, itself, is still secure.&lt;/p&gt;

&lt;p&gt;Similarly, HSMs help by limiting attack paths to machines that can &lt;em&gt;see&lt;/em&gt;
the HSM; if there&amp;rsquo;s no IP route between an attacker and a HSM then they
can&amp;rsquo;t make requests.  The attacker may have been able to exfiltrate the
authentication secret to talk to the HSM, but since they can&amp;rsquo;t &lt;em&gt;reach&lt;/em&gt;
the HSM from outside the network then they can&amp;rsquo;t make use of it.  They
need to maintain a persistent intrusion path, which may make it easier
to be detected.&lt;/p&gt;

&lt;h2 id=&#34;how-does-the-cloud-change-this&#34;&gt;How does the cloud change this&lt;/h2&gt;

&lt;p&gt;Dynamic elastic compute pretty much rules out IP based authentication.
In addition some PaaS systems or container ecosystems may use NAT rules
so that multiple applications all have the same externally visible IP
address.&lt;/p&gt;

&lt;p&gt;So we have to use an authentication based approach.  This suffers
the previously discussed problem of &lt;a href=&#34;https://www.sweharris.org/post/2016-06-27-container-identity/&#34;&gt;getting the credentials
into the application&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You need to make sure that you&amp;rsquo;re building your virtual networking
constructs so as to ensure that only approved IP ranges can reach the
HSM (e.g. in a 3 tier architecture, the application and database tiers
may be able to reach the HSM, but the web front end tier can&amp;rsquo;t).&lt;/p&gt;

&lt;p&gt;This, of course, raises the question on how well you trust the cloud
provider to maintain network security at their end; whether their
stuff could abuse hypervisor and control plane access&amp;hellip; but this
applies to the whole cloud environment!&lt;/p&gt;

&lt;h2 id=&#34;what-about-cloud-hsms&#34;&gt;What about cloud HSMs&lt;/h2&gt;

&lt;p&gt;Amazon can provision you a &lt;a href=&#34;https://aws.amazon.com/cloudhsm/&#34;&gt;Cloud HSM&lt;/a&gt;
which you can use instead of your own on-premise HSMs.  The idea is that
they are inside your VPC and so the latency is a lot less and so applications
that depend on them can see increased performance.&lt;/p&gt;

&lt;p&gt;The Amazon solution is based on SafeNet Luna SA devices, which provide
a strong separation between &amp;ldquo;administrative access&amp;rdquo; and &amp;ldquo;application
access&amp;rdquo;.  Amazon staff &lt;em&gt;shouldn&amp;rsquo;t&lt;/em&gt; be able to access your secrets in
the HSM.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;A HSM doesn&amp;rsquo;t appear to provide any real improvement for an &lt;em&gt;active&lt;/em&gt;
attack via an RCE or similar; the attacker can use the credentials and
access rights of the application to get the HSM to perform activities.&lt;/p&gt;

&lt;p&gt;However the HSM can help limit the consequences by making it easier to
revoke and restrict access to the secret key.&lt;/p&gt;

&lt;p&gt;The weakest part of a HSM is in the secret management; how do you help
prevent leakage of your credentials, while still allowing for automated
deployment.  In a PaaS environment you may have inherent trust on the
PaaS administrators, since they may be providing that initial &amp;ldquo;identity&amp;rdquo;.&lt;/p&gt;

&lt;h2 id=&#34;question&#34;&gt;Question&lt;/h2&gt;

&lt;p&gt;Are there any other ways a HSM can make things better?  Please let me know!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>SSH key management</title>
      <link>https://www.sweharris.org/post/2016-09-05-sshkeys/</link>
      <pubDate>Mon, 05 Sep 2016 10:39:14 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-09-05-sshkeys/</guid>
      <description>

&lt;p&gt;&lt;code&gt;SSH&lt;/code&gt; is probably the most common method of logging into Unix machines
over a network connection.  It has pretty much replaced the older &lt;code&gt;telnet&lt;/code&gt;
and &lt;code&gt;rlogin&lt;/code&gt; protocols because it encrypts data over the network and
has other &amp;ldquo;goodness&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;However one of the &amp;ldquo;good&amp;rdquo; parts of &lt;code&gt;ssh&lt;/code&gt; is probably the least well
managed; &lt;em&gt;ssh keys&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&#34;what-is-an-ssh-key&#34;&gt;What is an ssh key?&lt;/h2&gt;

&lt;p&gt;When attempting to login to a server, &lt;code&gt;ssh&lt;/code&gt; will attempt multiple different
&lt;em&gt;authenticators&lt;/em&gt;.  Now we all know (and hate) the standard password
mechanism.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh test2
sweh@test2&#39;s password: 
Last login: Sun Sep  4 12:02:13 2016 from test1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A few years ago I described &lt;a href=&#34;https://www.sweharris.org/post/2011-07-08-beginning-kerberos/&#34;&gt;some tests on using Kerberos&lt;/a&gt; as an authenticator.&lt;/p&gt;

&lt;p&gt;I even &lt;a href=&#34;https://www.sweharris.org/post/2013-09-26-googleauth/&#34;&gt;use Google Authenticator&lt;/a&gt; as a form of
two factor authentication.&lt;/p&gt;

&lt;p&gt;But the big one, and one of the most powerful, are &lt;em&gt;ssh keys&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;An ssh key is a public/private key pair.  A user can generate their own
key with &lt;code&gt;ssh-keygen&lt;/code&gt; and then copy the public part to the remote server.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/sweh/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/sweh/.ssh/id_rsa.
Your public key has been saved in /home/sweh/.ssh/id_rsa.pub.
The key fingerprint is:
ad:cc:ec:e6:9b:7f:ba:96:32:1d:83:b7:b4:1d:cf:00 sweh@test1.spuddy.org
The key&#39;s randomart image is:
+--[ RSA 2048]----+
|                 |
|                 |
|                 |
|         .E      |
|        S...     |
|       +..= o    |
|        =+ B =   |
|       .+.* o o  |
|       o=*++     |
+-----------------+
$ scp ~/.ssh/id_rsa.pub test2:.ssh/authorized_keys
sweh@test2&#39;s password:
id_rsa.pub                                    100%  403     0.4KB/s   00:00
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can now use this to authenticate instead:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh -i ~/.ssh/id_rsa sweh@test2
Enter passphrase for key &#39;/home/sweh/.ssh/id_rsa&#39;: 
Last login: Sun Sep  4 12:10:54 2016 from test1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Indeed, if the &lt;code&gt;id_rsa&lt;/code&gt; file exists (or one of a few other names) then it
will be selected automatically (with some details that don&amp;rsquo;t matter, here).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh sweh@test2
Enter passphrase for key &#39;/home/sweh/.ssh/id_rsa&#39;: 
Last login: Sun Sep  4 12:14:51 2016 from test1
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;why-would-you-do-this&#34;&gt;Why would you do this?&lt;/h2&gt;

&lt;p&gt;In the &amp;ldquo;bad old days&amp;rdquo; when servers were DES based, and so limited to
8 characters, ssh keys could use much longer pass&lt;em&gt;phrases&lt;/em&gt;.  This
benefit has been reduced with modern SHA hashing of passwords :-)&lt;/p&gt;

&lt;p&gt;But ssh keys still have some advantages.  From a user perspective we
can run an &lt;em&gt;agent&lt;/em&gt; that can remember the unlocked key and present it
automatically.  This means the user doesn&amp;rsquo;t have to keep retyping their
passwords:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ eval `ssh-agent`
Agent pid 1904
$ ssh-add ~/.ssh/id_rsa
Enter passphrase for /home/sweh/.ssh/id_rsa: 
Identity added: /home/sweh/.ssh/id_rsa (/home/sweh/.ssh/id_rsa)
$ ssh test2 echo running remotely with no password
running remotely with no password
$ ssh test2
Last login: Sun Sep  4 12:15:01 2016 from test1

$ logout
Connection to test2 closed.
$ ssh test2 echo third login                      
third login
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another, much more powerful configuration, is that &lt;em&gt;restrictions&lt;/em&gt; can be
placed on the ssh public key.  For example, we can say that it can
only be used from a specific server and can only be used to run a
specific command.&lt;/p&gt;

&lt;p&gt;eg on server &lt;code&gt;test2&lt;/code&gt; I modify the authorized_keys file so it starts:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;from=&amp;quot;10.0.0.158&amp;quot;,command=&amp;quot;/bin/echo forced command&amp;quot; ssh-rsa AAAAB3Nz....
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now if I try to use the key for a normal login:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh test2
forced command
Connection to test2 closed.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can see the &lt;code&gt;command=&lt;/code&gt; stuff was forced and I wasn&amp;rsquo;t able to do anything
else.  Similarly if I tried to use the key from a different server then
it won&amp;rsquo;t be permitted.&lt;/p&gt;

&lt;p&gt;This is &lt;em&gt;extremely&lt;/em&gt; powerful for automation purposes; for example a
production server could transfer files to DR on an automated basis
using an ssh key that has restrictions like this; the key can only
do what it is permitted to do, as opposed to having a password based
login that can do anything on the remote machine.&lt;/p&gt;

&lt;h2 id=&#34;so-what-problems-are-there-with-ssh-keys&#34;&gt;So what problems are there with ssh keys?&lt;/h2&gt;

&lt;h3 id=&#34;no-enforcement-on-passphrase-complexity&#34;&gt;No enforcement on passphrase complexity&lt;/h3&gt;

&lt;p&gt;The passphrase set on a key when we create it has no real complexity
rules that can be applied.  This is a pure client side activity.  Indeed
it&amp;rsquo;s possible to create keys &lt;em&gt;without&lt;/em&gt; a passphrase (which is good for
automation tasks, such as the DR file copy mentioned above) but a
potential risk.&lt;/p&gt;

&lt;h3 id=&#34;no-easy-distribution&#34;&gt;No easy distribution&lt;/h3&gt;

&lt;p&gt;If I want to login to 100 servers then I need to copy that key to all
100 servers.  If a new server is built then I need to remember to copy
the key there.  Some tools such as &lt;code&gt;ssh-copy-id&lt;/code&gt; help to do this, but
it&amp;rsquo;s still a mostly manual task.&lt;/p&gt;

&lt;h3 id=&#34;no-expiration&#34;&gt;No expiration&lt;/h3&gt;

&lt;p&gt;An ssh key is an authenticator and it can be &lt;em&gt;copied&lt;/em&gt; between machines.
This means that the &lt;em&gt;private&lt;/em&gt; key could be copied around and potentially
leaked.  At this point the the key is exposed to &lt;em&gt;offline&lt;/em&gt; attacks
against the passphrase (worse, the key could have been generated without
a passphrase!).&lt;/p&gt;

&lt;p&gt;In an enterprise environment with thousands of users, all it takes is one
exposed key to open a potential entry point for an attacker.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ve learned that &lt;a href=&#34;https://nakedsecurity.sophos.com/2016/08/18/nists-new-password-rules-what-you-need-to-know/&#34;&gt;expiring user passwords is bad&lt;/a&gt; because
it causes people to pick easy to hack passwords.&lt;/p&gt;

&lt;p&gt;However ssh keys are strong cryptographic keys, generated by tools, with
no human memory requirements.  They can theoretically be expired and a
new key forced, but there&amp;rsquo;s nothing &amp;ldquo;out of the box&amp;rdquo; that enables this.&lt;/p&gt;

&lt;h3 id=&#34;unauthorized-granting-of-access&#34;&gt;Unauthorized granting of access.&lt;/h3&gt;

&lt;p&gt;An authorized_keys file can have &lt;em&gt;multiple&lt;/em&gt; keys permitting access.
This is useful, especially for automation tasks; eg &lt;em&gt;key1&lt;/em&gt; can be used
from server1 and can copy files to directory1, and &lt;em&gt;key2&lt;/em&gt; can be used
from server2 and can copy files to directory2.&lt;/p&gt;

&lt;p&gt;But this also allows humans to add their keys to an account.  Let&amp;rsquo;s
say you have an &lt;code&gt;oracle&lt;/code&gt; account that your database runs under.  You don&amp;rsquo;t
allow people to login directly but force them to go via &amp;ldquo;break glass&amp;rdquo;
process, in order to control and monitor access to this privileged account.
Without any strong controls, the first time I login I could add &lt;em&gt;my&lt;/em&gt;
personl key to oracle&amp;rsquo;s authorized_keys file.  Now I can login as oracle
whenever I like, bypassing break-glass.&lt;/p&gt;

&lt;p&gt;Similarly, people tend to not share passwords, but if Fred has a login
on a server then he could add John&amp;rsquo;s public key to his authorized_keys
file and now John can login to the server as well&amp;hellip; without any
authorization or oversight.  Your central access admin request system
has been totally bypassed.&lt;/p&gt;

&lt;h3 id=&#34;keys-on-nfs-servers&#34;&gt;Keys on NFS servers&amp;hellip;&lt;/h3&gt;

&lt;p&gt;A &lt;a href=&#34;https://whyistheinternetbroken.wordpress.com/2014/12/04/techfeeling-insecure-about-nfs/&#34;&gt;long standing problem with NFS&lt;/a&gt; is that it is an effective &amp;ldquo;trust the
client&amp;rdquo; environment.  The client says &amp;ldquo;user 12345 wants to access file X&amp;rdquo;
and the server has to &lt;em&gt;trust&lt;/em&gt; the client when it says you are user 12345.
Now this has been changed, to some extent, with NFSv4 and with kerberos
but this isn&amp;rsquo;t as widely deployed as we might wish.&lt;/p&gt;

&lt;p&gt;And commonly, user HOME directories are on these NFS servers.  So now
it becomes possible for one SA to add their key to another user&amp;rsquo;s
authorized_keys file and now login to &lt;em&gt;other&lt;/em&gt; servers that they wouldn&amp;rsquo;t
normally be permitted to.  All of the previous problems are exposed by
having keys stored on NFS.&lt;/p&gt;

&lt;h2 id=&#34;so-why-use-it&#34;&gt;So why use it?&lt;/h2&gt;

&lt;p&gt;If ssh keys have all these problems then why use them?&lt;/p&gt;

&lt;p&gt;Mostly, as &lt;a href=&#34;http://nvlpubs.nist.gov/nistpubs/ir/2015/NIST.IR.7966.pdf&#34;&gt;NIST says&lt;/a&gt;, ssh keys are extremely powerful; the &lt;code&gt;command&lt;/code&gt; and &lt;code&gt;from&lt;/code&gt; restrictions
allow you to build solutions that are more tightly locked down than other
authenticators.&lt;/p&gt;

&lt;h2 id=&#34;host-keys&#34;&gt;HOST keys&lt;/h2&gt;

&lt;p&gt;In addition to the ssh keys we&amp;rsquo;ve been discussing there&amp;rsquo;s also the concept
of a &lt;em&gt;host&lt;/em&gt; key.  These are a form of ssh key that&amp;rsquo;s used to identify
the host.&lt;/p&gt;

&lt;p&gt;First time you login to a machine you&amp;rsquo;ll be presented with the public key
signature of a host, which you can accept.  Next time you login the client
will verify the key hasn&amp;rsquo;t changed; you have a level of trust that the
server you&amp;rsquo;re accessing &lt;em&gt;is&lt;/em&gt; the server you meant to access:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh test2
The authenticity of host &#39;test2 (10.0.0.159)&#39; can&#39;t be established.
ECDSA key fingerprint is 32:31:44:a0:9b:61:1b:ff:2f:db:76:ae:a9:a5:36:2b.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added &#39;test2,10.0.0.159&#39; (ECDSA) to the list of known hosts.
forced command
Connection to test2 closed.

$ ssh test2
forced command
Connection to test2 closed.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is (mostly) OK, but what happens if a server is rebuilt?  Now the key
will change.  In the modern dynamic world (eg dynamic building/destroying
of Amazon EC2 instances) your host keys may change all the time.&lt;/p&gt;

&lt;p&gt;Ideally we need a way to manage these host keys so that the client can
determine the current host key; this will solve the &amp;ldquo;trust key presented
on first connect&amp;rdquo; &lt;em&gt;and&lt;/em&gt; solve the &amp;ldquo;key changes on rebuild&amp;rdquo; problem.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Some of the problems with ssh keys can be mitigated by changing the
default config.  Instead of having the authorized_keys file in the user&amp;rsquo;s
home directory, the configuration can point to a location that only &lt;code&gt;root&lt;/code&gt;
can modify.&lt;/p&gt;

&lt;p&gt;e.g. &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; could read&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;AuthorizedKeysFile /etc/ssh/auth_keys/%u
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Each file in that directory should be owned by root:root and have permission
0644 (&lt;code&gt;-rw-r--r--&lt;/code&gt;).  Now Fred can not grant John access to the system,
unauthorized access to &lt;code&gt;oracle&lt;/code&gt; is prevented, NFS risks have gone away&amp;hellip;&lt;/p&gt;

&lt;p&gt;We haven&amp;rsquo;t solved the whole problem, of course; your SAs can still manage
this and bypass your access admin processes.&lt;/p&gt;

&lt;p&gt;And we&amp;rsquo;ve now got a massive &amp;ldquo;key distribution&amp;rdquo; problem.  Where should
John&amp;rsquo;s keys be copied to?  When he leaves, or changes teams, can we remove
all these keys?  Can we force key rotation when they get to a certain age?
Can all this be automated?  Maybe even hooked into your access admin
tools?&lt;/p&gt;

&lt;p&gt;&amp;ldquo;John is an Oracle DBA; he&amp;rsquo;s allowed to login to the oracle servers&amp;rdquo;
is a problem your access admin tools should already be solving; can some
form of ssh key management be added so that John&amp;rsquo;s public key is published
to those servers automatically?&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s a number of challenges that such an automation tool needs to deal
with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allow a human to have their own unique key (maybe self-generated or system generated), and have that deployed to servers they&amp;rsquo;re allowed to login to.&lt;/li&gt;
&lt;li&gt;Allow a functional account to have &lt;em&gt;multiple&lt;/em&gt; keys with &lt;code&gt;command&lt;/code&gt; and &lt;code&gt;from&lt;/code&gt;
(and other) restrictions applied to them.  Auto-generate the keys and
auto-deploy the &lt;em&gt;private&lt;/em&gt; key to the authorized servers.&lt;/li&gt;
&lt;li&gt;Handle key rotation so that automation processes don&amp;rsquo;t break (add new
public key to target servers, replace private keys, remove old public keys)&lt;/li&gt;
&lt;li&gt;Handle expiration, re-certification, automation, integration&amp;hellip;&lt;/li&gt;
&lt;li&gt;Manage the &lt;code&gt;GlobalKnownHostsFile&lt;/code&gt; so that clients can be told about
server host keys, handle rebuilds/redeploys, dynamic host builds, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SSH keys can be used to &lt;em&gt;bypass&lt;/em&gt; your existing controls solutions and
so need to be controlled.  This is an area that hasn&amp;rsquo;t seen a lot of
focus, but I predict a number of regulatory environments are going to
start looking at how keys are managed.  You can either forbid keys,
totally, or manage them.&lt;/p&gt;

&lt;p&gt;I recommend trying to manage them!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Single point of truth</title>
      <link>https://www.sweharris.org/post/2016-08-31-single-truth/</link>
      <pubDate>Wed, 31 Aug 2016 21:29:44 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-08-31-single-truth/</guid>
      <description>

&lt;p&gt;Something I&amp;rsquo;ve been pushing (and this is pretty much a truism amongst
anyone who&amp;rsquo;s looked at &amp;ldquo;Cloud&amp;rdquo;) is the idea of automation.  It doesn&amp;rsquo;t
matter if you&amp;rsquo;re just treating the cloud as an &lt;a href=&#34;https://www.sweharris.org/post/2016-08-08-lift_and_shift/&#34;&gt;outsourced datacenter&lt;/a&gt;
or if you&amp;rsquo;re doing full 12-factor dynamically scalable apps.  Automation
is the key to consitency and control.&lt;/p&gt;

&lt;p&gt;So, ideally, this means your automation system is the &amp;ldquo;single point of
truth&amp;rdquo; for your estate.  Whether you use &lt;code&gt;ansible&lt;/code&gt; or &lt;code&gt;chef&lt;/code&gt; or (saints
preserve us) &lt;code&gt;cfengine&lt;/code&gt;, your configuration file explicitly defines
your target state.  You can learn everything from that.&lt;/p&gt;

&lt;p&gt;But is this true?&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s nice in theory but, as is always the case, practice may be different.&lt;/p&gt;

&lt;p&gt;Your source of truth may &lt;em&gt;contradict&lt;/em&gt; itself.&lt;/p&gt;

&lt;p&gt;Now &lt;code&gt;cfengine&lt;/code&gt; is easy to see; one promise could say &amp;ldquo;X is true&amp;rdquo; and another
promise could says &amp;ldquo;!X is true&amp;rdquo;.  &lt;code&gt;cfengine&lt;/code&gt; will complain that these rules
don&amp;rsquo;t converge (assuming anyone reads the logs) and your server is in an
unknown state.  This is simple.&lt;/p&gt;

&lt;p&gt;But there&amp;rsquo;s a more subtle failure mode.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s say we use &lt;code&gt;ansible&lt;/code&gt; to build our environment.  The build process
calls a sequence of playbooks to take your machine from raw state through
to final configuration.  So far, so good.&lt;/p&gt;

&lt;p&gt;Now let&amp;rsquo;s say each playbook should be in its own &lt;code&gt;git&lt;/code&gt; repo; after all,
the playbook that installs and configures &lt;code&gt;apache&lt;/code&gt; doesn&amp;rsquo;t really need
to impact the playbook for &lt;code&gt;postfix&lt;/code&gt;.  It makes sense to seperate out these
playbooks into different areas; different teams may be responsible; different
access controls can be applied (you don&amp;rsquo;t want the SMTP team to impact your
web servers).&lt;/p&gt;

&lt;p&gt;OK, that&amp;rsquo;s a contrived example, but you can see how it goes; the team building
out your Postgres database automation shouldn&amp;rsquo;t necessarily have the ability
to change the configuration of your OpenLDAP servers.&lt;/p&gt;

&lt;p&gt;But here&amp;rsquo;s where things get complicated&amp;hellip;&lt;/p&gt;

&lt;p&gt;Sometimes there &lt;em&gt;is&lt;/em&gt; overlap.  Your &lt;code&gt;apache&lt;/code&gt; automation may configure the
addresses of your single sign on servers.  Your &lt;code&gt;nginx&lt;/code&gt; configuration may
require the same data.  If they&amp;rsquo;re in different repo&amp;rsquo;s, then how do you
ensure consistency?&lt;/p&gt;

&lt;p&gt;Your single point of truth (&amp;ldquo;this is the single signon server&amp;rdquo;) may not
be consistent.&lt;/p&gt;

&lt;h4 id=&#34;iteration&#34;&gt;Iteration&lt;/h4&gt;

&lt;p&gt;There&amp;rsquo;s no simple answer to this.  How you factor your code repositories,
how you factor your automation, how you build systems will &lt;em&gt;evolve&lt;/em&gt;
over time.  But be aware; if you define a variable (&amp;ldquo;single signon
server&amp;rdquo;) for one playbook, maybe it&amp;rsquo;s also useful elsewhere?  Define a
global namespace?&lt;/p&gt;

&lt;h4 id=&#34;laziness&#34;&gt;Laziness&lt;/h4&gt;

&lt;p&gt;I spotted this in my own tooling.  I have a script that will build my
DNS and DHCP configuration.  Given an entry in a config file it will
build A, AAAA and PTR records for the machine.&lt;/p&gt;

&lt;p&gt;I noticed, today, that one of my domains isn&amp;rsquo;t controlled this way.
It has an A and AAAA record that&amp;rsquo;s hard-coded.  I&amp;rsquo;m &lt;em&gt;sure&lt;/em&gt; this will
bite me in the bum down the line (when the primary server fails and
I need to failover to a secondary).  Will I remember this?  Or should
I fix my automation.  The answer is obvious&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Building an OS container</title>
      <link>https://www.sweharris.org/post/2016-08-23-build-os-container/</link>
      <pubDate>Tue, 23 Aug 2016 19:13:55 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-08-23-build-os-container/</guid>
      <description>

&lt;p&gt;In a previous blog entry I described some of the controls that are
needed if you want to use a
&lt;a href=/post/2016-08-15-container-as-vm/&gt;container as a VM&lt;/a&gt;.
Essentially, if you want to use it as a VM then you must &lt;em&gt;treat&lt;/em&gt; it as
a VM.&lt;/p&gt;

&lt;p&gt;This means that all your containers should have the same baseline as your
VM OS, the same configuration, the same security policies.&lt;/p&gt;

&lt;p&gt;Fortunately we can take a VM and &lt;em&gt;convert&lt;/em&gt; it into a container.  Mostly.&lt;/p&gt;

&lt;p&gt;In my lab setup (&amp;ldquo;lab&amp;rdquo; be a grandious word; it&amp;rsquo;s a single machine running
too many KVM virtual machines :-)) I&amp;rsquo;ve created a process for building
a new VM via kickstart.  I can run &lt;code&gt;virt_build test2&lt;/code&gt; and it will
create the LVM volumes, start an install of CentOS 7, patch it, apply
my local configs (create my account, install SSH keys, etc etc).  A few
minutes later I can then &lt;code&gt;ssh test2&lt;/code&gt; and, just like that, I have a new VM.&lt;/p&gt;

&lt;p&gt;Many enterprises will have a similar build process; whether it uses
PXE to do the initial boot and [Cobbler](&lt;a href=&#34;https://en.wikipedia.org/wiki/Cobbler_(software%29&#34;&gt;https://en.wikipedia.org/wiki/Cobbler_(software%29&lt;/a&gt;)
to dynamically build the kickstart file, or does it the simplistic
way I do doesn&amp;rsquo;t really matter.  The result is an automated consistent build.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Side note: Some artifacts of the automated build process might need to
be split into a &amp;ldquo;build&amp;rdquo; and &amp;ldquo;first boot&amp;rdquo; section; for example a server
may register itself to Active Directory for authentication, or to Tivoli
for monitoring&amp;hellip; these are now &amp;ldquo;first boot&amp;rdquo; type activities and can&amp;rsquo;t
be done at build time.  But let&amp;rsquo;s ignore this complexity :-)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The important parts of my kickstart file are:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;network --onboot yes --device eth0 --bootproto dhcp --ipv6 auto

rootpw  --iscrypted yeahyeahyeah
authconfig --enableshadow --passalgo=sha512
firewall --disabled
selinux --disabled

zerombr
clearpart --all --initlabel
part /boot --fstype=ext4 --asprimary --size=500
part swap --asprimary --size=512
part / --fstype=ext4 --asprimary --grow --size=1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There&amp;rsquo;s a &lt;code&gt;%packages&lt;/code&gt; and &lt;code&gt;%post&lt;/code&gt; section (which creates my account)
and so on.  This should be perfectly familiar to anyone used to kickstart.&lt;/p&gt;

&lt;p&gt;Now the result of my build process is an LVM disk image consisting of
three partitions&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;/boot&lt;/li&gt;
&lt;li&gt;swap&lt;/li&gt;
&lt;li&gt;/&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This, in my case, is &lt;code&gt;/dev/Raid10/vm.test2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So now we need to take this image and convert it to a docker container.&lt;/p&gt;

&lt;p&gt;So we need to make the image accessible to the host OS.  Then we can mount
it.  Then send it to the docker server, where it can be converted to an
image.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo kpartx -av /dev/Raid10/vm.test2
add map Raid10-vm.test2p1 (253:21): 0 1024000 linear /dev/Raid10/vm.test2 2048
add map Raid10-vm.test2p2 (253:22): 0 1048576 linear /dev/Raid10/vm.test2 1026048
add map Raid10-vm.test2p3 (253:23): 0 6313984 linear /dev/Raid10/vm.test2 2074624
$ sudo mkdir /tmpmount
$ sudo mount -r /dev/mapper/Raid10-vm.test2p3 /tmpmount
$ cd /tmpmount
$ sudo tar cf - . | ssh dockerserver docker import - c7test2

$ cd
$ sudo umount /tmpmount/
$ sudo kpartx -d /dev/Raid10/vm.test2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now this may through up a couple of errors about sockets (in my case it
complained about &lt;code&gt;postfix&lt;/code&gt; sockets), but we can ignore them.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;tar: ./var/lib/gssproxy/default.sock: socket ignored
tar: ./var/spool/postfix/private/virtual: socket ignored
tar: ./var/spool/postfix/private/bounce: socket ignored
....
tar: ./tmp/ssh-IB3AMGEQUc/agent.1873: socket ignored
sha256:374dc7777cfc8c6c2676021dfdd535aac1047a4794a1333814ddcf4936d32b33
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we now look on the docker server:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
c7test2             latest              374dc7777cfc        3 minutes ago       1.185 GB
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice how large this is, compared to the official docker centos image&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;docker.io/centos    latest              970633036444        3 weeks ago         196.7 MB
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But we now have an OS container that we can run!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ docker run --name container1 c7test2 /sbin/init &amp;amp;

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
0e640e27a91b        c7test2             &amp;quot;/sbin/init&amp;quot;        26 seconds ago      Up 22 seconds                           container1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And we can see the container is running a full OS tree&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ docker top container1 | head -4
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                30732               9504                0                   19:49               ?                   00:00:00            /sbin/init
root                30755               30732               0                   19:49               ?                   00:00:00            /usr/lib/systemd/systemd-journald
root                30793               30732               0                   19:49               ?                   00:00:00            /usr/sbin/rsyslogd -n
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I haven&amp;rsquo;t done anything clever with the networking here, but&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ docker inspect container1 | grep IPAddress
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;tells me this container is 172.17.0.3&lt;/p&gt;

&lt;p&gt;So we can now &lt;code&gt;ssh&lt;/code&gt; into it!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ssh 172.17.0.3                            
The authenticity of host &#39;172.17.0.3 (172.17.0.3)&#39; can&#39;t be established.
ECDSA key fingerprint is 32:31:44:a0:9b:61:1b:ff:2f:db:76:ae:a9:a5:36:2b.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added &#39;172.17.0.3&#39; (ECDSA) to the list of known hosts.

0e640e27a91b$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;My OS image is now a (mostly) working container with a funky hostname :-)&lt;/p&gt;

&lt;p&gt;What doesn&amp;rsquo;t work?  Well, I don&amp;rsquo;t seem to have a &lt;code&gt;getty&lt;/code&gt; process
running on the console.  And commands like &lt;code&gt;dmesg&lt;/code&gt; don&amp;rsquo;t work.
And I haven&amp;rsquo;t joined it to my main network (using the default &lt;code&gt;docker0&lt;/code&gt;
network).  But for all intents and purposes, this is a working OS container.&lt;/p&gt;

&lt;p&gt;(For clean-ness we should create a derived container based on this
image that automtically runs &lt;code&gt;init&lt;/code&gt; and lets the &lt;code&gt;docker&lt;/code&gt; command
return, but that&amp;rsquo;s a refinement).&lt;/p&gt;

&lt;h4 id=&#34;summary&#34;&gt;Summary&lt;/h4&gt;

&lt;p&gt;Now I&amp;rsquo;ve walked through how I could convert &lt;em&gt;my&lt;/em&gt; build process to creating
a docker OS container.  Naturally you&amp;rsquo;ll need to modify your own processes
to work in your environment, and the more complex the environment the more
tweaks necessary.  But this is the &lt;em&gt;concept&lt;/em&gt; you can follow; take a known
good build from your standard build process and convert it to a container.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not really a fan of the &amp;ldquo;container as a VM&amp;rdquo; model.  I can understand
that some people might want to do it and, as previously written, I think
that the lines between a container and a VM will blur (at which time
the build process will also become easier).&lt;/p&gt;

&lt;p&gt;But if you&amp;rsquo;re going to do it, building a process that maintains consistency
between your VM and container builds is a massive step forwards towards
controlling the estate and, with automation, can simplify your compliance
stance; you only &lt;em&gt;have&lt;/em&gt; the one build process to worry about :-)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Using a container as a lightweight VM</title>
      <link>https://www.sweharris.org/post/2016-08-15-container-as-vm/</link>
      <pubDate>Mon, 15 Aug 2016 11:39:58 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-08-15-container-as-vm/</guid>
      <description>

&lt;p&gt;In a lot of this blog I have been pushing for the use of containers
as an &amp;ldquo;application execution environment&amp;rdquo;.  You only put the minimal
necessary stuff inside the container, treat them as immutable images,
never login to them&amp;hellip;  the sort of thing that&amp;rsquo;s perfect for 12 factor
application.&lt;/p&gt;

&lt;p&gt;However there &lt;em&gt;are&lt;/em&gt; other ways of using containers.  The other main
version is to treat a container as a light-weight VM.  Sometimes this
is called &amp;ldquo;OS container&amp;rdquo; because you&amp;rsquo;ve got a complete OS (except
the kernel) here, and you treat it as if it was an OS.&lt;/p&gt;

&lt;p&gt;Indeed, this is how earlier container technology was used; on Solaris
the zones technology is essentially used to build a lightweight VM.
A number of the cheaper virtual host solutions use container technology
such as Virtuozo or OpenVZ to present something that looks like a VM.&lt;/p&gt;

&lt;h2 id=&#34;characteristics-of-an-os-container&#34;&gt;Characteristics of an OS container&lt;/h2&gt;

&lt;p&gt;A container used in this way has a number of characteristics that are
almost the opposite of what I&amp;rsquo;ve previously been talking about.  So
an OS container may have the following characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Persistent

&lt;ul&gt;
&lt;li&gt;Storage is allocated and dedicated to the container.  You can treat
&lt;code&gt;/home&lt;/code&gt; and &lt;code&gt;/usr&lt;/code&gt; and &lt;code&gt;/opt&lt;/code&gt; the same as you would on any server;
reboot the container and the files will remain.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Long lived

&lt;ul&gt;
&lt;li&gt;These containers may have uptimes of weeks or months, and even after
a reboot the container comes back as it was before&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Mutable

&lt;ul&gt;
&lt;li&gt;The contents change.  Applications may write log files, users may store
data, database datafiles may be present&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Accessible

&lt;ul&gt;
&lt;li&gt;People may be able to &lt;code&gt;ssh&lt;/code&gt; into these things&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Manual changes

&lt;ul&gt;
&lt;li&gt;If people can login and touch files then we have manual processes.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For me, this sounds exactly like how we would think of a traditional virtual
machine (VM).  And this means we must &lt;em&gt;treat&lt;/em&gt; them like a traditional VM.&lt;/p&gt;

&lt;h2 id=&#34;controls&#34;&gt;Controls&lt;/h2&gt;

&lt;p&gt;Now in the VM world we have a number of controls that take place inside the
VM.  You may have things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identity Management&lt;/li&gt;
&lt;li&gt;Privilege Escalation&lt;/li&gt;
&lt;li&gt;Logging&lt;/li&gt;
&lt;li&gt;Change management&lt;/li&gt;
&lt;li&gt;Auditing&lt;/li&gt;
&lt;li&gt;Backups&lt;/li&gt;
&lt;li&gt;Patching&lt;/li&gt;
&lt;li&gt;Monitoring&lt;/li&gt;
&lt;li&gt;Vulnerability scanning&lt;/li&gt;
&lt;li&gt;Intrusion detection&lt;/li&gt;
&lt;li&gt;&amp;hellip; and everything else!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For an OS container you will need all of these as well.  Container technology
doesn&amp;rsquo;t give you any special wins over traditional VM technology.  Because
you&amp;rsquo;re running an OS you have to manage an OS.&lt;/p&gt;

&lt;p&gt;Now we also have controls around the management of VMs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inventory management

&lt;ul&gt;
&lt;li&gt;what VMs are present, who owns them, what is their purpose&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;IP address allocation, DNS, etc&lt;/li&gt;
&lt;li&gt;Hypervisor access&lt;/li&gt;
&lt;li&gt;Console controls&lt;/li&gt;
&lt;li&gt;Control plane access

&lt;ul&gt;
&lt;li&gt;Changing the VM size, attached devices, power management&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Affinity rules

&lt;ul&gt;
&lt;li&gt;Production and DR should not be on the same physical machine&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&amp;hellip; and everything else!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We&amp;rsquo;ll need all of these in the OS Container model as well.  However some
of these controls may look different.  It&amp;rsquo;s easy to control access to
the hypervisor, but in a container world the same equivalent would be
access to the parent OS.  You have to treat those parent OSes as highly
privileged, as high as you treat your ESX Hypervisor (for example).&lt;/p&gt;

&lt;p&gt;This means building out a lot of infrastructure and tooling to manage
these containers; tooling you already have present for VMs.&lt;/p&gt;

&lt;h2 id=&#34;so-why-do-it&#34;&gt;So why do it?&lt;/h2&gt;

&lt;p&gt;Since you don&amp;rsquo;t really gain any of the normal container benefits,
why would you use the technology this way?  Some of the answers
I&amp;rsquo;ve received to this question are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Increased application density

&lt;ul&gt;
&lt;li&gt;We can fit more OS containers into a machine than we can VMs&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Easier for developers

&lt;ul&gt;
&lt;li&gt;In a strict development environment we can let dev teams spin up
OS containers and experiment in them (to me this points to a failing
of existing VM build processes).  Perhaps even on their laptops,
offline.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Lift and shift migration path

&lt;ul&gt;
&lt;li&gt;Build your app into a container, test it, get it working, then
migrate it to a public cloud service.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Are there other use cases?  If you can think of some then please let me
know in the comments!&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I commonly hear &amp;ldquo;you can&amp;rsquo;t pass audit&amp;rdquo; type statements with respect to
OS containers.  I&amp;rsquo;m not sure that&amp;rsquo;s true.  You &lt;em&gt;can&lt;/em&gt;, as long as you
have the right controls in place.  Since you&amp;rsquo;re using these containers
as a form of lightweight VM then you &lt;em&gt;must&lt;/em&gt; treat them as if they are a
VM.&lt;/p&gt;

&lt;p&gt;All of the existing controls must be in place, and the control
layer properly secured.   For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You don&amp;rsquo;t allow anyone to create VMs without some checks and balances;
you shouldn&amp;rsquo;t allow them to spin up OS containers without the same controls.&lt;/li&gt;
&lt;li&gt;You don&amp;rsquo;t allow anyone to access the hypervisor; you shouldn&amp;rsquo;t allow
anyone to access to host OS.&lt;/li&gt;
&lt;li&gt;You don&amp;rsquo;t allow unpatched vulnerabilities to exist on VMs; you shouldn&amp;rsquo;t
allow them to exist inside OS containers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We&amp;rsquo;re in the early days of OS containers (despite their age),
especially when coming to enterprise management of them.  We learned how
to manage VM farms; we&amp;rsquo;re going to need to learn to manage OS container
farms to the same level of control.  Indeed I foresee management planes
that will cover both VMs and OS containers in the same way.&lt;/p&gt;

&lt;p&gt;Remember that security isn&amp;rsquo;t absolute; there are gaps in hypervisor
security (KVM, Xen, ESX&amp;hellip; they&amp;rsquo;ve all had security gaps in the past).
Containers are newer and the kernel exposes a larger footprint and so
likely has more gaps.  However I can see a day where the line between
a VM and an OS container ends up blurring, and the traditional VM
itself ends up being reserved for the ability to run different OSes
(eg Windows, Solaris, Linux) on the same hardware and OS containers
become the predominant way of running multiple Linux installs.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Lift and Shift</title>
      <link>https://www.sweharris.org/post/2016-08-08-lift_and_shift/</link>
      <pubDate>Mon, 08 Aug 2016 15:36:52 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-08-08-lift_and_shift/</guid>
      <description>

&lt;p&gt;A phrase you might hear around cloud computing is &lt;em&gt;lift and shift&lt;/em&gt;.  In
this model you effectively take your existing application and move it,
wholesale, into a cloud environment such as Amazon EC2.  There&amp;rsquo;s no
re-architecting of the application; there&amp;rsquo;s no application redesign.
This make it very quick and very easy to move into the cloud.  It&amp;rsquo;s
not much different to a previous p2v (physical to virtual) activity
that companies performed when migration to virtual servers (eg VMware
ESX).&lt;/p&gt;

&lt;p&gt;Naturally, since you&amp;rsquo;re running in the cloud, you have great availability
and scalability.  Job done, right?&lt;/p&gt;

&lt;p&gt;Well, that depends on the problem you&amp;rsquo;re trying to solve.&lt;/p&gt;

&lt;p&gt;By performing a &amp;ldquo;lift and shift&amp;rdquo; you haven&amp;rsquo;t solved your resiliency
or reliability issues.  You haven&amp;rsquo;t solved your backup issues.  You
haven&amp;rsquo;t solved your security issues.  Indeed, these issues may become
worse, as we&amp;rsquo;ll see.&lt;/p&gt;

&lt;p&gt;Underneath your cloud instance is a physical machine.  Physical machines
need patching or repairing.  This is scheduled downtime that is now
out of your control.  Your cloud based operating system instance could
be shut down and rebooted without any notice.  This means you still have
to build old-school &amp;ldquo;high availability&amp;rdquo; solutions; clustering, fail-over,
etc.  Because you may not get any notice this HA solution needs to be
better automated than you might already have.&lt;/p&gt;

&lt;p&gt;Because you&amp;rsquo;ve just copied your existing solution into a cloud you still
have to manage your operating system instances; that means user identity
management, audit trails, change controls and so on.  However this cloud
instance may be (likely &lt;em&gt;will be&lt;/em&gt;) outside your security perimeter so
now you need to extend your Identity and Access Management systems to
that.  Worse, you now also have to control access to the cloud provider&amp;rsquo;s
dashboard; who is allowed to spawn new virtual machines, change network
definitions, firewall rules?&lt;/p&gt;

&lt;p&gt;Security scanning of your environment hasn&amp;rsquo;t gone away either; you need
the same level of control (patching, vulnerability management, etc) as
you had before.&lt;/p&gt;

&lt;p&gt;Your cloud provider may give you nice resilient disks; that&amp;rsquo;s nice!  But
resiliency isn&amp;rsquo;t the same as a backup solution.  You still need to backup
your files (e.g. for 7 or 10 year retention to meet audit requirements).&lt;/p&gt;

&lt;p&gt;All of this may work out &lt;em&gt;more expensive&lt;/em&gt; than doing it in house.  People
look at Amazon and say &amp;ldquo;wow, that&amp;rsquo;s cheap!  So much cheaper than my
company can provide a virtual machine for!&amp;rdquo;  And the up-front number &lt;em&gt;is&lt;/em&gt;
cheaper.  But then you add in all the additional tools that you use
(I&amp;amp;AM, vuln scanning, logging, &lt;em&gt;network traffic&lt;/em&gt;, backups, patching&amp;hellip;)
and notice your in-house cost has all that bundled in and it can easily
turn out that your cloud instance works out more expensive.&lt;/p&gt;

&lt;p&gt;So with all these negatives, why would you &amp;ldquo;lift and shift&amp;rdquo;?&lt;/p&gt;

&lt;p&gt;Well, it&amp;rsquo;s not a once size fits all problem.  A large mega-corp running
30 datacenters &lt;em&gt;should&lt;/em&gt; be able to provide virtual servers cheaper than
Amazon.  But a small company that only needs 100 servers?  Or only has
a couple of datacenters?  Well now the equation isn&amp;rsquo;t so clear cut.
It may well be worth effectively outsourcing the datacenter to a cloud
provider.   Why go to the hassle of maintaining physical servers, needing
physical security guards, staff to manage the HVAC systems, NOC teams
to replace failing kit&amp;hellip;&lt;/p&gt;

&lt;p&gt;Having your kit in the cloud can also help you migrate to a more
modern architecture; once you&amp;rsquo;ve got an API driven infrastructure it
becomes easier to look into building apps and environments that &lt;em&gt;can&lt;/em&gt;
start to make use of auto-scaling, micro-services, resilient
architectures, 12-factor apps&amp;hellip;&lt;/p&gt;

&lt;h4 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;&amp;ldquo;Lift and shift&amp;rdquo; is a viable model of using cloud computing, but it&amp;rsquo;s not
a panacea.  You have all of the management challenges of running in your
own datacenter (or co-located datacenter); you need to manage your servers,
build HA solutions, replicate data, have backups etc etc.  It may,
initially, even cost you more money than you expected.&lt;/p&gt;

&lt;p&gt;But once you are there you can start to take advantage of other features;
want to use Apache Spark?  Amazon already have this pre-built; you don&amp;rsquo;t
need to engineer that yourself.  Want to make use of multiple datacenters,
close to your customers?  They have plenty of points of presence to assist
in that.&lt;/p&gt;

&lt;p&gt;Don&amp;rsquo;t go looking at the problem as &amp;ldquo;We need to be in the cloud!
Let&amp;rsquo;s lift and shift&amp;rdquo;.  Instead look at the use cases; would it make
sense to re-architect and rebuild your app to be more &amp;ldquo;cloud native&amp;rdquo;?
Maybe even something simpler&amp;hellip;  perhaps you&amp;rsquo;ll find you don&amp;rsquo;t &lt;em&gt;need&lt;/em&gt;
to run your app 24x7; only spin it up one hour per day&amp;hellip;&lt;/p&gt;

&lt;p&gt;&amp;ldquo;Lift and shift&amp;rdquo; is one of the crudest methods of getting into the cloud.
But it doesn&amp;rsquo;t make it a &lt;em&gt;bad&lt;/em&gt; way of doing it.  It&amp;rsquo;s just another tool
in the toolbox.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Persistent data</title>
      <link>https://www.sweharris.org/post/2016-07-28-persistency/</link>
      <pubDate>Thu, 28 Jul 2016 08:35:00 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-07-28-persistency/</guid>
      <description>

&lt;p&gt;In this glorious new world I&amp;rsquo;ve been writing about, applications are non
persistent. They spin up and are destroyed at will.  They have no
state in them.  They can be rebuilt, scaled out, migrated, replaced
and your application shouldn&amp;rsquo;t notice&amp;hellip; if written properly!&lt;/p&gt;

&lt;p&gt;But applications are pointless if they don&amp;rsquo;t have data to work on.
In traditional compute an app is associated with a machine (or set of
machines).  These machines have filesystems.  We can write data there.
If we want to share data between machines we can use something like NFS.
It&amp;rsquo;s very easy to persist data.&lt;/p&gt;

&lt;p&gt;In our new dynamically scalable app migrating world we don&amp;rsquo;t have this.&lt;/p&gt;

&lt;p&gt;So where do we store our data?&lt;/p&gt;

&lt;p&gt;The standard answer is to use an external datastore, such as MySQL
or CouchDB or an object store (typically presented with an Amazon S3
compatible API, even if not actually &lt;em&gt;using&lt;/em&gt; Amazon S3).  Your application
doesn&amp;rsquo;t persist any data; these resources are &lt;em&gt;attached&lt;/em&gt; (or &lt;em&gt;bound&lt;/em&gt;)
to your app so they can be used.&lt;/p&gt;

&lt;p&gt;Even for users of databases this may require a change in behaviour; you
might write out all your important data into the database but write out
logs and performance data to the filesystem.  You can&amp;rsquo;t &lt;em&gt;do&lt;/em&gt; that any
more; everything you want to keep needs to stored in the database or S3
store.  And that requires a code rewrite.&lt;/p&gt;

&lt;h4 id=&#34;persistent-files&#34;&gt;Persistent files&lt;/h4&gt;

&lt;p&gt;But I&amp;rsquo;ve never been a fan of that.  Why can&amp;rsquo;t we treat a filesystem as
if it was another attached resource?  This data could also be shared
between instances of the app.&lt;/p&gt;

&lt;p&gt;With docker we have some of this ability with the &lt;code&gt;-v&lt;/code&gt; flag.  Let&amp;rsquo;s
create a directory and share it across two running instances:&lt;/p&gt;

&lt;p&gt;In terminal window 1:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;tty1$ sudo mkdir -p /export/myapp
tty1$ docker run --rm -it -v /export/myapp:/myapp --name inst1 centos 
[root@cd0c4a2b0055 /]# ls /myapp
[root@cd0c4a2b0055 /]# echo world &amp;gt; /myapp/hello
[root@cd0c4a2b0055 /]# 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In window 2:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;tty2$ docker run --rm -it -v /export/myapp:/myapp --name inst2 centos
[root@988151662ef1 /]# cat /myapp/hello 
world
[root@988151662ef1 /]# 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can shut down both containers, and they&amp;rsquo;ll be destroyed (because of the
&lt;code&gt;--rm&lt;/code&gt; flag) and the data will persist on the host&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[root@cd0c4a2b0055 /]# exit
tty1$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
tty1$ ls /export/myapp/
hello
tty1$ docker run --rm -it -v /export/myapp:/myapp --name inst3 centos
[root@7ed3b5e955f6 /]# cat /myapp/hello 
world
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So here&amp;rsquo;s an easy way of persisting data in a manner that developers are
already used to.&lt;/p&gt;

&lt;h4 id=&#34;it-s-not-that-easy&#34;&gt;It&amp;rsquo;s not that easy&lt;/h4&gt;

&lt;p&gt;There are a number of problems with this model.  First and most important
is data security.  Because the data is present on the host then anyone with
access to the host might be able to read this data.  This is why I&amp;rsquo;ve
recommended that production container servers should treat the parent OS
with high access restrictions; as restrictive as your hypervisors in a
traditional VM.&lt;/p&gt;

&lt;p&gt;There may be problems with &lt;code&gt;SELinux&lt;/code&gt; or other labelling systems; the
directory created didn&amp;rsquo;t have any of the right labels so if the OS
was set to &lt;em&gt;enforcing&lt;/em&gt; mode then access to this directory may be rejected
(indeed I had to do a &lt;code&gt;setenforce 0&lt;/code&gt; for these tests).&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ve only looked at a single host; in a real world environment your app
may spin up and down across dozens of different servers.  So you may need
your persistent datastore to be coming from an NFS server or similar.
You might just &lt;code&gt;mount&lt;/code&gt; that at the host level.  Docker also allows for
different &lt;em&gt;backends&lt;/em&gt; to be used with the &lt;code&gt;-v&lt;/code&gt; flag; it can talk directly
to an NFS server, for example.  That&amp;rsquo;s pretty powerful!&lt;/p&gt;

&lt;p&gt;At lot of this docker functionality is documented in a &lt;a href=&#34;https://docs.docker.com/engine/tutorials/dockervolumes/&#34;&gt;tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You also need your &lt;em&gt;orchestration&lt;/em&gt; tool to be able to support this
configuration and start up your containers with the right flags.
Mesos, for example, supports &lt;a href=&#34;http://mesos.apache.org/documentation/latest/persistent-volume/&#34;&gt;persistent volumes&lt;/a&gt;; Kubernettes supports &lt;a href=&#34;http://kubernetes.io/docs/user-guide/volumes/&#34;&gt;similar&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&#34;beyond-docker&#34;&gt;Beyond docker&lt;/h4&gt;

&lt;p&gt;There&amp;rsquo;s nothing that says this has to be docker only; for example, if you use
&lt;code&gt;systemd-nspawn&lt;/code&gt; to manage your containers then there is a &lt;a href=&#34;https://www.freedesktop.org/software/systemd/man/systemd-nspawn.html#--bind=&#34;&gt;&lt;code&gt;--bind&lt;/code&gt;&lt;/a&gt; option
to do similar stuff.&lt;/p&gt;

&lt;p&gt;Even Amazon are in this game with &lt;a href=&#34;https://aws.amazon.com/efs/&#34;&gt;Elastic File System&lt;/a&gt; which presents your storage as an NFSv4.1 accessible filesystem that
you can &lt;code&gt;mount&lt;/code&gt; onto your EC2 server.  This means you can take the persistency
out of your AMI and put it into EFS; the result is something very similar
to the docker examples earlier.&lt;/p&gt;

&lt;h4 id=&#34;summary&#34;&gt;Summary&lt;/h4&gt;

&lt;p&gt;We don&amp;rsquo;t &lt;em&gt;have&lt;/em&gt; to use storage tools such as S3 to keep to a 12 factor
design.  It&amp;rsquo;s perfectly possible to keep your standard filesystem semantics
and keep your application layer immutable and all the rest of the goodness.&lt;/p&gt;

&lt;p&gt;This can even make operations &lt;em&gt;easier&lt;/em&gt;; that same persistent volume could
be shared &lt;em&gt;read-only&lt;/em&gt; with an &amp;ldquo;operations application&amp;rdquo;; your operate
team can read the logs, analysis performance statistics on demand (only
spin up that app when needed) without needing to access the production
application container.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Man in the middle attacks</title>
      <link>https://www.sweharris.org/post/2016-07-16-mitm/</link>
      <pubDate>Sat, 16 Jul 2016 11:26:56 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-07-16-mitm/</guid>
      <description>

&lt;p&gt;A fair number of security advisories mention &lt;em&gt;Man In The Middle&lt;/em&gt; (MITM)
attacks.  It&amp;rsquo;s quite an evocative phrase, but it&amp;rsquo;s a phrase meant
mainly for the infosec community; it doesn&amp;rsquo;t help your typical end user
understand the risks.&lt;/p&gt;

&lt;h4 id=&#34;so-what-is-a-mitm-attack-and-how-can-i-avoid-becoming-a-victim&#34;&gt;So what is a MITM attack, and how can I avoid becoming a victim?&lt;/h4&gt;

&lt;p&gt;Before we get into &lt;em&gt;technology&lt;/em&gt; let&amp;rsquo;s look at something we all know
about; the boring snail mail postal system.  You write a letter,
stick it in an envelope, drop it in a postbox and then sometime later
it appears at the recipients house.&lt;/p&gt;

&lt;p&gt;In that travel many people may touch the letter; the postman who
takes it out of the postbox; all the people at the local post office
who sort it into local delivery or forward it to the regional hub; the
sorters at the regional hub and many other hubs, to the recipient&amp;rsquo;s
local post office.  If you send a postcard then &lt;em&gt;anyone&lt;/em&gt; at these
places could read your words, or even change them.  All of these
people are potential MITM attackers; they sit in between you and your
recipient and can do nasty things.&lt;/p&gt;

&lt;p&gt;So we put stuff inside envelopes and hope no one steams open the envelope
and reseals it afterwards.  This isn&amp;rsquo;t even a new problem, and is one
reason why [Wax seals](&lt;a href=&#34;https://en.wikipedia.org/wiki/Seal_(emblem%29&#34;&gt;https://en.wikipedia.org/wiki/Seal_(emblem%29&lt;/a&gt;)
were popular to provide evidence of tampering.&lt;/p&gt;

&lt;h4 id=&#34;so-what-does-this-have-to-do-with-the-internet-and-technology&#34;&gt;So what does this have to do with the internet and technology?&lt;/h4&gt;

&lt;p&gt;When you talk to a webserver the data you send travels somewhat like
your traditional letter.  It goes from your PC to your local router,
from there to your ISPs router, then across various other routers to
the webserver&amp;rsquo;s local gateway and then to the server.  At each point
the traffic could be snooped upon or modified.  Even worse there are
effectively &lt;em&gt;invisible&lt;/em&gt; points in between (switches, hubs, bridges etc)
where traffic can also be spied upon.&lt;/p&gt;

&lt;p&gt;Now in reality the majority of this &amp;ldquo;backbone&amp;rdquo; is pretty
secure.  Major ISPs, just like your post office, really try hard
to stop traffic from being stolen.  But just like &lt;a href=&#34;http://www.latimes.com/local/lanow/la-me-ln-postal-worker-credit-card-stolen-20160705-snap-story.html&#34;&gt;postal workers have
stolen&lt;/a&gt;,
it is possible for this backbone infrastructure to be compromised;
&lt;a href=&#34;http://serverfault.com/questions/152921/mitm-attacks-how-likely-are-they/153065#153065&#34;&gt;even from the outside&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Slightly annoyingly, some ISPs deliberately MITM consumer connections to
&lt;a href=&#34;http://webpolicy.org/2015/08/25/att-hotspots-now-with-advertising-injection/&#34;&gt;insert adverts&lt;/a&gt;
into the browser; Verizon have
&lt;a href=&#34;https://www.eff.org/deeplinks/2014/11/verizon-x-uidh&#34;&gt;added tracking cookies&lt;/a&gt;
on their mobile network.&lt;/p&gt;

&lt;p&gt;Depending on where you are, ISP level MITM attacks may not be a great
risk.  (At least if you ignore FBI, NSA et al!).  But some places
may be more risky; China and North Korea can be pretty much guaranteed
to be MITMing traffic.&lt;/p&gt;

&lt;p&gt;But if this was the only problem then a MITM attack wouldn&amp;rsquo;t be big news.
Fortunately the solution to the bigger risk can also help here.&lt;/p&gt;

&lt;h4 id=&#34;a-bigger-risk&#34;&gt;A bigger risk&lt;/h4&gt;

&lt;p&gt;The greater risk is closer to you; how &lt;em&gt;you&lt;/em&gt; connect to the network.&lt;/p&gt;

&lt;p&gt;Are you connecting from an office?  If so then you are likely to be connected
to a switch, rather than directly to a router.  In the old days this would
have been a hub and every one of your co-workers on the same hub could see
your traffic.  With a switch it&amp;rsquo;s harder for them to see it&amp;hellip; but some
switches can forced to drop back to hub mode.  Or your co-worker could
send &lt;em&gt;proxy ARP&lt;/em&gt; requests to make your machine think they are the
default gateway server.  Or even tamper with the wiring!&lt;/p&gt;

&lt;p&gt;Do you have to go via a proxy server to reach the internet?  That proxy
can see your traffic and so any admin on that machine could see it.&lt;/p&gt;

&lt;p&gt;Are you at home sharing your network with flatmates?  They might be able
to see your traffic.&lt;/p&gt;

&lt;p&gt;The traffic between your router and your ISP is probably secure (e.g
encrypted by DOCSIS cable modem standards, or via dedicated lines),
but is your router or cable modem secure?  A lot of home routers
have security holes or backdoors, even as simple as having a &lt;a href=&#34;http://websec.ca/advisories/view/Huawei-web-backdoor-and-remote-access&#34;&gt;default
admin password and the admin user interface being exposed to the
internet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The server you talk to also have some of these endpoint risks&amp;hellip; but
major players (Google, Microsoft, Twitter, Facebook, etc etc) work hard
to ensure their links to the ISP are secure.  Small self-hosted websites
(this one!) may be at risk (do I trust &lt;a href=&#34;https://www.linode.com&#34;&gt;linode&lt;/a&gt;
or &lt;a href=&#34;https://www.panix.com&#34;&gt;Panix&lt;/a&gt; to not break my traffic?)&lt;/p&gt;

&lt;p&gt;Then there&amp;rsquo;s the really big risk case&amp;hellip; &lt;em&gt;free public wifi&lt;/em&gt;.  You might
think that it&amp;rsquo;s nice to be able to go Starbucks and use their WiFi.
But &lt;em&gt;are&lt;/em&gt; you using their WiFi?  Or someone else&amp;rsquo;s WiFi that pretends
to be the Starbucks access point?&lt;/p&gt;

&lt;p&gt;This WiFi risk is, in my opinion, the greatest of the MITM attack vectors.
You can be sitting, sipping your coffee, and having all your internet
traffic being inspected.  Passwords you type in might be taken.  And
all this is automatic.  It doesn&amp;rsquo;t require &amp;ldquo;l33t hax0r sk1llz&amp;rdquo;; you
won&amp;rsquo;t see a dingy drugged out looking guy furiously typing on his keyboard;
it&amp;rsquo;s invisible.&lt;/p&gt;

&lt;h4 id=&#34;so-how-do-i-defend-myself&#34;&gt;So how do I defend myself?&lt;/h4&gt;

&lt;p&gt;Ensure your router is secure; disable any external admin interfaces,
change default passwords, apply the latest firmware.&lt;/p&gt;

&lt;p&gt;Encrypt your traffic where possible.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If you go to a web site, get into the habit of typing &lt;code&gt;https://&lt;/code&gt; in front
of the URL.  Perhaps consider a tool such as &lt;a href=&#34;https://www.eff.org/Https-everywhere&#34;&gt;HTTPS Everywhere&lt;/a&gt; to help with this.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;If you have configured your mail client to connect via IMAP or POP then
make sure the &lt;em&gt;use encryption&lt;/em&gt; options are ticked.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;If you use a chat application then turn on encryption  (ideally full
&lt;em&gt;end to end&lt;/em&gt; encryption, if supported, but even encryption between you
and the chat server is better than no encryption).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not let your machine connect to public WiFi points automatically; yes,
it&amp;rsquo;s nice to say &amp;ldquo;automatically connect to Starbucks&amp;rdquo;
but this allows people to create a fake Starbucks access point &lt;em&gt;anywhere&lt;/em&gt;
and your phone may connect to it, even while still in your pocket, and
any unencrypted communication may be stolen&amp;hellip; even when you&amp;rsquo;re nowhere
near a Starbucks!&lt;/p&gt;

&lt;p&gt;If you can, consider using a VPN.  This can automatically encrypt all
your traffic.  Even with &lt;code&gt;https&lt;/code&gt; and encrypted connections a MITM attacker
may still be able to learn &lt;em&gt;some&lt;/em&gt; information (e.g. you did a DNS lookup
of &lt;code&gt;www.myexamplebank.com&lt;/code&gt;; it&amp;rsquo;s possible that&amp;rsquo;s who you bank with!).
A VPN can hide even this information.&lt;/p&gt;

&lt;p&gt;Use a unique password for every site; even if you&amp;rsquo;ve tried hard to protect
against MITM attacks &lt;em&gt;some&lt;/em&gt; information may leak out.  If someone manages
to steal your Facebook password then they can&amp;rsquo;t use it to login to your
bank.   A password manager like &lt;a href=&#34;https://1password.com/&#34;&gt;1Password&lt;/a&gt; can
help here by generating complicated unique passwords.   (This is a good
thing to do anyway for more than just MITM reasons!).  Personally, I
use &lt;a href=&#34;http://keepass.info/&#34;&gt;KeePass&lt;/a&gt; in its various forms.&lt;/p&gt;

&lt;h4 id=&#34;anything-else&#34;&gt;Anything else?&lt;/h4&gt;

&lt;p&gt;I&amp;rsquo;m sure I&amp;rsquo;ve missed out some other ways MITM attacks can happen, and
ways we can defend ourselves.  Please drop me a comment if you have
any advice that can be added!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>There&#39;s a hole in my security bucket</title>
      <link>https://www.sweharris.org/post/2016-07-07-bucket/</link>
      <pubDate>Thu, 07 Jul 2016 12:05:45 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-07-07-bucket/</guid>
      <description>&lt;p&gt;In my spare time I&amp;rsquo;ve been playing on &lt;a href=&#34;http://unix.stackexchange.com/questions&#34;&gt;Unix
StackExchange&lt;/a&gt;.
And I&amp;rsquo;ve found the old song &lt;a href=&#34;https://en.wikipedia.org/wiki/There%27s_a_Hole_in_My_Bucket&#34;&gt;There&amp;rsquo;s a Hole In My
Bucket&lt;/a&gt;
going through my head.  It&amp;rsquo;s a conversation between Henry and Liza;
Henry has a problem and is asking Liza for help.&lt;/p&gt;

&lt;p&gt;In summary:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;H: There&#39;s a hole in my bucket
  L: Mend it!
H: How?
  L: With straw.
H: But it&#39;s too long
  L: So cut it
H: How?
  L: With an axe
H: But the axe is blunt
  L: Sharpen it
H: How?
  L: With a stone
H: The stone is dry
  L: So make it wet
H: How?
  L: With water
H: How do I get the water?
  L: In a bucket
H: But there&#39;s a hole in my bucket
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As problem solvers we&amp;rsquo;re typically in the Liza role.  Someone comes to
us with a problem that &lt;em&gt;seems&lt;/em&gt; simple (you have a hole in your bucket?
Well, fix it!).  And it seems frustrating to have to go through really
basic remediation steps (surely you know how to cut straw!) and it&amp;rsquo;s only
10 times around this loop that you start to learn what the real problem
is.&lt;/p&gt;

&lt;p&gt;This can be even more frustrating if the communication is high latency
(e.g. the other person is in a different timezone, such as between
New York and Singapore; each part of the conversation could take a
whole day!).  What should be a simple problem now takes a
week to solve.&lt;/p&gt;

&lt;p&gt;In an attempt to solve this you write detailed documentation; you try
to foresee all possible failure modes and write them down, create a
decision tree with steps to follow.  And thus begins the disconnect
between &amp;ldquo;engineering&amp;rdquo; and &amp;ldquo;operations&amp;rdquo;.  If this goes too far then the
ops teams will refuse to support stuff that isn&amp;rsquo;t fully documented,
leading to 100 page handover docs.  Ops turn into deskilled button pushers.&lt;/p&gt;

&lt;p&gt;This can now lead to security problems; the operations teams
don&amp;rsquo;t fully understand what they are doing, make the wrong choices,
take a path of the decision tree that &lt;em&gt;almost&lt;/em&gt; but not quite matches
their problem and so implement the wrong solution (they put the straw
in the bucket at an angle so it doesn&amp;rsquo;t fill the hole properly; water
leaks out).&lt;/p&gt;

&lt;p&gt;(This is one reason why &amp;ldquo;reliability engineering&amp;rdquo; is becoming popular; an
attempt to reverse the trend.  Take the button pushing out of the ops
role, re-skill the role to the level it &lt;em&gt;should&lt;/em&gt; be).&lt;/p&gt;

&lt;p&gt;As problem solvers we need to listen and engage more with our operations
teams; we need to remove barriers between teams.  This isn&amp;rsquo;t necessarily
a &amp;ldquo;devops&amp;rdquo; model (in some cases there are regulatory separation of duties
requirements that prevent this), but higher bandwidth communication
channels, co-located engineering/operations teams, shared responsibility
for problems and so on.  Encourage a collegiate atmosphere between the
teams, rather than an adversarial one which can form when barriers are
created (finger pointing between ops and engineering is a common
failure mode).&lt;/p&gt;

&lt;p&gt;Now we can make sure the right solution is applied to the problem, and
the security hole isn&amp;rsquo;t opened&amp;hellip; hopefully!&lt;/p&gt;

&lt;p&gt;Next up: how you are the security Itsy Bitsy Spider trying to climb the
drain pipe of security and the rain drops are the attackers washing away your
work.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>See me present!</title>
      <link>https://www.sweharris.org/post/2016-07-01-cloudexpo/</link>
      <pubDate>Fri, 01 Jul 2016 16:05:48 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-07-01-cloudexpo/</guid>
      <description>&lt;p&gt;Sesh Murthy from &lt;a href=&#34;http://www.cloudraxak&#34;&gt;Cloud Raxak&lt;/a&gt; asked me to
co-present at Cloud Expo NY June 2016.  I&amp;rsquo;ve never done such a thing
before, so this was a big deal for me.&lt;/p&gt;

&lt;p&gt;I put together a &lt;a href=&#34;https://www.sweharris.org/post/2016-06-13-cloudexpo&#34;&gt;base presentation&lt;/a&gt; that Sesh
modified.&lt;/p&gt;

&lt;p&gt;The video of this is now on YouTube.  My part starts at 8m30, and there
was a little Q/A at the end (31m35).&lt;/p&gt;

&lt;p&gt;&amp;ldquo;Enjoy&amp;rdquo; watching me do my &lt;a href=&#34;https://www.youtube.com/watch?v=NY7K51x-laQ#t=8m30s&#34;&gt;first ever public talk&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m a little embarrased&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Container Identity</title>
      <link>https://www.sweharris.org/post/2016-06-27-container-identity/</link>
      <pubDate>Mon, 27 Jun 2016 12:06:21 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-06-27-container-identity/</guid>
      <description>

&lt;p&gt;Containers and other elastic compute structures are good ways of deploying
applications, especially if you follow some of the guidelines I&amp;rsquo;ve made in
other posts on this topic.  However they don&amp;rsquo;t exist in a vacuum.  They
may need to call out to &amp;ldquo;external&amp;rdquo; services.  For example, an Oracle
database, or Amazon S3, or another API service provided by other containers.
In order to do this it needs to &lt;em&gt;authenticate&lt;/em&gt; to that service.  That
typically means requiring some form of authenticator (e.g
a username and password, or a userkey and secret key).&lt;/p&gt;

&lt;p&gt;Now in a traditional non-elastic environment this can be done at application
deploy time; an operate person can login to the server and supply the
necessary credentials.  If you&amp;rsquo;re more advanced then you might use a
password vault (e.g. &lt;a href=&#34;https://www.cyberark.com&#34;&gt;CyberArk&lt;/a&gt;).  These work
because the operating environment is pretty static.  In the case of CyberArk
they require an agent to be installed on the client machine, registered,
and authorised to the vault.  Clearly neither &amp;ldquo;ops supplying credentials&amp;rdquo;
nor &amp;ldquo;register agent&amp;rdquo; type solutions are very elastic friendly!  So we
need a different solution.&lt;/p&gt;

&lt;p&gt;If you look around there are various products that try to solve this; a
common one is &lt;a href=&#34;https://www.vaultproject.io&#34;&gt;Hashicorp Vault&lt;/a&gt;.  This has some
clever routines built into it, and was clearly built with an API-first
model in mind.  One clever feature is that it can &lt;em&gt;create&lt;/em&gt; time-limited
credentials, so if your app needs to login to MySQL then it can ask
HashiVault for a username/password, the vault will create them in the
database at that point in time, then delete them later.  Clever!&lt;/p&gt;

&lt;p&gt;Unfortunately it doesn&amp;rsquo;t address the question of how your application
authenticates to the vault in the first place.  We haven&amp;rsquo;t really solved
the problem with this technology; we&amp;rsquo;ve just rewritten it.&lt;/p&gt;

&lt;p&gt;Another solution I&amp;rsquo;ve heard a few places attempt is kerberos based
authentication; however this doesn&amp;rsquo;t really solve the problem, either.
How does your application get the initial TGT to be able to get the
service keys it needs?  If you use a keytab file, how does that get into
the app?  No, including that in your app source tree is not a suitable
solution :-)&lt;/p&gt;

&lt;p&gt;So what can we use as an identity anchor?  When your app spins up and
migrates around containers, when the network itself may be NAT&amp;rsquo;ed,
when the contents of containers may vary as applications are upgraded&amp;hellip;
what can we use to anchor the identity so your application can authenticate
to other services?&lt;/p&gt;

&lt;h2 id=&#34;viewpoints&#34;&gt;Viewpoints&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve found three ways of looking at this problem.&lt;/p&gt;

&lt;h4 id=&#34;seed-credential&#34;&gt;Seed credential&lt;/h4&gt;

&lt;p&gt;This the most obvious version; This may be your keytab file; if this can
be provided securely to the app then the application can now authenticate
to the Kerberos infrastructure and carry on.  It may be an authentication
token to a vault (eg HashiVault) from where it can then get the necessary
credentials necessary for further services.  How this is done will be
technology specific.  With something like docker you may be able to
provide a persistent backend data store with that credential and this
can be shared between the containers running the application.  Not all
container engines have this persistency layer so other solutions may be
required.&lt;/p&gt;

&lt;h4 id=&#34;provided-by-the-runtime-environment&#34;&gt;Provided by the runtime environment&lt;/h4&gt;

&lt;p&gt;This is the solution provided by &lt;a href=&#34;https://www.cloudfoundry.org&#34;&gt;Cloud
Foundry&lt;/a&gt;.  With this information can be
stored inside the &amp;ldquo;cloud controller&amp;rdquo; and passed onto the application
in the &lt;code&gt;VCAP_SERVICES&lt;/code&gt; variable.  It&amp;rsquo;s all handled by the orchestration
engine.  Unfortunately the CF solution stores all this data in plain text
and passes it in environment variables.  The concept seems reasonable
but the implementation is weak.  Of course the values provided here may
be the actual credentials needed, or a seed credential for vault access.&lt;/p&gt;

&lt;h4 id=&#34;have-a-trusted-identity-assertion&#34;&gt;Have a trusted identity assertion&lt;/h4&gt;

&lt;p&gt;Can we identify the app based on the execution environment?  Perhaps the
orchestration layer could generate a &amp;ldquo;signed identity&amp;rdquo; (perhaps a
client side SSL cert) and supply that to the app when it is instantiated.
This could be used as a seed credential.   Or maybe we can run a daemon
process in the parent OS that the client can call out to; we can make
use of the orchestration knowledge (e.g. the state maintained by &lt;code&gt;docker&lt;/code&gt;,
or a Cloud Foundry DEA configuration file) to identify the calling app;
effectively this daemon would assert identity on behalf of the app.&lt;/p&gt;

&lt;h2 id=&#34;putting-it-together&#34;&gt;Putting it together&lt;/h2&gt;

&lt;p&gt;These three viewpoints can overlap; for example the identity assertion
tool could talk to a backend datastore that can provide &lt;em&gt;encryption keys&lt;/em&gt;
(eg an RSA key).  The public key could be exposed to the world and so
the contents that cloud foundry normally stores in &lt;code&gt;VCAP_SERVICES&lt;/code&gt; can
be encrypted; the identity assertion process would ensure that only
application A could get RSA keys for itself and not for any other app.
The credential then decrypted could provide access to a vault.&lt;/p&gt;

&lt;p&gt;Of course there are implementation challenges in all these options; if
you create an encryption store then how do you ensure that the keys
remain secret, or have the ability to rotate keys?  If you provide a
persistent backend store then how do you ensure the contents won&amp;rsquo;t be
exposed elsewhere?  If you use a CF type solution then how do you
solve the plain-text problem?&lt;/p&gt;

&lt;p&gt;At the end of the day your orchestration layer becomes a critical component
in allowing an application to assert identity.  The solution you build
needs to be resilient, reliable and strongly protected.  Of course this
should apply to the whole orchestration layer, anyway!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Network Microsegmentation</title>
      <link>https://www.sweharris.org/post/2016-06-20-microsegmentation/</link>
      <pubDate>Mon, 20 Jun 2016 13:12:42 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-06-20-microsegmentation/</guid>
      <description>

&lt;p&gt;A major problem many environments have is a lack of real network
control inside the perimeter.  They may have large hard border controls
(multi-tier DMZs; proxy gateways; no routing between tiers), but once
inside traffic is unconstrained.  This is sometimes jokingly referred
to as &amp;ldquo;hard shell soft center&amp;rdquo; network design.&lt;/p&gt;

&lt;p&gt;If you&amp;rsquo;re lucky then your prod/dev/qa environments may be segmented.
More likely there&amp;rsquo;s no restriction at all; dev programs may accidentally
talk to a prod database.  Oops!&lt;/p&gt;

&lt;p&gt;And, of course, this &amp;ldquo;open network&amp;rdquo; enables an attacker who manages
to gain entry to the network the ability to pivot and attack other
unrelated servers.&lt;/p&gt;

&lt;p&gt;The question to ask is whether we can control things at a deeper layer.
Can we determine what applications need to talk to each other?  In a
microservices model, can we control which &lt;em&gt;service&lt;/em&gt; each application
component needs to talk to?&lt;/p&gt;

&lt;p&gt;In our existing environments this is hard to do; things have grown
haphazardly and we have no real visibility around where our &amp;ldquo;command and
control&amp;rdquo; (C2) servers are; your vuln scanning tool, your backup servers,
your CMDB collection tool, your automation tool&amp;hellip; these servers may
not have been placed in any consistent location and mapping out the
connections at scale is not easy.&lt;/p&gt;

&lt;p&gt;At best we might be able to restrict &amp;ldquo;consumer banking&amp;rdquo; servers from
interacting with &amp;ldquo;investment banking&amp;rdquo; servers; restrict the ATM network
from seeing the HR servers&amp;hellip;  a form of &amp;ldquo;macro segmentation&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;In the new &amp;ldquo;cloudy&amp;rdquo; world, however, we get a chance at revisiting this.
I&amp;rsquo;ve previously written about automation of application instantiation;
hands off deployment of servers, containers, applications.  We can
take this further and do hands off deployment of &lt;em&gt;networking&lt;/em&gt; as well.
&amp;ldquo;Software defined networking&amp;rdquo; allows us to build and modify network
constructs in a programmatic automated manner.  We can build logical
constructs for different applications, for services, and define rules for
communication between these constructs.  We can associate these rules
with the app deployment so that routing, packet filters (eg iptables)
and the like can be updated as part of application orchestration.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Egress&lt;/em&gt; rules can also be applied; your app configuration indicates
what services it needs to talk to.  Your orchestration layer can build
out egress iptable rules &lt;em&gt;outside&lt;/em&gt; the container (nothing that happens
inside the container can change this), and a set of logging rules can
be set up so that bad traffic is trapped and reported on.&lt;/p&gt;

&lt;p&gt;These logs can be sent to your
&lt;a href=&#34;https://en.wikipedia.org/wiki/Security_information_and_event_management&#34;&gt;SIEM&lt;/a&gt;
system and monitored the same as any other security log.  If you now
see an application container start to make a lot of port 22 connection
attempts then you know something has gone wrong and you can take action
(e.g. shutdown the container or track back where the attack came from;
analyse the attack vector and fix the code).  Of course the rules will
have prevented pivoting, but now you also get a deep level of visibility
of what is happening &lt;em&gt;inside&lt;/em&gt; your network, not just at the border.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Tools are still developing in this space; there are networking vendors
that can handle routing via BGP configurations (your app joins a BGP
group and the centralised rules determine what services are visible),
combined with kernel iptable/ipset rules configured via the BGP rules.
Some of these are drop-in replacements in the OpenStack setup and extends
the &amp;ldquo;security group&amp;rdquo; construct.&lt;/p&gt;

&lt;p&gt;The Cloud Foundry PaaS also has security groups associated with
applications that configure egress rules per application component.&lt;/p&gt;

&lt;p&gt;If you use Amazon then you can configure &amp;ldquo;virtual private clouds&amp;rdquo; and
segment networks.&lt;/p&gt;

&lt;p&gt;There are multiple ways of doing network segmentation, but taking
advantage of application redesign and new automation that needs to be
built out to handle a cloudy environment means we can avoid mistakes
of the past; increase security in a practical and controlled manner;
limit exposure when (not if, &lt;em&gt;when&lt;/em&gt;) an attacker gets in; gain greater
visibility of your network setup.&lt;/p&gt;

&lt;p&gt;Add in something like &lt;a href=&#34;http://www.networkworld.com/article/2922061/cisco-subnet/google-network-security-sans-perimeter.html&#34;&gt;Google&amp;rsquo;s
BeyondCorp&lt;/a&gt;
perimeterless network design to handle the physical layer and we&amp;rsquo;ve gone
a long way!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Using Containers Securely in Production</title>
      <link>https://www.sweharris.org/post/2016-06-13-cloudexpo/</link>
      <pubDate>Mon, 13 Jun 2016 19:38:31 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-06-13-cloudexpo/</guid>
      <description>

&lt;p&gt;This is the content of a presentation I put together for Cloud Expo
NY 2016.  The final presentation had a lot of this ripped out and
replaced with stuff from my co-presenter (Sesh Murthy from &lt;a href=&#34;http://www.cloudraxak.com&#34;&gt;Cloud
Raxak&lt;/a&gt;), because he had information he wanted
to present as well and we only had 35 minutes.  The resulting presentation
was, I think, a good hybrid.&lt;/p&gt;

&lt;p&gt;This is the original story I wanted to tell.  You may recognise some of this
content from other blog posts I&amp;rsquo;ve written :-)&lt;/p&gt;

&lt;p&gt;For each section I&amp;rsquo;ve added &lt;em&gt;in italics&lt;/em&gt; my thinking and what sort of thing
I&amp;rsquo;d have talked about.&lt;/p&gt;

&lt;p&gt;I attach the LibreOffice Impress &lt;a href=&#34;https://www.sweharris.org/CloudExpo.odp&#34;&gt;presentation&lt;/a&gt;
for those who want to see the original.&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&#34;what-is-a-container&#34;&gt;What is a container?&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Shared kernel&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Segmented view of resources&lt;/li&gt;
&lt;li&gt;Separate process ID space&lt;/li&gt;
&lt;li&gt;Separate filesystem mount space&lt;/li&gt;
&lt;li&gt;Separate IPC memory segments&lt;/li&gt;
&lt;li&gt;Separate view of the network&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Multi-platform&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Linux VServer (from 2001!)&lt;/li&gt;
&lt;li&gt;OpenVZ&lt;/li&gt;
&lt;li&gt;AIX WPARs&lt;/li&gt;
&lt;li&gt;Solaris ~Containers~ Zones (from Solaris 10, 2005)&lt;/li&gt;
&lt;li&gt;Linux containers (LXC, cgroups, etc)&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Warden&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;The thinking here is that there&amp;rsquo;s a lot of discussion about containers,
but there&amp;rsquo;s different ways of thinking about containers.  I wanted to
focus on the lower technology layer, rather than the packaging, at this point
to show that this type of technology wasn&amp;rsquo;t new.  I&amp;rsquo;d used the VServer
patches in 2001 to create &amp;ldquo;bastion&amp;rdquo; hosts on my firewall.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&#34;container-as-a-vm&#34;&gt;Container as a VM&lt;/h1&gt;

&lt;p&gt;Let&amp;rsquo;s look at the worst case scenario. A container may have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A cut down (maybe!) version of the OS

&lt;ul&gt;
&lt;li&gt;Glibc, bash, web server, support libraries, tools&lt;/li&gt;
&lt;li&gt;Maybe different versions than those running on the host!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Filesystems

&lt;ul&gt;
&lt;li&gt;Private to the container?&lt;/li&gt;
&lt;li&gt;Shared with the host?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Access to the network

&lt;ul&gt;
&lt;li&gt;Bridged to the main network?&lt;/li&gt;
&lt;li&gt;NAT?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Processes that run&lt;/li&gt;
&lt;li&gt;Network listeners&lt;/li&gt;
&lt;li&gt;User logins&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This sounds like a whole operating system to me. The only difference is
the shared kernel.&lt;/p&gt;

&lt;p&gt;So, in the worst case, we need to control this the same as the OS. And
deal with the unique challenges.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I call this &amp;ldquo;the hard way&amp;rdquo;.  You can treat containers like this; indeed
Solaris zones are exactly like this.  But effectively you&amp;rsquo;re creating
a form of &amp;ldquo;virtual machine&amp;rdquo;, and so need to control it that way.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&#34;challenges-with-this-model&#34;&gt;Challenges with this model&lt;/h1&gt;

&lt;table border=1&gt;
&lt;tr&gt;
  &lt;th&gt;&amp;nbsp;&lt;/th&gt;
  &lt;th&gt;Virtual Machine&lt;/th&gt;
  &lt;th&gt;Container&lt;/th&gt;
  &lt;th&gt;New threat&lt;/th&gt;
&lt;/tr&gt;

&lt;tr&gt;
  &lt;td&gt;&#34;Parent Access&#34;&lt;/td&gt;
  &lt;td&gt;Hypervisor attack; one VM may be able to use hypervisor bugs to gain access to another VM&lt;/td&gt;
  &lt;td&gt;Parent OS attack; process may be able to escape the container&lt;/td&gt;
  &lt;td&gt;More people may have access to the host OS than to the Hypervisor; more threat actors.&lt;br&gt;
Shared kernel is bigger than hypervisor; bigger attack surface&lt;br&gt;
Kernel may allow dynamically loaded modules; variable attack surface!&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
  &lt;td&gt;&#34;Shared resources&#34;&lt;/td&gt;
  &lt;td&gt;Rowhammer&lt;br&gt;
Noisy neighbour&lt;br&gt;
Overallocation&lt;br&gt;
...&lt;/td&gt;
  &lt;td&gt;Mostly the same&lt;/td&gt;
  &lt;td&gt;Resource separation is now in the kernel; not as well segregated; not all resources may be segregated&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
  &lt;td&gt;&#34;Unique Code&#34;&lt;/td&gt;
  &lt;td&gt;Each VM may run a different OS, different patch revisions, different software&lt;/td&gt;
  &lt;td&gt;Each container may run different software versions, different patch levels, different libraries&lt;/td&gt;
  &lt;td&gt;Scaling issue; we can run many more containers than VMs&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
  &lt;td&gt;&#34;Inventory management&#34;&lt;/td&gt;
  &lt;td&gt;What machines are out there?  What OS are they running?  Are they patched?  What services are they running?...&lt;/td&gt;
  &lt;td&gt;Mostly the same&lt;/td&gt;
  &lt;td&gt;We typically have strong controls as to who can create new VM&#39;s but we allow anyone to spin up a new container &#39;cos it&#39;s so quick and easy!&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
  &lt;td&gt;&#34;Rogue code&#34;&lt;/td&gt;
  &lt;td&gt;Is the software secure?  Acceptable license terms?  Vulnerability scanned?&lt;/td&gt;
  &lt;td&gt;Mostly the same&lt;/td&gt;
  &lt;td&gt;Anyone can build a container; it may have different versions of core code (eg glibc) than the core OS.  Developers may introduce buggy low-level routines without noticing&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;p&gt;If you are going to use a container as if it&amp;rsquo;s a VM then you need to
apply all your existing VM level controls to the container; you control
VM creation, you&amp;rsquo;re going to need to control container creation to the
same level!  Otherwise you run the risk of &amp;ldquo;Shadow IT&amp;rdquo; with unknown
software and potential vulnerabiltiies (shellshock, heartbleed etc).&lt;/p&gt;

&lt;p&gt;Why are you using containers this way?  Are you just using them as a
packing construct?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I don&amp;rsquo;t like spending a lot of time on this page, but people typically
lean forward and pay attention.  Maybe it&amp;rsquo;s the wall of text that makes
them think there&amp;rsquo;s good content!  The point here is to emphasise &amp;ldquo;the
hard way&amp;rdquo;.  And if you&amp;rsquo;re using containers as a VM technology then you
might want to rethink your approach.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&#34;what-makes-a-container-different&#34;&gt;What makes a container different?&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Very dynamic

&lt;ul&gt;
&lt;li&gt;Harder to track, maintain inventory&lt;/li&gt;
&lt;li&gt;If you don&amp;rsquo;t know what is out there, how can you patch?&lt;/li&gt;
&lt;li&gt;How many containers may suffer shellshock, heartbleed or CVE-2015-7547 (glibc) issues because we don&amp;rsquo;t know where they run?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Technology specific issues

&lt;ul&gt;
&lt;li&gt;Docker daemon running as root?&lt;/li&gt;
&lt;li&gt;SELinux interaction&lt;/li&gt;
&lt;li&gt;Root inside a container may be able to escape (eg via /sys)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Kernel bugs

&lt;ul&gt;
&lt;li&gt;Ensure your parent OS is patched!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What is now highlighted is that the existing solutions may not scale
properly. What works for a 1,000 (or even 10,000) VMs won&amp;rsquo;t work for
100,000 or millions of containers.&lt;/p&gt;

&lt;p&gt;Can your solutions deal with containers spinning up, running for a few
minutes, then shutting down again? Probably not.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This helps distinguish a container from a VM, especially the scaling
factor and dynamic nature&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&#34;the-easy-way&#34;&gt;The Easy way&lt;/h1&gt;

&lt;p&gt;Think of a container as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transient

&lt;ul&gt;
&lt;li&gt;There is no persistent storage&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Short lived

&lt;ul&gt;
&lt;li&gt;Anywhere from microseconds upwards&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Immutable

&lt;ul&gt;
&lt;li&gt;You don&amp;rsquo;t change the running container; you build a new image and deploy that&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Untouchable

&lt;ul&gt;
&lt;li&gt;You NEVER LOG IN!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Automated

&lt;ul&gt;
&lt;li&gt;If you can&amp;rsquo;t login, you better automate the builds&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we can start to focus on what matters; the &lt;em&gt;application&lt;/em&gt;.  Don&amp;rsquo;t allow
people to create containers; have an &amp;ldquo;application delivery platform&amp;rdquo;
that does it for them.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Short lived also means it has a drop-dead date; this may be minutes,
hours, weeks&amp;hellip; Have a chaos monkey do it, or have a risk-based
evaluation.. but a container should die.  They&amp;rsquo;re not persistent.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The &amp;ldquo;immutable&amp;rdquo; and &amp;ldquo;never log in&amp;rdquo; parts of this can be hard to swallow.
It means a change in AppDev processes (closer to 12-factor applications;
it means the app needs to instrument and log stuff better).   But this is
key to elastic compute.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&#34;minimize-attack-surface&#34;&gt;Minimize attack surface&lt;/h1&gt;

&lt;p&gt;Basic hygiene rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Harden the kernel

&lt;ul&gt;
&lt;li&gt;You don&amp;rsquo;t have to use the vendor provided one&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Ensure the OS is patched&lt;/li&gt;
&lt;li&gt;Integrate into your CI/CD process

&lt;ul&gt;
&lt;li&gt;No manual startup of containers&lt;/li&gt;
&lt;li&gt;Only those that passed testing, vuln scanning, etc can be run&lt;/li&gt;
&lt;li&gt;No external code without approval&lt;/li&gt;
&lt;li&gt;Standard code hygiene (provenance, licensing, etc)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Automate, automate, automate!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;A hardened kernel doesn&amp;rsquo;t mean &amp;ldquo;create your own patches&amp;rdquo;.  You can take
a kernel direct from &lt;a href=&#34;http://www.kernel.org&#34;&gt;www.kernel.org&lt;/a&gt; and configure it
with a minimal set of options built in. e.g. turn off dynamically loadable
modules (they open a large attack surface); only add in drivers necessary
for your hardware (easy if you always deploy to a VM platform); don&amp;rsquo;t add
features you don&amp;rsquo;t need.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&#34;container-life-cycle&#34;&gt;Container life cycle&lt;/h1&gt;

&lt;p&gt;The &lt;em&gt;contents&lt;/em&gt; of a container are also important&lt;/p&gt;

&lt;p&gt;In general there are a number steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build good containers

&lt;ul&gt;
&lt;li&gt;Known content, internal repos&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Deploy containers

&lt;ul&gt;
&lt;li&gt;Orchestration layer, autoscaler, track deployments&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Scan existing containers

&lt;ul&gt;
&lt;li&gt;Keep on top of new found bugs&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Replace bad containers

&lt;ul&gt;
&lt;li&gt;Replace stuff known to be broken&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;We&amp;rsquo;ll go through each of these steps in the next few slides&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&#34;build-good-containers&#34;&gt;Build good containers&lt;/h1&gt;

&lt;p&gt;You already know how to do this&amp;hellip; extension of your existing processes!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don&amp;rsquo;t create a whole copy of the OS to put inside the container

&lt;ul&gt;
&lt;li&gt;If you need an OS image then use a common base (the same base as you use for traditional compute?).  Don&amp;rsquo;t have a RedHat base, a Debian base, a Ubuntu base&amp;hellip; stick with one image&lt;/li&gt;
&lt;li&gt;If you use golang, how much do you actually need inside the container?  A few /dev files?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t pull code direct from the internet.

&lt;ul&gt;
&lt;li&gt;npm &amp;ldquo;left pad&amp;rdquo; chaos&lt;/li&gt;
&lt;li&gt;Use internal source repositories&lt;/li&gt;
&lt;li&gt;If using docker repos, use internal ones&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Curate&lt;/em&gt; the content that goes into them&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Code scan

&lt;ul&gt;
&lt;li&gt;Source code scanning&lt;/li&gt;
&lt;li&gt;Binary object scanning&lt;/li&gt;
&lt;li&gt;CVE detection, OWASP best practices&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Automated deployment

&lt;ul&gt;
&lt;li&gt;Final image push to a registry; deployed to dev (automated)&lt;/li&gt;
&lt;li&gt;Promoted to QA/UAT&lt;/li&gt;
&lt;li&gt;Promoted to prod&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Really this is meant to be an extension of current best practice that
people are already using for code creation and deployment, but extended
to handle the container build process.  So don&amp;rsquo;t pull docker images from
a public registry; use your own private one&amp;hellip; in exactly the same way
that you shouldn&amp;rsquo;t pull code live from the internet but have an internal
source repo.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can then start to automate things; e.g. have a Jenkins job that&amp;rsquo;s
triggered from a code checkin that does the code scanning, builds the
image from the internal repos/registries, validates it passes all checks,
pushes into the dev registry.  Consider that image immutable and your
code promotion becomes easier; just promote good images.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&#34;deploy-containers&#34;&gt;Deploy containers&lt;/h1&gt;

&lt;p&gt;Orchestration/Automation needs to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy only containers from registry&lt;/li&gt;
&lt;li&gt;Track which containers are running where

&lt;ul&gt;
&lt;li&gt;Effectively maintain &amp;ldquo;inventory&amp;rdquo; of code running&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Key to deployment at scale&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto scaling&lt;/li&gt;
&lt;li&gt;Auto repair&lt;/li&gt;
&lt;li&gt;Blue/Green deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This is a small slide, but important.  Your orchestration layer (Kubernettes,
Cloud Foundry, Swarm&amp;hellip; whatever you use) needs to be able to track and
report on what images are running, and how those images were built.  We&amp;rsquo;ll
see later why&amp;hellip;&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&#34;scan-existing-containers&#34;&gt;Scan Existing Containers&lt;/h1&gt;

&lt;p&gt;Target state isn&amp;rsquo;t static&lt;/p&gt;

&lt;p&gt;New CVEs found&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Libraries&lt;/li&gt;
&lt;li&gt;Base OS image&lt;/li&gt;
&lt;li&gt;Compiler&lt;/li&gt;
&lt;li&gt;JVM&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep scanning everything in the registry.  When new bug (eg shellshock) found we can identify every bad image&lt;/p&gt;

&lt;p&gt;&lt;em&gt;There&amp;rsquo;s a new OpenSSL bug every other month.  Just because your container
was clean when you built it doesn&amp;rsquo;t mean it&amp;rsquo;ll remain clean.  So we need
to keep scanning these container images in case a new bug is found anywhere
in the application stack.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&#34;replace-bad-containers&#34;&gt;Replace bad containers&lt;/h1&gt;

&lt;p&gt;Your scanning detected a problem&lt;/p&gt;

&lt;p&gt;Your &lt;em&gt;orchestration&lt;/em&gt; layer identifies where these images are running&lt;/p&gt;

&lt;p&gt;Risk based approach&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is where the orchestration layer importance comes in.  It&amp;rsquo;s all fine
and good knowing the &amp;ldquo;myapp&amp;rdquo; image is bad, but if we don&amp;rsquo;t know where it
is running then you can&amp;rsquo;t replace running images.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;How quickly you replace it is up to you; if you have an internet facing
shellshock then you might want to cycle your containers pretty quickly, but
in an internal public-data service may wait until the next container
recycle.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&#34;nothing-new&#34;&gt;Nothing new!&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;You&amp;rsquo;re already doing this for regular compute.&lt;/li&gt;
&lt;li&gt;Right?

&lt;ul&gt;
&lt;li&gt;Right?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Nasty secret&amp;hellip; it&amp;rsquo;s where we want to be, but large organisations take time to pivot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use this to fix existing procedures&lt;/p&gt;

&lt;p&gt;Same solution can work on VMs&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Internal IaaS&lt;/li&gt;
&lt;li&gt;Amazon AWS via AMI images&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;There&amp;rsquo;s nothing really unique about containers, here!  You can build OS
images the same way and build an orchestration layer on top of it and
manage virtual machines the same way!  Have we been managing VMs wrong
for the past 20 years?&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&#34;technology&#34;&gt;Technology&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Nothing here is technology focused

&lt;ul&gt;
&lt;li&gt;Process is the key&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Only need to care about low levels if building your own&lt;/li&gt;
&lt;li&gt;When using docker/Apprenda/CloudFoundry/$XYZZY treat it like any other vendor product

&lt;ul&gt;
&lt;li&gt;Track upstream bugs, patch&lt;/li&gt;
&lt;li&gt;Follow best practices&lt;/li&gt;
&lt;li&gt;1,000s of web pages on &amp;ldquo;how to docker&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Control the environment

&lt;ul&gt;
&lt;li&gt;Automation&lt;/li&gt;
&lt;li&gt;Hands free deployment&lt;/li&gt;
&lt;li&gt;You need to do this, anyway!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;That&amp;rsquo;s why this was sub-titled &amp;ldquo;It&amp;rsquo;s the process that matters, not the technology&amp;rdquo;.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&#34;big-wins&#34;&gt;Big wins&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;How many licenses are you using? You know because your automation tools will tell you what is running&lt;/li&gt;
&lt;li&gt;A CVE has been found; you know what images are vulnerable and where they are running

&lt;ul&gt;
&lt;li&gt;Your image is more lightweight so may not be vulnerable in the first place!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Patching doesn&amp;rsquo;t exist; you just redeploy&lt;/li&gt;
&lt;li&gt;Change management is simpler

&lt;ul&gt;
&lt;li&gt;No need for &amp;ldquo;tripwire&amp;rdquo;; no one can login to change contents&lt;/li&gt;
&lt;li&gt;No need for central IDadmin; no accounts to manage&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Financial regulatory controls become easier

&lt;ul&gt;
&lt;li&gt;But may require educating auditor and regulators on the &amp;ldquo;new world&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Controls end up being pushed to &amp;ldquo;code management&amp;rdquo;

&lt;ul&gt;
&lt;li&gt;Which you need to control, anyway!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And another benefit&amp;hellip; if your app can be delivered this way, you can
also start to deploy VMs this way.  A Linux OS without any form of
login? Let&amp;rsquo;s see someone brute-force ssh bad passwords that way :-)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Teaching regulators and auditors about this new world is going to be
interesting; they&amp;rsquo;re gonna freak out!&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Use the right tools for the job

&lt;ul&gt;
&lt;li&gt;If you want a VM then &lt;em&gt;use&lt;/em&gt; a VM&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;If you treat a container as if it&amp;rsquo;s a VM then you need to control it as if it&amp;rsquo;s a VM

&lt;ul&gt;
&lt;li&gt;Heavy process&lt;/li&gt;
&lt;li&gt;Not always scalable&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Must control containers

&lt;ul&gt;
&lt;li&gt;Avoid Shadow IT&lt;/li&gt;
&lt;li&gt;Must not allow a &amp;ldquo;wild west&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Not all tasks are suitable for containers&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id=&#34;reminder&#34;&gt;Reminder&lt;/h1&gt;

&lt;p&gt;Container security is weaker than VM security; the kernel has a large
surface area to be attacked.&lt;/p&gt;

&lt;p&gt;VM security is weaker than physical machine security; the hypervisor
provides an attack surface&lt;/p&gt;

&lt;p&gt;Network security is weaker than air-gap separation.&lt;/p&gt;

&lt;p&gt;Air-gapped machines are weaker than a server covered in cement and
dropped into the bottom of the ocean.&lt;/p&gt;

&lt;p&gt;Your security stance depends on your needs and risk evaluation. Pick
the technology that is right for you and use it appropriately.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I was told to always end a presentation with a joke&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What made me start thinking about security</title>
      <link>https://www.sweharris.org/post/2016-06-12-what-made-me-security/</link>
      <pubDate>Sun, 12 Jun 2016 13:14:18 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-06-12-what-made-me-security/</guid>
      <description>&lt;p&gt;Back in 1984 I thought I was pretty good at writing programs for my
BBC Micro.  I could write BASIC programs that worked; I was learning
6502 assembler.  I could hack on programs, break copy protection.
I definitely knew more than my teachers.&lt;/p&gt;

&lt;p&gt;But my brother was able to break my code.&lt;/p&gt;

&lt;p&gt;For example, I wrote a simple &amp;ldquo;football&amp;rdquo; program for him.  The idea
was that he&amp;rsquo;d select two teams and the game would simulate a match
and generate some scores.&lt;/p&gt;

&lt;p&gt;The opening screen would present a list of teams and let him select
them.  I thought it would go something like this:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/2016-06-12-expected.jpg&#34; alt=&#34;expected&#34;&gt;
&lt;/div&gt;


&lt;p&gt;What my brother did, to my surprise, was something like this:&lt;/p&gt;


&lt;div class=&#34;pure-u-1&#34;&gt;
  &lt;img class=&#34;pure-img&#34; src=&#34;https://www.sweharris.org/images/2016-06-12-actual.jpg&#34; alt=&#34;actual&#34;&gt;
&lt;/div&gt;


&lt;p&gt;That was a new thought for me; people entering unexpected input!  But a good
lesson to learn at such an early age.  Always validate the input.&lt;/p&gt;

&lt;p&gt;This lesson really came into its own in the early days of the &amp;lsquo;net; a
co-worker was really proud of the CGI program he wrote that would allow
stored files to be displayed.  He was less happy when I passed &lt;code&gt;?file=../../../../../../etc/passwd&lt;/code&gt; as a parameter :-)&lt;/p&gt;

&lt;p&gt;Today a number of these lessons have been formalised into patterns by
organisations such as &lt;a href=&#34;https://www.owasp.org&#34;&gt;OWASP&lt;/a&gt; top ten project.
Obviously, today, threats are so much more advanced than the simple problem
my brother found 30 years ago.  But sometimes just reminding people &amp;ldquo;don&amp;rsquo;t
trust the client to send good data&amp;rdquo; is essential; people can be focused
on making sure they get an A+ SSL rating but then allow SQL injection
attacks through blind trust of supplied input.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Building a small docker container</title>
      <link>https://www.sweharris.org/post/2016-06-04-small-container/</link>
      <pubDate>Sat, 04 Jun 2016 13:45:31 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-06-04-small-container/</guid>
      <description>

&lt;p&gt;In previous posts I&amp;rsquo;ve written about small containers; don&amp;rsquo;t bundle a
whole OS image with your app, just have the minimum necessary files and
support.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&#34;https://www.golang.org&#34;&gt;Go&lt;/a&gt; language makes it easy to build a static
executable, so let&amp;rsquo;s use this for an example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cat hello.go
package main

import &amp;quot;fmt&amp;quot;

func main() {
  fmt.Println(&amp;quot;Hello, World&amp;quot;)
}
$ go build hello.go
$ strip hello
$ ls -l hello
-rwxr-xr-x. 1 sweh sweh 1365448 Jun  4 13:48 hello*
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can use this as the basis of a docker container (I&amp;rsquo;m using &amp;ldquo;docker&amp;rdquo;
here because it&amp;rsquo;s a very common technology that&amp;rsquo;s used by lots of people):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cat Dockerfile                 
FROM scratch
COPY hello /
CMD [&amp;quot;/hello&amp;quot;]

$ sudo docker build -t hello:go .
Sending build context to Docker daemon 1.369 MB
Step 1 : FROM scratch
 ---&amp;gt; 
Step 2 : COPY hello /
 ---&amp;gt; 921eb0866d50
Removing intermediate container e518d193b269
Step 3 : CMD /hello
 ---&amp;gt; Running in 0080bf495dd0
 ---&amp;gt; 0480444b8e0a
Removing intermediate container 0080bf495dd0
Successfully built 0480444b8e0a

$ sudo docker run --rm -t hello:go 
Hello, World

$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
hello               go                  0480444b8e0a        58 seconds ago      1.365 MB
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;rsquo;s a nice small container!  Let&amp;rsquo;s see what it consists of&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ mkdir EXTRACT         
$ cd EXTRACT
$ sudo docker save 0480444b8e0a | tar xf -
$ for a in */layer.tar
do
tar tvf $a
done
-rwxr-xr-x 0/0         1365448 2016-06-04 13:48 hello
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So the whole container image contains just one file.&lt;/p&gt;

&lt;p&gt;Compare that to a more traditional container built with a Debian base:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cat Dockerfile                  
FROM debian:jessie
COPY hello /
CMD [&amp;quot;/hello&amp;quot;]
$ sudo docker build -t hello2:go .
Sending build context to Docker daemon  1.37 MB
Step 1 : FROM debian:jessie
Trying to pull repository docker.io/library/debian ... jessie: Pulling from library/debian
23286f48d129: Pull complete 
7a4c9a4d5e7a: Pull complete 
Digest: sha256:2ca1d757fce75accad6ff84339c3327c7aa96ad6e7b7d6fdde22b2a537fac703
Status: Downloaded newer image for docker.io/debian:jessie

 ---&amp;gt; 7a4c9a4d5e7a
Step 2 : COPY hello /
 ---&amp;gt; 53afe819cb68
Removing intermediate container b502f926d128
Step 3 : CMD /hello
 ---&amp;gt; Running in 47c55d108c18
 ---&amp;gt; 047bf1fe5c58
Removing intermediate container 47c55d108c18
Successfully built 047bf1fe5c58
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yikes, we&amp;rsquo;ve just pulled in external content.  That&amp;rsquo;s a &amp;ldquo;no no&amp;rdquo; from a
controls perspective.&lt;/p&gt;

&lt;p&gt;The container is now a lot bigger:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
hello2              go                  047bf1fe5c58        About a minute ago   126.4 MB
docker.io/debian    jessie              7a4c9a4d5e7a        11 days ago          125.1 MB

$ mkdir EXTRACT 
$ cd EXTRACT
$ sudo docker save 047bf1fe5c58 | tar xf -
$ for a in */layer.tar
&amp;gt; do
&amp;gt; tar tf $a
&amp;gt; done | wc -l
8249
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;8,249 files are now present in this container!  That&amp;rsquo;s a larger footprint
for an attacker to exploit; if an RCE is found in your &amp;lsquo;hello&amp;rsquo; app then
they now have a full shell environment to exploit.  It&amp;rsquo;s also more
complicated to patch and manage; if a bug is found in the underlying
&amp;lsquo;jessie&amp;rsquo; image then that needs updating &lt;em&gt;and&lt;/em&gt; any image that depends on
it needs to be restarted, as well.&lt;/p&gt;

&lt;p&gt;A PaaS such as &lt;a href=&#34;https://www.cloudfoundry.org&#34;&gt;Cloud Foundry&lt;/a&gt; tries to
make the layering a bit more invisible; the underlying &amp;ldquo;OS image&amp;rdquo; is
part of a &lt;em&gt;stem cell&lt;/em&gt;.  Your application and dependencies are part of
a &lt;em&gt;droplet&lt;/em&gt; and are created using &lt;em&gt;buildpacks&lt;/em&gt;.  In some ways this makes
it easier to manage; the team managing cloud foundry can update/replace
the stem cells and your app shouldn&amp;rsquo;t notice; it just gets restarted
with the new stem cell.  However it does mean there&amp;rsquo;s a full OS image
hiding inside the container, which could be used by an attacker.&lt;/p&gt;

&lt;h4 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;Now, admittedly this is a simple case; no networking, no web listener,
no additional content.  But we can see how simple it is to build a
container with no hidden &amp;ldquo;layered&amp;rdquo; dependencies.  You need to spend
more time working out your minimal dependencies first (statically
compiled languages such as &amp;ldquo;go&amp;rdquo; make this easier, but it can be done
with traditional binaries such as httpd, just by following the library
dependency chains).&lt;/p&gt;

&lt;p&gt;The end result is a smaller, more secure image.  There&amp;rsquo;s less to assist
attackers (no unnecessary files so harder to get a shell) and simpler
to maintain (smaller dependencies).&lt;/p&gt;

&lt;p&gt;It also helps segregate the application from the OS by making the
dependencies explicit; switching from a Debian base to a CentOS base
won&amp;rsquo;t suddenly cause application breakage because there &lt;em&gt;is&lt;/em&gt; no Debian
or CentOS base :-)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Why use SSL/TLS on websites?</title>
      <link>https://www.sweharris.org/post/2016-05-31-secure-webserver/</link>
      <pubDate>Tue, 31 May 2016 07:31:26 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-05-31-secure-webserver/</guid>
      <description>&lt;p&gt;Building a secure web application has multiple layers to it.  In
previous posts I&amp;rsquo;ve spoken about some design concepts relating to
building a secure container for your app, and hinted that some of the
same concepts could be used for building VMs as well.&lt;/p&gt;

&lt;p&gt;You also need to build secure apps.  &lt;a href=&#34;https://www.owasp.org/index.php/Main_Page&#34;&gt;OWASP&lt;/a&gt; is a great way to help get started on that.  I&amp;rsquo;m not going to
spend much time on this blog talking about application builds beyond
some generics because I&amp;rsquo;m not really a webdev.  When I &lt;a href=&#34;https://www.sweharris.org/post/2014-02-28-java/&#34;&gt;wrote Java&lt;/a&gt; we didn&amp;rsquo;t have modern IDEs, tree structures, &amp;ldquo;factories&amp;rdquo; and the
like, and I never kept up with that.  Other people can go on about specifics
a lot better than me ;-)&lt;/p&gt;

&lt;p&gt;However a strong OS base and a strong app doesn&amp;rsquo;t mean much if your
web server is weak.  An important step is using &lt;del&gt;SSL&lt;/del&gt; TLS for your
communication channel.&lt;/p&gt;

&lt;p&gt;TLS (&amp;ldquo;Transport Layer Security&amp;rdquo;) is the successor to SSL (&amp;ldquo;Secure
Socket Layer&amp;rdquo;).  SSL was created by Netscape in the mid 90s (I remember
installing &amp;ldquo;Netscape Commerce Server&amp;rdquo; in 1996).  When you hear people
talk about SSL and TLS they pretty much use the terms interchangeably.
You can think of it as a progression SSL2, SSL3, TLS1.0, TLS1.1, TLS1.2
with each version better than the previous.&lt;/p&gt;

&lt;p&gt;Why use TLS at all?  Isn&amp;rsquo;t this just paranoia?
Unfortunately not; if you are on a mobile network or
using a WiFi hotspot then the network, itself, may &lt;a href=&#34;http://webpolicy.org/2015/08/25/att-hotspots-now-with-advertising-injection/&#34;&gt;insert
adverts&lt;/a&gt;
into the browser; Verizon have &lt;a href=&#34;https://www.eff.org/deeplinks/2014/11/verizon-x-uidh&#34;&gt;added tracking
cookies&lt;/a&gt;
on their mobile network.&lt;/p&gt;

&lt;p&gt;By using TLS you are helping to prevent this, and so give your users the
site &lt;em&gt;you&lt;/em&gt; want them to see, untampered by third party injected adverts.
It also helps protect your users from malware that has &lt;a href=&#34;http://arstechnica.com/security/2016/03/big-name-sites-hit-by-rash-of-malicious-ads-spreading-crypto-ransomware/&#34;&gt;hit major Ad
networks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, obviously, any login that takes credentials (username/password/whatever)
should be over TLS to stop the password being passed in plain text over
the network.  But what isn&amp;rsquo;t necessarily so obvious to people is that the
form that people type into should &lt;em&gt;also&lt;/em&gt; be TLS enabled.  Why?  Because
otherwise an attacker could modify the form; as far as the user is
concerned they&amp;rsquo;re entering the data into their normal login screen but
the bad guy now takes a copy and then logs them in, as normal.  Oops!&lt;/p&gt;

&lt;p&gt;What&amp;rsquo;s even harder for some people to grasp is that any protected page
should also be TLS enabled.  A typical login process may require you
to enter your details into a form, submit these details.  If you&amp;rsquo;ve entered
the right data then the server will send back a cookie.  This cookie is a
&lt;em&gt;token&lt;/em&gt; that the rest of the site actually uses to verify you have an
authenticated session.  If the site is over HTTP then this cookie is
passed in plain text and can be stolen.  This is a form of &lt;em&gt;session hijacking&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So we have some important use cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Prevent network advert injection (and risking malware injection)&lt;/li&gt;
&lt;li&gt;Create secure login pages&lt;/li&gt;
&lt;li&gt;Login submission pages&lt;/li&gt;
&lt;li&gt;Any protected page&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Between them all this should be screaming &amp;ldquo;use TLS everywhere!&amp;rdquo;.  Every
page should be via TLS and not by HTTP.&lt;/p&gt;

&lt;p&gt;With the advent of &lt;a href=&#34;https://www.letsencrypt.org&#34;&gt;Lets Encrypt&lt;/a&gt;, allowing
for free &lt;em&gt;automatable&lt;/em&gt; certificate granting, even a lowly blog like this
can be TLS enabled.&lt;/p&gt;

&lt;p&gt;This blog is served over https for these reasons; there&amp;rsquo;s no confidential
information, no passwords, no secure data&amp;hellip; but I don&amp;rsquo;t want my content
hijacked by network providers.  I don&amp;rsquo;t want my (counts on fingers) 5
readers to risk malware infection because they wanted to read my stuff.&lt;/p&gt;

&lt;p&gt;There are some &amp;ldquo;gotchas&amp;rdquo; with TLS (make sure you&amp;rsquo;ve disabled older
protocols, weak ciphers, ensure users can&amp;rsquo;t be downgraded to non-TLS
sites, etc) which I&amp;rsquo;ll get into in a later post.  That&amp;rsquo;ll be more &amp;ldquo;hands
on&amp;rdquo; and describe how to configure Apache in order to get an A+ SSL rating.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>How public cloud can change your security stance</title>
      <link>https://www.sweharris.org/post/2016-05-23-stance/</link>
      <pubDate>Mon, 23 May 2016 10:20:32 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-05-23-stance/</guid>
      <description>&lt;p&gt;The core problem with a public cloud is &amp;ldquo;untrusted infrastructure&amp;rdquo;.
We could get a VM from Amazon; that&amp;rsquo;s easy.  What now?  The hypervisor
isn&amp;rsquo;t trusted (non company staff access it and could use this to bypass OS
controls).  The storage isn&amp;rsquo;t trusted (non company staff could access it).
The network isn&amp;rsquo;t trusted (non company&amp;hellip;).&lt;/p&gt;

&lt;p&gt;So could we store Personal Identifying Information in the cloud?  Could a
bank store your account data in a public cloud?&lt;/p&gt;

&lt;p&gt;Could we even store public data in the cloud?  Imagine if $MEGACORP
stored their TV promotional videos on Amazon; they become the official
promotional URLs.  And then some replaces it with some porn.  Umm&amp;hellip;&lt;/p&gt;

&lt;p&gt;So there are different security concerns in operating in a public cloud
environment and different mitigation strategies required  (some of which
may be contractual and with $100mm indemnity clauses; some of which may
be technical; some of which may just be restrictions on what we allow
to run there).&lt;/p&gt;

&lt;p&gt;And then once we&amp;rsquo;ve got the &amp;ldquo;cloud management&amp;rdquo; aspect under control,
at the end of the day we still just have a VM.  Many companies are
already pretty good at building VMs.  Automation tools can do this
in minutes.  But then we have the megaton of layered stuff that takes
a month of manual work.  It needs to hook into the authorization tools,
the inventory management tools, the security scanning tools, the change
mangement tools&amp;hellip;&lt;/p&gt;

&lt;p&gt;You &lt;em&gt;were&lt;/em&gt; planning on those integrations, right?  You weren&amp;rsquo;t just
going to run a production workload on uncontrolled machines.  Heck,
you weren&amp;rsquo;t going to run a DEV workload on a machine that can tunnel
through your security perimeter&amp;hellip;&lt;/p&gt;

&lt;p&gt;Building servers is easy.  Controlling servers is hard.&lt;/p&gt;

&lt;p&gt;So using Amazon just for &amp;ldquo;replacement IaaS&amp;rdquo; (Infrastructure as a service)
doesn&amp;rsquo;t really buy us much.  Theoretically many large companies can
create and run VMs cheaper than Amazon, especially those servers that run 24x7.&lt;/p&gt;

&lt;p&gt;Now Amazon IaaS is great for &amp;ldquo;short running high compute&amp;rdquo; apps.
Let&amp;rsquo;s say we have a monthly reconcile process that takes 80 physical
machines and runs for 24 hours a month.  That&amp;rsquo;d be cheaper to run in
Amazon; we don&amp;rsquo;t need to pay for 30 days of server we&amp;rsquo;re not using;
just for the one day.  Neat!  But for a 24x7 server that&amp;rsquo;s always up?
We can (and should!) do cheaper.  (Hint: many internal service costs
includes layered tools and monitoring and network and stuff; we&amp;rsquo;d have
to pay additional licensing fees and network usage charges and so on,
on top of the base Amazon EC2 charge).&lt;/p&gt;

&lt;p&gt;But this &amp;ldquo;run a server only when we need it&amp;rdquo; process requires a change
in how we deploy things.  This &amp;lsquo;month of manual work&amp;rsquo; just won&amp;rsquo;t do.
Existing monitoring, control and inventory management systems are all
based around persistent consistent data (your server is flagged red
because your license scanning tool can never reach the server because
the VM isn&amp;rsquo;t running!)  So now our existing security and audit and
access management tools need to be reconsidered.&lt;/p&gt;

&lt;p&gt;How does change management and patching work in a world where the server
isn&amp;rsquo;t ever up?   So now our vulnerability management processes need to
be reconsidered.&lt;/p&gt;

&lt;p&gt;Solutions we&amp;rsquo;ve built for traditional datacenters, based around relatively
static compute (inventory changes take place over days, rather than
minutes) may not be suitable for a cloud environment.&lt;/p&gt;

&lt;p&gt;Then we have regulators; their requirements aren&amp;rsquo;t necessarily cloud
friendly either.  Can we meet regulatory controls and demands in this
world?&lt;/p&gt;

&lt;p&gt;To me, this says &amp;ldquo;lift and shift&amp;rdquo; of existing apps from a corporate
datacenter into a cloud environment may not be the best options.  But if
we spend the time and effort&amp;hellip;  if we build out the datastructures and
controls; if we automate application deployment; if we move away from
&amp;ldquo;hands on keyboard&amp;rdquo; for operate staff (&amp;ldquo;No, do not ssh into the server;
have tools and processes to collect data upfront and then analyse the
data, fix the problem and then redeploy the fixed version&amp;rdquo;).  Basically
streamline the development process via automated testing/deployment tools
(CI/CD FTW)&amp;hellip;&lt;/p&gt;

&lt;p&gt;Now we can change our security posture.  Do we need central authentication
in a world where no one can login?  Do we need inventory license scanning
in a world where we state what apps are running where?  Do we need
application and config discovery when server configuration is defined
programmatically and never changes?&lt;/p&gt;

&lt;p&gt;Not all of these changes are dependent on the public cloud.  Some of
these things we should also drive in the traditional compute environment.
Think how much more productive your code release cycle would be if you
had full end-to-end automation processes?  Think how much more secure your
apps would be if no one can login.  You might gain many of the perceived
benefits of a public cloud internally just by adopting the same tooling.&lt;/p&gt;

&lt;p&gt;These operational changes then change our security stance, simply by
taking people out of the equation.  We don&amp;rsquo;t &lt;em&gt;discover&lt;/em&gt; the state of
the world, we &lt;em&gt;define&lt;/em&gt; it and automation ensures it.&lt;/p&gt;

&lt;p&gt;Why do we need a detail keystroke log of change activity if no one logs
in to do changes?  Why do we need a central authentication system when
no one &lt;em&gt;can&lt;/em&gt; login?&lt;/p&gt;

&lt;p&gt;The controls move out to the code management environment.  How does code
get passed through dev/test/qa/prod?  What automated scanning tools are
deployed?  Do you use a CI/CD process?  Can you use test-driven processes
(check code in, it autobuilds and deploys all tests)?&lt;/p&gt;

&lt;p&gt;This changes how companies report their security to external auditors
and regulators.  It changes how we deploy security technology.  And it
can actually reduce &amp;ldquo;time to market&amp;rdquo; delays!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The risks of Single Sign On</title>
      <link>https://www.sweharris.org/post/2016-05-16-no-sso/</link>
      <pubDate>Mon, 16 May 2016 17:22:14 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-05-16-no-sso/</guid>
      <description>

&lt;p&gt;If your organisation is anything typical then you have multiple web sites
and application that require authentication.  If you&amp;rsquo;re lucky then you
might have something like CA Siteminder, but your staff still complain
about needing to re-authenticate every so often.  The more times they need
to login, the greater the chance of a mistake, causing a lockout and driving
people to distraction.&lt;/p&gt;

&lt;p&gt;So you hatch a plan; let&amp;rsquo;s do a true Single Sign On.  And, hey, everyone
logs into their Windows desktop and Active Directory presents as a Kerberos
source, so why not use AD backed Kerberos as your SSO solution?  Now users
don&amp;rsquo;t need to retype passwords all the time.&lt;/p&gt;

&lt;p&gt;Problem solved, right?&lt;/p&gt;

&lt;p&gt;I feel this approach is misguided, and may open you to greater risk.&lt;/p&gt;

&lt;p&gt;The problem is one of &amp;ldquo;security boundaries&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;In my view staff have at least 3 roles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Basic &amp;ldquo;employee&amp;rdquo; role shared by pretty much everyone; ability to enter
the building, login to desktop, read email, enter timesheets&amp;hellip; that sort
of thing&lt;/li&gt;
&lt;li&gt;Stuff done on their own behalf.  eg setting up direct deposit of wages,
signing up for the company gym.  Here the staff are effectively &lt;em&gt;customers&lt;/em&gt;
of the company, using HR and similar systems&lt;/li&gt;
&lt;li&gt;Stuff done specific to their job; developers, SAs, DBAs, bank teller,
trader, sales representative, customer support&amp;hellip;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The question, in my mind, is whether the gym web site should use the
same authentication token as gaining SA shell access to a production
server&amp;hellip; especially when that access is mediated by a Windows desktop,
generally a weak point in any security setup.&lt;/p&gt;

&lt;p&gt;Now I&amp;rsquo;m of the general opinion that any type of Unix shell access on
a production server should be considered &amp;ldquo;privileged access&amp;rdquo;.  Similarly
interactive SQL access on databases.  Pretty much any access that&amp;rsquo;s not
&amp;ldquo;end user&amp;rdquo;.  So SAs, DBAs, Application Operate staff et al should not
have &amp;ldquo;SSO&amp;rdquo; access to their infrastructure.  Use something like two factor
authentication, or a break-glass process, or some other mediated access
solution that requires &amp;ldquo;step up&amp;rdquo; authentication.  Your desktop AD Kerberos
ticket should not grant you access.&lt;/p&gt;

&lt;p&gt;This means we can reframe the question in terms access levels:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Basic access (desktop, email, HR-like, etc)&lt;/li&gt;
&lt;li&gt;Application access (job specific)&lt;/li&gt;
&lt;li&gt;Infrastructure access (privileged)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Privileged access should definitely not be SSO.  Application access is
somewhere borderline between allowing your desktop credentials to be used
or not.  It may depend on the risk profile of the application.&lt;/p&gt;

&lt;p&gt;The second problem is in a span of control.  If everything is controlled
by a single authentication source (e.g. Active Directory) then a breach
in that environment can be used to pivot across your whole estate.  If
you have a small number of servers then this risk may be reasonable, but
if you have large numbers of Windows and Unix servers then consideration
should be paid towards segregating the controls environments.  Now if
Windows is broken into your Unix environment isn&amp;rsquo;t directly at risk;
similarly if Unix is broken into then your Windows estate is protected.&lt;/p&gt;

&lt;p&gt;Of course, more control points means more attackable servers, increased
complexity around access admin, auditing, log analysis.  You don&amp;rsquo;t get
something for nothing.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s a balancing act; desktop, windows servers, unix servers, databases&amp;hellip;
where do you decide an environment is big enough to warrant its own
&lt;a href=&#34;https://www.sweharris.org/post/2016-04-16-unix-iam-history/&#34;&gt;AAA&lt;/a&gt; infrastructure, and how much
risk are you willing to accept.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;There has been a drive to merge all authentication systems
together; allow Unix, Windows, databases, applications to share
the same datasource (primarily Active Directory, via Kerberos).
Tools such as &lt;a href=&#34;https://www.centrify.com/products/server-suite/&#34;&gt;Centrify&lt;/a&gt; and &lt;a href=&#34;https://www.beyondtrust.com/products/powerbroker-for-unix-linux/&#34;&gt;BeyondTrust
Powerbroker&lt;/a&gt;
(PBUL) allow Unix machines to participate in Active Directory a lot more
closely than just using native Kerberos configuration, providing a form
of central administration and control.&lt;/p&gt;

&lt;p&gt;But you need to consider whether this surface simplicity is the right thing
to do from a risk and controls perspective.  SSO may not be the correct
behaviour, and create a risk concentration around the AD infrastructure.&lt;/p&gt;

&lt;p&gt;Ideally, of course, &lt;a href=&#34;https://www.sweharris.org/post/2016-05-08-people/&#34;&gt;no one&lt;/a&gt; should have access
to infrastructure and everything is automated :-)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The People Problem</title>
      <link>https://www.sweharris.org/post/2016-05-08-people/</link>
      <pubDate>Sun, 08 May 2016 20:48:51 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-05-08-people/</guid>
      <description>&lt;p&gt;&lt;em&gt;&amp;ldquo;To summarise the summary of the summary; people are a problem&amp;rdquo;&lt;/em&gt; - Douglas
Adams, The Restaurant At The End Of The Universe&lt;/p&gt;

&lt;p&gt;In a traditional compute environment we may have a lot of controls.
There may be a lot of audit regulations.  Organisations create a lot of
processes and procedures.  Want to login to a Unix machine?  Better have
an approved account, with the right authorisations.  DMZ machines
may require 2FA.  Want to become root?  Off to a password vault for
break-glass (and in some environments, such as Monetary Authority of
Singapore, then keystroke logging may be involved!) with management
signing off on the activity afterwards.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s a lot of effort needed, just to login to a machine and make
a change.&lt;/p&gt;

&lt;p&gt;Changes&amp;hellip; I hope you had a approved change record for that activity.
Do we need tripwire to verify only the right files were touched?
How can we verify you didn&amp;rsquo;t read &amp;ldquo;supersecret.txt&amp;rdquo; while you had
root access?&lt;/p&gt;

&lt;p&gt;So let&amp;rsquo;s not do that.  Let&amp;rsquo;s not login at all.  If you can&amp;rsquo;t login then
you don&amp;rsquo;t need all of that technology and processes, and all the fun that
involves.  Script everything.  Automate everything.  Hands-off deployment.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&amp;ldquo;If you have to SSH into your servers, then your automation has failed&amp;rdquo;&lt;/em&gt; -
Rich Adams, &lt;a href=&#34;https://wblinks.com/notes/aws-tips-i-wish-id-known-before-i-started/&#34;&gt;https://wblinks.com/notes/aws-tips-i-wish-id-known-before-i-started/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how we need to manage cloudy environment.  We should automate
pretty much everything.  Ideally our physical servers can not be directly
reached.  From bare metal we should build our servers, our network,
our storage, our management plane and the complete cloud environment
via automation, in a few hours.   No human login needed.&lt;/p&gt;

&lt;p&gt;This automation also allows us to change the way we operate.  We never
patch a machine; we rebuild it from scratch.  The automation brings in
the latest version of the packages and the fresh deployment is our fully
patched server.  If a problem such as heartbleed or shellshock occurred
again we are in a position to redeploy all of the servers in a rolling
upgrade in hours.&lt;/p&gt;

&lt;p&gt;This is also the only way to scale.  If you&amp;rsquo;re building a dynamic
elastic environment (if you&amp;rsquo;re not, then why are you using cloud?) then
you may need to build 1000 servers that run for 2 hours then destroy
them again.  How will you do that &lt;em&gt;without&lt;/em&gt; automation?&lt;/p&gt;

&lt;p&gt;This is just the next step in a trend.  When I started doing stuff 30
years ago, servers had a shared well known root password.  DBAs knew this
password.  Some &amp;ldquo;trusted&amp;rdquo; developers knew this password.  SAs would login
as root and stay logged in for weeks at a time.  Slowly we removed access
starting with &amp;ldquo;root&amp;rdquo;; the developers screamed that they couldn&amp;rsquo;t deploy
their programs because they needed root to do it; the DBAs screamed that
they couldn&amp;rsquo;t extend their databases because they needed root to do it;
the SAs screamed that they couldn&amp;rsquo;t do&amp;hellip; pretty much anything, because
they are root.  And now we&amp;rsquo;re at the stage where no one even has a login!&lt;/p&gt;

&lt;p&gt;And if you can&amp;rsquo;t login, you can&amp;rsquo;t break it so easily.  We&amp;rsquo;ve also removed
a massive threat vector (no server login means the accounts can&amp;rsquo;t be
brute forced) and so reduced the risk.&lt;/p&gt;

&lt;p&gt;By removing human access from the servers we have simplified the
environment and made it easier to secure.&lt;/p&gt;

&lt;p&gt;And now we&amp;rsquo;ve got this concept, why stop there?  Let&amp;rsquo;s retro-fit these
controls into the traditional compute environment as well.  Automate
application delivery; automate patching; automate&amp;hellip; everything!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Shadow IT</title>
      <link>https://www.sweharris.org/post/2016-05-02-shadow-it/</link>
      <pubDate>Mon, 02 May 2016 11:15:23 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-05-02-shadow-it/</guid>
      <description>

&lt;p&gt;Shadow IT isn&amp;rsquo;t a new thing.  Any large corporation has seen it.  Sometimes
called &amp;ldquo;server under desk&amp;rdquo; or &amp;ldquo;production desktop&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Sometimes it grows out of a personal project that started on a spare
machine and that gradually morphed into a mission critical machine&amp;hellip; but
without any of the controls and tools normally associated with production
infrastructure (patches, backups, DR, access admin, security scanning&amp;hellip;).&lt;/p&gt;

&lt;p&gt;Other times it grows out of a desire to do things quickly; all of those
controls and tools take time and can hinder the developer experience.
Let&amp;rsquo;s hack together something now and then migrate it later&amp;hellip; except
the migration never happens and that under-desk server stays forever.&lt;/p&gt;

&lt;p&gt;We know this is bad but it still happens.  Central IT is frequently seen
as more of an inhibitor than a facilitator&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&#34;https://www.sweharris.org/images/mordac.gif&#34; alt=&#34;mordac&#34; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Despite this, at least this shadow IT was within the corporate boundary;
there was some level of protection provided by border firewalls.&lt;/p&gt;

&lt;h2 id=&#34;the-new-shadow-it&#34;&gt;The new Shadow IT&lt;/h2&gt;

&lt;p&gt;These days you don&amp;rsquo;t even need to rummage up an old desktop to turn it into
a server.  Just wave your corporate card at Amazon and, just like magic,
you have a server.  Two servers.  Ten servers.&lt;/p&gt;

&lt;p&gt;Now the situation is a lot worse.  Not only are these unmanaged and
uncontrolled servers, but they are also outside of your security perimeter.
On the internet, facing attacks.  Is your application secure against
hacking?  Do you have strong passwords?  Did you turn off all unnecessary
services?  How long will it be before someone brute-forces your root account?&lt;/p&gt;

&lt;p&gt;The result: data exposure.  &lt;a href=&#34;https://www.databreaches.net/personal-info-of-93-4-million-mexicans-exposed-on-amazon/&#34;&gt;The personal data of 93 million Mexicans&lt;/a&gt; were exposed because of just this type of problem.&lt;/p&gt;

&lt;p&gt;The first you may know about it is when your CEO is being contacted by
the Wall Street Journal for a quote, or when &lt;a href=&#34;https://www.troyhunt.com/&#34;&gt;Troy Hunt&lt;/a&gt; adds the data to &lt;a href=&#34;https://haveibeenpwned.com/&#34;&gt;Have I Been Pwned&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Shadow IT is pernicious.  It is hard to stop.  Instead we need to lessen
the incentive to do it; make it easier to obtain the resources in a
controlled manner.&lt;/p&gt;

&lt;p&gt;This is a culture change.  Abstract away from the Operating System and
focus on what the developers need; a PaaS, obtainable by self-service
processes; ability to push code into dev and automate promotion to
production; automated scanning, backup, resilliency&amp;hellip;  take all this
off their plate and provide it at the click of a button.&lt;/p&gt;

&lt;p&gt;Now there&amp;rsquo;s no need to wave your credit card at Amazon!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Vulnerability, Threat, Risk</title>
      <link>https://www.sweharris.org/post/2016-04-27-door-bear-mauled/</link>
      <pubDate>Wed, 27 Apr 2016 09:54:33 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-04-27-door-bear-mauled/</guid>
      <description>

&lt;p&gt;From &lt;a href=&#34;https://twitter.com/JGamblin/status/725127177205895169&#34;&gt;Twitter&lt;/a&gt;
came this gem:
&lt;center&gt;&lt;img src=&#34;https://www.sweharris.org/images/door-bear-mauled.png&#34; alt=&#34;door-bear-mauled&#34; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;This is a cute way of helping people understand the difference between
the three concepts.  It also helps start to drive conversation around
remediation activities and risk assessment.&lt;/p&gt;

&lt;p&gt;(Let&amp;rsquo;s not get too tied down with interpretation; all analogies have
holes :-))&lt;/p&gt;

&lt;p&gt;What if the door was a bedroom door, rather than a house front door?  How
does this change the probability of a bear getting in and thus getting
mauled?  Or does the open bedroom door cause a new threat (room mate seeing
you in a position you would find embarrassing)?&lt;/p&gt;

&lt;p&gt;Not every risk is identical.  An open door leading to a balcony that&amp;rsquo;s 30
floors up is unlikely to have a bear come through it!  If your exposure
to the threat is minimal then the risk of exploit is minimal and so your
remediation timelines need not be immediate.&lt;/p&gt;

&lt;p&gt;When we look at security we tend to have an &amp;ldquo;attackers &lt;em&gt;will&lt;/em&gt; get in&amp;rdquo;
mentality.  &amp;ldquo;Close the door because the bear &lt;em&gt;will&lt;/em&gt; get in&amp;rdquo;.  It&amp;rsquo;s a
fair position to take, especially since attackers can chain vulnerabilities
together (the front door was open and the bedroom door was open).&lt;/p&gt;

&lt;p&gt;So we take a security in depth view; don&amp;rsquo;t trust a single control (front
door was closed, but the kitchen back door was open) but layer controls.
More prosaically, don&amp;rsquo;t assume that firewalls will keep out attackers;
there are other ways of getting remote code execution (email client
bugs, phishing, desktop vulnerabilities, bad code&amp;hellip; or even a simple
misconfigured firewall!)&lt;/p&gt;

&lt;p&gt;This &amp;ldquo;in depth&amp;rdquo; view should use different types of controls that
overlap.  So you wouldn&amp;rsquo;t run two different virus scanning tools on
your desktop; instead you may run a virus scanner and a firewall
(to block outgoing connections to untrusted sites) and a filtering
proxy (for trusted outgoing connections) and&amp;hellip;; controls that may
overlap (the proxy may do virus scanning as well) but do other stuff;
if you &lt;em&gt;do&lt;/em&gt; get infected then the code can&amp;rsquo;t reach out to the IRC
control channel because of the firewall; it can&amp;rsquo;t download more payload
because of the proxy.&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;When you identify a vulnerability you should evaluate the threat and
the risk to your environment.  What&amp;rsquo;s the worst case scenario of the
vulnerability is exploited?  What&amp;rsquo;s the chance that it will be exploited?
What mitigations do you have in place to prevent the attack vector from
being exploited?&lt;/p&gt;

&lt;p&gt;Remember, though, that sometimes you have invited the bear in (insider
threat from disgruntled employees).  That needs to form part of your
risk assessment!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Container technology</title>
      <link>https://www.sweharris.org/post/2016-04-25-container-tech/</link>
      <pubDate>Mon, 25 Apr 2016 15:43:01 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-04-25-container-tech/</guid>
      <description>

&lt;p&gt;I&amp;rsquo;ve spent a few posts talking about the ecosystem required to keep a
container secure; hands off automation, code provenance, and the like.&lt;/p&gt;

&lt;p&gt;But a number of people have asked me about the &lt;em&gt;techology&lt;/em&gt;.  Mostly
they talk about &amp;ldquo;docker&amp;rdquo; and the security concerns.  I&amp;rsquo;ve been loathe
to talk about technology specifically because it changes.  Yesterday
docker daemon runs as root; tomorrow it may not.  Yesterday the kernel
exposed a problem, tomorrow it won&amp;rsquo;t.  I think that by focusing on the
technology implementation you&amp;rsquo;re missing the bigger picture; the management
of the ecosystem is more important than the technology itself.&lt;/p&gt;

&lt;p&gt;But with this in mind, here&amp;rsquo;s a few thoughts.&lt;/p&gt;

&lt;p&gt;Containers share a kernel.  The container technology tries to &lt;em&gt;isolate&lt;/em&gt;
each instance from each other.  This means that all the interfaces exposed
by the kernel to the code form part of the attack surface.  There are over
300 system calls.  Each of them need to ensure the isolation is maintained.
And any new syscall added needs to maintain the isolation.&lt;/p&gt;

&lt;p&gt;Containers make use of various kernel technologies to try and minimise
the risk.  Obvious techniques include having a separate network interface
that&amp;rsquo;s only visible inside the container (let&amp;rsquo;s hope there&amp;rsquo;s no data leak
between packets on different interfaces), having a separate view of the
filesystem (chroot on steroids), a separate view of the process space and
so on.&lt;/p&gt;

&lt;p&gt;In addition, with latter kernels, user and group ids can be mapped inside
containers.  User zero inside a container need not match user zero outside
of it.&lt;/p&gt;

&lt;p&gt;Then we can start to look at AppArmour and SELinux to add to the security.
Mandatory Access Controls (MAC).  If you are rolling your own solution
then you might also want to look at something like Computer Associates
&amp;ldquo;Control Minder&amp;rdquo; (previous known as eTrust Access Control, or even SEOS;
it&amp;rsquo;s changed names a lot).  This is a highly flexible MAC system; a lot
more flexible than SELinux.  But not cheap :-)&lt;/p&gt;

&lt;p&gt;Now a clever one; seccomp.  This allows you to drop permissions to use
specific syscalls.  If you can&amp;rsquo;t use them then you can&amp;rsquo;t leverage any
isolation bugs; basically reduce the attack surface area.&lt;/p&gt;

&lt;p&gt;Use of CAPabilities inside the container may allow some actions to be done
without needing root (eg &amp;ldquo;ping&amp;rdquo;).  Ensure you drop unwanted capabilities
before starting your app.&lt;/p&gt;

&lt;p&gt;Of course these are all kernel oriented, and so &lt;em&gt;themselves&lt;/em&gt; form part of
the attack surface.  Older Android machines have had kernel level exploits
due to SELinux bugs!&lt;/p&gt;

&lt;p&gt;You can see that there&amp;rsquo;s a lot to juggle and keep in mind.  It&amp;rsquo;s a full time
job.  Unless you have a specific requirement to build your solution, I&amp;rsquo;d
avoid it and use something more &amp;ldquo;off the shelf&amp;rdquo;.  After all, how many
people build their own OS?&lt;/p&gt;

&lt;p&gt;By using something common (Docker, Rocket, Cloud Foundry, etc) you&amp;rsquo;ll
have the advantage of a lot of developers, constantly improving the
product.  Docker 1.10 makes use of many of the tools listed above; it
works with seccomp, SELinux, AppArmour.  It deals with name spaces&amp;hellip;&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Don&amp;rsquo;t get too hung up with the technology implementation.  Be &lt;em&gt;aware&lt;/em&gt; of
what you&amp;rsquo;re using (e.g. docker daemon runs as root) and the best
practices around it.  There&amp;rsquo;s hundreds of pages on the web about that!&lt;/p&gt;

&lt;p&gt;Pick a technology stack that meets your use case (Docker? Rocket? Mesosphere?
Cloud Foundry? Google Function? Amazon Lambda?) and maintain it like
you&amp;rsquo;d maintain any vendor product.&lt;/p&gt;

&lt;p&gt;You&amp;rsquo;ll gain a bigger win by focusing on your processes and automation.
Which you need to do, &lt;em&gt;anyway&lt;/em&gt;, to ensure the content is secure.
And the nice part of that is by fixing this part you can scale your
solution from micro-service containers all the way up to VMs or even
physical server builds.  Hands-off automation all the way!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Business cards</title>
      <link>https://www.sweharris.org/post/2016-04-22-business-cards/</link>
      <pubDate>Fri, 22 Apr 2016 10:31:19 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-04-22-business-cards/</guid>
      <description>&lt;p&gt;A decade or so back, VistaPrint did a &amp;ldquo;free card&amp;rdquo; offer as long as you
used one of their templates.  So I got a bunch of cards printed&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&#34;https://www.sweharris.org/Cards/old-card.jpg&#34; alt=&#34;old style card&#34; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Over the years I&amp;rsquo;ve probably given out&amp;hellip;5 of them?  Heh.&lt;/p&gt;

&lt;p&gt;VistaPrint no longer seem to do freebies, but I decided to refresh my
image.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&#34;https://www.sweharris.org/Cards/business_card.jpg&#34; alt=&#34;new card&#34; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;The cost was $8 for 150 cards or $9 for 250, so I went for 250.  And then
after checkout they said for $1.50 more I could get another 250.  So total
of $10.50 gets me 500 cards.&lt;/p&gt;

&lt;p&gt;I expect they&amp;rsquo;ll last until after I&amp;rsquo;m dead!&lt;/p&gt;

&lt;p&gt;But if I&amp;rsquo;m gonna start going to conferences or give talks (maybe!!) then
having a card might be useful.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Maybe containers are VMs after all</title>
      <link>https://www.sweharris.org/post/2016-04-21-container-vm/</link>
      <pubDate>Thu, 21 Apr 2016 22:06:42 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-04-21-container-vm/</guid>
      <description>

&lt;p&gt;Back in &lt;a href=&#34;https://www.sweharris.org/post/2016-04-02-container-security/&#34;&gt;Container security&lt;/a&gt; I
said that we need to think about containers as VMs.  I then looked at an
&lt;a href=&#34;https://www.sweharris.org/post/2016-04-07-container-security-is-easy/&#34;&gt;easier way&lt;/a&gt; of looking at
containers, by &lt;em&gt;not&lt;/em&gt; treating them as VMs.   Hopefully, at this point,
some of you were thinking &amp;ldquo;Hmmm!&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Finally I discussed the &lt;a href=&#34;https://www.sweharris.org/post/2016-04-10-keeping-safe/&#34;&gt;processes and
workflows&lt;/a&gt; outside of the container
implementation that is needed to keep containers safe (build processes,
etc).&lt;/p&gt;

&lt;p&gt;We can turn what we&amp;rsquo;ve learned on its head.&lt;/p&gt;

&lt;p&gt;In order to build and maintain a container ecosystem we need to think
of containers as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transient

&lt;ul&gt;
&lt;li&gt;There is no persistent storage&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Short lived

&lt;ul&gt;
&lt;li&gt;Anywhere from microseconds upwards&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Immutable

&lt;ul&gt;
&lt;li&gt;You don&amp;rsquo;t change the running container; you build a new image and deploy that&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Untouchable

&lt;ul&gt;
&lt;li&gt;You NEVER LOG IN!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Automated

&lt;ul&gt;
&lt;li&gt;If you can&amp;rsquo;t login, you better automate the builds&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We need processes around the maintenance of containers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build good containers&lt;/li&gt;
&lt;li&gt;Scan existing containers&lt;/li&gt;
&lt;li&gt;Replace bad containers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Why should this apply solely to containers?&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s look at an Amazon EC2 instance.  Ideally we want to spin these
up &amp;ldquo;on demand&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;We shouldn&amp;rsquo;t store stuff in the VM disk image; either use Elastic Block
or S3 store or a database. For elastic compute where the same data needs
to be shared, S3 or a database.  Basically the data is transient.&lt;/p&gt;

&lt;p&gt;These EC2 instances aren&amp;rsquo;t necessarily short lived; they may live for
hours or days&amp;hellip; but, really, compared to traditional compute environments
this &lt;em&gt;is&lt;/em&gt; short lived.&lt;/p&gt;

&lt;p&gt;We could design workflows so that AMI images are not changed; new ones
are built.  Don&amp;rsquo;t patch in place, reboot from patched images.&lt;/p&gt;

&lt;p&gt;And, of course, never log in.  You automate your processes.  Your developer
teams instrument their apps.&lt;/p&gt;

&lt;p&gt;The key to all this is proper automation.&lt;/p&gt;

&lt;p&gt;That all sounds like what I defined as a container characteristic!&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;So here&amp;rsquo;s the challenge; maybe for the past
decade we&amp;rsquo;ve been managing VMs wrong!  We have old
heavy-weight processes.  This speaks somewhat to the &lt;a href=&#34;http://www.theregister.co.uk/2013/03/18/servers_pets_or_cattle_cern/&#34;&gt;pets vs
cattle&lt;/a&gt;
discussion, but coming at it from the other direction.&lt;/p&gt;

&lt;p&gt;Maybe we can treat containers the same as VMs.  Or, more accurately, we
can treat VMs as if they were containers.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Unix Identity and Access Management</title>
      <link>https://www.sweharris.org/post/2016-04-16-unix-iam-history/</link>
      <pubDate>Sat, 16 Apr 2016 19:41:39 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-04-16-unix-iam-history/</guid>
      <description>

&lt;p&gt;Identity and Access Management (IAM) historically consists of the three A&amp;rsquo;s&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication

&lt;ul&gt;
&lt;li&gt;What acccount is being accessed?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Authorization

&lt;ul&gt;
&lt;li&gt;Is this account allowed access to this machine?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Access Control

&lt;ul&gt;
&lt;li&gt;What resources are you allowed to use?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On top of this we may also need to consider&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auditing

&lt;ul&gt;
&lt;li&gt;Log the attempt to use the machine&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Provisioning

&lt;ul&gt;
&lt;li&gt;How does the account get onto the machine?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;ldquo;Access Control&amp;rdquo; is not directly under control of IAM.  In the unix world
this is defined by group permissions on files (group &lt;em&gt;membership&lt;/em&gt; is part of IAM), ACLs and so on.  For this blog entry I&amp;rsquo;m going to ignore it&amp;hellip; mostly.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s call the result (excluding Access Control) AAAP.&lt;/p&gt;

&lt;h2 id=&#34;historical-unix&#34;&gt;Historical Unix&lt;/h2&gt;

&lt;p&gt;In Unix we started pretty simple.  We had the password file &lt;code&gt;/etc/passwd&lt;/code&gt;.
The second field of this was a one-way encryption using your password as
the key.  The AAAP answers are now simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication

&lt;ul&gt;
&lt;li&gt;Did you enter the right password?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Authorization

&lt;ul&gt;
&lt;li&gt;Is the account in the passwd file?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Auditing

&lt;ul&gt;
&lt;li&gt;Log to syslog (and maybe elsewhere)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Provisioning

&lt;ul&gt;
&lt;li&gt;A superuser added the account.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(This password file also defined your primary group. Another file
&lt;code&gt;/etc/group&lt;/code&gt; defined your secondary groups; this is where IAM impacts
Access Control).&lt;/p&gt;

&lt;p&gt;In this world the mere existence of the account was authorization.&lt;/p&gt;

&lt;p&gt;Aside: this process still works today in an &amp;ldquo;out of the box&amp;rdquo; Linux build.
The crypt string has moved into &lt;code&gt;/etc/shadow&lt;/code&gt; because the old DES
algorithm was eventually too weak and open to simple attacks; a modern
machine will use SHA2 instead of DES. But a machine can still be setup
so it works just like it did 30 years ago; add the user to /etc/passwd
and /etc/shadow and they can login!&lt;/p&gt;

&lt;h2 id=&#34;yellow-pages-nis&#34;&gt;&lt;del&gt;Yellow Pages&lt;/del&gt;NIS&lt;/h2&gt;

&lt;p&gt;This started to hit scaling problems.  It was OK if you had 1 or 2 machines,
but 10?  20?  100?  Many organizations started to write simple synchronisation
scripts to try and keep the password in sync but these didn&amp;rsquo;t scale too well.&lt;/p&gt;

&lt;p&gt;In the &amp;lsquo;80s Sun Microsystems invented a solution called &amp;ldquo;Yellow Pages&amp;rdquo;.
Eventually (due to British Telecom trademark issues) it got renamed
NIS (Network Information Services).  Now what NIS did was to create a
network version of the password file (and other files, out of scope for
this discussion).  You can add a user to the central map and it will
show up on every machine.  Scaling solved!&lt;/p&gt;

&lt;p&gt;A new problem showed up; you may not want every user to login to every
machine.  So NIS also included the concept of a &amp;ldquo;netgroup&amp;rdquo;.  You could
create a netgroup called &amp;ldquo;sa_team&amp;rdquo; and put the SAs into it.  Another
netgroup could be called &amp;ldquo;dba&amp;rdquo; and your Oracle DBAs go into that.
Developers could go into &amp;ldquo;dev&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Now your passwd file consists of users, as before, &lt;em&gt;and&lt;/em&gt; @netgroup entries.
So every machine would have @sa_team but only the Oracle servers would have
@dba.  AAAP now reads:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication

&lt;ul&gt;
&lt;li&gt;Did you enter the right password?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Authorization

&lt;ul&gt;
&lt;li&gt;Is the account in the passwd file or in an included netgroup?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Auditing

&lt;ul&gt;
&lt;li&gt;Log to syslog (and maybe elsewhere)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Provisioning

&lt;ul&gt;
&lt;li&gt;A superuser added the account or a netgroup.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There&amp;rsquo;s still a scaling issue (every machine needs to be configured for
the right netgroups) but this is normally a one-off event or easily
scripted event.  You don&amp;rsquo;t need to touch hundreds of servers every time
someone leaves or joins.&lt;/p&gt;

&lt;p&gt;As a technology NIS had a number of security issues (e.g. spoofable,
allowed the crypt strings to be seen) but the ideas worked well.  Similar
ideas still persist today, using LDAP instead of NIS.  (We&amp;rsquo;ll not talk
about NIS+ and pretend it never existed).&lt;/p&gt;

&lt;h2 id=&#34;pam-and-nss&#34;&gt;PAM and NSS&lt;/h2&gt;

&lt;p&gt;What more do you need?&lt;/p&gt;

&lt;p&gt;Flexibility.&lt;/p&gt;

&lt;p&gt;Until now every program needed to know about all the backends.  The
programs like login/ftp/telnet/rsh on a SunOS machine all knew about
NIS.  But that&amp;rsquo;s all they knew.  You couldn&amp;rsquo;t add a new backend without
replacing every &amp;ldquo;front door&amp;rdquo; program.&lt;/p&gt;

&lt;p&gt;Starting in Solaris 2.5.1 and made better in Solaris 2.6, Sun created a
new structure &amp;ldquo;PAM&amp;rdquo; - Pluggable Authentication Modules.  Modern Linux also
has PAM.  Even AIX now has PAM (after going down its own path for a while).&lt;/p&gt;

&lt;p&gt;PAM and its partner NSS (Name Service Switch) are (at first glance)
a complicated process.  They splits out something that was done by the
passwd file into two separate sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Naming Services&lt;/li&gt;
&lt;li&gt;Authentication/Authorization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Naming services are handling things like &amp;ldquo;what UID is login fred?&amp;rdquo;  &amp;ldquo;What
account is uid 12345?&amp;ldquo;.  NSS allows for different backends (the local
passwd file; a NIS server; an LDAP server; a MySQL database&amp;hellip;).  It takes
what Sun created in the early NIS days and improves it to an API so every
program doesn&amp;rsquo;t need to know how to talk to every backend; they call (via
libc) a common stack.  This turns out to be very powerful and persists
today.&lt;/p&gt;

&lt;p&gt;PAM is where things get more interesting.  Historically we&amp;rsquo;ve seen that
&amp;ldquo;authorization&amp;rdquo; was simply based on a simple rule such as &amp;ldquo;are you in
the passwd file or an included netgroup&amp;rdquo;.  PAM potentially allows
&lt;em&gt;any&lt;/em&gt; rule to be defined; &amp;ldquo;Harry can login from these machines between
9am and 5pm&amp;rdquo;; &amp;ldquo;Fred must use an RSA token to login&amp;rdquo;.  Normally you wouldn&amp;rsquo;t
go to these extremes (you&amp;rsquo;d use &amp;ldquo;role based&amp;rdquo; rules - I&amp;rsquo;ll cover this in
a later blog) but because the rules are now programmable you can do everything.&lt;/p&gt;

&lt;p&gt;It also opens up a difference between traditional unix and modern unix.
Previously if you were in the password file then you were authorized.
&amp;ldquo;&lt;code&gt;id fred&lt;/code&gt;&amp;rdquo; was enough to tell you if you had an account.&lt;/p&gt;

&lt;p&gt;Now PAM may deny you access even if you exist.  &amp;ldquo;&lt;code&gt;id fred&lt;/code&gt;&amp;rdquo; may say that
Fred has a login, but PAM may still deny him.&lt;/p&gt;

&lt;p&gt;AAAP gets more complicated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication

&lt;ul&gt;
&lt;li&gt;Does NSS say your account exist?  Do the pam &amp;ldquo;auth&amp;rdquo; rules say the right credentials have been provided?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Authorization

&lt;ul&gt;
&lt;li&gt;Do the pam &amp;ldquo;account&amp;rdquo; rules permit this login at this time from this machine with this credential?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Auditing

&lt;ul&gt;
&lt;li&gt;Log to syslog (and maybe elsewhere)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Provisioning

&lt;ul&gt;
&lt;li&gt;Are you in the datastores queried by NSS?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;all-is-not-good-in-paradise&#34;&gt;All is not good in paradise&lt;/h2&gt;

&lt;p&gt;We can now handle lots of things.  What could possibly go wrong?&lt;/p&gt;

&lt;p&gt;Auditing is traditionally just syslog.  Remote syslog is unreliable
(UDP packet loss) or insecure (TCP packet sniffing). Authentication logs
should be considered high risk; who hasn&amp;rsquo;t mistakenly entered their
password into a login prompt?  &amp;ldquo;Failed login for mypasswd on ttya&amp;rdquo;;
&amp;ldquo;successful login for fred on ttya&amp;rdquo;&amp;hellip; can you guess Fred&amp;rsquo;s password?&lt;/p&gt;

&lt;p&gt;So audit logging needs to be handled better.&lt;/p&gt;

&lt;p&gt;Then there&amp;rsquo;s the provisioning stage; how are the rules for NSS and PAM
setup and maintained?&lt;/p&gt;

&lt;p&gt;A common setup is to allow &amp;ldquo;passwd: files ldap&amp;rdquo; (or similar).  This means
&amp;ldquo;look in the local passwd file first; and if the user isn&amp;rsquo;t found look
in LDAP&amp;rdquo;.  So far so good.  But this means that an SA could add &amp;ldquo;myacct&amp;rdquo;
to the passwd file and login with that.&lt;/p&gt;

&lt;p&gt;What happens when that SA leaves?  We may delete his LDAP account, but
&amp;ldquo;myacct&amp;rdquo; is still there&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;A number of organizations with an IAM function (e.g. banks, pharma) have
a &amp;ldquo;separations of duties&amp;rdquo; control structure.  One team controls access
(an IAM team) and another machine controls the machine (the SA team).
If the SA team can add users then we have a separation violation.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ll deal with this problem in a later blog.  This is where IAM gets
&amp;ldquo;interesting&amp;rdquo;.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Modern Unix systems use PAM and NSS to control access to machines.  In
their default configuration they look &lt;em&gt;just&lt;/em&gt; like a machine from 20 years
ago; add user to &lt;code&gt;/etc/passwd&lt;/code&gt; and crypt string to &lt;code&gt;/etc/shadow&lt;/code&gt; and the
user can login (if it wasn&amp;rsquo;t for &lt;code&gt;/etc/shadow&lt;/code&gt; then this would be 30
years ago).&lt;/p&gt;

&lt;p&gt;But they are a lot more flexible and can do a lot more than that.  Want
single signon from your windows desktop to the linux machine (no need
to enter your password!)?  The PAM kerberos module can help.  Want to
pull in usernames and groups from your Active Directory tree?  NSS
is the answer.&lt;/p&gt;

&lt;p&gt;PAM and NSS allow you to write code that&amp;rsquo;ll do almost anything you want.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Keeping containers safe</title>
      <link>https://www.sweharris.org/post/2016-04-10-keeping-safe/</link>
      <pubDate>Sun, 10 Apr 2016 10:18:21 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-04-10-keeping-safe/</guid>
      <description>

&lt;p&gt;In a previous post I showed that if you stop treating containers as if they
were VMs then &lt;a href=&#34;https://www.sweharris.org/post/2016-04-07-container-security-is-easy/&#34;&gt;container security is easy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now we need to look at how to keep the contents of containers safe.&lt;/p&gt;

&lt;p&gt;In general there are a number steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build good containers&lt;/li&gt;
&lt;li&gt;Scan existing containers&lt;/li&gt;
&lt;li&gt;Replace bad containers&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;build-good-containers&#34;&gt;Build good containers&lt;/h2&gt;

&lt;p&gt;This &lt;em&gt;should&lt;/em&gt; just be an extension of your existing source control process;
your CI/CD process; your &amp;ldquo;test driven&amp;rdquo; processes.  Whatever you use :-)&lt;/p&gt;

&lt;p&gt;A container won&amp;rsquo;t magically make an application secure, but if you build
them with &amp;ldquo;known good&amp;rdquo; code and only put things inside the container that
need to be there then you&amp;rsquo;ve made a good start.&lt;/p&gt;

&lt;p&gt;Some guidelines, which should just be common sense good coding practices
anyway.  These guidelines apply to traditional compute environments
on physical machines, on VMs, on containers.  Control your builds!&lt;/p&gt;

&lt;h4 id=&#34;don-t-create-a-whole-copy-of-the-os-to-put-inside-the-container&#34;&gt;Don&amp;rsquo;t create a whole copy of the OS to put inside the container&lt;/h4&gt;

&lt;p&gt;Some PaaS systems (eg Cloud Foundry) will provide the necessary infra
via &amp;ldquo;stemcells&amp;rdquo;.  If you&amp;rsquo;re using docker then you might want to use a
baseline to layer on top of. If you&amp;rsquo;re building a container from scratch
then only put in code that is essential.  If code isn&amp;rsquo;t present then it
can&amp;rsquo;t be exploited.  Minimise the footprint; minimise the attack surface.&lt;/p&gt;

&lt;h4 id=&#34;don-t-pull-code-direct-from-the-internet&#34;&gt;Don&amp;rsquo;t pull code direct from the internet.&lt;/h4&gt;

&lt;p&gt;In March we saw how
&lt;a href=&#34;http://www.theregister.co.uk/2016/03/23/npm_left_pad_chaos/&#34;&gt;one person removing code from npm&lt;/a&gt;
caused build systems from all over the internet to fail.  Your builds must
be repeatable, and in order to do that you must control the dependencies.&lt;/p&gt;

&lt;p&gt;Another risk of pulling from external repos is that if you don&amp;rsquo;t define
your dependencies to the specific version then new code may be introduced
upstream and break your app.  Or, worse, rogue code gets introduced that
creates a backdoor.&lt;/p&gt;

&lt;p&gt;Similarly if you use a binary repo (eg docker) then don&amp;rsquo;t have build time
dependencies on them; bring the objects in-house.&lt;/p&gt;

&lt;p&gt;This may mean you have your own internal repo and code against that.
You&amp;rsquo;ll also need to maintain this repo, but at least you get the chance
to scan the code, verify the licensing agreements, etc.  Do you want
your code to be BSD licensed?  Better verify none of the code you&amp;rsquo;re
using is GPL&amp;rsquo;d.&lt;/p&gt;

&lt;h4 id=&#34;code-scan&#34;&gt;Code scan&lt;/h4&gt;

&lt;p&gt;Everything you build should be scanned.  Binary objects should be scanned.
Results should be compared to known CVEs and to good coding practices
(eg those from &lt;a href=&#34;https://www.owasp.org/&#34;&gt;OWASP&lt;/a&gt;).  Good tools can identify
bad coding practices that could lead to exploits.&lt;/p&gt;

&lt;p&gt;Don&amp;rsquo;t rely on these, of course.  You should always strive to write good
code.  But scanning can be a useful backstop to catch mistakes.&lt;/p&gt;

&lt;h4 id=&#34;automated-deployment&#34;&gt;Automated deployment&lt;/h4&gt;

&lt;p&gt;The resulting image should go through your normal test/QA processes and
then the passing image pushed into your &amp;ldquo;registry&amp;rdquo;.  Production containers
should only be created from the approved registry, never from ad-hoc code.&lt;/p&gt;

&lt;h2 id=&#34;scan-existing-container-images&#34;&gt;Scan existing container images&lt;/h2&gt;

&lt;p&gt;You&amp;rsquo;ve just jumped through a hundred hoops to build your good container
image.  You can relax, right?  Nope.&lt;/p&gt;

&lt;p&gt;Unfortunately code has bugs in it.  I know that&amp;rsquo;ll come as a shock!
That code you scanned earlier; that library you depend on; that OS you
based your image on&amp;hellip; a new bug has been found in it.&lt;/p&gt;

&lt;p&gt;Fortunately you have your registry of good containers.  You should keep
&lt;em&gt;rescanning&lt;/em&gt; these containers.  When something like shellshock appears
you will be able to identify what images are vulnerable.&lt;/p&gt;

&lt;p&gt;The action you take may depend on the risk.  Perhaps you can block any
new instances from being created from this image.  Maybe you&amp;rsquo;ll just flag
it and make the owner responsible for fixing within 90 days.  You may be
able to automate repair (eg vendor provided an OS level fix; patch the
base image, auto-rebuild the dependent images).&lt;/p&gt;

&lt;p&gt;What you do here is very specific to your environment and risk exposure,
but it starts with knowing there&amp;rsquo;s a bug to be fixed.  That&amp;rsquo;s what this
repetetive scanning does.&lt;/p&gt;

&lt;h2 id=&#34;replace-bad-running-containers&#34;&gt;Replace bad running containers&lt;/h2&gt;

&lt;p&gt;It&amp;rsquo;s all well and good fixing your image registry, but what about all
those containers that are running?  You need to know where each image is
running so that you can shutdown and replace the bad image with the
repaired one.&lt;/p&gt;

&lt;p&gt;Your &amp;ldquo;orchestration layer&amp;rdquo; of the automated deployment should do this for you;
as it builds a running container it should track the container (where it
was deployed; what image it came from).  When the container is destroyed
it needs to track that as well.  Now, when your image has been corrected
you can push out the good version, remove the bad version.  You can also
report on known bad running images in order to identify your existing
risk.&lt;/p&gt;

&lt;p&gt;This is very important in a container world simply due to scale.  You
may have a million containers running around; you can&amp;rsquo;t keep track of them
all&amp;hellip; but your orchestration layer can!  Or your service discovery layer.
Or some other tool.  &lt;em&gt;Something&lt;/em&gt; has to track your containers.&lt;/p&gt;

&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Most of this is identical to the processes you should already be following
for good code deployments.  Containers don&amp;rsquo;t bring much new to this,
although they may change &lt;em&gt;how&lt;/em&gt; you do it.  Containers also encourage
the development of &lt;a href=&#34;http://12factor.net/&#34;&gt;12 factor&lt;/a&gt; applications.&lt;/p&gt;

&lt;p&gt;The challenge, of course, is that many enterprises &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; follow these
processes.  They allow a &lt;a href=&#34;https://www.sweharris.org/post/2016-04-02-container-security/&#34;&gt;wild west&lt;/a&gt;
development style and call it &amp;ldquo;DevOps&amp;rdquo; and &amp;ldquo;agile&amp;rdquo;; they focus on
speed of delivery and sacrifice many of the controls that are necessary.&lt;/p&gt;

&lt;p&gt;Take time, now, to build the management tooling and automation of these
steps.  Then you can genuinely build an environment where your developers
can get code live using whether named process they like.  Your automation
will help encourage good security, good code design, and also remove
hindrances to deployment.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Container Security is Easy</title>
      <link>https://www.sweharris.org/post/2016-04-07-container-security-is-easy/</link>
      <pubDate>Thu, 07 Apr 2016 20:02:40 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-04-07-container-security-is-easy/</guid>
      <description>

&lt;p&gt;People think container security is hard.  But it&amp;rsquo;s not&amp;hellip; if you
think about it the right way.  And that&amp;rsquo;s where people tend to go
wrong, and that&amp;rsquo;s why they think it is hard.&lt;/p&gt;

&lt;p&gt;So let&amp;rsquo;s follow a thought pattern&amp;hellip;&lt;/p&gt;

&lt;p&gt;First we need to consider what is a container and what distinguishes it
from a virtual machine.&lt;/p&gt;

&lt;p&gt;In general a container has the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shared kernel&lt;/li&gt;
&lt;li&gt;Segmented view of resources

&lt;ul&gt;
&lt;li&gt;Separate process ID space&lt;/li&gt;
&lt;li&gt;Separate filesystem mount space&lt;/li&gt;
&lt;li&gt;Separate IPC memory segments&lt;/li&gt;
&lt;li&gt;Separate view of the network&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Multi-platform

&lt;ul&gt;
&lt;li&gt;Linux VServer (from 2001!)&lt;/li&gt;
&lt;li&gt;OpenVZ&lt;/li&gt;
&lt;li&gt;AIX WPARs&lt;/li&gt;
&lt;li&gt;Solaris &lt;del&gt;Containers&lt;/del&gt; Zones (from Solaris 10, 2005)&lt;/li&gt;
&lt;li&gt;Linux containers (LXC, cgroups, etc)&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Warden&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see that containers aren&amp;rsquo;t even new.  I was using VServer on
a RedHat 6 build (not RHEL; the old old RedHat!) in 2001 to create
&amp;ldquo;bastion servers&amp;rdquo; on my firewall machine; one bastion had an apache
instance, another handled incoming SMTP, another handled incoming ssh.
(Yes, yes; overkill for a home network at the end of a 640/128K DSL
connections!)&lt;/p&gt;

&lt;p&gt;Solaris tended to treat their containers as lightweight VMs; you could
install a whole copy of the OS or you could create &amp;lsquo;sparse zones&amp;rsquo; which
used the parent OS image as a read-only copy inside the zone.  There was
a persistent filesystem (typically from ZFS) associated with the zone.&lt;/p&gt;

&lt;p&gt;There are plenty of ultra-cheap &amp;ldquo;virtual machine&amp;rdquo; providers that use
OpenVZ and similar to give you a &amp;ldquo;server&amp;rdquo;.  It&amp;rsquo;s not a VM, but it&amp;rsquo;s
mostly good enough.&lt;/p&gt;

&lt;h3 id=&#34;so-what-goes-into-a-container&#34;&gt;So what goes into a container?&lt;/h3&gt;

&lt;p&gt;Almost anything.  As we saw from Solaris, a container could contain a
whole OS install.
Including an ssh daemon, an IP address dedicated to the container
and so on (so now we have identity and access management issues;
remote scanning issues; change management issues&amp;hellip;)&lt;/p&gt;

&lt;p&gt;On the other hand a container could contain the minimum necessary to run
the code.  My &amp;ldquo;web&amp;rdquo; bastion server from 2001 had httpd and the minimum
necessary libraries and binaries to run it.&lt;/p&gt;

&lt;p&gt;With a language such as &amp;ldquo;go&amp;rdquo; (which compiles to a static binary) a container
could contain as little as a single binary plus a few pseudo devices to
make it work.  It could have an &amp;ldquo;internal to the machine&amp;rdquo; ethernet address
with the parent OS port forwarding traffic on a single port.&lt;/p&gt;

&lt;p&gt;Over on the docker blog, Mike Coleman &lt;a href=&#34;https://blog.docker.com/2016/03/containers-are-not-vms/&#34;&gt;argues that containers are not VMs&lt;/a&gt;.  He&amp;rsquo;s right that
they &lt;em&gt;shouldn&amp;rsquo;t&lt;/em&gt; be.  Unfortunately that&amp;rsquo;s how some people use them.
In an &lt;a href=&#34;https://www.sweharris.org/post/2016-04-02-container-security/&#34;&gt;earlier post&lt;/a&gt; I highlighted how some
people may treat a container as VM and flagged that this is wrong.&lt;/p&gt;

&lt;h3 id=&#34;if-containers-are-so-flexible-how-do-i-secure-them&#34;&gt;If containers are so flexible, how do I secure them?&lt;/h3&gt;

&lt;p&gt;Let&amp;rsquo;s look at the worst case scenario.
A container may have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A cut down (maybe!) version of the OS

&lt;ul&gt;
&lt;li&gt;Glibc, bash, web server, support libraries, tools&lt;/li&gt;
&lt;li&gt;Maybe different versions than those running on the host!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Filesystems

&lt;ul&gt;
&lt;li&gt;Private to the container?&lt;/li&gt;
&lt;li&gt;Shared with the host?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Access to the network

&lt;ul&gt;
&lt;li&gt;Bridged to the main network?&lt;/li&gt;
&lt;li&gt;NAT?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Processes that run

&lt;ul&gt;
&lt;li&gt;Network listeners&lt;/li&gt;
&lt;li&gt;User logins&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Despite Mike&amp;rsquo;s comments, this sounds like a whole operating system to me.
The only difference is the shared kernel.&lt;/p&gt;

&lt;p&gt;So, in the worst case, we need to control this the same as the OS.
And deal with the unique challenges.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s easy to draw parallels.  To start with:&lt;/p&gt;

&lt;table border=1&gt;
&lt;tr&gt;
  &lt;th&gt;&amp;nbsp;&lt;/th&gt;
  &lt;th&gt;Virtual Machine&lt;/th&gt;
  &lt;th&gt;Container&lt;/th&gt;
  &lt;th&gt;New threat&lt;/th&gt;
&lt;/tr&gt;

&lt;tr&gt;
  &lt;td&gt;&#34;Parent Access&#34;&lt;/td&gt;
  &lt;td&gt;Hypervisor attack; one VM may be able to use hypervisor bugs to gain access to another VM&lt;/td&gt;
  &lt;td&gt;Parent OS attack; process may be able to escape the container&lt;/td&gt;
  &lt;td&gt;More people may have access to the host OS than to the Hypervisor; more threat actors.&lt;br&gt;
Shared kernel is bigger than hypervisor; bigger attack surface&lt;br&gt;
Kernel may allow dynamically loaded modules; variable attack surface!&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
  &lt;td&gt;&#34;Shared resources&#34;&lt;/td&gt;
  &lt;td&gt;Rowhammer&lt;br&gt;
Noisy neighbour&lt;br&gt;
Overallocation&lt;br&gt;
...&lt;/td&gt;
  &lt;td&gt;Mostly the same&lt;/td&gt;
  &lt;td&gt;Resource separation is now in the kernel; not as well segregated; not all resources may be segregated&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
  &lt;td&gt;&#34;Unique Code&#34;&lt;/td&gt;
  &lt;td&gt;Each VM may run a different OS, different patch revisions, different software&lt;/td&gt;
  &lt;td&gt;Each container may run different software versions, different patch levels, different libraries&lt;/td&gt;
  &lt;td&gt;Scaling issue; we can run many more containers than VMs&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
  &lt;td&gt;&#34;Inventory management&#34;&lt;/td&gt;
  &lt;td&gt;What machines are out there?  What OS are they running?  Are they patched?  What services are they running?...&lt;/td&gt;
  &lt;td&gt;Mostly the same&lt;/td&gt;
  &lt;td&gt;We typically have strong controls as to who can create new VM&#39;s but we allow anyone to spin up a new container &#39;cos it&#39;s so quick and easy!&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
  &lt;td&gt;&#34;Rogue code&#34;&lt;/td&gt;
  &lt;td&gt;Is the software secure?  Acceptable license terms?  Vulnerability scanned?&lt;/td&gt;
  &lt;td&gt;Mostly the same&lt;/td&gt;
  &lt;td&gt;Anyone can build a container; it may have different versions of core code (eg glibc) than the core OS.  Developers may introduce buggy low-level routines without noticing&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;p&gt;I think it becomes clear that, in the worst case, there are no new problems.
We see all these at the VM level.&lt;/p&gt;

&lt;p&gt;So can we use the same solution?&lt;/p&gt;

&lt;h3 id=&#34;where-are-things-different&#34;&gt;Where are things different?&lt;/h3&gt;

&lt;p&gt;Unlike a VM, a container may have other characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Very dynamic

&lt;ul&gt;
&lt;li&gt;Harder to track, maintain inventory&lt;/li&gt;
&lt;li&gt;If you don&amp;rsquo;t know what is out there, how can you patch?&lt;/li&gt;
&lt;li&gt;How many containers may suffer shellshock, heartbleed or CVE-2015-7547 (glibc) issues because we don&amp;rsquo;t know where they run?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Technology specific issues

&lt;ul&gt;
&lt;li&gt;Docker daemon running as root?&lt;/li&gt;
&lt;li&gt;SELinux interaction&lt;/li&gt;
&lt;li&gt;Root inside a container may be able to escape (eg via /sys)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Kernel bugs

&lt;ul&gt;
&lt;li&gt;Ensure your parent OS is patched!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What is now highlighted is that the existing solutions may not scale
properly.  What works for a 1,000 (or even 10,000) VMs won&amp;rsquo;t work for
100,000 or millions of containers.&lt;/p&gt;

&lt;p&gt;Can your solutions deal with containers spinning up, running for a few
minutes, then shutting down again?  Probably not.&lt;/p&gt;

&lt;h3 id=&#34;the-easy-way&#34;&gt;The easy way.&lt;/h3&gt;

&lt;p&gt;The above is the &lt;em&gt;hard&lt;/em&gt; way of doing it.  You can manage your containers
that way if you want.  If you do then you&amp;rsquo;re just using the container as
a lighter-weight VM.  You&amp;rsquo;re likely to hit problems.  If you want a VM
then &lt;em&gt;build&lt;/em&gt; VMs.  Automate your VM build processes; don&amp;rsquo;t rely on
docker repositories (I &lt;em&gt;hope&lt;/em&gt; no enterprise is using external docker
repos, anyway&amp;hellip; that should go without saying).&lt;/p&gt;

&lt;p&gt;Instead, if you want to make use of containers you &lt;em&gt;must&lt;/em&gt; follow Mike&amp;rsquo;s
advice and &lt;em&gt;stop&lt;/em&gt; thinking about containers as light-weight VMs.&lt;/p&gt;

&lt;p&gt;Now you can start to think of the flexibility containers can give you.
You can scale bigger and better.&lt;/p&gt;

&lt;p&gt;While container technology allows you to treat a container as VM, you
should think of a container as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transient

&lt;ul&gt;
&lt;li&gt;There is no persistent storage&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Short lived

&lt;ul&gt;
&lt;li&gt;Anywhere from microseconds upwards&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Immutable

&lt;ul&gt;
&lt;li&gt;You don&amp;rsquo;t change the running container; you build a new image and deploy that&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Untouchable

&lt;ul&gt;
&lt;li&gt;You NEVER LOG IN!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Automated

&lt;ul&gt;
&lt;li&gt;If you can&amp;rsquo;t login, you better automate the builds&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we can start to build a container security model.  We have an application
focus, rather than an OS focus.  You don&amp;rsquo;t allow people to deploy containers;
your &amp;ldquo;application delivery system&amp;rdquo; does it for them.&lt;/p&gt;

&lt;p&gt;Now we&amp;rsquo;re on the path to elastic compute; if your app deployment is hands off
then you can start to scale!&lt;/p&gt;

&lt;h3 id=&#34;minimizing-attack-surface&#34;&gt;Minimizing attack surface&lt;/h3&gt;

&lt;p&gt;We can follow basic hygiene rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Harden the kernel

&lt;ul&gt;
&lt;li&gt;You don&amp;rsquo;t have to use the vendor provided one&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Ensure the OS is patched&lt;/li&gt;
&lt;li&gt;Integrate into your CI/CD process

&lt;ul&gt;
&lt;li&gt;No manual startup of containers&lt;/li&gt;
&lt;li&gt;Only those that passed testing, vuln scanning, etc can be run&lt;/li&gt;
&lt;li&gt;No external code without approval&lt;/li&gt;
&lt;li&gt;Standard code hygiene (provenance, licensing, etc)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Automate, automate, automate!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives big wins.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many licenses are you using?  You &lt;em&gt;know&lt;/em&gt; because your automation tools
will tell you what is running&lt;/li&gt;
&lt;li&gt;A CVE has been found; you &lt;em&gt;know&lt;/em&gt; what images are vulnerable and where they
are running

&lt;ul&gt;
&lt;li&gt;Your image is more lightweight so may not be vulnerable in the first place!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Patching doesn&amp;rsquo;t exist; you just redeploy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And another benefit&amp;hellip; if your app can be delivered this way, you can &lt;em&gt;also&lt;/em&gt;
start to deploy VMs this way.  A Linux OS without any form of login?  Let&amp;rsquo;s
see someone brute-force ssh bad passwords that way :-)&lt;/p&gt;

&lt;h3 id=&#34;but-remember&#34;&gt;But remember&lt;/h3&gt;

&lt;p&gt;Container security is weaker than VM security; the kernel has a large
surface area to be attacked.&lt;/p&gt;

&lt;p&gt;VM security is weaker than physical machine security.&lt;/p&gt;

&lt;p&gt;Network security is weaker than air-gap separation.&lt;/p&gt;

&lt;p&gt;Air-gapped machines are weaker than a server covered in cement and dropped
into the bottom of the ocean.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ve seen that using a container as a light-weight VM doesn&amp;rsquo;t make sense;
you haven&amp;rsquo;t solved any security issues, you&amp;rsquo;ve just increased them!&lt;/p&gt;

&lt;p&gt;Your security stance depends on your needs and risk evaluation.  Pick the
technology that is right for you and &lt;em&gt;use it appropriately&lt;/em&gt;.&lt;/p&gt;

&lt;h3 id=&#34;summary&#34;&gt;Summary&lt;/h3&gt;

&lt;p&gt;Google have been using containers for around a decade.  Docker has made
massive strides in bring containers down a easily automatable format.&lt;/p&gt;

&lt;p&gt;But containers &lt;del&gt;are not&lt;/del&gt; should not be VMs.&lt;/p&gt;

&lt;p&gt;Google Functions?  Amazon Lamba?  They&amp;rsquo;re containers!  A rules engine
triggers on an event, starts up a container, runs your function, destroys
the container.  A container that spins up, runs, is destroyed in a fraction
of a second.  How cool is that?&lt;/p&gt;

&lt;p&gt;A PaaS like Cloud Foundry; your app runs inside a container.  The autoscaler
will spin up new containers across the cloud.  A VM dies, the PaaS will spin
up a new copy.   All you deal with is your app code; you don&amp;rsquo;t touch the OS.&lt;/p&gt;

&lt;p&gt;Docker can build light weight containers that can then be thrown into
Mesosphere; a Swarm of apps can be started up in containers across the
cloud quicker than you can read this post.&lt;/p&gt;

&lt;p&gt;And they all work by following the basic rules&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transient&lt;/li&gt;
&lt;li&gt;Immutable&lt;/li&gt;
&lt;li&gt;Untouchable&lt;/li&gt;
&lt;li&gt;Shortlived&lt;/li&gt;
&lt;li&gt;Automated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think this post is long enough; we still need to touch on lifecycle managment to complete the security model.&lt;/p&gt;

&lt;p&gt;But you already have that&amp;hellip; right?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Container security</title>
      <link>https://www.sweharris.org/post/2016-04-02-container-security/</link>
      <pubDate>Sat, 02 Apr 2016 20:29:33 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-04-02-container-security/</guid>
      <description>&lt;p&gt;It started with a
&lt;a href=&#34;https://github.com/athornton/containers-for-curmudgeons/blob/master/talk.rst&#34;&gt;set of slides&lt;/a&gt;
by a friend:&lt;/p&gt;

&lt;p&gt;My first thought was to wonder wonder how heartbleed, shellshock,
cve-2015-7547 and the like fit into this story.  He answered &amp;ldquo;rebuild
the world and redeploy&amp;rdquo;.  Which I felt missed the problem.&lt;/p&gt;

&lt;p&gt;You also need a level of control around &lt;em&gt;what&lt;/em&gt; goes into containers,
who can build containers, where they get deployed.&lt;/p&gt;

&lt;p&gt;We have decades of history of knowing that self-run machines are badly
patched and badly maintained; if the bug isn&amp;rsquo;t in the application code
then it&amp;rsquo;s mostly invisible to the developer.  Hell, even SAs are bad
at patching unless forced (&amp;ldquo;my server has 1000 days uptime!&amp;rdquo; is not a
good brag).&lt;/p&gt;

&lt;p&gt;What has changed?  Why will we expect developers to start maintaining
their private OS instance (which is, effectively, what a container is)
now?  Worse, in an environment where everyone and their dog can spin up
containers then you may not even know where your vulnerable systems are.&lt;/p&gt;

&lt;p&gt;With an opinionated PaaS like Cloud Foundry the developer gets no say;
it&amp;rsquo;s handled under the covers.  But if you open up containers without
control?&lt;/p&gt;

&lt;p&gt;The story I hear (and Adam&amp;rsquo;s slides seem to go in that direction)
is that containers are great for self-service; allow the developers
to push whatever the hell they like; they have the ability to fix it,
to make sure the code works; they are now masters of their own fate and
they can&amp;rsquo;t break the host.&lt;/p&gt;

&lt;p&gt;But nowhere do I hear &amp;ldquo;security&amp;rdquo;.  Indeed Adam&amp;rsquo;s slides specifically &lt;em&gt;permit&lt;/em&gt;
insecurities:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;    No need to worry about doing it the right way: just throw the
    library binaries, framework templates, ancient, buggy,
    security-vulnerable versions of Java, whatever in there
    higgedly-piggledy!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a bad view of security.  If you&amp;rsquo;re running buggy code (&amp;ldquo;I&amp;rsquo;m
looking at &lt;em&gt;you&lt;/em&gt;, Wordpress!&amp;ldquo;) then your container gets pwned.  OK&amp;hellip; not
the whole host, but there&amp;rsquo;s now an RCE in your environment.  And it can
talk to the persistent data stores.  And can exfiltrate that data. And
can be used to pivot to other internal services that may not have been
exposed&amp;hellip; and let&amp;rsquo;s hope the parent host has a patched kernel so it
doesn&amp;rsquo;t allow container escape.&lt;/p&gt;

&lt;p&gt;From a security perspective we need to look at containers as if they are
a VM of their own.  They have the same vulnerability footprint as a real
OS, plus new additional ones.  We can&amp;rsquo;t use traditional external-scans
to help detect faults; they were never a good idea, and simply won&amp;rsquo;t
scale to a dynamic elastic environment.  We need to build this in.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s &lt;em&gt;not&lt;/em&gt; stopping DevOps; we need to embed the culture of security
into the development pipeline.  Have your Jenkins job do a vuln scan
during your auto-build.  Have a deployment engine that tracks what
is where.  Have a control mechanism to hard-stop pwned services.&lt;/p&gt;

&lt;p&gt;Sorry; despite the lure of freedom, containers &lt;em&gt;must not&lt;/em&gt; become the
wild west; we&amp;rsquo;ll lose, big time, if we let it.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>New site</title>
      <link>https://www.sweharris.org/post/2016-04-02-newsite/</link>
      <pubDate>Sat, 02 Apr 2016 07:55:25 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-04-02-newsite/</guid>
      <description>&lt;p&gt;My &lt;a href=&#34;http://sweh.spuddy.org&#34;&gt;old site&lt;/a&gt; was nicely hand crafted HTML.  Each
bit loving created.  It worked&amp;hellip; but it did smell a little 90&amp;rsquo;s.  Which
doesn&amp;rsquo;t surprise me; the last time I did any web development &lt;em&gt;was&lt;/em&gt; the 90s!&lt;/p&gt;

&lt;p&gt;So I thought I&amp;rsquo;d try something a little more modern.&lt;/p&gt;

&lt;p&gt;Unfortunately most CMS systems (eg WordPress, Joomla, Drupal) appear to
want to use a database of some form.  The content is displayed dynamically
based on the user request and the database content.&lt;/p&gt;

&lt;p&gt;I have 3 servers (a &lt;a href=&#34;http://www.linode.com&#34;&gt;Linode&lt;/a&gt;,
a &lt;a href=&#34;http://www.panix.com/v-colo&#34;&gt;Panix v-colo&lt;/a&gt;,
and an OVH &lt;a href=&#34;http://www.soyoustart.com/us/&#34;&gt;So You Start&lt;/a&gt; colo server).
Each one has identical content and could stand in as a DR for the others
for web, mail, DNS.&lt;/p&gt;

&lt;p&gt;Using a database backed CMS introduces challenges (eg database replication,
backups) as well as potential performance issues.&lt;/p&gt;

&lt;p&gt;I wanted something that was more &amp;ldquo;static file&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Some net-friends pointed me at some site generators.  Some were written
in python, some in Ruby, some in perl.  They have large run-time
dependencies to build the site (none for actually serving it).&lt;/p&gt;

&lt;p&gt;But &lt;a href=&#34;http://gohugo.io&#34;&gt;Hugo&lt;/a&gt; is written in Go and so compiles to a
static binary.  Ooh!  This looks interesting&amp;hellip;&lt;/p&gt;

&lt;p&gt;I played around with some themes and decided on the &lt;a href=&#34;http://themes.gohugo.io/theme/blackburn/&#34;&gt;Blackburn&lt;/a&gt; theme, with a few tweaks.&lt;/p&gt;

&lt;p&gt;Hugo has some nice features, including a built in server.  I can write a
new markdown document and immediately Hugo will detect this and publish it.
It&amp;rsquo;ll even cause the viewing browser to refresh.  So in one window I can
type and &lt;code&gt;:w&lt;/code&gt; (yes; &lt;code&gt;vi&lt;/code&gt;) and the browser in a background window automatically
refreshes.  That&amp;rsquo;s cool!&lt;/p&gt;

&lt;p&gt;Once I&amp;rsquo;m happy with the content I can then tell it to generate the static
content.  And then I can rsync it to my 3 servers to publish it.&lt;/p&gt;

&lt;p&gt;The one downside to this theme is that it does call a number of off-platform
javascript and fonts.  I&amp;rsquo;ve tried to modify it to host as much locally as
possible (from a security perspective, calling random javascript from a
random CDN seems &lt;em&gt;wrong&lt;/em&gt;) but there&amp;rsquo;s still a large amount.  &lt;em&gt;Sigh&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I also debated having a comment system.  I&amp;rsquo;m of two minds.  Currently I
have Disqus set up.  This does allow anonymous posts and does a level of
spam trapping for me.  I&amp;rsquo;m not a total fan of Disqus (tonnes of javascript,
cross-site tracking) and may turn it off.  But it works.&lt;/p&gt;

&lt;p&gt;My ultimate aim is to start blogging more frequently (hence the blog format
of this new site).  Mostly writing about security stuff, probably.  I&amp;rsquo;ve
made my content CC BY-NC-ND, just in case I write something someone else
likes :-)&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ll probably keep the old site running because some stuff (eg reference
information) isn&amp;rsquo;t too suited for a blog format.  We&amp;rsquo;ll see.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>About me</title>
      <link>https://www.sweharris.org/about/</link>
      <pubDate>Fri, 01 Apr 2016 12:26:31 -0400</pubDate>
      
      <guid>https://www.sweharris.org/about/</guid>
      <description>&lt;p&gt;&lt;center&gt;&lt;img src=&#34;https://www.sweharris.org/images/dilbert-unix-small.gif&#34; alt=&#34;Dilbert&#34; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;I first got into Unix in 1987.  SunOS 3 on the Oxford &amp;ldquo;mclab&amp;rdquo; network
(who else remembers &amp;ldquo;NFS server pampa not responding, still trying&amp;rdquo;?).
At the same time I had access to the &amp;ldquo;High Level Hardware Orion&amp;rdquo; machines,
in the Clarendon Nuclear Physics lab as a member of Oxford Microsoc.&lt;/p&gt;

&lt;p&gt;I had no idea what I was doing.  But I learned pretty quickly!&lt;/p&gt;

&lt;p&gt;My first job was as a SA for Papachristidis Limited; a Greek shipping based
out of London.  It was a small office so I ended up doing almost everything
(coding, networking, SA, fax machine, telephones, even the door entry security
system).  It was a good place to learn and hone my skills.&lt;/p&gt;

&lt;p&gt;At this point I started with Linux (0.11 kernel) and even &lt;a href=&#34;http://www.linuxjournal.com/article/1111&#34;&gt;got interviewed
by Linux Journal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Around the same time I took over the running of Spuddy (&lt;a href=&#34;https://www.sweharris.org/spuddy/&#34;&gt;link to old old
old spuddy website&lt;/a&gt;), which provided free email and usenet
in the UK.  Basically a Sun 2 with a Magma serial port extender and a
handful of modems.  A British Telecom engineer once claimed I had more
phone lines in my spare bedroom than some companies!  Spuddy even got
written up in the national computer press and was compared favourably
to commercial providers.&lt;/p&gt;

&lt;p&gt;My next job was at VNU Business Publications in London, working in a
startup division called MatriX Publishing Network.  (I remember one of the
staff members claiming &amp;ldquo;We got Spuddy!&amp;rdquo; when I accepted the contract).
I did SA, networking, web development, I even wrote a few magazine
articles.  The division got shut down (we were making a profit, but not
in the core business areas) and I moved into the central IT team where
I began my path of automation and centralisation; rolled out Big Brother,
created a paging sytem, backups&amp;hellip; Eventually I had the Unix servers under
control so they made me learn Oracle DBA&amp;hellip; then Windows NT4 admin&amp;hellip; and then Lotus Notes
(at which point I ran away).&lt;/p&gt;

&lt;p&gt;In 1999 I started to work for JPMorgan (now JPMorganChase).  I&amp;rsquo;ve
been in various roles in that company.  Most recently I did cloud
security engineering.  And in 2016 I started with First Data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DISCLAIMER:&lt;/strong&gt; Nothing I write can be considered official policy
of any company I have worked for.  It&amp;rsquo;s just my opinion.  And, hey,
I have opinions!   In the long long distant past of usenet I had a
signature:
&lt;pre&gt;
      The truth is the truth, and opinion just opinion.  But what is what?
       My employer pays to ignore my opinions; you get to do it for free.
&lt;/pre&gt;
I hope my employers now listen to my opinions, but you can still ignore them!&lt;/p&gt;

&lt;p&gt;But my life with computers started before then.  In 1981 I started to
play with the school&amp;rsquo;s Commodore PETs.  I taught myself 6502 assembler
from a book and hand assembled some simple stuff.  Like lots of kids
I typed in listings from magazines and then debugged the typos.&lt;/p&gt;

&lt;p&gt;For Christmas 1983 I got my own computer; a BBC Micro.  I still have it!
&lt;center&gt;&lt;img src=&#34;https://www.sweharris.org/images/bbc-micro.jpg&#34; alt=&#34;BBC&#34; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;So 1984 was when I started to hit my stride.  And that&amp;rsquo;s when I first
learned that people will break things; without trying!  My brother was a
great help, here.  I recall writing him a simple &amp;ldquo;football score emulator&amp;rdquo;
(each team had a random weighting and the program would create score
cards, similar to that shown on TV every Saturday).  I presented a menu
and expected people to enter &amp;ldquo;1-22&amp;rdquo;.  My brother typed in the team name.
Whuh?  Naturally the program crashed (out of range error).&lt;/p&gt;

&lt;p&gt;And this is where I started my &amp;ldquo;security&amp;rdquo; journey.  All the way back over
30 years ago.  I taught myself defensive coding; sanitise and validation
of input.  As time went on those techiques grew into general purpose rules
(e.g. &amp;ldquo;don&amp;rsquo;t trust the client&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;When the web became popular and people stuck validation routines into
their javascript but didn&amp;rsquo;t implement them at the backend then I laughed;
and demonstrated their folly.&lt;/p&gt;

&lt;p&gt;But I&amp;rsquo;ve never been a hacker; not really.  I&amp;rsquo;m not a &amp;ldquo;security researcher&amp;rdquo;.
I&amp;rsquo;m not a trained security individual (no CISSP, here!).  I don&amp;rsquo;t play
&amp;ldquo;defense&amp;rdquo; or &amp;ldquo;offense&amp;rdquo; in the infosec world, although I have a tendancy
towards defense.&lt;/p&gt;

&lt;p&gt;What I am, though, is a security aware person.  I have over 30 years of
experience and can apply it to new situations.  Build &amp;ldquo;secure from the
start&amp;rdquo; solutions.  Take a newly found bug and evaluate it.  This puts
me somewhere between &amp;ldquo;risk evaluation&amp;rdquo; and &amp;ldquo;security&amp;rdquo;.  It&amp;rsquo;s a role I
don&amp;rsquo;t see many people filling!&lt;/p&gt;

&lt;p&gt;Which leads, inevitably, to my &lt;a href=&#34;https://www.sweharris.org/cv.pdf&#34;&gt;CV (or resume, in American)&lt;/a&gt; (PDF).&lt;/p&gt;

&lt;p&gt;Note that this blog is inherently an &amp;ldquo;enterprise&amp;rdquo; view of the world.  An
organisation with controls requirements, potentially regulators and
auditors.&lt;/p&gt;

&lt;p&gt;But some of the concerns also affect everyone; do you want to run code
that is hackable?  That causes an RCE (Remote Code Execution) and so
people can &amp;ldquo;pivot&amp;rdquo; and attack other servers?  Even education research
environments should care about this.&lt;/p&gt;

&lt;p&gt;So if you&amp;rsquo;re interested in a non-sensational (I hope!) viewpoint on
modern internet security as it pertains to the enterprise, maybe this
blog will be a good place to look.&lt;/p&gt;

&lt;p&gt;I can&amp;rsquo;t promise frequent updates; I can&amp;rsquo;t promise 100% accurate evaluations.
But it may still be interesting.&lt;/p&gt;

&lt;p&gt;If you need to contact me for any reason and leaving a comment on a blog
post entry isn&amp;rsquo;t what you&amp;rsquo;re looking for then here&amp;rsquo;s my business card!&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&#34;https://www.sweharris.org/Cards/business_card.jpg&#34; alt=&#34;new card&#34; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;And who are you reading?  Well, this is me&amp;hellip; or it was in 2016, anyway!&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&#34;https://www.sweharris.org/images/sweharris.jpg&#34; alt=&#34;Me&#34; /&gt;&lt;/center&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Breaking the MBR on every hard disk</title>
      <link>https://www.sweharris.org/post/2016-02-10-break-mbr/</link>
      <pubDate>Wed, 10 Feb 2016 19:46:00 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2016-02-10-break-mbr/</guid>
      <description>&lt;p&gt;I was reminded of a &lt;a href=&#34;https://www.backblaze.com/blog/hard-drive-smart-stats/&#34;&gt;backblaze
article&lt;/a&gt; about
SMART numbers.  This nudged me to look up the stats on my drives to see
if any numbers had budged.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s collect the data for processing:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  for a in /dev/sd?
  do
    smartctl -a $a &amp;gt; $a
  done
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Spot the error.&lt;/p&gt;

&lt;p&gt;I ran the code.  Did an &amp;ldquo;ls&amp;rdquo;&amp;hellip; and didn&amp;rsquo;t see any output.  I started
to panic a little&amp;hellip; I didn&amp;rsquo;t just do what I think I just did&amp;hellip; did I?&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s right!  I just overwrote the MBR on ALL my disks with smartctl
output.  8*4Tb, 4*2Tb, 2*512Gb SSD and a 1Tb external disk.  All broke.&lt;/p&gt;

&lt;p&gt;Oh fuckety fuckety fuckety fuck.&lt;/p&gt;

&lt;p&gt;At this point I was running around biting my knuckles.  My heart was racing.&lt;/p&gt;

&lt;p&gt;I switched to decaf.  Used the walk to the coffee machine to force some
thinking time.&lt;/p&gt;

&lt;p&gt;The machine was still working.  It hadn&amp;rsquo;t noticed.&lt;/p&gt;

&lt;p&gt;I started to calm down&amp;hellip;&lt;/p&gt;

&lt;p&gt;The largest of the output was 10K long.  Fortunately I don&amp;rsquo;t put the
raw disks into RAID arrays; I create one large partition on each disk
and use that.  10K is 20-ish sectors.  The first partition on every disk
was 2048 or 4096 sectors in, except for the external disk which was 64
sectors in.  Yes, I waste 2Mbyte of disk this way&amp;hellip;&lt;/p&gt;

&lt;p&gt;But that wasted space may have saved me.  I began to think that my data
was safe.  All I needed to do was recreate the MBR.&lt;/p&gt;

&lt;p&gt;For that I needed the partition data.  It must be in the kernel somewhere,
right?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/proc/partitions&lt;/code&gt; was particularly useless.  It tells me what partitions
were there and the size&amp;hellip; but not where it started.&lt;/p&gt;

&lt;p&gt;Ah, &lt;code&gt;/sys/block/$disk/$partition&lt;/code&gt; has two entries; &amp;ldquo;start&amp;rdquo; and &amp;ldquo;size&amp;rdquo;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sda/sda1/start:2048
sda/sda1/size:16775168
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That looks useful!  I think I can recover&amp;hellip;  No partition &lt;em&gt;type&lt;/em&gt;,
but I know that :-)&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s grab all that data just in case the machine does crash and I
lose it.  This is my best chance of recovery.&lt;/p&gt;

&lt;p&gt;A vague memory&amp;hellip; GPT data is stored near the end of the disk&amp;hellip; on a
GPT disk the MBR is basically just used to &amp;ldquo;protect&amp;rdquo; the contents from
non-GPT aware apps.&lt;/p&gt;

&lt;p&gt;Bleh, parted bitches and moans.   gdisk?  Ooh, nice!  It told me the MBR
was barfed, and the GPT failed checksum&amp;hellip; but gave me the option to use
the GPT anyway.  I took it&amp;hellip; and it gave me the correct values!  SAVE!&lt;/p&gt;

&lt;p&gt;I was able to recover the 4*2Tb and 8*4Tb disks this way.&lt;/p&gt;

&lt;p&gt;The other 3 disks were too small so I hadn&amp;rsquo;t bothered with GPT; they
were just MBR partitioned.&lt;/p&gt;

&lt;p&gt;Now let&amp;rsquo;s see what we can do with sda&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sda/sda1/start:2048
sda/sda1/size:16775168

sda/sda3/start:16777216
sda/sda3/size:983438000
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;fdisk, units, create primary 1, start at 2048, +16775168.  create primary
3&amp;hellip; oh, can&amp;rsquo;t start at 16777216.  Partition 1 is 1 sector too large.
Need to reduce the size by 1.  Remember also to do that for Partion 3.
Set the types to FD (Autoraid), make partition 1 active.&lt;/p&gt;

&lt;p&gt;Repeat that for the other SSD.  Similarly for the 1Tb disk.&lt;/p&gt;

&lt;p&gt;Run grub-install against the two SSDs; they&amp;rsquo;re my boot mirrors.&lt;/p&gt;

&lt;p&gt;Now the moment of truth&amp;hellip;&lt;/p&gt;

&lt;p&gt;reboot!&lt;/p&gt;

&lt;p&gt;And&amp;hellip; relax.&lt;/p&gt;

&lt;p&gt;All the md RAID devices assembled correctly.  The machine booted cleanly,
as if nothing had gone wrong.&lt;/p&gt;

&lt;p&gt;Of course there&amp;rsquo;s still junk in the MBR of most of the disks&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% sudo dd if=/dev/sdb bs=1c count=256 | hdump -16
00000000  73 6D 61 72 74 63 74 6C 20 35 2E 34 33 20 32 30   smartctl 5.43 20
00000010  31 32 2D 30 36 2D 33 30 20 72 33 35 37 33 20 5B   12-06-30 r3573 [
00000020  78 38 36 5F 36 34 2D 6C 69 6E 75 78 2D 32 2E 36   x86_64-linux-2.6
00000030  2E 33 32 2D 35 37 33 2E 31 32 2E 31 2E 65 6C 36   .32-573.12.1.el6
00000040  2E 78 38 36 5F 36 34 5D 20 28 6C 6F 63 61 6C 20   .x86_64] (local
00000050  62 75 69 6C 64 29 0A 43 6F 70 79 72 69 67 68 74   build).Copyright
00000060  20 28 43 29 20 32 30 30 32 2D 31 32 20 62 79 20    (C) 2002-12 by
00000070  42 72 75 63 65 20 41 6C 6C 65 6E 2C 20 68 74 74   Bruce Allen, htt
00000080  70 3A 2F 2F 73 6D 61 72 74 6D 6F 6E 74 6F 6F 6C   p://smartmontool
00000090  73 2E 73 6F 75 72 63 65 66 6F 72 67 65 2E 6E 65   s.sourceforge.ne
000000a0  74 0A 0A 3D 3D 3D 20 53 54 41 52 54 20 4F 46 20   t..=== START OF
000000b0  49 4E 46 4F 52 4D 41 54 49 4F 4E 20 53 45 43 54   INFORMATION SECT
000000c0  49 4F 4E 20 3D 3D 3D 0A 4D 6F 64 65 6C 20 46 61   ION ===.Model Fa
000000d0  6D 69 6C 79 3A 20 20 20 20 20 53 65 61 67 61 74   mily:     Seagat
000000e0  65 20 42 61 72 72 61 63 75 64 61 20 47 72 65 65   e Barracuda Gree
000000f0  6E 20 28 41 64 76 2E 20 46 6F 72 6D 61 74 29 0A   n (Adv. Format).
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But the important part is the partition table&amp;hellip; and that&amp;rsquo;s just fine :-)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;000001a0  62 79 74 65 73 20 5B 32 2E 30 30 20 54 42 5D 0A   bytes [2.00 TB].
000001b0  53 65 63 74 6F 72 20 53 00 00 00 00 00 00 00 00   Sector S........
000001c0  02 00 EE FF FF FF 01 00 00 00 AF 88 E0 E8 00 00   ................
000001d0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
000001e0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
000001f0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA   ..............U.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Lesson: stop doing shit as root.  If I&amp;rsquo;d have done&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo smartctl -a $a &amp;gt; $a
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;then the redirect would have failed and I would have saved myself a
tonne of heartache.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Gullible</title>
      <link>https://www.sweharris.org/post/2015-08-24-gullible/</link>
      <pubDate>Mon, 24 Aug 2015 15:27:00 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2015-08-24-gullible/</guid>
      <description>&lt;p&gt;Coworker: i&amp;rsquo;ve found that networking/factime can pay dividends&lt;/p&gt;

&lt;p&gt;CW: *face time&lt;/p&gt;

&lt;p&gt;Me: &amp;ldquo;factime&amp;rdquo; - that was the early name for &amp;ldquo;bullet time&amp;rdquo;, but they realised &amp;ldquo;fast and circular&amp;rdquo; didn&amp;rsquo;t sound as cool.&lt;/p&gt;

&lt;p&gt;CW: stephen you ever play trivial pursuit and if so how&amp;rsquo;d you do?&lt;/p&gt;

&lt;p&gt;CW: or maybe jeopardy&lt;/p&gt;

&lt;p&gt;Me: Umm, you really shouldn&amp;rsquo;t believe everything I write :-)&lt;/p&gt;

&lt;p&gt;CW: lol&lt;/p&gt;

&lt;p&gt;CW2: Stephen, have you ever played balderdash? And if so, how&amp;rsquo;d you do? ;-)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>DHS redux</title>
      <link>https://www.sweharris.org/post/2015-07-08-dhs-redux/</link>
      <pubDate>Sat, 04 Jul 2015 07:30:00 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2015-07-08-dhs-redux/</guid>
      <description>&lt;p&gt;So it looks like those scans were coming from &lt;a href=&#34;https://www.us-cert.gov/ccubedvp/getting-started-federal&#34;&gt;NCATS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is only meant to scan networks associated with the Federal
government. I&amp;rsquo;m guessing there was a misconfiguration, somewhere,
&amp;lsquo;cos Panix tell me they never requested any scans of their network :-)&lt;/p&gt;

&lt;p&gt;Through a friend I contacted their SOC. I saw another scan yesterday
and escalated. They just replied and told me that they&amp;rsquo;ve removed the
IP ranges from their config.&lt;/p&gt;

&lt;p&gt;On the plus side, the only thing flagged by their scanning was that I
had TRACE enabled on my web site. Everything else looked good :-)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Huh, the department of homeland security is attacking me?</title>
      <link>https://www.sweharris.org/post/2015-07-04-dhs-attack/</link>
      <pubDate>Sat, 04 Jul 2015 07:30:00 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2015-07-04-dhs-attack/</guid>
      <description>&lt;p&gt;Either the DHS is attacking me, or else they&amp;rsquo;ve got compromised computers&amp;hellip;&lt;/p&gt;

&lt;p&gt;In my logs I see 1147 attempts from 64.69.57.20 to my web server; e.g.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;64.69.57.20 - - [03/Jul/2015:00:40:32 -0400] &amp;quot;\x16\x03\x01&amp;quot; 501 295 &amp;quot;-&amp;quot; &amp;quot;-&amp;quot;
64.69.57.20 - - [03/Jul/2015:00:40:40 -0400] &amp;quot;GNUTELLA CONNECT/0.6&amp;quot; 400 306 &amp;quot;-&amp;quot; &amp;quot;-&amp;quot;
64.69.57.20 - - [03/Jul/2015:00:40:41 -0400] &amp;quot;GET http://rfi.nessus.org/check_proxy.html HTTP/1.0&amp;quot; 404 293 &amp;quot;-&amp;quot; &amp;quot;Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)&amp;quot;
64.69.57.20 - - [03/Jul/2015:00:40:42 -0400] &amp;quot;ABKJFC / HTTP/1.1&amp;quot; 501 303 &amp;quot;-&amp;quot; &amp;quot;Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)&amp;quot;
64.69.57.20 - - [03/Jul/2015:00:40:42 -0400] &amp;quot;GET /aboutprinter.html HTTP/1.1&amp;quot; 404 300 &amp;quot;-&amp;quot; &amp;quot;Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)&amp;quot;
64.69.57.20 - - [03/Jul/2015:00:40:42 -0400] &amp;quot;GET /properties/configuration.php?tab=Status HTTP/1.1&amp;quot; 404 311 &amp;quot;-&amp;quot; &amp;quot;Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)&amp;quot;
64.69.57.20 - - [03/Jul/2015:00:40:52 -0400] &amp;quot;GET /etc/passwd HTTP/1.1&amp;quot; 404 293 &amp;quot;-&amp;quot; &amp;quot;Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)&amp;quot;
64.69.57.20 - - [03/Jul/2015:00:41:09 -0400] &amp;quot;GET /?&amp;lt;meta%20http-equiv=Set-Cookie%20content=%22testrdhw=3733%22&amp;gt; HTTP/1.1&amp;quot; 200 6059 &amp;quot;-&amp;quot; &amp;quot;Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;logwatch summary:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; Requests with error response codes
    400 Bad Request
       %.: 2 Time(s)
       %5c%2e%2e%5c%2e%2e%5c%2e%2e%5c%2e%2e%5c%2e ... winnt%5cwin.ini: 2 Time(s)
       .: 2 Time(s)
       ../../../../../../../../../../../../windows/win.ini: 2 Time(s)
       ../../../../../../../../../../../../winnt/win.ini: 2 Time(s)
       ..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\windows\\win.ini: 2 Time(s)
       ..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\winnt\\win.ini: 2 Time(s)
       ..\\..\\..\\..\\..\\..\\windows\\win.ini: 2 Time(s)
       ..\\..\\..\\..\\..\\..\\winnt\\win.ini: 2 Time(s)
       ./././././././././././././././././././././ ... ../../../../../: 2 Time(s)
       .\\.\\.\\.\\.\\.\\.\\.\\.\\.\\/windows/win.ini: 2 Time(s)
       .\\.\\.\\.\\.\\.\\.\\.\\.\\.\\/winnt/win.ini: 2 Time(s)
       /: 9 Time(s)
       /%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e ... e%2e/etc/passwd: 2 Time(s)
       /%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e ... e/winnt/win.ini: 2 Time(s)
       /%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e ... windows/win.ini: 2 Time(s)
       /%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd: 2 Time(s)
       /%NETHOOD%/: 2 Time(s)
       /%uff0e%uff0e/%uff0e%uff0e/%uff0e%uff0e/%u ... e/winnt/win.ini: 2 Time(s)
       /%uff0e%uff0e/%uff0e%uff0e/%uff0e%uff0e/%u ... ff0e/etc/passwd: 2 Time(s)
       /%uff0e%uff0e/%uff0e%uff0e/%uff0e%uff0e/%u ... windows/win.ini: 2 Time(s)
       /../../../../../../../../../../../../etc/passwd: 2 Time(s)
       /../../../../../../../../../../../../windows/win.ini: 2 Time(s)
       /../../../../../../../../../../../../winnt/win.ini: 2 Time(s)
       /./../../../../../../../../../../../etc/passwd: 2 Time(s)
       /././..: 2 Time(s)
       /././././././../../../../../etc/passwd: 2 Time(s)
       /././././././../../../../../windows/win.ini: 2 Time(s)
       /././././././../../../../../winnt/win.ini: 2 Time(s)
       //../../../../../../../../../../../../etc/passwd: 2 Time(s)
       /password: 2 Time(s)
       /tmUnblock.cgi: 1 Time(s)
       1435898497:@166.84.7.9/: 4 Time(s)
       : 1 Time(s)
       : 1 Time(s)
       : 1 Time(s)
       : 1 Time(s)
       CONNECT/0.4: 2 Time(s)
       CONNECT/0.6: 2 Time(s)
       c:\\boot.ini: 2 Time(s)
       invalid: 2 Time(s)
    403 Forbidden
       /: 1 Time(s)
       /.htaccess.1: 2 Time(s)
       /.htaccess.bak: 2 Time(s)
       /.htaccess.copy: 2 Time(s)
       /.htaccess.old: 2 Time(s)
       /.htaccess.tmp: 2 Time(s)
       /.htaccess.~1~: 2 Time(s)
       /.htaccess~: 2 Time(s)
    404 Not Found SUMMARY - 733 URLs, total: 1483 Time(s)
    405 Method Not Allowed
       /: 4 Time(s)
       /gprvpp1.html: 1 Time(s)
       /pevwoo1.html: 1 Time(s)
    417 Expectation Failed
       /: 1 Time(s)
    501 Not Implemented
       *: 2 Time(s)
       /: 4 Time(s)
       null: 5 Time(s)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Nessus proxy check line makes me think this might be a generic
scan&amp;hellip; but why my machine?&lt;/p&gt;

&lt;p&gt;They didn&amp;rsquo;t stop there&amp;hellip; I have SSHD running on a non-standard port. If
someone attempts to connect too frequently then they get blocked (simple
iptables rule). I can see 6 dropped packets from the same SRC=64.69.57.20
to my SSH port.&lt;/p&gt;

&lt;p&gt;Didn&amp;rsquo;t stop there, either. DNS attempts?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;client 64.69.57.20 bad zone transfer request: &#39;dastardly.spuddy.org/IN&#39;: non-authoritative zone (NOTAUTH): 1 Time(s)
client 64.69.57.20 bad zone transfer request: &#39;org/IN&#39;: non-authoritative zone (NOTAUTH): 1 Time(s)
client 64.69.57.20 bad zone transfer request: &#39;ssl.spuddy.org/IN&#39;: non-authoritative zone (NOTAUTH): 1 Time(s)
client 64.69.57.20 update forwarding &#39;spuddy.org/IN&#39; denied: 1 Time(s)
client 64.69.57.20 query (cache) &#39;example.com/A/IN&#39; denied
client 64.69.57.20 query (cache) &#39;\.\./nessus/A/IN&#39; denied
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Looks like also some port scans, &amp;lsquo;cos I can see &amp;ldquo;rsync&amp;rdquo; (started from
xinetd) being woken up (but it rejects them access).&lt;/p&gt;

&lt;p&gt;And, from another machine on the same network, SMTP attacks!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;CONNECT from unknown[64.69.57.28]: 503 5.5.0 : Client host rejected: Improper use of SMTP command pipelining; proto=SMTP
non-SMTP command from unknown[64.69.57.28]: GET / HTTP/1.0 : 1 Time(s)
non-SMTP command from unknown[64.69.57.28]: GET /nice%20ports%2C/Tri%6Eity.txt%2ebak HTTP/1.0 : 1 Time(s)                
non-SMTP command from unknown[64.69.57.28]: Via: SIP/2.0/TCP nm;branch=foo: 1 Time(s)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(66 attempts against SMTP)&lt;/p&gt;

&lt;p&gt;OK, OK, this all looks like an &amp;ldquo;out of the box&amp;rdquo; type scan from some
misconfigured security tool. But it&amp;rsquo;s funny that it&amp;rsquo;s the DHS!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A joke I learned in 1978</title>
      <link>https://www.sweharris.org/post/2015-05-26-joke/</link>
      <pubDate>Tue, 26 May 2015 14:48:00 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2015-05-26-joke/</guid>
      <description>&lt;p&gt;When I was 10 my teacher told us this joke.&lt;/p&gt;

&lt;p&gt;So in the old Wild West&amp;hellip; General Custer was chasing Sitting Bull. He had
his cavalry and supply wagons and soldiers. They&amp;rsquo;d been chasing Sitting
Bull for days and the weather was starting to go bad. A lieutentant came
to Custer and told him &amp;ldquo;Sir, the men are tired, the weather is bad,
we need to rest.&amp;rdquo; Custer thought about it and replied &amp;ldquo;OK, I&amp;rsquo;ve been
here before; a couple of miles ahead is a valley where we can make camp&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;So they set up camp. But this valley focused the wind and the cavalry
were miserable. The lieutenant complained again to Custer; &amp;ldquo;As I said,
I&amp;rsquo;ve been here before. At the far end of the valley there is a grove of
hazelnut trees; you can cut those down and make huts to protect us from
the wind&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Which they did. But hazelnut branches are twisty and there were lots
of gaps in the walls for the wind to fit though. Still the cavalry
shivered. A third time the lieutenant went to his General; &amp;ldquo;The rear
wagon is full of chocolate; melt that and poor it over the huts. That
will seal the holes&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Finally the cavalry were able to rest.&lt;/p&gt;

&lt;p&gt;Now high above them, on the valley&amp;rsquo;s edge, Standing Bull (son of Sitting
Bull) watched on. He saw the cavalry do all this, and was confused. He
reported to his father.&lt;/p&gt;

&lt;p&gt;&amp;ldquo;So, my son! Tell me what my old enemy General Custer is doing now.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;And so Standing Bull told him of the cavalry, of the wagon train, of
the cutting down of trees, the building&amp;hellip;&lt;/p&gt;

&lt;p&gt;&amp;ldquo;Father, I don&amp;rsquo;t understand these actions. Has your enemy gone mad?&amp;rdquo;&lt;/p&gt;

&lt;p&gt;&amp;ldquo;No my son, it is very simple. (singing) Huts, oh hazel huts, cavalry
make them and they cover them with chocolate!&amp;rdquo;&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=6t9ZJK-vc-I&#34;&gt;Youtube&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Some good Voyager</title>
      <link>https://www.sweharris.org/post/2015-04-30-voyager/</link>
      <pubDate>Thu, 30 Apr 2015 22:15:02 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2015-04-30-voyager/</guid>
      <description>&lt;p&gt;So I wrote that &lt;a href=&#34;https://www.sweharris.org/post/2015-04-22-voyager/&#34;&gt;Voyager was the worst ST ever&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I still agree with that, because of the overall structure.&lt;/p&gt;

&lt;p&gt;This doesn&amp;rsquo;t deny that some &lt;em&gt;episodes&lt;/em&gt; were good though.&lt;/p&gt;

&lt;p&gt;Viewing Voyager as a &amp;ldquo;old school story telling&amp;rdquo; structure allows you to
see each episode as an individual story.&lt;/p&gt;

&lt;p&gt;One really good one is &amp;ldquo;Child&amp;rsquo;s Play&amp;rdquo; (season 6). This is a &amp;ldquo;7 of
9 episode&amp;rdquo; (one of the downsides of Voyager was &amp;ldquo;harry episode&amp;rdquo;,
&amp;ldquo;tom episode&amp;rdquo;, &amp;ldquo;tuvok episode&amp;rdquo; etc etc), but it was one of the better
standalone episodes, talking to what it means to be an individual, to
have self-agency. It&amp;rsquo;s a well done story&amp;hellip; but it only works because
of the episodic nature; next week it doesn&amp;rsquo;t matter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ETA&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And then the beginning of the next episode has Janeway telling Kim
$foo, who tells Seven $bar, who creates a PHYSICAL order for Belana,
who hands that to RANDOM person who walks a mile to UNKNOWN person who
clicks a button.&lt;/p&gt;

&lt;p&gt;WTF?&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s just stupid process.&lt;/p&gt;

&lt;p&gt;And I work in a company with stupid processes. &lt;strong&gt;&lt;em&gt;THIS&lt;/em&gt;&lt;/strong&gt; chain of events
is&amp;hellip; wrong.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title> Why Star Trek Voyager was the worst of all</title>
      <link>https://www.sweharris.org/post/2015-04-22-voyager/</link>
      <pubDate>Wed, 22 Apr 2015 20:53:00 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2015-04-22-voyager/</guid>
      <description>&lt;p&gt;&amp;ldquo;Voyager&amp;rdquo; has a reputation for being awful. And I agree with this. But
maybe not for the reason commonly cited.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s an article of faith amongst some people that Voyager is panned
simply because it had a woman in the captain&amp;rsquo;s chair. I have no doubt
that there are plenty of Neanderthals out there who do have this stupid
knee jerk reaction. I remember some of the media speculation around
having a female captain, and how the audience would take it. I didn&amp;rsquo;t
understand why this was a big deal. Hmm, this was 1995 so I would have
been 25 or 27. I&amp;rsquo;d grown up with Heinlein and others. I had a strong
mother (smarter than my father). I &lt;em&gt;knew&lt;/em&gt; women were just as capable as
men. So why wouldn&amp;rsquo;t there be a female captain? (Pretty sure we&amp;rsquo;d seem
them in ST:TNG as well, just not as the lead character).&lt;/p&gt;

&lt;p&gt;The show started and&amp;hellip; ugh, the voice. Janeway&amp;rsquo;s voice was
grating. But&amp;hellip; I got used to it. Just like having to get used to a new
Doctor Who, I got used to Janeway&amp;rsquo;s voice.&lt;/p&gt;

&lt;p&gt;Now ST:DS9 had already been running for a couple of years so the idea
of a combined crew not uniquely Star Fleet was well established. The
combined Maquis/Fleet would have worked. But that&amp;rsquo;s not what we got;
we got a &amp;ldquo;determined Star Fleet&amp;rdquo; ship, with some of the tension being
how the Maquis fit in. Disappointment #1.&lt;/p&gt;

&lt;p&gt;But that&amp;rsquo;s not the real problem I had with the show.&lt;/p&gt;

&lt;p&gt;Babylon 5 had just completed its run. It &lt;em&gt;changed&lt;/em&gt; how SciFi TV story
telling was done. Good shows were no longer episodic in nature; they
were one linear story told over multiple episodes. Things were revealed,
consequences had actions. We didn&amp;rsquo;t &amp;lsquo;reset at the end of the episode&amp;rsquo;.&lt;/p&gt;

&lt;p&gt;Now previous Star Trek stories were definitely episodic. TOS and TNG were
products of their time; everything was episodic. DS9 started that way,
but midway through they realised &amp;ldquo;hey, story arcs are good!&amp;rdquo; and built
one around the war with the Dominion. The characters grew and changed;
actions had consequences that continued on. The story now had &amp;ldquo;state&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Voyager started episodic&amp;hellip; and continued episodic. It never grew; it
never changed. &amp;ldquo;Whee! we got a super-duper transwarp drive! Home in 2
weeks! Oh, but we can&amp;rsquo;t use it ever again &amp;lsquo;cos it&amp;rsquo;d break the ship. Back
to 69 more years of travel&amp;hellip;&amp;ldquo;. Seriously, that happened!&lt;/p&gt;

&lt;p&gt;And, somehow, despite being beyond the reach of Star Fleet and short on
energy (hence needing Neelix to create fresh food) there&amp;rsquo;s always more
photon torpedoes, spare parts. That&amp;rsquo;s all replicated? Ha, no.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s one episode in season 5 where Tom Paris gets demoted from Lt down
to Ensign. Now, other than his title changing in every episode afterwards
&lt;em&gt;everything else&lt;/em&gt; is exactly the same. There&amp;rsquo;s no change in the character,
in the way Janeway acts towards him. There&amp;rsquo;s no real consequence. It&amp;rsquo;s
just a name change.&lt;/p&gt;

&lt;p&gt;This is why Voyager was the worst Star Trek of all; it&amp;rsquo;s method of story
telling was 5 years or more out of date before it started. We&amp;rsquo;d seen the
future (Babylon 5), and Voyager was a disappointment in comparison. If
it had been done 7 years earlier then it would have stood up pretty well
(definitely better than Enterprise in many respects; that bloody Temporal
War&amp;hellip;), but it wasn&amp;rsquo;t. It was old school story telling, made even more
prominent by DS9 overlapping and using the new school.&lt;/p&gt;

&lt;p&gt;I finally bought the Voyager DVDs (they were on sale, cheap) and I&amp;rsquo;m
in the middle of watching them (just about to finish season 5). As
an episodic series I &lt;em&gt;like&lt;/em&gt; it. The distance of time can make me
forget that I expected more, I expected better. If I mentally place
it &amp;ldquo;pre-B5&amp;rdquo; then I can forgive the episodic sins (except the infinite
photon supply!). It&amp;rsquo;s good harmless fun. But I know that I can watch 50
more episodes and nothing&amp;rsquo;s gonna change (until the series finale when
&amp;ldquo;magic happens&amp;rdquo;). You have to take each episode on their own and not
expect anything more than 45 minutes of entertainment.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>How does the web still work?</title>
      <link>https://www.sweharris.org/post/2015-03-24-javascript/</link>
      <pubDate>Tue, 24 Mar 2015 08:45:51 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2015-03-24-javascript/</guid>
      <description>&lt;p&gt;I hit a web page which, naturally, refused to work properly. So I
looked at the NoScript report. This one page ws pulling in scripts from
(hand-typed so maybe tpyos)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;adobedtm.com
cdna-assets.com
chartbeat.com
cloudfront.net
criteo.com
disqus.com
disquscdn.com
doubleclick.net
dunhilltraveldeals.com
effectivemeasure.net
facebook.com
gigya.com
google.com
googlesyndication.com
googletagservices.com
imrworldwide.com
inksinmedia.com
krxd.net
mediavoice.com
mmcdn.us
ooyala.com
optimizely.com
outbrain.com
parsly.com
quantserve.com
qubitproducts.com
revsci.net
scorecardresearch.com
skimresources.com
visualrevenue.com
whistleout.com
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;Boggle!&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>So You Start Server</title>
      <link>https://www.sweharris.org/post/2014-03-11-soyoustart/</link>
      <pubDate>Tue, 11 Mar 2014 22:34:30 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2014-03-11-soyoustart/</guid>
      <description>&lt;p&gt;I have a &lt;a href=&#34;http://www.linode.com&#34;&gt;linode&lt;/a&gt; and a
&lt;a href=&#34;http://www.panix.com/v-colo/&#34;&gt;Panix v-colo&lt;/a&gt;.  These servers do
everything I want.&lt;/p&gt;

&lt;p&gt;But &lt;a href=&#34;http://www.ovh.net&#34;&gt;OVH&lt;/a&gt; do a physical server rental program.
It&amp;rsquo;s not necessarily the best server in the world, but it&amp;rsquo;s pretty good.
The &lt;a href=&#34;http://www.soyoustart.com/us/&#34;&gt;So You Start&lt;/a&gt;(SYS) server starts at
around $50 month.  Now a linode is $20/month.  10% discount for paying
1 yr in advance, so $18/month.&lt;/p&gt;

&lt;p&gt;To compare; for $18/month I get a 8vCPU, 1Gb RAM, 48Gb of disk on my
linode.  On SoYouStart for $50 I get a quad-core Xeon E3-1245 (HT==&amp;gt;
8 CPU), with 32Gb RAM and 2*2Tb disk.&lt;/p&gt;

&lt;p&gt;You look at the numbers and a SYS server knocks linode out of the park.&lt;/p&gt;

&lt;p&gt;Except I really don&amp;rsquo;t need that much processing power.  Which is why
alcohol got involved and I bought one.&lt;/p&gt;

&lt;p&gt;I called the new machine &lt;a href=&#34;http://en.wikipedia.org/wiki/Count_Duckula&#34;&gt;duckula&lt;/a&gt;
because it&amp;rsquo;s sucking money out of me for no good reason, just like
a vampire.&lt;/p&gt;

&lt;p&gt;But what do you get?&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s actually pretty impressive.  SYS is a cut-down service from the
standard OVH service so the control panel is very limited.  &amp;ldquo;Redeploy an
OS&amp;rdquo;, &amp;ldquo;reboot&amp;rdquo; and &amp;ldquo;rDNS&amp;rdquo; are pretty much all you can do.  The &amp;ldquo;deploy OS&amp;rdquo;
has a small amount of flexibility, but not much.  Compared to Linode or
even Panix the SYS control panel is crap.  In particular you don&amp;rsquo;t get
console access.&lt;/p&gt;

&lt;p&gt;You also need to be aware; the SYS server has some back doors installed.
Well&amp;hellip;  If you google &amp;ldquo;ovh backdoor&amp;rdquo; you&amp;rsquo;ll see a lot of posts.  I can&amp;rsquo;t
verify all of them; I&amp;rsquo;d overridden the root authorised_keys stuff and
sshd_config pretty early on in my setup so I don&amp;rsquo;t know if they push keys
in the standard build.  They &lt;em&gt;do&lt;/em&gt; have a per-minute cron that pushes a
fuck-tonne of crap about your server into their monitoring system.&lt;/p&gt;

&lt;p&gt;Essentially, their standard build is &lt;em&gt;not&lt;/em&gt; vendor standard.  There are
additional components and potential backdoors &amp;lsquo;for support purposes&amp;rsquo;.
I think I&amp;rsquo;ve turned them all off.&lt;/p&gt;

&lt;p&gt;But that seems to be where the negatives stop&amp;hellip; mostly&lt;/p&gt;

&lt;p&gt;What you get for $50 a month&amp;hellip; 32Gb RAM, 2*2Tb disk in RAID1, ECC RAM,
quad core Xeon (HT), IPv4, IPv6/64, rDNS.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s a pretty impressive spec machine.  Except for disk space, that&amp;rsquo;s
better than my home machine (more memory, ECC memory, better CPU).  If you
wanted to buy such a machine and colo it then it&amp;rsquo;d probably cost you more.&lt;/p&gt;

&lt;p&gt;My gut feeling about SYS is &amp;ldquo;ugh, they backdoor&amp;hellip;&amp;rdquo;, but other than that
I&amp;rsquo;m feeling this isn&amp;rsquo;t a bad offering and seems pretty competitive in
terms of what you get for your buck.&lt;/p&gt;

&lt;p&gt;Do I need such a machine?  No.  But&amp;hellip; I&amp;rsquo;ve already had one benefit;
I can use Linux kvm to host a small server for a friend!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Historical Java</title>
      <link>https://www.sweharris.org/post/2014-02-28-java/</link>
      <pubDate>Fri, 28 Feb 2014 12:23:32 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2014-02-28-java/</guid>
      <description>&lt;p&gt;Discussions elsewhere (in more than one place; coincidence?) reminded me
that in the long long distant past I was &amp;ldquo;hot&amp;rdquo; java programmer (&amp;ldquo;hotjava&amp;rdquo;,
geddit? Ah shaddup!). I actually wrote what I believe was the first
website Java applet sold commercially in the UK, back in 1995. It was a
teaser site for the SciFi Channel (which was due to launch around then)
called &amp;ldquo;zorg&amp;rdquo;. We got involved &amp;lsquo;cos we were Sun partners and the client
had gone to Sun asking for some Java development.&lt;/p&gt;

&lt;p&gt;The ad company (Star Interactive) had the concept of &amp;ldquo;aliens were
trying to communicate with us and learn our language&amp;rdquo;. So they paid for
teaser icons to be placed on some high traffic UK web sites (with no
explanation; just some &amp;ldquo;alien looking writing&amp;rdquo;) that linked to the zorg
site. There you were presented with a sort of rip-off of Stargate as a
Java applet. There was a pretty neat graphic of a square alien device
with writing on it. And a &amp;ldquo;throbbing&amp;rdquo; type sound. If you clicked on
the writing then the writing would flash at random and various of the
writings would stay lit. The sound increased in speed and pitch. Click
again, the same thing happens. Click a third time and&amp;hellip;&lt;/p&gt;

&lt;p&gt;If you got it wrong the screen flashed red and you were transported
to some foreign web site, such as the Swedish Phone Directory. Get it
almost right and the sound effects would ramp up and then stop, and
you&amp;rsquo;d be transported to one of the teaser sites. If you got it correct
and the sounds effects would ramp up, a vortex would open and then you
got passed onto the second game (which was a traditional HTML game;
no more java). If you won all three games then you got to an &amp;ldquo;egg&amp;rdquo;
image with partially decoded alien writing. As the channel launch date
came closer more of the writing was decoded.&lt;/p&gt;

&lt;p&gt;The rule was pretty simple; each icon was numbered. If you clicked
on todays number then you failed (so the solution was different each
day). If you clicked either side of today then you won. Else you almost
won. It worked :-)&lt;/p&gt;

&lt;p&gt;This was very early in Java history. Sun HotJava Alpha 3 was the only
java browser. Netscape 2.0b1 arrived and this had a different java
model. And every version of the Netscape betas changed something in
java each time. So the index page turned into a quick CGI that went to
whatever code version was required for your browser (or a html based
one for non-java people). But it worked and we got a few hits.&lt;/p&gt;

&lt;p&gt;It was fun. I hadn&amp;rsquo;t even seen the Stargate film at the time, but I
think I did a pretty good immitation :-) Gamelan rated the site as &amp;ldquo;cool&amp;rdquo;
with a comment such as &amp;ldquo;we don&amp;rsquo;t know what it does, but it&amp;rsquo;s fun!&amp;rdquo; Later,
after the launch was complete I added a comment explaining what the site
was about. I doubt anyone would have got the ad peoples &amp;ldquo;concept&amp;rdquo;!&lt;/p&gt;

&lt;p&gt;There are few mentions of it anymore.  Unfortunately I&amp;rsquo;ve lost the source :-(&lt;/p&gt;

&lt;p&gt;This led me into delving through old directories of crud I&amp;rsquo;ve
accumulated over the years. And I found my &lt;a href=&#34;https://www.sweharris.org/Java/dragndrop.alpha3.txt&#34;&gt;very first piece of
Java&lt;/a&gt;, written for HotJava Alpha3. This
was a simple drag&amp;rsquo;n&amp;rsquo;drop system; click on an icon and drag it around and
release it. I also added the icon changing when you clicked on it and some
simple sound effects. A slightly &lt;a href=&#34;https://www.sweharris.org/Java/dragndrop.async.txt&#34;&gt;newer version&lt;/a&gt;
still works on current browsers, and can be found &lt;a href=&#34;https://www.sweharris.org/Java/&#34;&gt;here&lt;/a&gt; &amp;ndash; or, at
least &lt;em&gt;did&lt;/em&gt; work until browsers such as chrome dropped java support
totally.&lt;/p&gt;

&lt;p&gt;One big difference between HotJava Alpha3 and Netscape can be seen in the
current version. First time you click on something there&amp;rsquo;s a delay. This
is because Netscape delays actual loading of data (such as images and
sounds) until it&amp;rsquo;s needed, whereas HotJava would download immediately. So
in HotJava,&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;Image im1 = getImage(s + &amp;quot;/T&amp;quot; + i + &amp;quot;.gif&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;would result in an immediate hit on the webserver; in Netscape it didn&amp;rsquo;t. So
when I wrote the zorg game I had to pre-cache all the data to improve
&amp;ldquo;game play&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;And then I didn&amp;rsquo;t touch Java at all for 7 or 8 more years, when I wrote
a simple graphing program (which would allow arbitrary zooming and stuff)
for work. And I haven&amp;rsquo;t touched it since.&lt;/p&gt;

&lt;p&gt;My web design skills are basically stuck back in 1996 with HTML2 and
tables. One day I should really learn CSS and Javascript and DHTML and
all the neato stuff that&amp;rsquo;s around. Until then&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Scripts</title>
      <link>https://www.sweharris.org/scripting/</link>
      <pubDate>Mon, 09 Dec 2013 14:47:02 -0500</pubDate>
      
      <guid>https://www.sweharris.org/scripting/</guid>
      <description>&lt;p&gt;I can code, but mostly I write quick scripts for various purposes.  I&amp;rsquo;ve
become pretty infamous at work for the horrendous one-off one-line pipelines
I create!   I try and make actual scripts a little more readable&amp;hellip;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sweharris.org/Scripts/denon_daemon.txt&#34;&gt;denon_demon&lt;/a&gt;&lt;br&gt;
My Denon receiver has a serial port.  This serial port can be used
to control and report on what the receiver is doing.  So if I send it
&#34;PW?&#34; then it will report on the power state.  This daemon (written for
MacOS) will listen for commands on a pipe and communicate with the receiver
and write out status entries so it is easy for a program to see what is
going on.  It also writes out a log file.
&lt;pre&gt;Wed Feb 22 21:21:27 2012 status.Volume = 47 -33.0dB
Wed Feb 22 21:21:30 2012 status.Volume = 465 -33.5dB
Wed Feb 22 21:21:59 2012 status.MainSurround = STEREO
Wed Feb 22 21:22:00 2012 status.MainSurround = STEREO
Wed Feb 22 21:23:58 2012 status.MainSurround = STEREO
Wed Feb 22 21:24:02 2012 status.Power = STANDBY
Wed Feb 22 21:24:02 2012 status.MainZone = OFF&lt;/pre&gt;
&lt;p&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sweharris.org/Scripts/denon.txt&#34;&gt;denon&lt;/a&gt;&lt;br&gt;
A simple command client to talk to the pipe above, and report on the status
of the receiver
&lt;pre&gt;% denon volume -25
          Input: TIVO
   MainSurround: DOLBY PL2 C
       MainZone: ON
           Mute: OFF
          Power: ON
         Volume: 55 -25.0dB
         Z2Mute: OFF
       Z2Volume: 99 ---.-dB
          Zone2: OFF
     Zone2Input: SOURCE&lt;/pre&gt;
&lt;p&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sweharris.org/Scripts/phone.txt&#34;&gt;phone&lt;/a&gt;&lt;br&gt;
Pulling data from Google contacts using LWP::Simple and XML::XPath
rather than WWW::Google::Contacts, which has a horrendous dependency
path.  Since we&#39;re only reading data here we can do things more easily.
&lt;p&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sweharris.org/Scripts/phone_droid3.txt&#34;&gt;phone_droid3&lt;/a&gt;&lt;br&gt;
I had a Droid 3 phone.  This script will scp the contacts.db and then
use DBD::Sqlite to read the data and present it in text format.  Why
am I doing this?  &#39;Cos I&#39;m stupid :-)
&lt;p&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sweharris.org/Scripts/movemouse.c&#34;&gt;movemouse.c&lt;/a&gt;&lt;br&gt;
OK, this is a C program and not a script, but it&#39;s small enough so...
Basically moves the OS-X mouse cursor to a given co-ordinate.  This is
because my Mac Mini will reset the cursor to top-left frequently and
when I play DVDs then this stops the application menu bar going away, so
I use this to move the mouse first.
&lt;p&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sweharris.org/Scripts/dvdplay.txt&#34;&gt;dvdplay&lt;/a&gt;&lt;br&gt;
This is a a bash script that creates applescript to start DVD Player
playing a VIDEO_TS directory.
&lt;p&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sweharris.org/Scripts/dvd.txt&#34;&gt;dvd&lt;/a&gt;&lt;br&gt;
A script that generates various small applescripts to report/control on
DVD Player.  Uses dvdplay to start a new DVD.  So I can do &#34;dvd pause&#34;
to pause playback.
&lt;p&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sweharris.org/Scripts/play10.txt&#34;&gt;play&lt;/a&gt; (iTunes 10 version)&lt;br&gt;
Shell script to create applescript to create an iTunes play list
to play the mp3s listed on the command line
&lt;p&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sweharris.org/Scripts/itunes10.txt&#34;&gt;itunes&lt;/a&gt; (iTunes 10 version)&lt;br&gt;
A script that generates various small applescripts to report/control on
iTunes.  So I can do &#34;itunes dj&#34; to play the &#34;iTunes DJ&#34; playlist.

Unfortunately the latest version of iTunes has broken a lot of
functionality; the applescript calls don&#39;t work properly any more
and a number of controls no longer have directly accessible function
calls.
&lt;p&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sweharris.org/Scripts/itunes.txt&#34;&gt;itunes&lt;/a&gt;&lt;br&gt;
    &lt;a href=&#34;https://www.sweharris.org/Scripts/play.txt&#34;&gt;play&lt;/a&gt;&lt;br&gt;
A version of the &#34;play&#34; and &#34;itunes&#34; scripts that work with Itunes 12.
This includes some kludge workarounds for manipulating the shuffle and
repeat settings.
&lt;p&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sweharris.org/Scripts/airplay.txt&#34;&gt;airplay&lt;/a&gt;&lt;br&gt;
A craptastic script that tries to turn on/off airplay on iTunes
so that I can listen to the music on a secondary receiver.  Apple don&#39;t
seem to expose the AirPlay interface so this pretends to click buttons
and stuff.  Ugh.
&lt;p&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sweharris.org/Scripts/virt_build.txt&#34;&gt;virt_build&lt;/a&gt;&lt;br&gt;
A BUILD script for KVM `virsh` to create VMs.  It&#39;s a wrapper around
`virt-install` to create a disk image or LVM, define the machine,
kickstart boot it.  
Additional disks can be added to images using &lt;a href=&#34;https://www.sweharris.org/Scripts/virt_add_disk.txt&#34;&gt;virt_add_disk&lt;/a&gt;.
The &lt;a href=&#34;https://www.sweharris.org/Scripts/centos6.cfg.txt&#34;&gt;CentOS 6&lt;/a&gt;
and &lt;a href=&#34;https://www.sweharris.org/Scripts/centos7.cfg.txt&#34;&gt;CentOS 7&lt;/a&gt; kickstart files.
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Google Authenticator</title>
      <link>https://www.sweharris.org/post/2013-09-26-googleauth/</link>
      <pubDate>Mon, 23 Sep 2013 07:41:48 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2013-09-26-googleauth/</guid>
      <description>&lt;p&gt;So I decided to play a little bit with google authenticator on my systems
that are visible to the internet. ie my linode, Panix v-colo and
&amp;lsquo;bastion&amp;rsquo; host at home.&lt;/p&gt;

&lt;p&gt;The way sshd works, if you authenticate with public keys then PAM &amp;ldquo;auth&amp;rdquo;
doesn&amp;rsquo;t seem to get called. So this is pretty much for &amp;ldquo;ChallengeResponse&amp;rdquo;
(instead of &amp;ldquo;password&amp;rdquo;) authentication. Which makes it great for my need;
if I&amp;rsquo;m coming from one of my own machines with my SSH key then I&amp;rsquo;m not
impacted. If I&amp;rsquo;m coming in from someone elses machine then I need to
know my password and the one-time-password.&lt;/p&gt;

&lt;p&gt;Now on these hosts the only account&amp;rsquo;s with a valid password are my own
and &lt;code&gt;root&lt;/code&gt; and sshd is configured to not allow passwords for &lt;code&gt;root&lt;/code&gt; (ssh
keys only). I also run sshd on a non-standard port and this has stopped
dead random password hack attempts. And no one is trying to attack me
(I don&amp;rsquo;t run any popular blog; I&amp;rsquo;m not a bank, I&amp;rsquo;m not a target). So,
in practice, google authenticator doesn&amp;rsquo;t really add anything for me.&lt;/p&gt;

&lt;p&gt;But it was interesting to play with.&lt;/p&gt;

&lt;p&gt;(Of course if I&amp;rsquo;m away from my machine and my phone then I have a problem!)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Teaching myself javascript</title>
      <link>https://www.sweharris.org/post/2013-01-06-javascript/</link>
      <pubDate>Sun, 06 Jan 2013 11:50:26 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2013-01-06-javascript/</guid>
      <description>&lt;p&gt;My web design skills are a little on the old side.  Probably frozen
around 1997; Netscape Navigator 2 would probably render most of my
stuff properly.&lt;/p&gt;

&lt;p&gt;As part of the &amp;ldquo;make work&amp;rdquo; project I did last month I wanted to try
something new.  With the existing version if you clicked on a link to
get cover-art then it would just be a simple link.  You see the image
then press &amp;ldquo;BACK&amp;rdquo;.  This worked well for years, but some mobile devices
don&amp;rsquo;t cache too well.  And even if they do then the rendering time can
be quite large.  One obvious option would be to open in a new window
(tab, whatever), but I thought I&amp;rsquo;d try to do &amp;ldquo;popups&amp;rdquo;.  It turns out
the term of art is &amp;ldquo;lightbox&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Armed with that I found &lt;a href=&#34;http://lokeshdhakar.com/projects/lightbox2&#34;&gt;Lightbox 2&lt;/a&gt;.
It took 5 minutes to integrate that into my page.  And it worked.
Trouble is that it required jQuery so the whole thing took over 100K.
Considering the original page was less than 80K, I&amp;rsquo;ve over doubled my
download size.&lt;/p&gt;

&lt;p&gt;Also I didn&amp;rsquo;t &lt;em&gt;learn&lt;/em&gt; anything from this.  So a solution that worked,
but was unsatisfying.&lt;/p&gt;

&lt;p&gt;I did some more searching around.  I found some &amp;ldquo;10 line&amp;rdquo; solutions,
which looked fun&amp;hellip; but they all worked on the concept of setting the
image to be invisible and then show it on demand.  Which, given I was
planning on 1200 images, would have meant pre-loading all 1200 images
on the page in the off-chance of clicking on one or two links.&lt;/p&gt;

&lt;p&gt;But I did learn from these things.&lt;/p&gt;

&lt;p&gt;My goal was to have 1 image; change what the image displayed; move it
to the right place; then display it.&lt;/p&gt;

&lt;p&gt;It turns out to be a simple concept, but slightly messy.&lt;/p&gt;

&lt;p&gt;The core code is a small CSS:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-css&#34;&gt;  &amp;lt;style&amp;gt;
    .white_content {
      display: none;
      position: absolute;
      padding: 16px;
      background-color:#eae9d4;
      z-index:1000;
      overflow: auto;
    }
  &amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then some javascript&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
var oldfocus = null;

function set_img(i,e)
{
  document.images[&#39;popup&#39;].src=i;
  oldfocus=e;
  var x=e.offsetLeft+e.offsetParent.offsetLeft-20;
  var y=e.offsetTop+e.offsetParent.offsetTop-200;
  if (x&amp;lt;0) { x=0; }
  if (y&amp;lt;0) { y=0; }
  document.getElementById(&#39;light&#39;).style.left=x + &#39;px&#39;;
  document.getElementById(&#39;light&#39;).style.top=y + &#39;px&#39;;
  document.getElementById(&#39;light&#39;).style.display=&#39;block&#39;;
  document.getElementById(&#39;poplink&#39;).focus();
  return false;
}
function hide()
{
  document.getElementById(&#39;light&#39;).style.display=&#39;none&#39;;
  oldfocus.focus();
}
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Add in a DIV to hold the image:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;div id=&amp;quot;light&amp;quot; class=&amp;quot;white_content&amp;quot;&amp;gt;
&amp;lt;a id=&#39;poplink&#39; href=&#39;javascript:void(0)&#39; onclick=&amp;quot;hide()&amp;quot;&amp;gt;&amp;lt;img border=0 name=popup src=&amp;quot;images/spacer.gif&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now it&amp;rsquo;s easy to call:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;a target=_blank href=&amp;quot;images/sp-sweh.gif&amp;quot; onClick=&amp;quot;return set_img(&#39;images/sp-sweh.gif&#39;,this)&amp;quot;&amp;gt;South Park&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Originally I wrote the code to track X,Y position by catching mousedown
events.  But keyboard navigation (eg TABbing to a link and pressing
RETURN) doesn&amp;rsquo;t cause mousedown events, so no X,Y is captured.  So this
code tries to work out where the link is on the page and use that.
It turns out the &amp;ldquo;offsetParent&amp;rdquo; stuff should really be chained; eg a
link inside a table has the link offset relative to the cell; the cell
offset relative to the table; the table offset relative to the page.
So that code got rewritten as a loop in my final version.  But, basically,
that&amp;rsquo;s a lightbox with 33 lines of code.&lt;/p&gt;

&lt;p&gt;Next I wanted to see if I could render HTML rather than show images.
Turns out it&amp;rsquo;s mostly the same thing;  Using the &amp;ldquo;innterHTML&amp;rdquo; attribute
allows a DIV to render almost anything, not just images.&lt;/p&gt;

&lt;p&gt;The final solution&amp;hellip;&lt;a href=&#34;http://sweh.spuddy.org/sf.pl&#34;&gt;Image popups&lt;/a&gt; and &lt;a href=&#34;http://sweh.spuddy.org/cds.pl&#34;&gt;HTML popups&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Exelink</title>
      <link>https://www.sweharris.org/post/2012-06-01-exelink/</link>
      <pubDate>Fri, 01 Jun 2012 13:44:03 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2012-06-01-exelink/</guid>
      <description>&lt;p&gt;In the early 90s I was learning DOS and Unix. One thing I really liked
about Unix was the concept of &amp;ldquo;symbolic links&amp;rdquo;. It meant you could
install programs in their own directories and symlink the executable
to somewhere in your $PATH.  DOS couldn&amp;rsquo;t do that. So you ended up with
horrendously long path names. And DOS had a 120 character limit. Ugh.&lt;/p&gt;

&lt;p&gt;So I wrote a TSR, called &amp;ldquo;exelink&amp;rdquo; which kludged it. I used it for years
until I gave up on DOS and became a Unix person. Even sold a copy to
&amp;ldquo;PC Plus&amp;rdquo; for a cover disk.&lt;/p&gt;

&lt;p&gt;Annoyingly I lost the code. Random searches of the internet didn&amp;rsquo;t find
anything useful. Except a random search, today, found a usenet posting
where I mentioned that I&amp;rsquo;d uploaded it to SIMTEL20. Huh. And that was
enough to &lt;a href=&#34;https://www.sweharris.org/exelink2.zip&#34;&gt;find it&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;And, heh, here&amp;rsquo;s the README file&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;                                  EXELINK.COM
                                  ===========
 
IMPORTANT NOTE:  Needs DOS 3.0 or greater
 
#include &amp;lt;std_disclaimer.h&amp;gt;
 
All the code in this package is my own work.  No responsibility will be
taken for loss of data or damage caused by running this program.  This
program has been tested and I use it myself, so if you do come across
any problems then let me know!
 
The program can be freely distributed.  There are no restrictions on use.
Just keep my name on it please!
The program is &amp;quot;postcardware&amp;quot; - send me a postcard if you like :-)
 
Introduction
============
A big problem with Hard discs is that they can store so much data!
This isn&#39;t as silly as it sounds; if you have four or five applications
on your disc (maybe Pascal, C, Assembler, Word Processor, Norton etc)
and wish to keep some sort of organisation do your disc then your PATH
variable gets a little large.  Until you reach the dreaded 127
character limit.  Although programs exist that enable you to get up to
255 characters in the PATH, this is a bit long and unwieldy, and can
make you computer spend too much time skipping around directories just
to find the program you want.  I had this problem and decided to find a
better solution, and EXELINK is it (well I think its better!)
 
What EXELINK does
=================
NOTE: EXELINK will not work with .BAT files since the command shell
interprets them internally and doesn&#39;t call the DOS &#39;exec&#39; routines.
Only routines that call &#39;exec&#39; (eg .EXE and .COM files, Overlays?)
work.
 
When you execute a command, MS-DOS needs to find where the file is that
you are trying to run.  It first looks in the current directory, then
in the first directory on the PATH, then the next, then the next...
until it finds what you wanted.
 
eg if you have your path set up as
c:\dos;c:\app\turbop;c:\app\turboc;c:\app\tasm;c:\app\wp;c:\app\norton
then typing the command &#39;nu&#39;  (for norton utilities) will involve
looking for
     .\NU.???
     c:\dos\NU.???
     c:\app\turbop\NU.???
     c:\app\turboc\NU.???
     c:\app\tasm\NU.???
     c:\app\wp\NU.???
     c:\app\norton\NU.???
which it will eventually find.  Any files in any of these directories
which are not executable will slow down the searching...
Of course an easy way to speed up access to NU would be to put it at
the front of the PATH, at the expense of some other program!
 
EXELINK sets aside directory which you include on your PATH (for speed
you put it at the beginning) and this contains a set of files which
appear to DOS to be executable.  Instead of being run though, EXELINK
reads the contents of this file and gets the filename of the REAL
program from there.  Since the link directory is at the beginning of
the PATH and there are only executables it will find the link file very
quickly.
In the example above, you could now have the following setup:
PATH=c:\links;c:\dos
and searching would be
     .\NU.???
     c:\links\NU.???  &amp;lt;- found!  Open the file, read its contents and
                         execute!
 
Less searching is done, executables are found quicker, PATH is shorter
and less disk head movement is used.
 
But what is this I hear?  You can do this by creating a BATch files which
calls the real program?  Almost true, but there are a  few problems with
batch files:
 (1) There is difficulty passing an unknown number of parameters.  A batch
     file such as
     @c:\app\wp %1 %2 %3 %4 %5
     can be taken as meaning that is passes exactly five parameters, some
     of which are NULL (GEM programs can suffer from this problem)
 (2) It only works from the DOS prompt - a program such as MAKE is
     unable to use BATch files unless you specifically call COMMAND.COM
     which is slower and takes more memory.
 (3) It is an interpreted file.  DOS opens the BATch file, reads
     a line.  If it executes an external program, closes the BATch
     file, executes the command, opens the BATch file, etc.  Lots of
     disc accessing...
 
The only real alternative would be to write a specialised Pascal or C
program which just executed the real version with all the parameters
passed on.  This will work in all cases, but has the problem that you
need to compile a new link program for each new executable you want
linked, and even the simplest compiled program takes about 2.5k -
wasting 4k of disc space!
example in Turbo C 2.01:
 
main(int argc,char *argv[], char **envp)
{
  argv[0]=&amp;quot;real_name.exe&amp;quot;;
  execve(&amp;quot;real_path_name.exe&amp;quot;,argv,envp);
}
 
Which would then need compiling, and even in the TINY memory model
takes over 3k!
 
Using EXELINK you need to create a 1 line ASCII file which you can do
with the COPY command.
How EXELINK works
=================
EXELINK is a Terminate and Stay Resident (TSR) program.  While resident
it takes an astounding 400 bytes of memory!  The only vector it
attaches to is INT 21h and any call that is not Function 4Bh (exec) is
passed directly onto the original handler.  To cut down on resident size
it frees the environment block passes to it by DOS, and relocates itself
over the PSP, which is no longer needed once the program has gone resident.
 
If the call is an &#39;exec&#39; then the pathname of the program to be called
is worked out.  If this program is in the EXELINK directory (by default
C:\LINKS) then the file is opened for reading and the contents of the
file (up to 127 characters) are read in.  A little processing is done
to convert this to an ASCIIZ string and then the original routine
continues with this new name.  All registers are preserved through this
except for DS:DX which point to the filenames so any options passed to
&#39;exec&#39; are preserved.  Also, as far as the called application is concerned,
it was run by typing the full pathname of the program, so that programs that
use the command line (eg WordPerfect) to find the directory it is running
in work properly.
 
 
Requirements
============
EXELINK makes use of an internal DOS function:  INT 21h Function 60h -
CANONICALIZE FILENAME OR PATH
This is only available on MS-DOS 3.0 onwards, and I am not sure if this is
a fully documented call.
 
EXELINK has been tested with:
     PC-DOS 3.20
     vanilla MS-DOS 3.30
     Atari PC2 specific MS-DOS 3.21
     Tri-Gem MS-DOS 3.30
     OEM MS-DOS 5.0
     4DOS v3.01, v3.02, v3.02a, v4.0, v4.01 (a good COMMAND.COM replacement)
     Windows 3.0, 3.1
     DesqView 386 v2.3, v2.4
     Various applications.
 
Known incompatibilities:
     MKS Tools 3.1c version of the Korn-Shell.
       I have had a lot of problems with the Korn Shell, from TSR&#39;s to
       bog-standard applications.  I am unsure as to why this shell fails
       to work with EXELINK since it seems to support INT21/AX=60h
       I have not tested with later versions of MKS tools.
 
     Turbo C exec() call.
       Turbo C seems to try to open the executable and read the header
       contents to determine the file type.  Of course, these files are
       ASCII and so TurboC returns &amp;quot;Invalid exec type&amp;quot; :-(
       This also affects Borland C++ 3.1 (the Run Time Library Sources
       show why Borland do this - to enable exec() to overlay better)
 
     Windows 3.0, 3.1.
       I think Windows also tries to open the file to determine
       if a file is a DOS or a Windows executable.  I am not sure.
       However,  EXELINK works happily inside a DOS window.
     DesqView 386.
       It appears that DesqView has its own exec() replacement, and so
       each window that you wish to use EXELINK in must have its own
       copy of EXELINK loaded.  Once this has happened, it works happily
       inside that window.
     Word Perfect for Windows 5.1
       Word Perfect seems to search the PATH to find where your windows
       system resides, so it knows where to put the INI GRP DLL files.
       If WIN.COM is in the links directory then WP4W assumes this is where
       windows lives!  Silly Word Perfect.....before installing this program
       you should modify your PATH so that it has the real windows directory
       at the front.  This is only needed to work around the install problem,
       and is not needed at runtime.
 
    Most problems appear to boil down to the program trying to open the
    executable as a file to determine its type.  In Windows this is only
    a problem at the menu level (normally!) and creating an icon
    pointing to the real program is no major problem.  With DesqView
    creating an &amp;quot;Open Program&amp;quot; item pointing to the real program solves the
    problem as well, with a special &amp;quot;DOS&amp;quot; shell running exelink when that is
    needed.
 
    I had debated with the idea of extending exelink so that the open() call
    is also linked, but decided against this for various reasons, mainly
    that I would also need to trap filesize() and other related calls to
    maintain consistency, which would make exelink too large and unwieldly.
    Finally there would also need to be a way to deactivate exelink so that
    the link file could be editted!
 
What if the link points to a non-existent file?
   With 4DOS if you have an link pointing to a non-existent file then 4DOS
   will give the error: Invalid path &amp;quot;link_name&amp;quot;.  The name it gives is
   the file in the LINK directory, so you can TYPE this file and find out
   why it doesn&#39;t work.  Under command.com 3.3 the error you get reads
   &amp;quot;EXE failure&amp;quot;.  Under command.com 5.0 the error is:
   Cannot Execute &amp;quot;link_name&amp;quot;.
 
Installation
============
1) Put EXELINK.COM in a directory on your PATH
2) Add the line
   [drive:][directory]EXELINK
   to your autoexec.bat file.  It is recommended that this is one of the
   first TSR&#39;s loaded so that the links are active as soon as possible.
   Then either reboot to run the new autoexec sequence, or run EXELINK
   by hand to be able to use it now.  EXELINK will load high with no problem
   (at least it does with QEMM).
3) Put the link directory at the beginning of your path
4) create the link directory.
5) create all the links needed.  Remember, a link file is just an ASCII
   file which contains the filename of the program you really want run.
Helpful Hints
=============
Applications called via EXELINK can live on any disk accessible by DOS.
There may be problems with &#39;join&#39; and &#39;assign&#39;.  The function INT21/AX=60h
used to test whether the called program is in the link directory returns the
filename as if there were no join&#39;s or assign&#39;s.  Your milage may vary.
 
Using 4DOS a nice utility that goes well is a small alias:
     alias addlink `for %add in (%&amp;amp;) echo %@full[%add]
            &amp;gt; c:\links\%@name[%add].%@ext[%add]`
[all on the same line of course!]
Alternatively you could create ADDLINK.BTM which performs the same
thing.  Then you could do something like
     cdd c:\app\turbop
     addlink *.com *.exe
which would create links for all .exe and .com files in the turbop
directory, enabling you to remove c:\app\turbop from the PATH.
If you have &#39;noclobber&#39; set (setdos /n1) then any link that already exists
will not be overwritten.
 
Under MS-DOS command.com you could do the following:
create a file addlink.bat containing
     echo %1\%2 &amp;gt; c:\links\%2
Then you could do
     cd \app\turbop
     for %a in (*.com *.exe) do addlink c:\app\turbop %a
 
WARNING:  This method would erase any old link of the same name, as would
the 4DOS version without &#39;noclobber&#39; set.
 
The link files are PURE ASCII and can be edited using any editor
from Edlin upwards.  The first character with a code of 32 or less counts
as the end of the string, so a ^Z or CR or LF are all ways of ending the
link file.   Up to 127 characters are allowed in the filename
on one line.  Anything longer than that will be truncated.  Filenames
must be FULLY QUALIFIED.  ie  they must be of the form drive:\path\file.ext
If they are not, then the command executed will be relative to the current
disk/directory.
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Virtualization All Change!</title>
      <link>https://www.sweharris.org/post/2012-03-04-virtualization-allchange/</link>
      <pubDate>Sun, 04 Mar 2012 17:14:52 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2012-03-04-virtualization-allchange/</guid>
      <description>&lt;p&gt;Just two weeks ago, I &lt;a href=&#34;https://www.sweharris.org/post/2012-02-20-virtualization-update/&#34;&gt;revisited my virtualization
options&lt;/a&gt; with a view to making the
system more reliable - primarily by using mirrored disks.&lt;/p&gt;

&lt;p&gt;In the end I stuck with a kludged up process for Citrix XenServer, but
with a worry about how this would impact patching and upgrades.&lt;/p&gt;

&lt;p&gt;This week my XenCenter instance told me that 6.0.2 was out and I should
upgrade.&lt;/p&gt;

&lt;p&gt;Now there are two ways to upgrade a XenServer; one is via the
XenCenter console where it pushes the updates, the other is to boot off the
CD and upgrade.&lt;/p&gt;

&lt;p&gt;Things started to look worrying when the XenCenter method (which I&amp;rsquo;ve never
tried before) reported losing connection to the XenServer, and looking in
the logs it reports that there is insufficient disk space to perform the
upgrade.  Huh.  Things took a turn for the worse when the CD method
refused to believe the old install even existed, and would only do a new
install (which might have been due to the system not finding or activating
the md devices, and due to the installer only looking at physical disks).&lt;/p&gt;

&lt;p&gt;So my worries were definitely on firm ground; how do I upgrade?&lt;/p&gt;

&lt;p&gt;Now &lt;em&gt;this&lt;/em&gt; upgrade was merely a series of minor patches and changes
that didn&amp;rsquo;t impact me.  But, going forward, I would end up being stuck
with an out-of-date platform if I wasn&amp;rsquo;t careful.&lt;/p&gt;

&lt;p&gt;So XenServer was, pretty much, out of the game.  I was going to be forced
to use something else.&lt;/p&gt;

&lt;p&gt;I looked back at my work, 2 weeks ago, and decided to give CentOS+KVM
another shot.  The main reason I&amp;rsquo;d dropped this was that serial console
installs would not work.&lt;/p&gt;

&lt;p&gt;This time I bit the bullet, and decided to build out a &amp;ldquo;templating&amp;rdquo;
solution.  I built one CentOS 5.7 install and one CentOS 6.2 install.
I used RAW image files.  So now I can use &amp;ldquo;losetup&amp;rdquo; and &amp;ldquo;kpartx&amp;rdquo; and
then mount the images and &amp;ldquo;sanitise&amp;rdquo; the result (disable SELinux, remove
firewalls, add my default user/passwd, remove log entries).  The result is
an OS template image which can be copied around as needed.  I then worked
out a simple XML file which can be used to generate new virsh definitions.&lt;/p&gt;

&lt;p&gt;The result is a BUILD script and
an TEMPLATE.xml file which can
be used:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# ./BUILD RH62.x86_64.template.img newstest d6:05:8b:cd:37:c0
Copying /var/lib/libvirt/images/TEMPLATES/RH62.x86_64.template.img to /var/lib/libvirt/images/newstest.img
Defining VM
Domain newstest defined from /tmp/tmp.NaiOX4rJNe

# virsh start newstest
Domain newstest started

% virsh console newstest
Connected to domain newstest
Escape character is ^]

CentOS release 6.2 (Final)
Kernel 2.6.32-220.4.2.el6.x86_64 on an x86_64

newstest login: 
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;EDIT 2018/01/13 - the original scripts I used are no longer available
so I have removed them as links.  I don&amp;rsquo;t use templates any more.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this case I specified a MAC address so that this new machine matched
the DHCP config I&amp;rsquo;d already setup; otherwise I let virsh pick a MAC address
at random and the new host gets a random IP address from the pool.&lt;/p&gt;

&lt;p&gt;Using this method I don&amp;rsquo;t need to worry too much about serial installs;
I don&amp;rsquo;t even need to do an install for new VMs I&amp;rsquo;ve previously templated.&lt;/p&gt;

&lt;p&gt;Now I built these machines out using a 4Gb disk which results in approx
3.2Gb root.  The OS takes up 700Mb, maybe.  That doesn&amp;rsquo;t sound like a lot,
but the idea is that data volumes can be added extra to this.  Thus the
&lt;a href=&#34;https://www.sweharris.org/Scripts/virt_add_disk.txt&#34;&gt;ADD_DISK&lt;/a&gt; script, which can be
used to add vdb&amp;hellip;vdk as datadisks.  For these I&amp;rsquo;ll likely not partition
them, and use as raw devices, so it&amp;rsquo;d be easy to resize as necessary.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;newstest.ttyS0% df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/vda2              3107344    740068   2209428  26% /
tmpfs                   251356         0    251356   0% /dev/shm
/dev/vda1               495844     49071    421173  11% /boot
/dev/vdb              20158332    176196  18958136   1% /datadisk
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So far I&amp;rsquo;ve spoken about Linux.  I also did a standard install of Windows
to verify it works.  Just as expected.  I&amp;rsquo;m not sure if this is slower or
faster than XenServer; it&amp;rsquo;s hard to tell when the display technology is
different!&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ll have to see how this works out, long term.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Virtualization Update</title>
      <link>https://www.sweharris.org/post/2012-02-20-virtualization-update/</link>
      <pubDate>Mon, 20 Feb 2012 15:03:25 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2012-02-20-virtualization-update/</guid>
      <description>&lt;p&gt;Two years ago I looked at some &lt;a href=&#34;https://www.sweharris.org/post/2010-06-06-virtualization-options/&#34;&gt;options for doing virtualisation at
home&lt;/a&gt;.  I decided on running Citrix
XenServer.  This has actually worked out quite well.  So much so that
I want to move some of my remaining physical hardware onto virtual.&lt;/p&gt;

&lt;p&gt;And here I run into a problem.  XenServer doesn&amp;rsquo;t want to work nicely
with mirrored disks.  It&amp;rsquo;s expecting SAN or similar to provide the
redundancy for disks.  Now people have worked out
&lt;a href=&#34;http://linuxnet.ch/groups/linuxnet/revisions/c370e/6/&#34;&gt;options&lt;/a&gt;
to convert a XenServer to a RAID disk, but I&amp;rsquo;m very very worried about how
upgrades might break the OS partition.  The XenServer upgrade process
appears to recreate sda and I&amp;rsquo;m afraid of it either not working or
breaking the mirror.  Of course I can&amp;rsquo;t tell until I actually have to
do an upgrade, but I&amp;rsquo;m not sure I want to to risk it.&lt;/p&gt;

&lt;p&gt;So&amp;hellip; let&amp;rsquo;s see how the world has moved on in the past two years.&lt;/p&gt;

&lt;p&gt;Now XenServer can &amp;ldquo;export&amp;rdquo; backups of VMs in &amp;ldquo;xva&amp;rdquo; format.  This is a
proprietary format that&amp;rsquo;s mostly a tar file with disk blocks.  Fortunately
you can &lt;a href=&#34;http://jolokianetworks.com/70Knowledge/Virtualization/Converting_from_Citrix_XenServer_to_Xen_open_source/Xenmigrate.py&#34;&gt;convert&lt;/a&gt; these
files into raw disk images.&lt;/p&gt;

&lt;p&gt;Whatever I replace the XenServer with should be able to handle these
image files.  I don&amp;rsquo;t expect the Linux images to be hard, but the
Windows images&amp;hellip; hmm.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CentOS 6.2 and Xen&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m primarily a CentOS user, so my first thought would be using CentOS
6.2.  Now the GUI installer for this handles RAID, after a fashion.
I created a mirrored root, mirrored /boot and installed a minimal OS.
After that completed I converted the rest of the disk (sda3/sdb3) into
a mirror and LVMd it.  So far, so normal.&lt;/p&gt;

&lt;p&gt;Now I start to run into issues; RedHat uses KVM for virtualization, and not
Xen.  But there is a &lt;a href=&#34;http://www.howtoforge.com/virtualization-with-xen-on-centos-6.2-x86_64-paravirtualization-and-hardware-virtualization&#34;&gt;process&lt;/a&gt;.
Basically, install a xen kernel, and replace libvirt with one that
understands Xen.  Not the easiest to do, but not &lt;em&gt;hard&lt;/em&gt; and, in
theory, a one-off.  Although kernel and libvirt patching might become
an issue down the line.&lt;/p&gt;

&lt;p&gt;So, within an hour of rebuilding the machine I had a fully mirrored Xen
system and had test installed a new Linux image using a logical volume
for storage.  So far so good.  I then installed virt-manager on my Ubuntu
desktop, and was able to use that to create and install an XP image using
a datafile in &lt;code&gt;/var/lib/libvirt/images&lt;/code&gt;.  virt-manager is nowhere
near as powerful as Citrix XenCenter, but it works for basic stuff.
Hmm, the distinction between using libvirtd for management vs Xen&amp;rsquo;s own
tools seems to be a little confusing.&lt;/p&gt;

&lt;p&gt;But then a problem&amp;hellip; closing down a VM caused the whole machine to
crash.  Not every time, and not consistently, but I got 2 kernel crashes
in one day.  Not good.  Not suitable.&lt;/p&gt;

&lt;p&gt;At least following that method, CentOS 6.2+Xen is not stable enough for me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CentOS 6.2 + KVM&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I possibly should have tried this one first time around, since KVM is the
native solution in CentOS.  An important question will be whether the
KVM emulated hardware is sufficiently close to the Xen hardware for the
Windows sessions to work in it (assuming I can convert the disks, of course)
and how much work will be needed to convert the Linux images, but.. first
steps first; is KVM usable?&lt;/p&gt;

&lt;p&gt;This time around I install all three virtualization groups from the
CentOS installer.  Also, rather than using virt-manager from my Ubuntu
desktop I would ssh into the VM host and use the virt-manager from there
(so RedHat^WCentos tools all the way.  Needed &amp;ldquo;dejavu-lgc-sans-fonts&amp;rdquo;
installed for words to display properly!).  Hmm, this appears to add some
niceness in building out the network devices and the storage pools, so
the ISO images can be seen.  I don&amp;rsquo;t &lt;em&gt;recall&lt;/em&gt; seeing those options
in my previous test but I might have been blind!&lt;/p&gt;

&lt;p&gt;Now here is where I might be stupid.  Using virt-manager I did a basic
CentOS install and it worked just fine&amp;hellip; except the network didn&amp;rsquo;t come
up inside the guest.  This might be a RedHat/CentOS oddity with Network
Manager (I&amp;rsquo;ve seen messages similar on the mailing lists); setting the
device to not use NM and to dhcp boot worked just fine.  So then I tried
another install, but this time &lt;em&gt;without&lt;/em&gt; any graphical console; using
virt-manager I removed the VNC, the input device, the screen.  So there
was just a serial connection.  It started up as normal&amp;hellip;but then after
selecting &amp;ldquo;install&amp;rdquo; from the CentOS menu it froze.  Umm.&lt;/p&gt;

&lt;p&gt;So I try it from the command line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;virt-install -n t2 --vcpus=1 -s 8 -r 512 -b br0 -l /OS_ISO_images/CentOS-6.2-x86_64-bin-DVD1.iso -f /var/lib/libvirt/images/t2.img --nographics
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And I get exactly the same problem.  If I don&amp;rsquo;t use &amp;ldquo;&amp;ndash;nographics&amp;rdquo; then I
get a good install (but with the network config issue), whereas if I do
specify it then the install freezes.&lt;/p&gt;

&lt;p&gt;Hmm.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debian 6 with Xen 4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;(rant: &amp;ldquo;amd64&amp;rdquo; doesn&amp;rsquo;t mean AMD in Debian land, apparently!  Also the
installer is crap; does some work and makes you think it&amp;rsquo;s gonna run on its
own, but then asks more questions later.  On the plus side, the loader is
better than the text-based CentOS one and works nicely with the existing
mirrors.)&lt;/p&gt;

&lt;p&gt;There are a quite few web pages that explain how to &lt;a href=&#34;http://wiki.stocksy.co.uk/wiki/Xen_on_Debian_Squeeze_dom0&#34;&gt;install Xen on
Debian&lt;/a&gt;.
It looks pretty simple.  So let&amp;rsquo;s give it a try!&lt;/p&gt;

&lt;p&gt;After getting my base Debian install setup, I followed some of the setup
on that page.  Hmm, Debian Xen seems to be a little different to CentOS
(and XenServer?).  When a domain is shutdown it no longer appears in the
&amp;lsquo;xm list&amp;rsquo; output (so you can&amp;rsquo;t just do &amp;ldquo;xm start name&amp;rdquo;; you have to do
&amp;ldquo;xm create /etc/xen/name.cfg&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;The &amp;ldquo;xen-create-image&amp;rdquo; command is funky, and a great way of creating new
Debian images.  If I wanted a Debian image!&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s see if I can boot one of the older CentOS images I created in an earlier
test&amp;hellip;  well, by setting the mac address and using pygrub then it worked
to boot that.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;bootloader = &#39;/usr/lib/xen-default/bin/pygrub&#39;
vcpus       = &#39;1&#39;
memory      = &#39;512&#39;
root        = &#39;/dev/xvda1 ro&#39;
disk        = [
                  &#39;file:/VMs/t1.img,xvda,w&#39;,
              ]
name        = &#39;t1old&#39;
dhcp        = &#39;dhcp&#39;
vif         = [ &#39;mac=52:54:00:01:72:1B&#39; ]
on_poweroff = &#39;destroy&#39;
on_reboot   = &#39;restart&#39;
on_crash    = &#39;restart&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But what about an XP VM?  Looking at an &lt;a href=&#34;http://wiki.stocksy.co.uk/wiki/Microsoft_Windows_XP_as_a_Xen_domU&#34;&gt;example page&lt;/a&gt;, this seems to need
xen-qemu-dm to be installed, and this drags in a lot of dependencies.  But
OK&amp;hellip; let&amp;rsquo;s go for it!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# dd if=/dev/zero of=/VMs/xp.img bs=1 count=0 seek=8G
# cat /etc/xen/xp.cfg
import os, re
arch = os.uname()[4]
kernel = &amp;quot;/usr/lib/xen-default/boot/hvmloader&amp;quot;
builder=&#39;hvm&#39;

memory = 512
shadow_memory = 8
name = &amp;quot;xp&amp;quot;
# Setting ne2k_pci is essential if you want the virtual NIC to work
vif = [ &#39;type=ioemu, bridge=eth0, model=ne2k_pci&#39; ]

disk = [ &#39;file:/VMs/xp.img,xvda,w&#39;, &#39;file:/OS_ISO_images/XPSP3.iso,xvdc:cdrom,r&#39; ]
device_model = &#39;/usr/lib/xen-default/bin/qemu-dm&#39;
boot=&amp;quot;cd&amp;quot;

sdl=0
# Enable VNC
vnc=1
vncconsole=1
listen=&#39;0.0.0.0&#39;
vncviewer=0
nographic=0
stdvga=0
serial=&#39;pty&#39;
audio=0
localtime=1
acpi=0
apic=0

# xm create --vncviewer xp.cfg
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, the installer kicks off, lets me format the disk, copies the files,
then reboots.  At this point I need to &amp;ldquo;xm vnc xp&amp;rdquo; to reconnect to the
machine and the next part of the installer is running.  Just as expected.
Indeed, the build completed and runs just fine.  Although the tightvnc
viewer that comes with Debian doesn&amp;rsquo;t seem to work as well as the viewer
with CentOS; definite mouse-coordination issues.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s try the VM I created on CentOS.. hmm failed to start
(it crashed and on restart brings up the &amp;lsquo;fail&amp;rsquo; menu, but then fails again,
even in safe mode).  Hmm, OK, turning on acpi and apic and now the image
boots!  Neat.  But, again, mouse coordination issues.  Let&amp;rsquo;s try an
image all the way from the original XenServer.  Hmm&amp;hellip; it&amp;rsquo;s running, but
taking forever to get through the startup screen.  Hmm.  &amp;ldquo;xm list&amp;rdquo; always
shows it in blocked state, but the indicator bar on the boot screen is
moving.  Hmm.&lt;/p&gt;

&lt;p&gt;Hmm, after 11 hours it&amp;rsquo;s still in the same state.  We might be able
to kludge things, but&amp;hellip;  hmm.&lt;/p&gt;

&lt;p&gt;However, I&amp;rsquo;m not feeling &amp;ldquo;comfortable&amp;rdquo;.  And here we come to the core
of the matter; the Xen install on Debian appears to be nice and stable.
But it&amp;rsquo;s not very friendly.  It&amp;rsquo;s all command-line, and (from what I&amp;rsquo;ve
read), you need to have different config files for install vs run.
Which seems odd.  The CentOS libvirt method is a lot smoother and
prettier&amp;hellip; but doesn&amp;rsquo;t appear to be stable.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not sure either is suitable to replace the XenServer.  If the CentOS
one hadn&amp;rsquo;t crashed (twice) in testing, then I might have continued
further with it, but maybe not (considering the libvirt compatibility thing).&lt;/p&gt;

&lt;p&gt;So this leads to the next test&amp;hellip;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debian 6 with Xen 4 and libvirt&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Starting from a fresh install of Debian, we&amp;rsquo;ll do an install of
virt-manager and see how well that improves the user experience.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;apt-get install virt-manager xen-qemu-dm xen-linux-system
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This seems to pull in world+dog, but that&amp;rsquo;s OK :-)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;0 upgraded, 220 newly installed, 0 to remove and 0 not upgraded.
Need to get 177 MB of archives.
After this operation, 474 MB of additional disk space will be used.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Hmm, xend needed to be configured to listen to http requests on localhost:8000
before virt-manager could talk, but that&amp;rsquo;s a minor issue.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s see what we can do with this version!  OK, we can set up storage pools,
so I can find the ISO images.  But I can&amp;rsquo;t set up network bridging via
virt-manager.  Maybe that&amp;rsquo;s not important; let&amp;rsquo;s create a VM and see
what happens!  OK, the &amp;ldquo;create a VM&amp;rdquo; has more options for different types
of Linux.  On the final screen I manually specify &amp;ldquo;eth0&amp;rdquo; as the bridge
device.&lt;/p&gt;

&lt;p&gt;And the build fails:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;xend.err &amp;quot;Error creating domain: device model &#39;/usr/lib64/xen/bin/qemu-dm&#39; not found&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;rsquo;s because it&amp;rsquo;s in &lt;code&gt;/usr/lib/xen-default/bin/qemu-dm&lt;/code&gt; (/usr/lib64
is a symlink to /usr/lib).  Hmm.  OK, let&amp;rsquo;s symlink /usr/lib/xen -&amp;gt;
xen-default and try again!  Now I get the vnc based boot screen.
Of course I only gave 512Mb to the VM and that&amp;rsquo;s, apparently, not enough
for a GUI install, but the TUI install ran.  So far, so good.  Except that
on reboot it needed me to kludge the settings to boot into HD.  Hmm.
The resulting image also has the network-manager problem seen previously;
I&amp;rsquo;m beginning to think this is a CentOS/RedHat issue.  Heh.&lt;/p&gt;

&lt;p&gt;Oh, hold on&amp;hellip; that&amp;rsquo;s doing a full virtualisation and not paravirt.  Why?
Oh, huh&amp;hellip; &amp;ldquo;only URL or import installs work with paravirt&amp;rdquo;.  Hmm, seems an
odd restriction, but OK&amp;hellip; I can do that.  Umm, OK, not via PXEboot, but
via HTTP it allows it.  OK, I can do that as well.  Here we go, a second
build using paravirt.  I do not recall if virt-manager on CentOS had
that restriction or not!  I don&amp;rsquo;t &lt;em&gt;think&lt;/em&gt; it did; I&amp;rsquo;m pretty sure I
select Xen (paravirt), but I might be misremembering.&lt;/p&gt;

&lt;p&gt;Hmm, if I try to install a second image then virt-manager keeps grey-ing
out (&amp;ldquo;not responding&amp;rdquo; type indication in Ubuntu).&lt;/p&gt;

&lt;p&gt;Interesting&amp;hellip; the second image booted cleanly and brought up the network!  Hmm.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s import that XP VM I just built in the previous test.  Yup, that worked.
And the virt-manager display keeps the mouse in sync properly.  Although
screen updates are a little slow and jerky.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s try with the VM that still didn&amp;rsquo;t work after 12 hours :-)  Oh, huh,
in virt-manager I clearly get the choice of i686 or x86_64; I wonder if the
previous import was the wrong CPU type.  Hmm.  No, it still does the same
thing, irregardless.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Results&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And, to be honest, I&amp;rsquo;m still not happy.&lt;/p&gt;

&lt;p&gt;Modern OS management of Xen has definitely improved a lot over 2 years ago.
But I don&amp;rsquo;t get the feeling of &amp;ldquo;comfort&amp;rdquo; that I get from XenServer.  For
the time being, I&amp;rsquo;m gonna stick with that and the kludged up mirror solution,
and hope that the update process doesn&amp;rsquo;t break things!&lt;/p&gt;

&lt;p&gt;&amp;hellip; unless someone can point me at a better VM management solution!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The Windows 7 taskbar</title>
      <link>https://www.sweharris.org/post/2011-10-21-win7taskbar/</link>
      <pubDate>Fri, 21 Oct 2011 12:23:22 -0500</pubDate>
      
      <guid>https://www.sweharris.org/post/2011-10-21-win7taskbar/</guid>
      <description>&lt;p&gt;People keep telling me how Windows 7 is so much better than XP.
Eventually, at work, I get forced into using it.  The first thing
I notice is that the taskbar is now all icons, which you have to
mouse over to see what windows each application has.  And there&amp;rsquo;s
no quick launch area any more; you can pin applications to the taskbar
so they&amp;rsquo;re there.&lt;/p&gt;

&lt;p&gt;However, I like having the XP option of having a program bar for
each running program.  Fortunately you can tell Win7 to do this.
Unfortunately it&amp;rsquo;s not very friendly.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;So here we have a normal setup; I have open Outlook, a message I&amp;rsquo;m
writting, firefox and IE8.  Note the position of the programs on the task bar.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&#34;https://www.sweharris.org/win7taskbar/v1.png&#34; alt=&#34;v1&#34; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Next, I opened OCS and Paint.  Note that the programs have moved to the
right &amp;lsquo;cos OCS has expanded from an icon to a program.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&#34;https://www.sweharris.org/win7taskbar/v2.png&#34; alt=&#34;v2&#34; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Finally, I opened a chat and started a new email.  The outlook program item
has moved to where mozilla was in the 1st screen shot, and the IE8
program has moved so far along the task bar that it&amp;rsquo;s moved to the
second row!  Also note that the pinned icons for programs not running
are also moving around.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src=&#34;https://www.sweharris.org/win7taskbar/v3.png&#34; alt=&#34;v3&#34; /&gt;&lt;/center&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;This is a real PITA &amp;lsquo;cos it means you have to continually scan the task
bar to find the program you want to select.  I can&amp;rsquo;t quickly move my mouse
and click on &amp;ldquo;Word&amp;rdquo;; I have to find it, first!&lt;/p&gt;

&lt;p&gt;With XP and the &amp;ldquo;quick launch&amp;rdquo; toolbar meant that programs didn&amp;rsquo;t bounce
around on the taskbar in this manner; I could quickly and easily find
quick launch icons, and long running programs gravitated to the left of
the program area.&lt;/p&gt;

&lt;p&gt;So it seems I have the option of losing information (glancing at the
taskbar to see what is open) or losing ease of use (I have to hunt for
the icon or program I want to use).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sigh&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;A POTENTIAL FIX!&lt;/em&gt;&lt;/strong&gt;
After this rant, someone pointed me to
&lt;a href=&#34;http://www.howtogeek.com/howto/windows-7/add-the-quick-launch-bar-to-the-taskbar-in-windows-7&#34;&gt;these instructions&lt;/a&gt;.  It&amp;rsquo;s a way of adding the
quick launch toolbar back.  And this solves 90% of my problems.&lt;/p&gt;

&lt;p&gt;Basically the steps are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unlock taskbar (rightclick on it; ensure &amp;ldquo;lock the taskbar&amp;rdquo; is not clicked)&lt;/li&gt;
&lt;li&gt;Add new toolbar (rightclick on taskbar; toolbars/New toolbar)&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;%appdata%\Microsoft\Internet Explorer\Quick Launch&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;This will add it to the right; drag it to the left, and resize it&lt;/li&gt;
&lt;li&gt;Now remove the title/text options; right click near the dotted line
and a menu should popup with &amp;ldquo;show text&amp;rdquo; and &amp;ldquo;show title&amp;rdquo; options; untick
them
*relock the taskback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You now have quick launch back!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>IP6 Updates</title>
      <link>https://www.sweharris.org/post/2011-09-19-ip6-updates/</link>
      <pubDate>Mon, 19 Sep 2011 23:05:47 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2011-09-19-ip6-updates/</guid>
      <description>&lt;p&gt;Since those experiments, linode is now also providing native IPv6 so
my linode was switched to the auto-provided address they provide.  By
default they only provide 1 IPv6 address but they allow rDNS to work,
so I haven&amp;rsquo;t needed any more, yet!&lt;/p&gt;

&lt;p&gt;IPv6 speeds internationally are a lot faster as well.  I did some speed
tests to a site in a UK exchange (connected at 100Mbit/s).  It would
saturate my home FIOS connection, peaking for periods of time at 3.65MB/s.
When I attempted the same speedtest from my linode it was quite variable
and bounced between 1 and 4MB/s, and was averaging slower than my FIOS.
But when I tried it via IPv6 from the linode the average was 7.42MB/s
with peaks up to 9.8MB/s.  So here we see the IPv6 connection running
over 3 times faster than the IPv4 connection!  Funky stuff.&lt;/p&gt;

&lt;p&gt;My home tunnel is now endpointed on a Seagate Dockstar, which I&amp;rsquo;ve got
running Debian.  The Dockstar is a &amp;ldquo;pogo-plug&amp;rdquo; type device, and has a
Gbit network port.  I&amp;rsquo;m not sure how fast the machine can drive it, but
it&amp;rsquo;s definitely fast enough for IPv6 traffic to the outside world.  This
machine runs the tunnel and ip6tables.  Now what this also means is that
my linode and v-colo can talk &amp;ldquo;directly&amp;rdquo; to my home machines.  So I no
longer need my UUCP over SSL method of sending email; my home machine can
talk SMTP over IPv6 to my virtual hosts (redundancy!) and those hosts and
send mail directly to me.  Faster, more efficient, more resillient.&lt;/p&gt;

&lt;p&gt;What I do need to work out, however, is &amp;ldquo;fixing&amp;rdquo; the tunnel if my IPv4
address changes.  HE tunnelbroker provide a web page to allow automatic
updates, but they don&amp;rsquo;t like you hitting it for no good reason.  And I
can&amp;rsquo;t find an automatic way of reading what the IPv4 endpoint address is.
So once or twice I&amp;rsquo;ve had my IPv4 change and so the tunnel freezes.  I
need to work on fixing that!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>IPv6 on the LAN</title>
      <link>https://www.sweharris.org/post/2011-09-19-ipv6-on-the-lan/</link>
      <pubDate>Mon, 19 Sep 2011 22:54:15 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2011-09-19-ipv6-on-the-lan/</guid>
      <description>&lt;p&gt;Just for the lulz I fired up a CentOS VM (I knew that Citrix XenServer
would come in handy!) and configured a tunnel to HE via that.&lt;/p&gt;

&lt;p&gt;I then configured a static IP6 address on eth0 and fired up radvd. My
main Linux machine automatically picked up an address on that subnet and
could ping6 to the outside world. I could also ssh from my linode directly
to my main Linux machine (did I mention I need an IPv6 firewall?).&lt;/p&gt;

&lt;p&gt;Heh, the Mac Mini also automatically picked up an address as well.&lt;/p&gt;

&lt;p&gt;So it kinda just works.&lt;/p&gt;

&lt;p&gt;The problem I have, though, is that the IPv6 addresses being assigned are
based on MAC addresses but I have no easy association between that and
the host. So ipv6 assigned via autoconf and router discovery may be fine
for dynamic hosts, but not so much for servers. And for dynamic hosts
there&amp;rsquo;s not an easy association between the IPv4 and IPv6 addresses (eg
dhcp214.home on IP4 is known; what&amp;rsquo;s the equivalent IPv6 address?). So
it looks like I need a DHCPv6 server instead, so give out known IPv6
address ranges, rather than allowing autoconf via router discovery.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Messing around with ipv6</title>
      <link>https://www.sweharris.org/post/2011-09-19-ipv6/</link>
      <pubDate>Mon, 19 Sep 2011 22:51:58 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2011-09-19-ipv6/</guid>
      <description>&lt;p&gt;My v-colo at Panix can be configured to use IPv6.  Now it looks a little
bit like Panix is kludging routing slightly (they give you a /96 but
with a /64 netmask).  It&amp;rsquo;s very possible that their router is just at
the end of a HE tunnelbroker, since HE are an upstream provider to Panix.&lt;/p&gt;

&lt;p&gt;Enabling IPv6 on the v-colo was simple; I just enabled it on their
&amp;ldquo;config&amp;rdquo; website and&amp;hellip;it worked.  I could even set up a rDNS entry for
that IP.  Since I don&amp;rsquo;t currently need more than the one address I didn&amp;rsquo;t
bother looking at the other addresses.&lt;/p&gt;

&lt;p&gt;My linode required a specific tunnel being set up.  So I signed up for
one, associated my linode IPv4 address with it.  Then configured my
CentOS machine:&lt;/p&gt;

&lt;p&gt;Add to /etc/sysconfig/network&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;NETWORKING_IPV6=yes
IPV6_DEFAULTDEV=sit1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Create /etc/sysconfig/network-scripts/ifcfg-sit1&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;DEVICE=sit1
BOOTPROTO=none
ONBOOT=yes
IPV6INIT=yes
IPV6TUNNELIPV4=&amp;lt;HE&#39;s IP4 tunnel address&amp;gt;
IPV6ADDR=&amp;lt;Assigned IPv6 tunnel address&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then &amp;ldquo;ifup sit1&amp;rdquo; and&amp;hellip; it was on the network!&lt;/p&gt;

&lt;p&gt;But, here, the rDNS of the tunnel is specific directly by HE.  So I had
to use one of the /64 addresses assigned to me.  This was as simple as
adding a line such as&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;IPV6ADDR_SECONDARIES=&amp;lt;one_of_my_ip_addresses&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&amp;ldquo;ifdown sit1&amp;rdquo; then &amp;ldquo;ifup sit1&amp;rdquo; and the address was assigned.&lt;/p&gt;

&lt;p&gt;Now one thing I don&amp;rsquo;t understand is how the kernel decides on what source
address should be used when making a connection, since &amp;ldquo;ip addr&amp;rdquo; shows
both as a /64.  But it seems to work; outgoing ssh connections show the
connection coming from my routed address and not the tunnel address.&lt;/p&gt;

&lt;p&gt;Of course, using a routed address meant I needed to setup rDNS for
that.  HE allows delegation of the routed subnet and a little bit of
trail-and-error seems to have got that to work.&lt;/p&gt;

&lt;p&gt;Because this is a test, I&amp;rsquo;m using a different name for my IPv6 addresses.
When I&amp;rsquo;m convinced it all works then I&amp;rsquo;ll probably switch to having the
same name for IPv4 and IPv6.  Although I noticed my web server config
doesn&amp;rsquo;t listen on IPv6.  Umm.&lt;/p&gt;

&lt;p&gt;Why am I doing this?  I don&amp;rsquo;t believe IPv4 is going away for a fair few
years yet (those areas with IPv6 only will have ISP provided proxies
for web servers and 6to4 NAT gateway, for example) but I thought it&amp;rsquo;d
be something to play with.&lt;/p&gt;

&lt;p&gt;What&amp;rsquo;s interesting is this&amp;hellip;&lt;/p&gt;

&lt;p&gt;From my linode to my v-colo&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;IPv4:
6 packets transmitted, 6 received, 0% packet loss, time 5007ms
rtt min/avg/max/mdev = 83.076/83.313/83.760/0.436 ms, pipe 2

IPv6:
6 packets transmitted, 6 received, 0% packet loss, time 5001ms
rtt min/avg/max/mdev = 71.254/72.490/76.062/1.670 ms, pipe 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Various traceroutes later, it seems the cross-country transit from NYC
to LAX (which is HE, both ways) is quicker on IPv6 which surprises me.&lt;/p&gt;

&lt;p&gt;I guess my next step will be to add a tunnelbroker connection to my
home network.  But that will require a little more thought; I don&amp;rsquo;t
necessarily want to expose my Windows machines to the outside world
(the NAT gateway acts as a nice little firewall for IPv4) so I&amp;rsquo;ll need
to be a little bit cleverer.  It also seems my preferred WTR54G firmware
(Tomato) doesn&amp;rsquo;t support IPv6 so I&amp;rsquo;ll need to work on that as well.&lt;/p&gt;

&lt;p&gt;*&lt;strong&gt;&lt;em&gt;UPDATE:&lt;/em&gt;&lt;/strong&gt;*&lt;/p&gt;

&lt;p&gt;I realised that the way I was seeing traceroutes to my routed IPv6 range
meant that it wasn&amp;rsquo;t actually using the end-tunnel IPv6 address for the
route. So I just tried assigning one of the routed addresses directly
to the interface and not use the tunnel address. It seems to work just
as well, so I don&amp;rsquo;t have to worry about what source ip6 address will be
used for outgoing connections.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Kerberos and IPv6</title>
      <link>https://www.sweharris.org/post/2011-07-09-kerberos-ipv6/</link>
      <pubDate>Sat, 09 Jul 2011 12:39:58 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2011-07-09-kerberos-ipv6/</guid>
      <description>&lt;p&gt;Not only have I been playing with Kerberos, but I&amp;rsquo;ve also been playing with IPv6.  So, naturally, kerberos over IPv6 was a test I had to do.&lt;/p&gt;

&lt;p&gt;Now because I&amp;rsquo;m only playing with IPv6 I&amp;rsquo;ve been using different DNS names; so kdc.spuddy.org is on IPv4 but kdc.ip6.spuddy.org is on IPv6.&lt;/p&gt;

&lt;p&gt;So, test!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ telnet -a -f kdc.ip6.spuddy.org
Trying 2001:470:1f07:dc4:3c46:1aff:fef4:d7a3...
Connected to kdc.ip6.spuddy.org (2001:470:1f07:dc4:3c46:1aff:fef4:d7a3).
Escape character is &#39;^]&#39;.
[ Kerberos V5 accepts you as ``sweh@SPUDDY.ORG&#39;&#39; ]
[ Kerberos V5 accepted forwarded credentials ]
Last login: Sat Jul  9 07:48:04 from kclient.spuddy.org
[sweh@kdc ~]$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Perfect!&lt;/p&gt;

&lt;p&gt;But SSH&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[sweh@kclient ~]$ ssh -o &#39;GSSAPIDelegateCredentials=yes&#39; kdc.ip6.spuddy.org
sweh@kdc.ip6.spuddy.org&#39;s password: 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ugh.  It&amp;rsquo;s asking for a password, so the ticket wasn&amp;rsquo;t accepted.  Ugh.&lt;/p&gt;

&lt;p&gt;To debug it, I ran &amp;ldquo;sshd -d -p 2222&amp;rdquo; and tried connecting to that.  This showed in the debug output&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;debug1: userauth-request for user sweh service ssh-connection method gssapi-with-mic
debug1: attempt 1 failures 1
Postponed gssapi-with-mic for sweh from 2001:470:1f07:dc4:1c79:45ff:fe48:1534 port 58243 ssh2
debug1: Unspecified GSS failure.  Minor code may provide more information
Wrong principal in request
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Wrong principal.  Doesn&amp;rsquo;t sound good!  I&amp;rsquo;d already ensured that the keytab had both ip4 and ip6 principals in it (&amp;ldquo;klist -k&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;Googling around makes me think this is a problem with older versions of OpenSSH.  eg &lt;a href=&#34;http://mailman.mit.edu/pipermail/kerberos/2007-January/011126.html&#34;&gt;http://mailman.mit.edu/pipermail/kerberos/2007-January/011126.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;cite&gt;But now it appears the solution is upgrading to OpenSSH 4.5p1 along with the associated GSSAPI Key Exchange patch.  The 4.5p1 GSSKEX patch supports a new config option (introduced in 4.4p1) &amp;ldquo;GSSAPIStrictAcceptorCheck=no&amp;rdquo; which, according to the man page:&lt;/p&gt;

&lt;p&gt;&lt;cite&gt;If &amp;lsquo;no&amp;rsquo; then the client may authenticate against any service key  stored in the machine&amp;rsquo;s default store.  This facility is provided to assist with operation on multi home machines&lt;/cite&gt;&lt;/p&gt;

&lt;p&gt;Huh, so if I make /etc/hosts on kclient have the IPv6 address associated with the kdc&amp;hellip; it worked!  So it seems the name the ssh client tries to connect to impacts whether the remote sshd accepts the ticket or not.  Odd.  This&amp;rsquo;d impact anyone with CNAMEs or multiple A records or&amp;hellip;   The &amp;ldquo;acceptor check&amp;rdquo; flag lets sshd check against any principal in the keytab, not just the first.&lt;/p&gt;

&lt;p&gt;Of course, RedHat is &amp;ldquo;long term release&amp;rdquo; and it doesn&amp;rsquo;t look like this enhancement has been backported to RHEL5.&lt;/p&gt;

&lt;p&gt;A little annoying!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Kerberos and Active Directory</title>
      <link>https://www.sweharris.org/post/2011-07-08-kerberos-and-ad/</link>
      <pubDate>Fri, 08 Jul 2011 22:52:08 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2011-07-08-kerberos-and-ad/</guid>
      <description>&lt;p&gt;So I built a quick AD domain based on W2k3 R2.  I created TESTDOM.AD.SPUDDY.ORG as my AD domain, and made my primary DNS delegate that part of DNS to the AD server.&lt;/p&gt;

&lt;p&gt;I was able to join an XP client to the domain.&lt;/p&gt;

&lt;p&gt;So far, so good!&lt;/p&gt;

&lt;p&gt;So then I built a CentOS 5.6 machine and configured it for Kerberos.
set up krb5.conf:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[libdefaults]
 default_realm = TESTDOM.AD.SPUDDY.ORG
 dns_lookup_realm = true
 dns_lookup_kdc = true
 ticket_lifetime = 24h
 forwardable = yes

[realms]
 # TESTDOM.AD.SPUDDY.ORG ={
  # kdc = adprimary.testdom.ad.spuddy.org:88
  # admin_server = adprimary.testdom.ad.spuddy.org:749
  # default_domain = testdom.ad.spuddy.org
 # }

[domain_realm]
 .testdom.ad.spuddy.org = TESTDOM.AD.SPUDDY.ORG
 testdom.ad.spuddy.org = TESTDOM.AD.SPUDDY.ORG
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I configured sshd for kerberos, same as for my real kerberos machine.&lt;/p&gt;

&lt;p&gt;So far, so good:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sweh@dhcp219&#39;s password: 
Last login: Sun Jul  3 18:26:12 2011 from mercury.spuddy.org
$ klist
Ticket cache: FILE:/tmp/krb5cc_500_JYPNYK7309
Default principal: sweh@TESTDOM.AD.SPUDDY.ORG

Valid starting     Expires            Service principal
07/03/11 18:42:31  07/04/11 04:42:32  krbtgt/TESTDOM.AD.SPUDDY.ORG@TESTDOM.AD.SPUDDY.ORG
        renew until 07/04/11 18:42:31


Kerberos 4 ticket cache: /tmp/tkt500
klist: You have no tickets cached
$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course I&amp;rsquo;m using local users, but with Kerberos password authentication, and happily getting tickets.&lt;/p&gt;

&lt;p&gt;Next step is to join the machine to the domain so I can use tickets.  Here things get a little interesting.  Samba&amp;rsquo;s &amp;ldquo;net ads join&amp;rdquo; command can seem to do it, but I didn&amp;rsquo;t want to modify the standard Samba config.  Fortunately you can specify &amp;ldquo;-s&amp;rdquo; to a different config file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# cat smb.conf.AD 
[global]
workgroup = TESTDOM
realm = TESTDOM.AD.SPUDDY.ORG
security = ads
password server = adprimary.testdom.ad.spuddy.org
use kerberos keytab = true

# net ads join -s smb.conf.AD  -U administrator
administrator&#39;s password: 
Using short domain name -- TESTDOM
DNS update failed!
Joined &#39;DHCP219&#39; to realm &#39;TESTDOM.AD.SPUDDY.ORG&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The DNS failure doesn&amp;rsquo;t seem important; it&amp;rsquo;s probably an artifact of my having a different DNS domain for my machines than the AD server.  But looking at AD from the W2K3 GUI, I see the host is created.  So not we can create they keytab:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# net ads keytab create -s smb.conf.AD -U administrator
administrator&#39;s password: 
# klist -k
Keytab name: FILE:/etc/krb5.keytab
KVNO Principal
---- --------------------------------------------------------------------------
   5 host/dhcp219.spuddy.org@TESTDOM.AD.SPUDDY.ORG
   5 host/dhcp219.spuddy.org@TESTDOM.AD.SPUDDY.ORG
   5 host/dhcp219.spuddy.org@TESTDOM.AD.SPUDDY.ORG
   5 host/dhcp219@TESTDOM.AD.SPUDDY.ORG
   5 host/dhcp219@TESTDOM.AD.SPUDDY.ORG
   5 host/dhcp219@TESTDOM.AD.SPUDDY.ORG
   5 DHCP219$@TESTDOM.AD.SPUDDY.ORG
   5 DHCP219$@TESTDOM.AD.SPUDDY.ORG
   5 DHCP219$@TESTDOM.AD.SPUDDY.ORG
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So far so good&amp;hellip;  I can login using tickets!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ klist
Ticket cache: FILE:/tmp/krb5cc_500_JYPNYK7309
Default principal: sweh@TESTDOM.AD.SPUDDY.ORG

Valid starting     Expires            Service principal
07/03/11 18:42:31  07/04/11 04:42:32  krbtgt/TESTDOM.AD.SPUDDY.ORG@TESTDOM.AD.SPUDDY.ORG
        renew until 07/04/11 18:42:31


Kerberos 4 ticket cache: /tmp/tkt500
klist: You have no tickets cached
$ ssh -o &#39;GSSAPIDelegateCredentials=yes&#39; dhcp219
Last login: Sun Jul  3 18:42:31 2011 from mercury.spuddy.org
$
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At first attempt ksu didn&amp;rsquo;t work either.&lt;/p&gt;

&lt;p&gt;But adding this domain_realm mapping:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  .spuddy.org = TESTDOM.AD.SPUDDY.ORG
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and now ksu works:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ klist
Ticket cache: FILE:/tmp/krb5cc_500_Zvavdv8343
Default principal: sweh@TESTDOM.AD.SPUDDY.ORG

Valid starting     Expires            Service principal
07/03/11 23:55:16  07/04/11 09:55:17  krbtgt/TESTDOM.AD.SPUDDY.ORG@TESTDOM.AD.SPUDDY.ORG
        renew until 07/04/11 23:55:16


Kerberos 4 ticket cache: /tmp/tkt500
klist: You have no tickets cached
$ ksu
Authenticated sweh@TESTDOM.AD.SPUDDY.ORG
Account root: authorization for sweh@TESTDOM.AD.SPUDDY.ORG successful
Changing uid to root (0)
[root@dhcp219 sweh]#
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I guess I don&amp;rsquo;t understand the domain_realm mappings; I&amp;rsquo;d been
cargo-culting. I guess they&amp;rsquo;re host DNS domain maps to kerberos
realm. Which, really, doesn&amp;rsquo;t strike me as necessarily sane. Why wouldn&amp;rsquo;t
the default_realm value from the [libdefaults] section take precedence,
anyway?&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s not all sunshine and roses, though.  /var/cache/samba/gencache.tdb
is modified; I don&amp;rsquo;t know if this would impact existing samba usage.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Beginning kerberos</title>
      <link>https://www.sweharris.org/post/2011-07-08-beginning-kerberos/</link>
      <pubDate>Fri, 08 Jul 2011 22:52:01 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2011-07-08-beginning-kerberos/</guid>
      <description>&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; I know nothing about Kerberos.  I&amp;rsquo;m learning it all from scratch.&lt;/p&gt;

&lt;p&gt;I wanted to do some playing around with Kerberos (once I know Kerberos
then I can look better at how to integrate with AD), so at home I
set up a couple of CentOS 5.6 server VMs on my home network, built
one out as a KDC (&amp;ldquo;yum install krb5-server&amp;rdquo;) and one as a Kerberos
client talking to the KDC (krb5-workstation installed by default).
&lt;a href=&#34;http://www.kerberos.org/software/adminkerberos.pdf&#34;&gt;This&lt;/a&gt; is a
pretty good &amp;ldquo;getting started&amp;rdquo; guide.&lt;/p&gt;

&lt;p&gt;On a machine that isn&amp;rsquo;t kerberized, I have no tickets&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;non-kerb-client% klist
klist: No credentials cache found (ticket cache FILE:/tmp/krb5cc_500)

Kerberos 4 ticket cache: /tmp/tkt500
klist: You have no tickets cached
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that the default filenames used are /tmp/krb5cc_&lt;uid&gt; (for kerberos5) and /tmp/tkt&lt;uid&gt; for Kerberos4.&lt;/p&gt;

&lt;p&gt;On the Kerberos client machine I configured sshd to perform kerberos authentication. So now I login to it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;non-kerb-client% ssh mylogin@kclient
mylogin@kclient&#39;s password:
Last login: Wed Jun 29 09:47:29 2011 from mercury.spuddy.org
[mylogin@kclient ~]$ klist
Ticket cache: FILE:/tmp/krb5cc_500_KhWkrB4506
Default principal: mylogin@SPUDDY.ORG

Valid starting Expires Service principal
06/29/11 09:48:53 06/30/11 09:48:53 krbtgt/SPUDDY.ORG@SPUDDY.ORG

Kerberos 4 ticket cache: /tmp/tkt500
klist: You have no tickets cached
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note the krb5 ticket file has a different name; this is a per-session kerberos ticket file that was created by ssh when I logged in.&lt;/p&gt;

&lt;p&gt;I have a &amp;ldquo;krbtgt&amp;rdquo; which is a kerberos ticket granting ticket, which means I can now use this session to access other resources&amp;hellip;&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s access another machine by ssh. In this case the kerberos key distribution center (kdc)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[mylogin@kclient ~]$ ssh kdc
Last login: Wed Jun 29 09:48:11 2011 from kclient.spuddy.org
[mylogin@kdc ~]$ klist
klist: No credentials cache found (ticket cache FILE:/tmp/krb5cc_500)

Kerberos 4 ticket cache: /tmp/tkt500
klist: You have no tickets cached
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, it let me in without needing a password&amp;hellip; but my ticket didn&amp;rsquo;t carry over! That&amp;rsquo;s because I didn&amp;rsquo;t ask for the ticket to be forwarded&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[mylogin@kdc ~]$ logout
Connection to kdc closed.
[mylogin@kclient ~]$ ssh -o &#39;GSSAPIDelegateCredentials=yes&#39; kdc
Last login: Wed Jun 29 09:49:11 2011 from kclient.spuddy.org
[mylogin@kdc ~]$ klist
Ticket cache: FILE:/tmp/krb5cc_500_GSTIKd5634
Default principal: mylogin@SPUDDY.ORG

Valid starting Expires Service principal
06/29/11 09:49:21 06/30/11 09:48:53 krbtgt/SPUDDY.ORG@SPUDDY.ORG

Kerberos 4 ticket cache: /tmp/tkt500
klist: You have no tickets cached
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ah ha! Here we go. By telling ssh to delegate credentials, we get a new TGT on the remote server, which can be used for further access.&lt;/p&gt;

&lt;p&gt;ktelnet can also do this&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[mylogin@kdc ~]$ logout
Connection to kdc closed.
[mylogin@kclient ~]$ telnet -a -f kdc
Trying 10.0.0.23...
Connected to kdc.spuddy.org (10.0.0.23).
Escape character is &#39;^]&#39;.
[ Kerberos V5 accepts you as ``mylogin@SPUDDY.ORG&#39;&#39; ]
[ Kerberos V5 accepted forwarded credentials ]
Last login: Wed Jun 29 09:49:21 from kclient.spuddy.org
[mylogin@kdc ~]$ klist
Ticket cache: FILE:/tmp/krb5cc_p5780
Default principal: mylogin@SPUDDY.ORG

Valid starting Expires Service principal
06/29/11 09:51:41 06/30/11 09:48:53 krbtgt/SPUDDY.ORG@SPUDDY.ORG

Kerberos 4 ticket cache: /tmp/tkt500
klist: You have no tickets cached
[mylogin@kdc ~]$ logout
Connection closed by foreign host.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Different temporary filename, but it works the same.&lt;/p&gt;

&lt;p&gt;Kerberos can also be used for &amp;lsquo;su&amp;rsquo;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[mylogin@kclient ~]$ ksu
Authenticated mylogin@SPUDDY.ORG
Account root: authorization for mylogin@SPUDDY.ORG
Changing uid to root (0)
[root@kclient mylogin]# klist
Ticket cache: FILE:/tmp/krb5cc_0.1
Default principal: mylogin@SPUDDY.ORG

Valid starting Expires Service principal
06/29/11 09:48:53 06/30/11 09:48:53 krbtgt/SPUDDY.ORG@SPUDDY.ORG
06/29/11 09:51:06 06/30/11 09:48:53 host/kclient.spuddy.org@SPUDDY.ORG

Kerberos 4 ticket cache: /tmp/tkt0
klist: You have no tickets cached

[root@kclient mylogin]# cat /root/.k5login
mylogin@SPUDDY.ORG
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&amp;rsquo;m pretty sure this is not a good idea; at work we want stronger controls over who can access root, so it means we&amp;rsquo;ll have to check for .k5login files if we ever switch to kerberos for authentication!&lt;/p&gt;

&lt;p&gt;Note that &amp;lsquo;root&amp;rsquo; now also has the host key in the kerberos cache.&lt;/p&gt;

&lt;p&gt;Note that Kerberos is just an authentication system; it doesn&amp;rsquo;t handle naming services nor authorizations; it&amp;rsquo;s just a &amp;ldquo;secure password repository&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;This is exactly the sort of testing I wanted my XenServer for!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>X-No-Archive considered pointless</title>
      <link>https://www.sweharris.org/post/2011-07-05-x-no-archive/</link>
      <pubDate>Tue, 05 Jul 2011 22:12:46 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2011-07-05-x-no-archive/</guid>
      <description>&lt;p&gt;Because of who we are and what we do, a number of people who post to newsgroups
like to hide themselves; use anonymous names, try to stop archives from
retaining messages and so on.  I, personally, am open with who I am and
what I am but this doesn&amp;rsquo;t mean I decry the attempts of others to maintain
anonymity.&lt;/p&gt;

&lt;p&gt;One such attempt is the use of X-No-Archive: headers in newsgroup postings.
This tells
&lt;a href=&#34;http://groups.google.com/support/bin/answer.py?hl=en-GB&amp;amp;answer=46487&#34;&gt;google&lt;/a&gt;
to not archive the message.  Other archivers may also use this convention.&lt;/p&gt;

&lt;p&gt;Note an important thing about this though:
&lt;em&gt;the line must either be a header or the first line of the message&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This has a major implications on follow ups.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By default, a followup to a X-No-Archive message is &lt;em&gt;not&lt;/em&gt;
itself X-No-Archived.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The new message will not have the message header in place (if the original
had it in the header) and any message body with the line in would be
quoted (typically with a &amp;gt; symbol) and appear after attributions line
(eg &amp;ldquo;Fred Bloggs wrote:&amp;ldquo;).&lt;/p&gt;

&lt;p&gt;For convenience, I&amp;rsquo;ll simply refer to this header as XNA in the rest of this
document.&lt;/p&gt;

&lt;p&gt;I have been taken to task, before, for not XNAing my responses to a XNAd
message.  It was even, once, criticised as being deliberate.  As can be
seen from above, a followup to an XNA message is not, itself, XNAd without
additional action on my behalf.  And that action is actually quite an onus:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I don&amp;rsquo;t automatically put XNA headers in my post because I don&amp;rsquo;t
want my articles non-archived (tin allows per-newsgroup headers if needed)&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;If a message has XNA header then I don&amp;rsquo;t even &lt;em&gt;see&lt;/em&gt; them becuase
I have my newsreader set to hide them.  Most definitely X- headers (a
&amp;ldquo;do what you like&amp;rdquo; header with no standing in RFC-1036 beyond that) don&amp;rsquo;t
get copied into reply messages (otherwise X-Face: and other stuff would
also get copied)&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;If the XNA line is the first line of the message then when I
quote the response then the quoted line (a) has a &amp;gt; in front and (b) isn&amp;rsquo;t
the first line of text, and so is ignored by google.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This means that if people want me to honor the request to propogate I have to&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;notice it&lt;/li&gt;
&lt;li&gt;go out of my way to &lt;strong&gt;ADD&lt;/strong&gt; text to my message&lt;/li&gt;
&lt;li&gt;go against my desire to want to archive my text&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Basically, XNA has no standing in Usenet; it&amp;rsquo;s a flag for google
(and other archivers that may decide to follow the standard).  It&amp;rsquo;s no better
than X-No-Ahbou: or any other of the potential 1000 X-No- headers that people
may decide to create off the top of their head (X-No-War-In-Iraq: perhaps?)&lt;/p&gt;

&lt;p&gt;Now, it&amp;rsquo;s been argued that people can have good reasons why they don&amp;rsquo;t
want their posts to be available forever and that by failing to honour
the XNA request is in the same general category as outing a person
(but not as bad); outing as in identifying them as a member of some minority
that may cause them distress elsewhere (eg a closetted gay person, a BDSM
practioner, whatever).&lt;/p&gt;

&lt;p&gt;I disagree totally.  The only place XNA has any meaning is in the google
groups archive (and potentially other archives which also use this
convention). I effectively have an archive; my own personal newsserver
never expires messages and so has messages going back to Jun 6 2001.
It most surely never follows any X- header request because it&amp;rsquo;s a Usenet
server and X- headers are meaningless to Usenet.  I can (and have)
quoted messages from the past when they are relevant.&lt;/p&gt;

&lt;p&gt;Contrarily, I consider if offensive that other people wish to prescribe and
force behaviour on me that I do not wish, especially when their are no RFCs
or BCPs that cover the situation, and (indeed) where the RFCs say that the
header in question has no meaning.&lt;/p&gt;

&lt;p&gt;RFC-822 (the one that defines headers and which RFC-1036 - usenet - refers
to) says:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    extension-field =
                    &amp;lt;Any field which is defined in a document
                    published as a formal extension to this
                    specification; none will have names beginning
                    with the string &amp;quot;X-&amp;quot;&amp;gt;

     user-defined-field =
                    &amp;lt;Any field which has not been defined
                    in this specification or published as an
                    extension to this specification; names for
                    such fields must be unique and may be
                    pre-empted by published extensions&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That means NO field defined by any RFC standard will begin with X- which
implies that the XNA header is a user-defined-field.&lt;/p&gt;

&lt;p&gt;Another argument could be that this is a fairly well defined convention
and that while the standards don&amp;rsquo;t specify, there is no reason to not
accept this.  My response is simply that HTML format messages and MIME
encoded binaries are also well defined conventions.  If it becomes the
onus on the person following up to check for and maintain a non-standard
header because of the wishes of the sender, then why shouldn&amp;rsquo;t the sender
also be allowed to send HTML messages, with the onus on the reader to
get software that can handle it?&lt;/p&gt;

&lt;p&gt;This is why we have standards documents.&lt;/p&gt;

&lt;p&gt;What this boils down to is that the XNA concept is fatally flawed as
a means of keeping responses to messages out of google.  Responses (either by
accident or by design or by simple not-caring) may easily quote a XNAd
message and not have the header itself.  In my case it&amp;rsquo;s simple &amp;ldquo;not caring&amp;rdquo;;
if someone posts a message then they must expect it to be quoted and followed
up, and along the way it may easily be archived.&lt;/p&gt;

&lt;p&gt;Anyone who relies on XNA to be no more than a &lt;em&gt;request&lt;/em&gt;
for their own message is deluding themselves as to the state of Usenet.&lt;/p&gt;

&lt;p&gt;As an alternative, people concerned about their anonymity could create
a free webmail address (eg hotmail, excite, yahoo, whatever) and use
that in their postings.  If they XNA their own message, then the originating
IP address (their ISP) won&amp;rsquo;t appear in the archives and any followup
(be it XNAd or not) will merely quote their webmail address.  It would
take a deliberate act to copy any NNTP-Posting-Host headers into the
follow up message (or an act of &amp;ldquo;pilot error&amp;rdquo; - ie a mistake).  Their
anonymity is maintained.  If they don&amp;rsquo;t want people reading their words
in 5 years time, then don&amp;rsquo;t post in the first place.  Once a message has
been thrown out to usenet it has an indefinite life time.  XNA does not,
and can not, change this.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Virtualization Options</title>
      <link>https://www.sweharris.org/post/2010-06-06-virtualization-options/</link>
      <pubDate>Sun, 06 Jun 2010 16:52:02 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2010-06-06-virtualization-options/</guid>
      <description>&lt;p&gt;Many of us are geeks who like to play with technology &amp;ldquo;because it is
there&amp;rdquo;.  We might want to try out a new OS, or a new piece of
software.  Maybe install a beta version of something, or be able
to test a client-server setup.  Historically that has meant having
one (or more) test machines, configured as multi-boot.  In 2002 I
spent $600 on a Celeron 1200Mhz machine with 256Mb RAM and a 40Gb disk
for precisely this purpose; it multi-booted into XP, NetBSD, Solaris
86, Fedora&amp;hellip; at that point I ran out of primary boot partitions.
&lt;em&gt;sigh&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Today, however, machines are a lot more powerful.  Since I had a
spare case, power supply and 3*500Gb disk sitting around I spent $500
getting a new motherboard ($90), an i5-750 CPU($200) and 8Gb of RAM
($210).  I picked this setup because it was a VT-x compatible CPU
so could do hardware virtualization for Windows guests.  Also, in
the worst case, it could quickly be used as a standby machine if my
primary server (Q6600, 4Gb RAM) died.  Redundancy :-)&lt;/p&gt;

&lt;p&gt;Then I had to decide on what virtualization technology to use on this
machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Types of hypervisor&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hypervisors come labelled in two types; &amp;ldquo;type 1&amp;rdquo; and &amp;ldquo;type 2&amp;rdquo;.
It&amp;rsquo;s really a little but kludgy to have this separation but&amp;hellip;&lt;/p&gt;

&lt;p&gt;Type 1 hypervisors are typically small kernels that essentially act as
a message bus between guest OS&amp;rsquo;s and a &amp;ldquo;control domain&amp;rdquo;.  The
guest may think it&amp;rsquo;s talking to a SCSI controller but really this talks
to the hypervisor, which passes the request to the control domain,
which then does the work of talking to the hardware.  Hypervisors
built on this model can be quite small and are potentially suitable for
embedding into server firmware.  Because of this they&amp;rsquo;re commonly
known as &amp;ldquo;bare metal&amp;rdquo; hypervisors.  This is what Sun have done
with some of their newer hardware; the sun4v platform is a hypervisor&amp;rsquo;d
virtual SPARC chip; LDOMs are guest domains.  In the Intel (read
&amp;ldquo;Intel, AMD and similar&amp;rdquo;) space Xen is the common OpenSource type 1
hypervisor; VMware ESX is a common commercial one.  Microsoft&amp;rsquo;s
HyperV is a Type 1 solution.&lt;/p&gt;

&lt;p&gt;Type 2 hypervisors run a step away from the hardware; you have your
primary OS install and the hypervisor runs inside that; this is called
&amp;ldquo;hosted&amp;rdquo;.  As with type 1, guests request access to their SCSI
controller, the hypervisors traps this and then makes a request of the
primary kernel.  This sounds inefficient and would be, except that
common type 2 hypervisors have kernel loadable modules and so
essentially run in the kernel space of the primary OS.  This may
make them as efficient as Type 1.  VMware Server, VMware Player,
and VirtualBox are examples of Type2 hypervisors.&lt;/p&gt;

&lt;p&gt;What about full machine virtualisation?  Where the whole machine
is &amp;ldquo;virtual&amp;rdquo;.  I consider this an extreme example of a type 2
setup.  An example of this is &amp;lsquo;User Mode Linux&amp;rsquo;, where the Linux
kernel itself runs as an application instance inside another install.&lt;/p&gt;

&lt;p&gt;Essentialy, with a type 1 hypervisor the hypervisor is loaded first and
all the OS instances (control domain, guests) load afterwards.
With a type 2 hypervisor an OS instance loads first, and the hypervisor
afterwards (or, with kernel modules to confuse things, at the same
time).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paravirtualization?  Huh?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In order for the guest to access things like network or disks they need
to have drivers.  So, typically, your VM solution will emulate
some common hardware (maybe a RealTek or Intel ethernet card; an IDE or
BusLogic SCSI disk).  The guest will have drivers for this
already, so they&amp;rsquo;ll &amp;ldquo;just work&amp;rdquo;.  But as you can guess this may
not be very efficient and may result in many context switches as the
guest&amp;rsquo;s requests bounces around the system before it gets to the
physical hardware.  To help shortcut this the hypervisor may
expose an easier-to-emulate interface to the guest which can be
processed a lot quicker.  To the guest these devices will look
like a different piece of hardware entirely and so will require
drivers.  This technique is called paravirtualization and can
result is massively improved performance in the guest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hardware assisted virtualization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A hard part of virtualization is emulating the CPU.  Some of the
instructions are, apparently, complicated and expensive to virtualize
and this causes the hypervisor to do lots of work.  Intel created
something known as &amp;ldquo;VT&amp;rdquo; (aka &amp;lsquo;Vanderpool&amp;rsquo;); AMD have AMD-V
(&amp;lsquo;Pacifica&amp;rsquo;).  This allows the CPU, itself, to virtualize some
parts of the instruction set taking the load off the hypervisor, and
speeding up virtualization.&lt;/p&gt;

&lt;p&gt;Related to this is the ability to virtualize hardware devices, such as
PCIe plugin cards.  Intel call this VT-d (Virtualization
Technology for Directed I/O).  With this it&amp;rsquo;s possible for a guest
OS to have direct exclusive access to hardware devices (maybe one of
the USB controllers, or a disk controller).  This is, really, a
layer violation but it can be a performance gain or allow VMs to access
hardware that the hypervisor can not emulate.  My machine,
apparently, supports VT-d in the BIOS but either the chipset (H55)
doesn&amp;rsquo;t support it or something else is wrong; the capability isn&amp;rsquo;t
available to the hypervisor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What are my requirements?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I wanted a virtualization platform that would let me use the computer
to host different OS images and run them.  I wanted it to &amp;ldquo;just
work&amp;rdquo;; even though I&amp;rsquo;m a geek and enjoy playing with technology this
was one area where I wanted to play with the VMs, not with the VM
technology.  I didn&amp;rsquo;t want to delay messing around with &amp;lt;x&amp;gt;
because I had to fight my VM system of choice in order to deploy new
images.&lt;/p&gt;

&lt;p&gt;Obviously stability was a requirement; if I had to keep rebooting the
host because the platform then I&amp;rsquo;d get annoyed.&lt;/p&gt;

&lt;p&gt;Got to be able to run Windows.  If I want to test-drive Windows
2008 (well, I &lt;em&gt;might&lt;/em&gt; on a
trial license) or test W2K3 was an Active Directory controller or
whatever&amp;hellip;  Hmm, could this be used to work around the expiration
of the Windows trial license?  Whenever the license is due to
expire just destroy the VM and rebuild it.  For something like AD
have two servers, promote the other to primary, bring up a new
replica.  Heh.  Not that I&amp;rsquo;d ever advocate working around
license agreements like this!&lt;/p&gt;

&lt;p&gt;No artificial limitation on the number of guest OSes; I don&amp;rsquo;t want to
be stuck just running 4 VMs.&lt;/p&gt;

&lt;p&gt;CLI to manage it would be nice; GUI to manage it almost essential (see
ease of use, my primary requirement).&lt;/p&gt;

&lt;p&gt;You&amp;rsquo;ll notice that speed wasn&amp;rsquo;t a primary goal; full virtualization or
paravirtualization wasn&amp;rsquo;t too important, since these weren&amp;rsquo;t high
throughput high demand systems. So what I&amp;rsquo;m testing for isn&amp;rsquo;t
performance.  This also isn&amp;rsquo;t a long term test.  I&amp;rsquo;m
primarily focusing on ease of use, of of setup, ease of
administration.  That is, after all, my primary goal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So what did I test?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My primary server OS of choice is CentOS 5 (currently 5.4).
Partly because I&amp;rsquo;ve been using RedHat variants for&amp;hellip; 14 years?  I
started with RedHat 4.0 (no, &lt;em&gt;not&lt;/em&gt;
Enterprise Linux 4, just standard &amp;ldquo;RedHat&amp;rdquo;) around 1996, from an
InfoMagic disk.  Previously I&amp;rsquo;d used home-grown setups,
Yggdrassil, SLS, MCC-Interim&amp;hellip;  Not sure when I first got
hold  of a Debian disk but by this point it was too late for me to
change.  It also helps that my employer&amp;rsquo;s primary Linux OS is
RedHat so what I use at home is very close to what I use at work.
RedHat/CentOS comes with two different virtualization technologies (Xen
and KVM) so I tested both of them.  I also tested the commercial
version of Xen (Citrix XenServer).  No comparison would be
complete without VMware ESXi.  I&amp;rsquo;ve previously used VMware Server
and VirtualBox.  And I daily use UserModeLinux.&lt;/p&gt;

&lt;p&gt;So that&amp;rsquo;s the list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RedHat (ahem, sorry, CentOS!) 5.4 64bit Xen&lt;/li&gt;
&lt;li&gt;CentOS 5.4 64bit KVM&lt;/li&gt;
&lt;li&gt;Citrix XenServer 5.5&lt;/li&gt;
&lt;li&gt;VMware ESXi 4.0&lt;/li&gt;
&lt;li&gt;VirtualBox 2.2&lt;/li&gt;
&lt;li&gt;VMware Server (version unknown)&lt;/li&gt;
&lt;li&gt;User Mode Linux (2.6.20.7 based kernel)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the CentOS/Citrix/VMware solutions I let my existing machine act as
a DHCP server, so the management
interface was picked up from a static DHCP config.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CentOS 5.4 64bit Xen&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stick the DVD in the machine, boot off it, install as if you&amp;rsquo;re doing a
normal Linux install, select the &amp;ldquo;virtualization&amp;rdquo; group.  And let
it go.  20 minutes later your machine will be ready with a CentOS
Dom0 control domain and the Xen 3.1.2 hypervisor.  Simple!
Being Xen, there are plenty of command line tools available for the
install, create, destruction of guest domains (DomU).  Some of the
jargon is a little quirky (for example &amp;ldquo;destroy&amp;rdquo; doesn&amp;rsquo;t mean destroy
the VM image, just the running VM instance).  But I didn&amp;rsquo;t want to
learn the ins and outs of the command line.  Fortunately CentOS
comes with an X based GUI, &amp;ldquo;virt-manager&amp;rdquo;.  This is pretty
minimal, but sufficient to build an OS, manage resources, connect to
the console&amp;hellip;  basic requirements.&lt;/p&gt;

&lt;p&gt;First up, install a CentOS guest image.  Simple process&amp;hellip; I told
it to bridge its ethernet device to my main network (so it looks like
it&amp;rsquo;s on the LAN).  Heh, the Dom0 is Linux so I NFS mounted my ISO
images to this and now they&amp;rsquo;re available to act as boot CDs/DVDs for
the build process.  This is simple; under 10 minutes later I had a
fully working CentOS guest image&amp;hellip; and it was running paravirtualized
as well!  Neat!  This found my DHCP server and got an address
and did everything I expected of a newly built CentOS machine.&lt;/p&gt;

&lt;p&gt;This is what I wanted from a virtual server; building a complete server
in minutes without getting off my arse.&lt;/p&gt;

&lt;p&gt;So, next, Windows.  Follow a similar install path from the
virt-manager GUI and&amp;hellip; now things didn&amp;rsquo;t quite go according to
plan.  Just creating the raw disk image took a long time, then
booting for the first time caused a hang.  The guest instance just
didn&amp;rsquo;t boot cleanly for installation.  Hmm.  Indeed it looks
like the hypervisor started to slowly freeze up.  The DomU became
unresponsive.  I couldn&amp;rsquo;t login on the console&amp;hellip; needed a
physical reboot.  Ugh.  But, OK, after the reboot I started
the guest and the install carried on.  The Windows setup process
ran, copied data to the hard disk, then rebooted&amp;hellip;. and here the Xen
guest stopped.  Needed to be started again and the OS install then
carried on as normal and completed.  To be fair, this step is
documented.  It just makes unattended installs harder.  Not
that the standard Windows install is anywhere near unattended anyway
(asking questions 5 minutes into the process &lt;em&gt;sigh&lt;/em&gt;) so it&amp;rsquo;s not a big
loss.  But, anyway, I had a Windows instance running.
However I had stability concerns (would I need to reboot every time I
created a new windows instance?).  So I tried again&amp;hellip; yup, reboot
needed!  Oh dear.  I think this fails one of my primary
requirements.  It seems a fully patched CentOS 5 64bit Xen install
isn&amp;rsquo;t sufficiently stable using full virtualization.  This could
easily be because it&amp;rsquo;s an old old version of Xen (3.1.2; current
version is 3.4.5).&lt;/p&gt;

&lt;p&gt;Data is stored in /var/lib, including the disk images.  So either
the relevant areas need to be mounted from a separate partition or a
big root disk created.  It &lt;em&gt;is&lt;/em&gt;
possible to store data elsewhere but SELinux may get in the way and
need reconfiguring or turning off.  Personally I turn it off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CentOS 5.4 64bit KVM&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nicely enough, it&amp;rsquo;s possible to add KVM to my previous install.
&amp;ldquo;yum install kvm&amp;rdquo; adds a new kernel and 3 other rpm&amp;rsquo;s.  Reboot
into the non-Xen kernel and we have a KVM system.  Apparently this
can also be done at initial install time by selecting the right options
in the &amp;ldquo;virtualization&amp;rdquo; options menu.  So an equally simple
install compared to the Xen variant.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not sure if this is considered a Type 1 or Type 2
virtualization.  Not that it really matters.  RedHat nicely
hides the differences between Xen and KVM behind the same interfaces,
so virt-manager is also used to manage KVM instances.  This time I
didn&amp;rsquo;t bother with a CentOS guest, I went straight to building
Windows.  And this went off without a hitch.  A fully
virtualized Windows machine.&lt;/p&gt;

&lt;p&gt;Well, I say without a hitch&amp;hellip;  there was no option to select a
bridge onto my LAN; it could only use a NAT&amp;rsquo;d network.  Unlike the
Xen install (which creates this bridge out of the box) the KVM install
doesn&amp;rsquo;t.  The RedHat documentation &lt;em&gt;does&lt;/em&gt; explain how to build a bridge
but it&amp;rsquo;s not automatic.  The guide also describes to how convert
this instance into a paravirtualized instance.  Except it&amp;rsquo;s not
quite so easy and requires manual hacking of config files.  Yes,
it does work.  It&amp;rsquo;s definitely a step up from the Xen instance (it&amp;rsquo;s stable!),
but I wasn&amp;rsquo;t feeling the &amp;ldquo;friendliness&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Citrix XenServer 5.5&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My hope, here, was to be able to install this onto the 2nd hard disk so
it could co-exist with my physical Windows instance and the CentOS
instance I&amp;rsquo;ve just installed.  This&amp;rsquo;d give me a multi-boot test
platform so I could switch and compare.  Fortunately it allowed me
to do exactly that!  At install time a list of disks is presented,
so I selected the 2nd one.  A few minutes later we had a XenServer
install.&lt;/p&gt;

&lt;p&gt;The boot sequence looks familiar&amp;hellip; huh, under the covers it&amp;rsquo;s actually
CentOS 5.2 (as reported by &amp;ldquo;rpm -q centos-release&amp;rdquo;) with Xen
3.3.1.  The console comes up with a text menu; let&amp;rsquo;s you select
various statistics, start/stop VMs, reboot etc.  It doesn&amp;rsquo;t let
you create new VM instances.  You can ssh into the dom0 and access
the same menu remotely, so you don&amp;rsquo;t need to be at the console.&lt;/p&gt;

&lt;p&gt;Out of the box you get a limited time license; to fully activate the
service you need a free license from Citrix.  A little
annoying.  More annoying is the fact that this license only lasts
1 year, so it has to be renewed.  Let&amp;rsquo;s hope Citrix don&amp;rsquo;t change
their policies and stop giving out free licenses, or use this to force
people onto the upgrade treadmill.&lt;/p&gt;

&lt;p&gt;To create VM instances requires a piece of software that only runs on
Windows.  A little annoying, since it just makes https webservices
requests.  Well, I guess it should also be possible to do the same
via the dom0 command line.  But see &amp;ldquo;ease of use&amp;rdquo;.  For my
purposes a Windows client it is.  It&amp;rsquo;s pretty small and installs
quickly.  From here you can license your server (also see
non-subtle adverts for &amp;ldquo;Xen Essentials&amp;rdquo;, a paid for enhanced interface)
and perform various management functions, including
create/delete/start/stop VMs. You can also attach to the console of the
server and each VM.&lt;/p&gt;

&lt;p&gt;Templated support for Guest OS&amp;rsquo;s is limited (RedHat and variants -
Centos/Oracle/XenApp, Debian 4 and 5, SUSE server, Windows Variants).
Installation of guests using the ISO library I&amp;rsquo;ve got was simple. My
CentOS guest came up properly virtualised.  I could then attach
the xs-tools CD image (directly from the console tab, nice) and install
the guest tools which allows the guest to better use the paravirt
interfaces and report statistics to the manager.  A Windows
install was just as easy; install the OS, attach the CD.  And the
tools come with Windows paravirt drivers (at least for XP Pro) which
just installed and worked.  I like that.&lt;/p&gt;

&lt;p&gt;But that&amp;rsquo;s pretty much where paravirt support ends; I test installed
OpenSolaris 2009.06.  I know this &lt;em&gt;has&lt;/em&gt; paravirt support&amp;hellip;but under
XenServer it runs fully virtualized.  I guess I could delve into
the internals and work out the right kernel and stuff but&amp;hellip;see ease of
use.  Similarly a Ubuntu Server 9.10 came up fully
virtualized.  XenServer really needs to support more OS platforms,
both for paravirt and for xs-tools.&lt;/p&gt;

&lt;p&gt;Stability appears to be rock solid.&lt;/p&gt;

&lt;p&gt;A nice touch in &amp;ldquo;guest installation&amp;rdquo; manual is a description on how to
convert a Windows build into a template (including using sysprep) so
more instances can be cloned quickly.  Given how slow a standard
Windows build is, this is nice information.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s possible to create virtual networks totally internal to the server
(no connection to the outside world) so you can build connections
between servers.  I couldn&amp;rsquo;t see an easy way of making the
XenServer act as DHCP server for that network so either you&amp;rsquo;d need to
run your own DHCP server or make sure all the machines were statically
configured on that LAN.&lt;/p&gt;

&lt;p&gt;For the Linux minded, the install takes the whole disk; partition 1 is
the dom0 (CentOS 5.2) and takes 4Gb; partition 2 is of  the same
size; not sure what that is used for.  The rest of the disk is
assigned to a VG.  Guest instances are LVs carved out of the
VG.  This is flexible (add a disk, extend the VG, more guest
capability) and simple.  You don&amp;rsquo;t need to know any of this, though, to use XenServer.&lt;/p&gt;

&lt;p&gt;On the plus side I can also make this work from my primary grub
partition with chainloader, so I can have a physical Windows instance
for when I actually need one (game playing?) and boot into XenServer
for virtualization and my test instances very easily.&lt;/p&gt;

&lt;p&gt;Ease of install, ease of use, the simple Windows management GUI are all
pluses.  Yearly license and limited paravirt/xs-tools support are
minuses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VMware ESXi&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After my experiences with XenServer I was hoping for something similar
here.  Obviously that didn&amp;rsquo;t happen.  My hardware was
considered &amp;ldquo;consumer grade&amp;rdquo; and VMware ESXi only supports server grade
hardware.  Essentially, check the hardware compatibility list
carefully before installing ESX.  Fortunately other people had
worked out how to get ESXi to work on similar hardware, and along with
some guesses of my own I managed to get it working.  As with
XenServer I could select a disk, so disk 3 went to ESXi.  Install,
reboot (more hacking needed here) and I had a running ESXi instance.&lt;/p&gt;

&lt;p&gt;Not exactly a friendly out-of-box experience, but now I&amp;rsquo;ve documented
it (and kept a copy of the required files) I could rebuild this pretty
easily.  I won&amp;rsquo;t hold it too badly against VMware :-)&lt;/p&gt;

&lt;p&gt;ESXi comes with a 90 days trial license.  You can get a free &lt;em&gt;indefinite&lt;/em&gt; license by registering
at VMware.  Nice.  Except functionality in this freeware is
very limited.  Here&amp;rsquo;s a comparison:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Trial license Product Features:
    Up to 8-way virtual SMP
    vCenter agent for ESX Server
    vStorage APIs
    VMsafe
    dvFilter
    VMware HA
    Hot-Pluggable virtual HW
    VMotion
    VMware FT
    Data Recovery
    vShield Zones
    VMware DRS
    Storage VMotion
    MPIO / Third-Party Multi-Pathing
    Distributed Virtual Switch
    Host profiles
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The indefinite license has:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Product: ESXi 4 Single Server Licensed for 1 physical CPUs (1-6 cores per CPU)
Expires: Never

Product Features:
    Up to 256 GB of memory
    Up to 4-way virtual SMP
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Pretty minimal set of features!&lt;/p&gt;

&lt;p&gt;One thing VMware ESXi does support is &amp;ldquo;pass-through PCI&amp;rdquo;.  Except my hardware doesn&amp;rsquo;t seem to support it.&lt;/p&gt;

&lt;p&gt;ESXi normally hides the control domain; you can&amp;rsquo;t access it.  Normally
you&amp;rsquo;re meant to use their CLI emulation (perl wrappers calling webservices).&lt;/p&gt;

&lt;p&gt;However if you switch to console 1 (ALT-F1) and type&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;unsupported
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and then enter the root password
you created then you get access to the command line.  It&amp;rsquo;s possible,
from here, to enable ssh.  Although it&amp;rsquo;s a Linux based OS the software
looks more like an embedded Linux system (busybox, ash, dropbear etc).
Not that this has any impact on the usage of VMware.&lt;/p&gt;

&lt;p&gt;As with XenServer, proper management of the server requires a Windows
client.  In fact XenServer is a very clear copy of VMware, from
how the console looks to the layout of the Windows GUI.  Except
the VMware version is massively heavier.  330Mb for VMware (vs
15Mb for XenServer).  The VMware GUI looks more &amp;ldquo;next generation&amp;rdquo;
but this can mean &amp;ldquo;harder to find stuff&amp;rdquo;.  But, yes, all the
functionality you need is there to create and manage VMs.&lt;/p&gt;

&lt;p&gt;All in all the experience was very similar to XenServer; not surprising
if XenServer was designed to copy VMware look&amp;rsquo;n&amp;rsquo;feel.  I found the
VMware version slightly harder to use; some of the options were not in
obvious places.  A few times I remmeber thinking &amp;ldquo;I &lt;em&gt;know&lt;/em&gt; I&amp;rsquo;ve seen this option&amp;hellip; where was it?!&amp;ldquo;.&lt;/p&gt;

&lt;p&gt;Again, virtual networks can be built; again I couldn&amp;rsquo;t see how to make ESXi act as a DHCP server to the network.&lt;/p&gt;

&lt;p&gt;Neat idea; effectively there&amp;rsquo;s an app store available from the client
where you can download and install prebuilt images into your
server.  Want to test Zimbra?  Click-click-deploy&amp;hellip; there&amp;rsquo;s
a Zimbra instance on your network.  The implementation wasn&amp;rsquo;t the
best in the world, but the idea is good.&lt;/p&gt;

&lt;p&gt;Windows paravirtualization just worked.  But this time I kinda
expected it.  But the slowness of the GUI and lack of direct
access to the control domain were beginning to annoy me.  I
understand VMware has more guest tools availability than XenServer, but
I never tested them.&lt;/p&gt;

&lt;p&gt;One downside to the Linux guest tools; they don&amp;rsquo;t appear to dynamically
handle changes in kernel so you might find yourself running fully
virtualised network/disk devices by mistake.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VirtualBox 2.2&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I didn&amp;rsquo;t test his recently; this is from earlier usage (Jan-&amp;gt;Jul 2009).&lt;/p&gt;

&lt;p&gt;This is a type 2 hypervisor.  I loaded it onto an existing CentOS
5 install.  Because it requires kernel modules to work effeciently
it needs to be aware of primary OS kernel updates; to handle this it
uses DKMS.  It works well and is, essentially, transparent.
You can upgrade your kernel and on reboot the vbox drivers are
recompiled to match.&lt;/p&gt;

&lt;p&gt;This comes in 2 editions; VirtualBox and VirtualBox OpenSource
(OSE).  Since I wasn&amp;rsquo;t overly concerned about OpenSource purity (I
wanted something that worked) I went for the closed source enhanced
version.  This adds built in RDP servers, ability to to pass USB
ports from the host to the guest, and the ability to use USB ports over
the RDP protocol (with a suitably enhanced rdesktop client, that they
provide).  Given one idea was to replace my sole Windows desktop
with a Linux machine but I still needed Windows for ActiveSync to my
cellphone, this looked like a nice idea&amp;hellip;&lt;/p&gt;

&lt;p&gt;Since I was running this on a Linux machine, the management GUIs were
all X based.  I understand it can also be run on a Windows host
with Windows GUIs, but I never tested that.&lt;/p&gt;

&lt;p&gt;Client installation was simple enough; Windows installed, ran, worked
as expected.  At the time I tested there were no paravirt drivers;
today it seems there are some.  The wonders of OpenSource; one
person creates them, many projects take advantage. Similarly OpenSolaris loaded and installed just fine.&lt;/p&gt;

&lt;p&gt;The main problem I had with VirtualBox was that it felt like a desktop
virtualization environment.  By default all the images lived in
$HOME/.VirtualBox.  This is great is you have many users who want
to manage their own virtual environments; not so great if you want
simple automation (&amp;lsquo;start these VMs at boot time&amp;rsquo;).  I wrote some
simple rc scripts to work around this, but the resulting solution felt
like a kludge.  It also felt too dependent on my keeping the host
OS stable; if I ever update from CentOS 5 to CentOS 6 (it&amp;rsquo;ll happen,
eventually) or even switch to another Linux distro (maybe not) then I
didn&amp;rsquo;t feel comfortable that VBox would easily migrate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VMware Server (version unknown)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another type 2 hypervisor; I use this (infrequently) at work to load up
an older OS base install that I use to compile software; this install
is minimally patched so I can be relatively sure that the software I
build is compatible with all the deployed instances in the company;
there shouldn&amp;rsquo;t be anything with a lower revision than this!&lt;/p&gt;

&lt;p&gt;This doesn&amp;rsquo;t use DKMS, so if I change the kernel then I need to re-run
a script to ensure the driver interfaces are recompiled and
loaded.  It warns you at boot time, but who reads boot
messages?  Really, VMware should look into DKMS for their tools
(both server and guest).  Otherwise there&amp;rsquo;s little to say about
this&amp;hellip; &amp;ldquo;it works&amp;rdquo;.  It&amp;rsquo;s less desktop oriented (to my feeling)
than VirtualBox, but pretty much requires root level access to do
anything.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s a similar worry with Virtualbox about major OS upgrades.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User Mode Linux (2.6.20.7 based kernel)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the odd-one of the bunch.  It&amp;rsquo;s not a virtual machine in
the above context.  What we have here is a copy of the Linux
kernel where the devices are emulated.  The whole Linux instance
runs as an application inside the host.  As you can image, this is
hardly efficient.  But it works.  There&amp;rsquo;s no pretty GUI,
there&amp;rsquo;s no automated deployment tools&amp;hellip; there&amp;rsquo;s nothing that I said I
wanted.  So why am I looking at User Mode Linux (UML)?&lt;/p&gt;

&lt;p&gt;6 years ago I got a Virtual Private Server (VPS) at a company called
Linode.  At the time they were using UML.  Also at the time I
was using an old Pentium Pro 200 as my firewall, and running Vserver to
run security separated instances; I ran one for email (UUCP over SSL),
and one for ssh and http.  They were effectively bastion
hosts.  The core OS ran PPPoE and so was my internet gateway onto
DSL.  Time went forward and the PPPoE gateway got replaced with a
Linksys WRT54G, but the PPro still lived on for the bastion
hosts.  This was lunacy.  So I sat down and built out my own
toolset to build and deploy UML instances.  And, mostly, they
work!  I can deploy a new Linux instance in 3 minutes.
Efficiency isn&amp;rsquo;t as bad as I expected either.  I had a P4 3Ghz HT;
I loaded a Postgres database and wrote code that took 2 hours to run
(heavy transformation of tables).  I created an equivalent UML
instance on the Q6600, 2.4Ghz and the same code ran in 1.5 hours.
Despite all the software layers behind UML it ran faster than the
physical machine.  Maybe the host OS disk caching helped (1GB RAM
on the P4, vs 4Gb RAM on Q6600), but the Q6600 was doing more different
work.&lt;/p&gt;

&lt;p&gt;The neat thing about UML is that its footprint is so minimal; you can
assign 128Mb of RAM and 300Mb of disk to an instance and you know
that&amp;rsquo;s exactly what is taken up.  This made it perfect for my
bastion hosts.&lt;/p&gt;

&lt;p&gt;Indeed I ported this technology to work and one of my DR instances is actually a UML instance running on my desktop.  Sssh!&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m a fan of UML, but it&amp;rsquo;s really not a general purpose virtualization
solution.  Apart from the fact it&amp;rsquo;s Linux only, you do need to be
a heavy geek to use it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;RedHat Xen&amp;hellip; too unstable.  I can&amp;rsquo;t use it.  Potentially I
could use the latest OpenSource Xen drivers instead of the RedHat
provided ones, but then I&amp;rsquo;d need to make sure the virt-manager stuff
all worked properly and I&amp;rsquo;d be worried about OS updates blowing away
customization.  I don&amp;rsquo;t want to use a different Linux distro,
because that&amp;rsquo;s yet another variation to support and manage.&lt;/p&gt;

&lt;p&gt;RedHat KVM&amp;hellip; technologically it may be there.  User friendliness,
umm.  Maybe if I sat down and built out a toolkit for myself so I
could quickly and easily deploy instances (shouldn&amp;rsquo;t really take more
than a weekend of trial&amp;rsquo;n&amp;rsquo;error) then this may doable.&lt;/p&gt;

&lt;p&gt;Citrix XenServer&amp;hellip;  best of the bunch so far; just wish it
supported more platforms for paravirt and tools.  And that one
year license&amp;hellip;.&lt;/p&gt;

&lt;p&gt;VMware ESX4i&amp;hellip;  I wanted this to win because it&amp;rsquo;d give me an idea
of how we do stuff at work.  But it was just a headache from start
to finish.&lt;/p&gt;

&lt;p&gt;VirtualBox&amp;hellip; if you want virtualization on a desktop OS then this is a
really strong contender.  The USB enhancements make it stand
out.  I didn&amp;rsquo;t feel the love as a server based solution, though.&lt;/p&gt;

&lt;p&gt;VMware Server.  Strong basic virtualization.  Again, good for
your desktop OS, but if you want to use it as a server then you have
the additional host OS patching requirements.&lt;/p&gt;

&lt;p&gt;User Mode Linux.  Not in the same class, but really good for small footprint minimal overhead low-power installs.&lt;/p&gt;

&lt;p&gt;What am I going to use?  I&amp;rsquo;m not sure!  I&amp;rsquo;m tending towards Citrix XenServer.  But not decided, yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://www.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/5.4/html/Virtualization_Guide/index.html&#34;&gt;RedHat Virtualization Guide (Xen, KVM)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.citrix.com/English/ps2/products/feature.asp?contentID=1686939&#34;&gt;Citrix XenServer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.vmware.com/tryvmware/index.php?p=free-esxi&amp;amp;amp;lp=1&#34;&gt;VMware ESXi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.virtualbox.org/wiki/Editions&#34;&gt;VirtualBox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.vmware.com/products/server/&#34;&gt;VMware Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://user-mode-linux.sourceforge.net/&#34;&gt;User Mode Linux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Thin Client Options</title>
      <link>https://www.sweharris.org/post/2010-04-19-thin-client/</link>
      <pubDate>Mon, 19 Apr 2010 19:21:59 -0400</pubDate>
      
      <guid>https://www.sweharris.org/post/2010-04-19-thin-client/</guid>
      <description>&lt;p&gt;In my spare room I have what I grandiously like to call a library.
(By library I mean approx 112ft of bookshelf space, on 3 of the 4
walls).  What does any library need?  A computer!  Internet access,
ability to print, access files etc.  I have a random vision of
the future of having my eBooks managed &amp;ldquo;somehow&amp;rdquo; (plug the &lt;a href=&#34;http://www.bookeen.com/shop/productdetails.aspx?ProductID=417&#34;&gt;eBook
reader&lt;/a&gt;
in, download the book(s) I want&amp;hellip;).&lt;/p&gt;

&lt;p&gt;Nothing high powered; possibly playing youtube videos would be the hardest
thing this computer would need to do.  However I would like this machine
to be able to print to a locally connected (USB) printer and also scan
from it (it&amp;rsquo;s a HP printer/scanner).  I could live without printouts
(especially since that&amp;rsquo;s an inkjet printer so the ink&amp;rsquo;ll probably dry
out before I use it again!) but the scanner is one of the reasons I want
the machine there (eg to scan the covers of my books for my online index).&lt;/p&gt;

&lt;p&gt;But first I need a computer.  Most of the time this machine is going to
be turned off (or, if power drain is sufficiently small, in standby mode)
so a quick boot is required.  Optimally no moving parts (no hard disk,
no fans).  It doesn&amp;rsquo;t need to be Windows (indeed, probably better off
&lt;em&gt;not&lt;/em&gt; being Windows, given the headache of keeping patches and antivirus
software up to date!).  So this sounded like a perfect job for a diskless
X terminal.  Netboot, NFS mount root, etc etc.&lt;/p&gt;

&lt;p&gt;My first attempt at this was an &lt;a href=&#34;http://en.wikipedia.org/wiki/I-Opener&#34;&gt;iOpener&lt;/a&gt;;
&lt;a href=&#34;http://www.panix.com&#34;&gt;Panix&lt;/a&gt; used to use these when doing &amp;ldquo;internet
rooms&amp;rdquo; at conventions; they&amp;rsquo;d hacked them so they had a NetBSD kernel
and then would NFS mount everything else.  Just needed the one server
for the con room.  These iOpeners didn&amp;rsquo;t have ethernet, but a USB dongle
worked adequately for 10baseT.  I&amp;rsquo;ve previously done a minor consulting
favour for Panix and in lieu of any recompense I took two of these devices
off their hands.  I played around with them a little, but never felt the
&amp;ldquo;love&amp;rdquo; or desire to actually get them working.  It might be the small RAM
(its been a while since I powered them up; maybe 64M?) or the small flash
disk that replaces the hard disk (16M) or the small screen (800x600).
Whatever the reason, I never really got these machines doing much more
than booting into a command prompt.  They&amp;rsquo;re still sitting in my basement
gathering dust.  One day I&amp;rsquo;ll revisit this project!&lt;/p&gt;

&lt;p&gt;My second attempt was to just use a laptop.  Unfortunately Linux
(at the time) didn&amp;rsquo;t do very well for sleep modes and these older
machines (the newest laptop I have is a Celeron 2.4Ghz &lt;a href=&#34;http://reviews.cnet.com/laptops/dell-inspiron-1100/1707-3121_7-21127907.html&#34;&gt;Dell Inspiron
1100&lt;/a&gt;)
take a fair time to boot.  Windows&amp;hellip; well, see the above comments!
Also didn&amp;rsquo;t help that this machine only had 256Mb of RAM, so Windows
was pig slow (even now I&amp;rsquo;ve upgraded it to 1Gb of RAM it&amp;rsquo;s still slow!
Very slow hard disk, it seems).&lt;/p&gt;

&lt;p&gt;My third attempt was to use a netbook.  I originally got an &lt;a href=&#34;http://en.wikipedia.org/wiki/Asus_Eee_PC&#34;&gt;Eee700&lt;/a&gt;.
This suffers from a small 7&amp;rdquo; screen, small keyboard etc but in most
respects it could be hacked into doing what I wanted&amp;hellip; worst case I&amp;rsquo;d
put on a different Linux distribution (Ubuntu netbook?).  The
problem was actually that this machine better filled the niche of
&amp;ldquo;guest PC&amp;rdquo; for the living room; if someone wanted to check on email or
surf the net or look up IMDB during the Oscars or whatever then this
was a perfect machine!  It was too useful to be relegated to
library use :-)    In fact I ended buying a 2nd
(refurbished) Eee (an Eee900 this time) which I have at work connected
to the guest wireless network so I can access personal email etc from
work.  I like these EeePCs!&lt;/p&gt;

&lt;p&gt;So now attempt 4.  I managed to get hold of
a HP t5720.  These actually come in two variations; the
&lt;a href=&#34;http://h18000.www1.hp.com/products/quickspecs/archives_North_America/12388_na_v7/12388_na.HTML&#34;&gt;t5720&lt;/a&gt;
which runs Microsoft Windows XPembedded, and the
&lt;a href=&#34;http://h18000.www1.hp.com/products/quickspecs/12584_div/12584_div.HTML&#34;&gt;t5725&lt;/a&gt;
which runs a Linux variant (based on Debian Etch).  The hardware seems
identical, it&amp;rsquo;s just the OS that they boot into that distinguishes them.
These can be obtained for around $100 from eBay.  Now these machines
were designed as thin clients.&lt;/p&gt;

&lt;p&gt;Inside they have a &lt;a href=&#34;http://en.wikipedia.org/wiki/Geode_%28processor%29#Geode_NX&#34;&gt;1Ghz AMD Geode 1500
processor&lt;/a&gt;
with 256Mb RAM and 512Mb of flash disk (instead of a hard disk).
The memory can be upgraded using SODIMM memory.  There&amp;rsquo;s a plethora
of USB ports, built in audio, PS/2 keyboard/mouse ports&amp;hellip; in other
words it looks pretty much like a bog standard (underpowered) PC.
Interesting there&amp;rsquo;s no moving parts at all; it&amp;rsquo;s all passively cooled
with a couple of massive heat sinks on each end of the case.&lt;/p&gt;

&lt;p&gt;I plugged in a USB-DVD drive and booted (&amp;ldquo;rescue mode&amp;rdquo;) from a
&lt;a href=&#34;http://www.centos.org/&#34;&gt;CentOS&lt;/a&gt; DVD I had around and confirmed this could
read the hardware normally.  Given the small amount of memory and disk
I don&amp;rsquo;t think I&amp;rsquo;ll install CentOS on this machine,but this is powerful
enough that I should be able to run a real OS without much problem.
I just need a quick boot time!&lt;/p&gt;

&lt;p&gt;Looking around at the different Linux thin-client builds it seems
there&amp;rsquo;s quite a few options to chose from.  Firstly we have the
standard HP build, which can be downloaded from their website.
This is based on &lt;a href=&#34;http://www.debian.org&#34;&gt;Debian&lt;/a&gt; Etch.  It&amp;rsquo;s
pretty old, now.  Installation was simple enough; make
a bootable USB drive, let it boot, and it completely overwrites the
internal flash drive with the new image.  It&amp;rsquo;s slow, but it
works.  Remove the USB device, reboot&amp;hellip; and we have a Linux
install.  From &lt;a href=&#34;http://en.wikipedia.org/wiki/Power-on_self-test&#34;&gt;POST&lt;/a&gt;
completion to the OS being ready for use takes around 30 seconds.&lt;/p&gt;

&lt;p&gt;By default the machine drops straight into a local
X configuration; from here you can run firefox (sorry,
&lt;a href=&#34;http://en.wikipedia.org/wiki/GNU_IceCat&#34;&gt;iceweasel&lt;/a&gt;) - but it&amp;rsquo;s an
old version. Now, it looks like HP have added some of their own &lt;a href=&#34;http://en.wikipedia.org/wiki/Advanced_Packaging_Tool&#34;&gt;APT&lt;/a&gt;
repositories, and also left references to a main etch respository
so I thought I&amp;rsquo;d try to update the machine.  Here the limits of the
small hard disk show up.  &amp;ldquo;apt update&amp;rdquo; worked just fine.  &amp;ldquo;apt upgrade&amp;rdquo;
complained about the Debian official packages not being properly signed
(I guess HP didn&amp;rsquo;t put the right public key in the image) but otherwise
worked&amp;hellip; until the disk filled up.  Attempting to recover from this
ended up with an unbootable system.  Umm.  Perhaps someone more versed
in Debian recovery than me could have got it working again, but I didn&amp;rsquo;t
need to; I just reflashed it again from the HP image.  This time round
I just updated iceweasel.  However this still only took me to 2.0.0.19,
which is very old in firefox terms.  Hmm.&lt;/p&gt;

&lt;p&gt;The HP image can also work as a more general &amp;ldquo;X terminal&amp;rdquo;, where you
connect to a remote XDMCP server, authenticate and then run the X
session on the remote machine.  The desktop macune just runs the X
server.  In this mode it doesn&amp;rsquo;t really matter than the provided
software is old because you don&amp;rsquo;t really run it.  I&amp;rsquo;ve not tested
this option yet; I need to work out how to configure the display
manager on my server to accept requests from remote machines but &lt;em&gt;not&lt;/em&gt;
run X on my local console (&amp;lsquo;cos I prefer a text terminal on my server
consoles, thank you very much).  I think that if I&amp;rsquo;m going to use the
HP image then I&amp;rsquo;ll have to investigate this mode more.  I&amp;rsquo;ll also have
to determine how well audio works, and how quickly (slowly?)  the system
starts up.&lt;/p&gt;

&lt;p&gt;Another way of doing terminal services is the &lt;a href=&#34;http://www.ltsp.org/&#34;&gt;Linux Terminal Server
Project&lt;/a&gt;.  This is pretty much designed to control
and manage diskless workstations.  Unfortunately I started to get a
headache just reading the site.  It seems that the codebase is currently
being redesigned (from LTSP4 to LTSP5) and the documentation isn&amp;rsquo;t always
clear in what it&amp;rsquo;s describing.  It also looks like it might be a lot of
work to get it running on my existing CentOS server and needs network
reconfiguration of the server.  Umm.  I&amp;rsquo;m not sure I want to go to all
that hassle!  So I&amp;rsquo;m currently giving LTSP a skip.&lt;/p&gt;

&lt;p&gt;Previously I&amp;rsquo;ve used &lt;a href=&#34;http://www.damnsmalllinux.org/&#34;&gt;Damn Small Linux&lt;/a&gt;
on tiny PCs (eg a laptop with 16Mb RAM).  It&amp;rsquo;s amazing that it
works so well, but it also looks like it&amp;rsquo;s stuck in the past (a
2.4 based kernel.  I&amp;rsquo;d be surprised if modern software (firefox
3.5 for example) would run on it.  There was a more modern version
(&lt;a href=&#34;http://www.damnsmalllinux.org/dsl-n/&#34;&gt;DNS-N&lt;/a&gt;) but this also looks like
there&amp;rsquo;s been no update for years.&lt;/p&gt;

&lt;p&gt;Then there&amp;rsquo;s &lt;a href=&#34;http://www.thinstation.org/&#34;&gt;ThinStation&lt;/a&gt;.
This looks interesting.  Currently I&amp;rsquo;m testing this via PXEboot
(network boot) so I can switch between this and the HP image just by
rebooting.  This took 50 seconds to boot but some of that delay
may be due to needing to download the image.   Of course
booting from the network with this image gives a fresh start each time,
so there&amp;rsquo;s no history.  It runs a very basic setup using iceWM,
has firefox 3.0.x and has many forms of connectivity (eg rdesktop, ssh,
Citrix ICA, NoMachine NX, VMware view etc etc etc).    I
need to see what power-saving functionality is available on this build,
or whether I need to shutdown/reboot each time, and whether the local
printer/scanner functionality will work.&lt;/p&gt;

&lt;p&gt;Next up is &lt;a href=&#34;http://www.xpud.org/&#34;&gt;xPUD&lt;/a&gt;.  This is
almost a web-based OS.  It comes as a kernel image with a 44Mb
initrd image attached (so it takes a little while to netboot because
there&amp;rsquo;s a bit of data to transfer!) but once it&amp;rsquo;s got the data into RAM
it boots fast; under 10 seconds from kernel startup to running
system.  It&amp;rsquo;s a different look&amp;rsquo;n&amp;rsquo;feel, but it seems to work.
The main downside is that the ethernet controller on this HP (a
via-rhine) doesn&amp;rsquo;t have a driver in the base OS image so if I netboot
then it won&amp;rsquo;t find the ethernet controller so I can&amp;rsquo;t actually see the
internet!  If I boot from a USB flash drive then I can put the
optional drivers package on the drive as well, and this has the
via-rhine driver needed.   Firefox is 3.5.5, which is prety
new.  Attempts to update to the latest, though, don&amp;rsquo;t appear to
work.  And is probably pointless given that a reboot would just
rollback to the downloaded image.  This is something I need to be
aware of with xPUD; if I want newer application versions I may end up
having to roll my own.  But it&amp;rsquo;s interesting and something to look
at.&lt;/p&gt;

&lt;p&gt;And this is where I am at the moment; playing with the HP/Debain build, ThinStation and xPUD.&lt;/p&gt;

&lt;p&gt;Of course I don&amp;rsquo;t have ethernet in the library, so I need to go wireless.
This adds a new dimension&amp;hellip; some USB wireless cards are only supported
under newer kernels and these images (eg the HP one) may not have the
required drivers.  So do I go with a wireless USB card, or do I get a
&lt;a href=&#34;http://en.wikipedia.org/wiki/Linksys_WRT54G_series#WRT54GL&#34;&gt;WRT54GL&lt;/a&gt;
(or compatible) running a firmware such as
&lt;a href=&#34;http://en.wikibooks.org/wiki/Tomato_Firmware&#34;&gt;Tomato&lt;/a&gt; in &amp;ldquo;access point&amp;rdquo;
mode so it acts like a bridge, effectively providing ethernet to that
room?&lt;/p&gt;

&lt;p&gt;At the moment I&amp;rsquo;ve got my laptop in there running Windows (&lt;em&gt;sigh&lt;/em&gt;) I think I&amp;rsquo;ve got a way to go on this project, yet!&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
