<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[blog.immontilla.eu]]></title><description><![CDATA[Ideas, code and experiences.]]></description><link>https://blog.immontilla.eu/</link><image><url>https://blog.immontilla.eu/favicon.png</url><title>blog.immontilla.eu</title><link>https://blog.immontilla.eu/</link></image><generator>Ghost 3.19</generator><lastBuildDate>Wed, 30 Dec 2020 16:33:26 GMT</lastBuildDate><atom:link href="https://blog.immontilla.eu/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[I broke my site but I survived]]></title><description><![CDATA[I made a mess. I upgraded my server without checking possible compatibility issues with my blog platform, Ghost. Huge mistake. Basically, nvm save my life.]]></description><link>https://blog.immontilla.eu/i-broke-my-site-but-i-survived/</link><guid isPermaLink="false">5ee4b2cdbfb5470a7db74fdb</guid><dc:creator><![CDATA[immontilla]]></dc:creator><pubDate>Sun, 14 Jun 2020 03:12:03 GMT</pubDate><content:encoded><![CDATA[<blockquote>Anything that can go wrong will go wrong</blockquote><p>Long story. I decided to upgrade my server OS. Everything, almost everything, went fine. But, when I try to access my website, I couldn't. I just update some nginx settings and reload the configuration file, and it worked. Nothing fancy, quite easy, actually. </p><p>I visited my web site and tried to reach my blog, but I couldn't. I thought, I just forgot to restart <em>forever.</em> Then, I did but nothing happened. I started Ghost manually and saw the problem. Node were upgraded and my old Ghost blog didn't support this new version. </p><p>I should check Ghost/nodeJS version compatibility but I didn't. Actually, I should have a <em>Dockerised</em> environment of my droplet. By doing so, I would have known what could happen if I upgrade my server operating system. A zero-cost environment could saved me a lot of time and stress. Huge mistake.</p><p>Crying over the spilled milk never is a good choice. My choices were, either downgrade nodeJS and keep my old Ghost version or upgrade Ghost. I chose the latter. I installed the Ghost client, MySQL and the latest Ghost version. Nice and easy, at first, though. I tried to import my old blog post into my new Ghost, but I couldn't. Another issue came out. Ghost asked me for a JSON backup and I haven't done that before. I thought a database backup was enough, but it wasn't. Another mistake to my bag.</p>]]></content:encoded></item><item><title><![CDATA[INFOSEC Colours]]></title><description><![CDATA[Learn about the features and differences between Yellow, Red, Blue, Orange, Green, Purple and White teams in the INFOSEC world.]]></description><link>https://blog.immontilla.eu/infosec-colours/</link><guid isPermaLink="false">5ee39da9bfb5470a7db74f9b</guid><dc:creator><![CDATA[immontilla]]></dc:creator><pubDate>Sat, 05 Oct 2019 17:29:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Looking for information about Red, Blue and Purple teams, I found out an interesting article written by Daniel Miessler titled <a href="https://danielmiessler.com/study/red-blue-purple-teams/" title="The Difference Between Red, Blue, and Purple Teams" target="_blank">The Difference Between Red, Blue, and Purple Teams</a>.</p>
<p>There, the author extraordinarily condensed into a single image all the INFOSEC color meanings.</p>
<p><img src="https://blog.immontilla.eu/content/images/2019/10/BAD-pyramid-miessler.png" alt="BAD Pyramid"><small>Originally posted at <a href="https://danielmiessler.com/images/BAD-pyramid-miessler.png">https://danielmiessler.com/images/BAD-pyramid-miessler.png</a></small></p>
<p>As you can see, the author referenced April Wright work at the image footer. Thanks to that, I searched and downloaded her BlackHat 17 USA presentation <em><a href="https://www.blackhat.com/docs/us-17/wednesday/us-17-Wright-Orange-Is-The-New-Purple.pdf" title="Orange is the new purple. How and why to integrate software teams with red and blue teams" target="_blank">Orange is the new purple</a></em>. There, April introduced the Yellow colour to represent the builders which led to new derived colours: Orange and Green. Just like Daniel, I consider, Orange and Green a mindset rather than a fully dedicated team.</p>
<p>Personally, I am a <em>builder</em> who in 2016 received a Penetration Testing report pointing some security issues affecting my applications. Luckily for me, I could talk to the pentesters openly to interchange ideas and opinions about information security. Those conversations helped me not only to understand the issues and correct them effective and efficiently but also to include the information security from the very beginning in the development cycle.</p>
<p>What I did was to start to think as an attacker trying to get access to my applications as well as a defender building defense mechanisms to deter, detect and monitor the more possibles attacks. In few words, I was a member of the Yellow team whose mindset sometimes has to turn Orange or Green to build more secure and resilient applications.</p>
<p>Back in 2018, I began to pursue an MSc in Digital Investigation &amp; Forensic Computing at University College Dublin. Now, I am sure I could join a Red, Blue or Purple team.</p>
<h6 id="additionallinks">Additional links</h6>
<ul>
<li><a href="https://hackernoon.com/introducing-the-infosec-colour-wheel-blending-developers-with-red-and-blue-security-teams-6437c1a07700" title="Introducing the InfoSec colour wheel - blending developers with red and blue security teams" target="_blank">Introducing the InfoSec colour wheel - blending developers with red and blue security teams</a>.</li>
<li><a href="https://architectsecurity.org/" title="Architect Security with April Wright" target="_blank">Architect Security with April Wright</a>.</li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Splunk]]></title><description><![CDATA[Find a docker-compose file to start diving into Splunk]]></description><link>https://blog.immontilla.eu/splunk/</link><guid isPermaLink="false">5ee39da9bfb5470a7db74f9a</guid><dc:creator><![CDATA[immontilla]]></dc:creator><pubDate>Sun, 08 Sep 2019 20:35:59 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Splunk is a platform that let us look into huge sets of data generated by several sources.</p>
<p>The official image is available at <a href="https://hub.docker.com/r/splunk/splunk/">https://hub.docker.com/r/splunk/splunk/</a>.</p>
<p>This is a ready-to-use docker-compose file to deploy Splunk wherever you want.</p>
<pre><code class="language-yml">version: '3'

services:
  vsplunk:
    image: busybox
    volumes:
      - &quot;/opt/splunk/etc&quot;
      - &quot;/opt/splunk/var&quot;
  
  splunkapp:
    hostname: splunkapp
    image: splunk/splunk:latest
    environment:
      SPLUNK_PASSWORD: ${RANDOMPASS}
      SPLUNK_START_ARGS: --accept-license
      SPLUNK_ENABLE_LISTEN: 9997
      SPLUNK_ADD: tcp 1514
    volumes_from:
      - vsplunk
    ports:
      - &quot;8000:8000&quot;
      - &quot;9997:9997&quot;
      - &quot;8088:8088&quot;
      - &quot;1514:1514&quot;
</code></pre>
<p>Feel free to copy or clone it from -&gt; <a href="https://github.com/immontilla/splunk" title="https://github.com/immontilla/splunk" target="blank">https://github.com/immontilla/splunk</a></p>
<p>If you decided to copy it, you will need to assign a password into an environment variable named RANDOMPASS.</p>
<p>In a UNIX based system, you can issue this command:</p>
<pre><code class="language-bash">export RANDOMPASS=`date +%s | sha256sum | base64 | head -c 32 ; echo`
</code></pre>
<p>Do not forget to review its value because you will need it when you want to access <a href="http://localhost:8000/" title="http://localhost:8000/" target="blank">http://localhost:8000/</a> as the admin user.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Exporting Adobe Connect recordings]]></title><description><![CDATA[Learn how to download an Adobe Conect recording to watch it off-line using Powershell. ]]></description><link>https://blog.immontilla.eu/export-adobe-connect-recording/</link><guid isPermaLink="false">5ee39da9bfb5470a7db74f98</guid><dc:creator><![CDATA[immontilla]]></dc:creator><pubDate>Fri, 14 Dec 2018 20:17:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I wanted to watch <em>off-line</em> some Adobe Connect recordings in my commuting time. <em>Googling</em> about it, I found out that you can download any Adobe Connect recording just by appending <em>output/filename.zip?download=zip</em> to its url.</p>
<p>The resulting zip file is just a mix of FLV (video) and XML (configuration) files. In Windows, FLV files could be played using VLC media player.</p>
<p>This is just a simple Powershell script to automate this task</p>
<script src="https://gist.github.com/immontilla/be114487dbfebbf436bfbd8ea0b6c7d2.js"></script>
<p>You can run it this way:</p>
<pre><code>.\adbconnect2zip.ps1 -filename {desired file name} -url {recording url link}
</code></pre>
<p>don't forget to replace {desired file name} and {recording url link} appropriately before running.</p>
<p>Alternatively, you can use curl or wget to do the same thing in Linux, Mac or Windows:</p>
<pre><code>wget -O {desired file name} {recording url link}
</code></pre>
<pre><code>curl -o {desired file name} {recording url link}
</code></pre>
<p>curl and wget are common Unix utilities. In Mac OS and Windows, both utilities could be installed using package managers like <em>brew</em> and <em>chocolatey</em>, respectively.</p>
<p><em><strong>Update</strong></em></p>
<p>Using ffmpeg we can extract MP3 audio from FLV files by issuing this:</p>
<pre><code>ffmpeg -i {flv filename} -acodec libmp3lame -b:a 192k {mp3 filename}
</code></pre>
<p>replacing {flv filename} and {mp3 filename} appropriately.</p>
<p>FFmpeg Windows 10 builds could be downloaded from <a href="https://ffmpeg.zeranoe.com/builds/" title="FFmpeg Builds" target="_blank">https://ffmpeg.zeranoe.com/builds/</a>.</p>
<p>Using 7-Zip we can extract only the FLV files from the <em>recording</em> zip file downloaded before by running:</p>
<pre><code>7z e {zip file} -o{extract directory} *.flv -r
</code></pre>
<p>replacing {zip file} and {extract directory} appropriately. Note: <u>there is no space between -o and the extract directory name</u>.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Switching to Debian]]></title><description><![CDATA[If you, are using an encrypted Debian laptop and you are the only user, you can find here how to auto-boot, auto-login, and turn off the terminal bell sound.]]></description><link>https://blog.immontilla.eu/switching-to-debian/</link><guid isPermaLink="false">5ee39da9bfb5470a7db74f97</guid><dc:creator><![CDATA[immontilla]]></dc:creator><pubDate>Sun, 16 Sep 2018 19:45:34 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I have switched my machine from <em>Linux Mint</em> to <em>Debian Stretch</em> keeping my <em>beloved</em> Cinnamon as desktop environment. The process itself, was not a big deal. However, I did some additional tasks to suit my taste.</p>
<h4 id="scenario">Scenario</h4>
<p>First of all, I am going to share my <em>scenario</em>:</p>
<ul>
<li>
<p>My laptop will have only one operating system, Debian.</p>
</li>
<li>
<p>My laptop disk will be fully encrypted.</p>
</li>
<li>
<p>I will be the only laptop user.</p>
</li>
<li>
<p>I will never add my laptop user to the <em>sudo</em> group.</p>
</li>
</ul>
<p><em>With this scenario, I had to make some changes in the Debian default configuration to have a better user experience</em></p>
<h6 id="uautoboottodebianu"><u>Auto-boot to Debian</u></h6>
<p>I don't like to choose my operating system every time I turn on my laptop because there is only one option, so I did this:</p>
<ul>
<li>Log in as <em>root</em></li>
<li>Edit the <em>/etc/default/grub</em> file</li>
<li>Set the GRUB_TIMEOUT to 0</li>
</ul>
<pre><code>(GRUB_TIMEOUT=0)
</code></pre>
<ul>
<li>Save the file, and then run:</li>
</ul>
<pre><code>update-grub
</code></pre>
<h6 id="uturnofftheannoyingsystembellsoundu"><u>Turn off the <em>annoying</em> system bell sound</u></h6>
<p>I really hate the sound I heard when I press the TAB key.  I don't understand why is turned on by default. Well, to turn this s**t off, logged as root I had to:</p>
<ul>
<li>Edit the <em>/etc/inputrc</em> file and uncomment the line</li>
</ul>
<pre><code>set bell-style none
</code></pre>
<ul>
<li>Edit the ~/.bashrc file and append this:</li>
</ul>
<pre><code>if [ -n &quot;$DISPLAY&quot; ]; then
  xset b off
fi
</code></pre>
<ul>
<li>Run</li>
</ul>
<pre><code>source ~./profile
</code></pre>
<h6 id="uenableautologinu"><u>Enable auto-login</u></h6>
<p>My user <strong>can't</strong> <em>sudo</em>, and my encryption key is sufficient strong and secure, so I don't want to authenticate every time I turn on my laptop. Well, I manage to auto-login on my laptop by doing this:</p>
<ul>
<li>Log in as <em>root</em></li>
<li>Open the <em>/usr/share/lightdm/lightdm.conf.d/01_debian.conf</em> file, and</li>
<li>Append this lines in it, replacing <em>username</em> with yours.</li>
</ul>
<pre><code>[SeatDefaults]
autologin-user=username
autologin-user-timeout=0
</code></pre>
<h6 id="conclusions">Conclusions</h6>
<p>If you don't like something, change it. As simple as it sounds. Is Linux.</p>
<h6 id="references">References</h6>
<ul>
<li>How to enable auto-login in Debian 9 Xfce:<br><a href="https://steemit.com/software/@kskarthik/how-to-enable-auto-login-in-lightdm" title="How to enable auto-login in Debian 9 Xfce" target="_blank">https://steemit.com/software/@kskarthik/how-to-enable-auto-login-in-lightdm</a></li>
<li>Debian - How to turn off the system bell<br><a href="https://blog.sleeplessbeastie.eu/2012/12/28/debian-how-to-turn-off-the-system-bell/" title="Debian - How to turn off the system bell" target="_blank">https://blog.sleeplessbeastie.eu/2012/12/28/debian-how-to-turn-off-the-system-bell/</a></li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Go & MongoDB]]></title><description><![CDATA[Find here a post about golang and mongodb. I will show you how to code in Go a small api using goji(http toolkit for Go) and mgo (mongoDB driver for Go). ]]></description><link>https://blog.immontilla.eu/go-mongodb/</link><guid isPermaLink="false">5ee39da9bfb5470a7db74f96</guid><dc:creator><![CDATA[immontilla]]></dc:creator><pubDate>Sun, 02 Sep 2018 17:25:34 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>In this post, I will show you how to code in Go &amp; mongoDB a small API using a couple of Go tool-kits: Goji and mgo. As usual, find the code at Github: <a href="https://github.com/immontilla/mgo-n-goji.git" title="https://github.com/immontilla/mgo-n-goji.git" target="_blank">https://github.com/immontilla/mgo-n-goji.git</a>.</p>
<p>Before to start, in case you have never give <a href="https://golang.org/" title="The Go Programming Language" target="_blank">Go</a> a try, I suggest you to check <a href="https://tour.golang.org/" title="A tour of Go" target="_blank">https://tour.golang.org/</a> first, and back here afterwards. If you want to learn more about <a href="https://www.mongodb.com/" title="MongoDB for GIANT ideas" target="_blank">mongoDB</a> before to continue as well, you have a great set of free courses at MongoDB University, pick some from its <a href="https://university.mongodb.com/courses/catalog" title="Online Course Catalogue" target="_blank">catalogue</a> and return here later.</p>
<p><em><p style="text-align: right;">Welcome back from your learning tour...</p></em></p>
<h6 id="apispecification">API Specification</h6>
<p>Our <em>phone book</em> API will meet these requirements:</p>
<ul>
<li>A contact should have a unique nick.</li>
<li>The nick has to be alphanumeric with a length greater or equal than 3 and lower or equal than 36.</li>
<li>A contact should have at least one mobile number associated.</li>
<li>A contact could have one or more email addresses associated.</li>
</ul>
<h6 id="prerequisites">Pre-requisites</h6>
<ul>
<li>
<p><strong>Go</strong><br>
<br>You can find the official installation instructions <a href="https://golang.org/doc/install#install" title="Install the Go tools" target="_blank">here</a>. I have installed: <a href="https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz" title="go1.10.3.linux-amd64.tar.gz" target="_blank">https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz</a> on my Linux Mint machine.<br>Ubuntu users have an installation wiki at <a href="https://github.com/golang/go/wiki/Ubuntu" title="Ubuntu" target="_blank">https://github.com/golang/go/wiki/Ubuntu</a>.</p>
</li>
<li>
<p><strong>mongoDB</strong><br>
<br>If you want to install it on your machine, follow this guide: <a href="https://docs.mongodb.com/manual/administration/install-community/" title="Install MongoDB Community Edition" target="_blank">https://docs.mongodb.com/manual/administration/install-community/</a>.<br>If you are an Ubuntu user you have this specific guide <a href="https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/" title="Install MongoDB Community Edition on Ubuntu" target="_blank">https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/</a>.<br>You could create an Atlas Free Tier Cluster following <a href="https://docs.mongodb.com/manual/tutorial/atlas-free-tier-setup/" title="Create an Atlas Free Tier Cluster" target="_blank">https://docs.mongodb.com/manual/tutorial/atlas-free-tier-setup/</a>.<br>Last but no least, you could use this Vagrant file: <a href="https://s3.amazonaws.com/edu-downloads.10gen.com/M040_2018_August/static/handouts/m040/environment_setup.zip" title="Vagrant" target="_blank">https://s3.amazonaws.com/edu-downloads.10gen.com/M040_2018_August/static/handouts/m040/environment_setup.zip</a>. This file belongs to the &quot;<em>M040: New Features and Tools in MongoDB 4.0</em>&quot; course and contains a ready-to-use MongoDB 4.0 instance.</p>
</li>
</ul>
<h6 id="gotoolkits">Go tool-kits</h6>
<ul>
<li><strong><a href="https://goji.io/" title="A minimalistic and flexible request multiplexer for Go" target="_blank">Goji</a></strong>: a HTTP request multiplexer which compares the incoming requests to a list of registered <em>Patterns</em> dispatching to the <em>Handler</em> that corresponds to the first matching <em>Pattern</em>.</li>
<li><strong><a href="https://github.com/go-mgo/mgo" title="Rich MongoDB driver for Go" target="_blank">mgo</a></strong>: a MongoDB driver for the Go language. I am using this fork: <a href="https://github.com/globalsign/mgo" title="github.com/globalsign/mgo" target="_blank">github.com/globalsign/mgo</a> because the original project is unmaintained.</li>
</ul>
<h6 id="installation">Installation</h6>
<p>To clone:</p>
<pre><code>cd $GOPATH/src &amp;&amp; git clone https://github.com/immontilla/mgo-n-goji.git
</code></pre>
<p>To install:</p>
<pre><code>cd $GOPATH &amp;&amp; go install mgo-n-goji/cmd/app/
</code></pre>
<p>To test:</p>
<pre><code>cd $GOPATH/src/mgo-n-goji/tests/postman/ &amp;&amp; npm install &amp;&amp; npm run test-n-report
</code></pre>
<p>To see the test results open your browser at <a href="http://localhost:4444/" title="http://localhost:4444/" target="_blank">http://localhost:4444/</a></p>
<h6 id="pending"><em><strong>Pending</strong></em></h6>
<ul>
<li>Swagger documentation</li>
<li>Testing - BDD</li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Feature Policy Security Header]]></title><description><![CDATA[Feature Policy is a new header that allows a site to control which features and APIs can be used in the browser. I'll show you how to added it in ngnix.]]></description><link>https://blog.immontilla.eu/a-new-security-header-feature-policy/</link><guid isPermaLink="false">5ee39da9bfb5470a7db74f95</guid><dc:creator><![CDATA[immontilla]]></dc:creator><pubDate>Sat, 11 Aug 2018 11:14:05 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>A new security header has been added to the <a href="https://securityheaders.com/" title="https://securityheaders.com/" target="_blank">https://securityheaders.com/</a> checking service, the <em>Feature Policy</em> header.</p>
<p>The <em>Feature Policy</em> is a new header that allows a site to control which features and APIs can be used in the browser. In my case, on my both websites, I had blocked everything except the fullscreen feature.</p>
<p>This is the line I inserted in my ngnix configuration file to do that:</p>
<pre><code>add_header Feature-Policy &quot;geolocation none;midi none;notifications none;push none;sync-xhr none;microphone none;camera none;magnetometer none;gyroscope none;speaker none;vibrate none;fullscreen self;payment none;&quot;;
</code></pre>
<p><strong>References</strong></p>
<ul>
<li>Feature Policy - Draft Community Group Report, 26 July 2018 <a href="https://wicg.github.io/feature-policy/" title="Feature Policy - Draft Community Group Report, 26 July 2018" target="_blank">https://wicg.github.io/feature-policy/</a></li>
<li>Introduction to Feature Policy by Eric Bidelman <a href="https://developers.google.com/web/updates/2018/06/feature-policy" title="Introduction to Feature Policy" target="_blank">https://developers.google.com/web/updates/2018/06/feature-policy</a></li>
<li>A new security header: Feature Policy &lt;a href=&quot;https://scotthelme.co.uk/a-new-security-header-feature-policy/&quot; title=&quot;A new security header: Feature Policy&quot; https://scotthelme.co.uk/a-new-security-header-feature-policy/target=&quot;_blank&quot;&gt;https://scotthelme.co.uk/a-new-security-header-feature-policy/</li>
</ul>
<p><strong>Analyse your HTTP response headers</strong></p>
<p>Scan your site now at <a href="https://securityheaders.com/" title="https://securityheaders.com/" target="_blank">https://securityheaders.com/</a> and get a decent grade like A or A+, please.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Just an ancient chinese Proverb]]></title><description><![CDATA[When the wind of change blows, some people build walls, others build windmills.]]></description><link>https://blog.immontilla.eu/just-an-ancient-chinese-proverb/</link><guid isPermaLink="false">5ee39da9bfb5470a7db74f94</guid><dc:creator><![CDATA[immontilla]]></dc:creator><pubDate>Fri, 10 Aug 2018 14:01:59 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><em>Originally read at &quot;The Business Blockchain&quot;, a William Mougayar book...</em></p>
<blockquote>
<p>When the wind of change blows, some people build walls, others build windmills.</p>
</blockquote>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Playing with Hyperledger Composer]]></title><description><![CDATA[This is a little example about a pretty simple bank application coded in Hyperledger Composer. The code is available at Github. ]]></description><link>https://blog.immontilla.eu/playing-with-hyperledger-composer/</link><guid isPermaLink="false">5ee39da9bfb5470a7db74f93</guid><dc:creator><![CDATA[immontilla]]></dc:creator><pubDate>Wed, 08 Aug 2018 16:07:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I'm starting to delve into blockchain from my developer point of view. Maybe the following warning is not absolutely necessary but just in case: <strong>This post is not about cryptocurrencies</strong>, it is about the Hyperledger Composer.</p>
<p>According to the Wikipedia, Hyperledger is an umbrella project of open source blockchains and related tools, started in December 2015 by the Linux Foundation to support the collaborative development of blockchain-based distributed ledgers.</p>
<p>One of these open source blockchain related tools is the <em><a href="https://www.hyperledger.org/projects/composer" title="Hyperledger Composer" target="_blank">Hyperledger Composer</a></em>.  If you want to give it a try, your machine have to meet some pre-requisites. If you are an Ubuntu user like me, please follow this <em><a href="https://hyperledger.github.io/composer/latest/installing/installing-prereqs.html#ubuntu" title="Installing pre-requisites Ubuntu" target="_blank">link</a></em>. The installation instructions are <em><a href="https://hyperledger.github.io/composer/latest/installing/development-tools.html" title="Installing the development environment" target="_blank">here</a></em>. Its beginner tutorial is <em><a href="https://hyperledger.github.io/composer/latest/tutorials/developer-tutorial" title="Developer tutorial for creating a Hyperledger Composer solution" target="_blank">here</a></em>.</p>
<p>My advice: stop reading this post now and follow the beginner tutorial by your own. Afterwards, take a look at my repository <a href="https://github.com/immontilla/hyperledger-composer-bank" title="github.com/immontilla/hyperledger-composer-bank" target="_blank">https://github.com/immontilla/hyperledger-composer-bank</a>, where you can find a basic/minimal implementation of a bank.</p>
<p>To see it quickly in action, open a shell and run these commands:</p>
<pre><code>git clone https://github.com/immontilla/hyperledger-composer-bank &amp;&amp; cd hyperledger-composer-bank &amp;&amp; npm install &amp;&amp; npm test
</code></pre>
<p>You will see something like this:</p>
<script src="https://gist.github.com/immontilla/46eb902ee3c8302d98cb7a7c69e41a6a.js"></script>
<p>As you can see,  I have added, some testing. Sadly, the tutorial do not include it or even mention it. This is wrong, testing is one important part of any software project.</p>
<p>Finally, let me invite you to play with Hyperledger Composer too. Think about some actions (<em>transactions</em>) someone (<em>participant</em>) like/need/want to do with its stuff (<em>assets</em>) and implement it using the Hyperledger Composer.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Spring Boot 2.0 Upgrade]]></title><description><![CDATA[Upgrading from Spring Boot 1.5.x to 2.0 demands some changes that I am going to share in this post. ]]></description><link>https://blog.immontilla.eu/spring-boot-2-0-upgrade/</link><guid isPermaLink="false">5ee39da9bfb5470a7db74f92</guid><dc:creator><![CDATA[immontilla]]></dc:creator><pubDate>Sun, 11 Mar 2018 14:06:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I upgraded my Spring Boot projects on Github from the 1.5.x version to the newest 2.0 over the weekend. These are my experiences:</p>
<h6 id="immontillafileuploadingwebapp">immontilla/file-uploading-web-app</h6>
<ul>
<li><strong>webjars-locator dependency missing</strong></li>
</ul>
<p>I had to change the dependency org.webjar.webjars-locator to  org.webjar.webjars-locator-core. I found out how to solve it in this article: <a href="https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide#webjars-locator" title="WebJars Locator" target="_blank">Spring-Boot-2.0-Migration-Guide#webjars-locator</a>.</p>
<ul>
<li><strong>Spring 5 - MockMvcRequestBuilders.fileUpload deprecation</strong></li>
</ul>
<p>In Spring 5, <em>MockMvcRequestBuilders.fileUpload</em> has been deprecated in favour of MockMvcRequestBuilders.multipart. Read the details here: <a href="https://docs.spring.io/spring-framework/docs/5.0.3.RELEASE/javadoc-api/deprecated-list.html#method" title="Deprecated List (Spring Framework 5.0.3.RELEASE API)" target="_blank">Deprecated List (Spring Framework 5.0.3.RELEASE API)</a>.</p>
<p>I had to change this:</p>
<pre><code class="language-language-java">MockMultipartFile csvFile = new MockMultipartFile(&quot;file&quot;, &quot;test&quot;, &quot;text/csv&quot;, &quot;a,b,c,d,e,f&quot;.getBytes());
this.mvc.perform(fileUpload(&quot;/upload&quot;).file(csvFile)).andExpect(status().isBadRequest()).andExpect(jsonPath(&quot;$.validFileExtension&quot;).value(&quot;false&quot;));
</code></pre>
<p>to:</p>
<pre><code class="language-language-java">ResultMatcher badRequest = MockMvcResultMatchers.status().isBadRequest();
MockMultipartFile csvFile = new MockMultipartFile(&quot;file&quot;, &quot;test&quot;, &quot;text/csv&quot;, &quot;a,b,c,d,e,f&quot;.getBytes());
MockHttpServletRequestBuilder uploadRequest = MockMvcRequestBuilders.multipart(&quot;/upload&quot;).file(csvFile);
mockMVC.perform(uploadRequest).andExpect(badRequest).andExpect(jsonPath(&quot;$.validFileExtension&quot;).value(&quot;false&quot;));
</code></pre>
<p>Honouring <em>&quot;Uncle Bob&quot;</em>, I tweaked a little the test code readability as well.</p>
<ul>
<li><strong>Upgraded project dependencies</strong></li>
</ul>
<p>These changes are not related to the Spring Boot version upgrade. Its only goal is to keep the project's dependencies up-to-date.<br>
<strong>org.apache.tika.tika-core</strong> was upgraded from 1.16 to 1.17<br><br>
<strong>com.google.guava.guava</strong> has been split in two versions jre and android. Formerly was just 23, now is 24.0-jre<br><br>
<strong>org.webjars.bootstrap</strong> is not an alpha version anymore. I upgraded it from 4.0.0-alpha.6-1 to 4.0.0-2 version<br><br>
<strong>org.webjars.jquery</strong> was upgraded  from 3.2.1 to 3.3.1-1<br><br>
<strong>org.webjars.tether</strong> was upgraded  from 1.4.0 to 1.4.3<br></p>
<h6 id="immontillaspringboothttpsserver">immontilla/spring-boot-https-server</h6>
<ul>
<li><strong>Plugin io.spring.dependency-management</strong></li>
</ul>
<p>I had to add the <em>io.spring.dependency-management</em> plugin to the <em>build.gradle</em> file. Without it, the building process will fail.</p>
<ul>
<li><strong>ErrorAttributes and ErrorController classes</strong></li>
</ul>
<p>In Spring Boot 2.0, the  ErrorAttributes and ErrorController classes has been packaged in <em>org.springframework.boot.autoconfigure.web</em>. In Spring Boot 1.5.x, was packaged in <em>org.springframework.boot.web.servlet.error</em>.</p>
<ul>
<li><strong>Upgraded project dependencies</strong></li>
</ul>
<p><strong>org.webjars:webjars-locator:0.32-1</strong> was changed to <strong>org.webjars.webjars-locator-core</strong>.<br><br>
<strong>org.webjars.bootstrap</strong> was upgraded from 4.0.0-alpha.6-1 to 4.0.0-2 version.<br><br>
<strong>com.google.code.gson</strong> was upgraded from 2.8.1 to 2.8.2 version.<br></p>
<h6 id="immontillawedeploynorrisws">immontilla/wedeploy-norrisws</h6>
<p>This project required the same fixes than immontilla/spring-boot-https-server except any dependency upgrade.</p>
<h4 id="finalthoughts">Final thoughts</h4>
<p>I recommend to apply the Spring Boot upgrade sooner than later. At least in my case, it was a really straightforward process.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Valentine's Day HTTP codes]]></title><description><![CDATA[A fun and artistic point of view of HTTP codes. ]]></description><link>https://blog.immontilla.eu/valentines-day-http-codes/</link><guid isPermaLink="false">5ee39da9bfb5470a7db74f91</guid><dc:creator><![CDATA[immontilla]]></dc:creator><pubDate>Sun, 11 Feb 2018 14:32:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I have found an artistic, fun and original article about HTTP codes published at <a href="https://medium.com/@hanilim/http-codes-as-valentines-day-comics-8c03c805faa0" title="HTTP codes as Valentine’s Day comics" target="_blank">Medium</a> by <a href="https://medium.com/@hanilim" title="Hani Lim" target="_blank">Hani Lim</a>. I am going to share its images here.</p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*kwO3FGPDyIXK_k4sWcObFw.png" alt="The ideal ending for a browser + server, and a developer + their project"></p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*q9QKWeqdzFB_ODBHir6ylg.png" alt="301 Moved Permanently"></p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*2JkmAAF4qrDwJ7F4UcWMkw.png" alt="307 Temporary Redirect"></p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*pC3Q2MunxRCKLnIXOrsiqg.png" alt="304 Not Changed"></p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*b9qaO4GzYxqqtSqZe-J65w.png" alt="400 Bad Request"></p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*REugz7ao4EFuYqUVCS-oIA.png" alt="401 Unauthorized"></p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*fdexvE6MyrD2wHkdVS1BKg.png" alt="403 Forbidden"></p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*hdR6W4ZX9TfI9B806b2OJg.png" alt="404 Not Found"></p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*Cfm-bGfjEJW2SQsyMWtYEQ.png" alt="407 Proxy authentication required"></p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*CQVH65MfNn0ZoVcWuJYwyA.png" alt="408 Request Timeout"></p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*Tn2yINfOEa_6QuoXajKMNg.png" alt="409 Conflict"></p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*kH47JOkzsBgjlxX53CUwag.png" alt="410 Gone"></p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*zE2AgbyqABz7-5e_eIUTyQ.png" alt="426 Upgraded Required"></p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*PuqKcSXthqTa6sP1CnT7eg.png" alt="500 Server error"></p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*C-cINDGqR44-8NV2KJLAxw.png" alt="502 Bad Gateway"></p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*bxkr0O8sApIBgB2P7QbG9A.png" alt="503 Temporarily Unavailable"></p>
<p><img src="https://cdn-images-1.medium.com/max/1600/1*nfshYGP6k4dnxETaJyuiIw.png" alt="504 gateway Timeout"></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[WTFs per minute - The only valid measurement of code quality]]></title><description><![CDATA[Even bad code can function]]></description><link>https://blog.immontilla.eu/wtfs-per-minute-the-only-valid-measurement-of-code-quality/</link><guid isPermaLink="false">5ee39da9bfb5470a7db74f90</guid><dc:creator><![CDATA[immontilla]]></dc:creator><pubDate>Sun, 14 Jan 2018 10:00:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><img src="https://github.com/immontilla/spring-boot-https-server/blob/master/client/src/main/resources/static/img/wtfm.jpg?raw=true" alt="The only valid measurement of code quality: WTFs/minute"><br>
<br><br>
<em>Even bad code can function</em><br>
<br><br>
<cite>Taken from <strong>Clean Code: A Handbook of Agile Software Craftsmanship</strong> by <strong>Robert C. Martin</strong></cite></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Ephemeral Docker Volumes]]></title><description><![CDATA[Increase docker container's security level by using ephemeral volumes. The tmpfs flag mark the volume as ephemeral whereas the v mark it as persistant. ]]></description><link>https://blog.immontilla.eu/ephemeral-docker-volumes/</link><guid isPermaLink="false">5ee39da9bfb5470a7db74f8f</guid><dc:creator><![CDATA[immontilla]]></dc:creator><pubDate>Wed, 13 Dec 2017 21:23:18 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>There may be cases where you do not want to store a container’s data on the host machine, but you also don’t want to write the data into the container’s writable layer, for performance or security reasons.</p>
</blockquote>
<p><sub><em>Use tmpfs mounts <a href="https://docs.docker.com/engine/admin/volumes/tmpfs/" title="Use tmpfs mounts" target="_blank">https://docs.docker.com/engine/admin/volumes/tmpfs/</a></em></sub></p>
<p>That's why I removed the VOLUME instruction in the <em>immontilla/secure-file-uploader</em>'s Dockerfile.</p>
<pre><code class="language-docker">FROM alpine/git as clone
LABEL maintainer=&quot;Iván Mauricio Montilla Figueroa&quot;
WORKDIR /app
RUN git clone --progress https://github.com/immontilla/file-uploading-web-app.git

FROM maven:alpine as build
WORKDIR /app
COPY --from=clone /app/file-uploading-web-app /app
RUN mvn -DskipTests=true clean install &amp;&amp; cp target/secure-upload-1.0.0.jar app.jar

FROM openjdk:8-jdk-alpine
WORKDIR /app
COPY --from=build /app/app.jar /app
EXPOSE 8090
ENTRYPOINT [&quot;java&quot;,&quot;-Djava.security.egd=file:/dev/./urandom&quot;,&quot;-jar&quot;,&quot;app.jar&quot;]
</code></pre>
<p>First, you have to start the ClamAV container, otherwise, all the files will be rejected because they can't be scanned for virus.</p>
<pre><code>docker run -d --name av mkodockx/docker-clamav  
</code></pre>
<p>Then, you can start the file uploader container.</p>
<pre><code>docker run -d --link av:clamavd --volume csv-files:/tmp/safe --tmpfs /tmp/unsafe -p 8090:8090 --name secure-csv-uploader immontilla/secure-file-uploader
</code></pre>
<p>Finally, you can check the functionality trying to upload some files at <a href="http://localhost:8090/" title="secure-csv-uploader" target="_blank">http://localhost:8090/</a>.</p>
<h6 id="commandstoremember">Commands to remember</h6>
<ul>
<li>To list the docker volumes</li>
</ul>
<pre><code>docker volume ls
</code></pre>
<ul>
<li>To see information about the volume <em>csv-files</em> - including its path on the host machine.</li>
</ul>
<pre><code>docker volume inspect csv-files
</code></pre>
<ul>
<li>To list the uploaded files</li>
</ul>
<pre><code>csvFilesPath=$(docker volume inspect csv-files | grep -oP '(?&lt;=&quot;Mountpoint&quot;: &quot;)[^&quot;]*')

sudo ls -l $csvFilesPath
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[A Docker automated build image of my secure file uploading web app]]></title><description><![CDATA[Docker automated building help you to keep up-to-date your image because if your change your code an build will be triggered.]]></description><link>https://blog.immontilla.eu/a-docker-automated-build-image-of-my-secure-file-uploading-web-app/</link><guid isPermaLink="false">5ee39da9bfb5470a7db74f8e</guid><dc:creator><![CDATA[immontilla]]></dc:creator><pubDate>Sun, 10 Dec 2017 15:56:30 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>Automated Builds have several advantages:</p>
</blockquote>
<ul>
<li>Images built in this way are built exactly as specified.</li>
<li>The Dockerfile is available to anyone with access to your Docker Hub repository.</li>
<li>Your repository is kept up-to-date with code changes automatically.</li>
</ul>
<p>-- <cite>Configure automated builds on Docker Hub <a href="https://docs.docker.com/docker-hub/builds/" title="Configure automated builds on Docker Hub" target="_blank">https://docs.docker.com/docker-hub/builds/</a></cite></p>
<p>I had a personal project at <a href="https://github.com/immontilla/file-uploading-web-app" title="file-uploading-web-app" target="_blank">Github</a> named <em>file-uploading-web-app</em>. It is a web application to upload CSV files in a secure way. The code could be easily adapted to accept any other file types.</p>
<p>I pushed its image on Docker Hub using a maven plugin following this <a href="https://spring.io/guides/gs/spring-boot-docker/" title="Spring Boot with Docker" target="_blank">post</a>. However, as I wanted to build the image automatically, I have to create a new <a href="https://github.com/immontilla/secure-file-uploader" title="immontilla/secure-file-uploader" target="_blank">Github</a> repository linked to <a href="https://hub.docker.com/r/immontilla/secure-file-uploader/" title="immontilla/secure-file-uploader/" target="_blank">Dockerhub</a>. Doing so, every change I make in <a href="https://github.com/immontilla/secure-file-uploader" title="immontilla/secure-file-uploader" target="_blank">https://github.com/immontilla/secure-file-uploader</a> will trigger an automated build task on <a href="https://hub.docker.com/r/immontilla/secure-file-uploader/" title="immontilla/secure-file-uploader/" target="_blank">https://hub.docker.com/r/immontilla/secure-file-uploader/</a>.</p>
<p>This is the Dockerfile:</p>
<pre><code class="language-dockerfile">FROM alpine/git as clone
LABEL maintainer=&quot;Iván Mauricio Montilla Figueroa&quot;
WORKDIR /app
RUN git clone --progress https://github.com/immontilla/file-uploading-web-app.git

FROM maven:alpine as build
WORKDIR /app
COPY --from=clone /app/file-uploading-web-app /app
RUN mvn -DskipTests=true clean install &amp;&amp; cp target/secure-upload-1.0.0.jar app.jar

FROM openjdk:8-jdk-alpine
WORKDIR /app
COPY --from=build /app/app.jar /app
RUN mkdir /tmp/safe &amp;&amp; mkdir /tmp/unsafe
VOLUME /tmp
EXPOSE 8090
ENTRYPOINT [&quot;java&quot;,&quot;-Djava.security.egd=file:/dev/./urandom&quot;,&quot;-jar&quot;,&quot;app.jar&quot;]
</code></pre>
 <br>
To run the web application, it is necessary to start mkodockx/docker-clamav first. Also, it is mandatory to name it **av**.
```
docker run -d --name av mkodockx/docker-clamav
```
Then, **av** has to be linked to immontilla/secure-file-uploader like this:
```
docker run -d --link av:clamavd --volume csv-files:/tmp/safe --tmpfs /tmp/unsafe -p 8090:8090 --name secure-csv-uploader immontilla/secure-file-uploader
```
Few seconds later, the secure-csv-uploader will be available at <a href="http://localhost:8090/" title="secure-csv-uploader" target="_blank">http://localhost:8090/</a>.
<h6 id="commandstoremember">Commands to remember</h6>
<ul>
<li>To gain access to the console</li>
</ul>
<pre><code>docker exec -it secure-csv-uploader sh
</code></pre>
<ul>
<li>To list the uploaded files</li>
</ul>
<pre><code>csvFilesPath=$(docker volume inspect csv-files | grep -oP '(?&lt;=&quot;Mountpoint&quot;: &quot;)[^&quot;]*')

sudo ls -l $csvFilesPath
</code></pre>
<ul>
<li>To see the secure-csv-uploader log</li>
</ul>
<pre><code>docker logs secure-csv-uploader
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Docker multi-stage builds]]></title><description><![CDATA[Find out what I did to reduce "immontilla/docker-mitreid-oidc-server"   image size  from 488 Mb to 212 Mb dividing its  Dockerfile build in stages. ]]></description><link>https://blog.immontilla.eu/docker-multi-stage-builds/</link><guid isPermaLink="false">5ee39da9bfb5470a7db74f8d</guid><dc:creator><![CDATA[immontilla]]></dc:creator><pubDate>Sun, 03 Dec 2017 20:16:07 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Last week, I pushed <a href="https://hub.docker.com/r/immontilla/docker-mitreid-oidc-server/" title="immontilla/docker-mitreid-oidc-server" target="_blank">docker-mitreid-oidc-server</a> at Docker Hub. It has been pulled 50 times so far. I have received some comments demanding me to fix the  <em>simple-web-app log-in bug</em>, and also, customize the Tomcat server default page with links to the MITREid OpenID Connect administration server and its protected client web app. Additionally, I am not satisfied with the image file size because it is larger (488Mb) than I was expecting (160 Mb).</p>
<p>Here you will find out what I did to fix the <em>simple-web-app log-in bug</em>, replace the Tomcat server default page, and reduce the image file size from 488 to 212 Mb.</p>
<h6 id="simplewebapploginbug">simple-web-app log-in bug</h6>
<p><br>I have decided to stop cloning the MITREid repositories directly in the Dockerfile, I am going to fork and clone them from my own repositories instead. Doing so, I can fix any bug with no delay. However, I have to keep an eye on the MITREid repositories updates.</p>
<h6 id="tomcatserverdefaultpage">Tomcat server default page</h6>
<p><br>I just need to remove the ROOT folder content at <em>/usr/local/tomcat/webapps/ROOT/</em> path, and copy an index.html from my <a href="https://github.com/immontilla/docker-mitreid-oidc-server/blob/master/index.html" title="index.html" target="_blank">GitHub</a> repo. Doing this, I can update the html file whenever I want.</p>
<h6 id="reduceimagefilesize">Reduce image file size</h6>
<p><br>I found a guide titled Multi-stage builds at <a href="https://docs.docker.com/engine/userguide/eng-image/multistage-build/" title="Use multi-stage builds" target="_blank">Docker docs</a>. There you will read:</p>
<blockquote>
<p>With multi-stage builds, you use multiple FROM statements in your Dockerfile. Each FROM instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image.</p>
</blockquote>
<p>-- <cite>Use multi-stage builds</cite></p>
<blockquote>
<p>By default, the stages are not named, and you refer to them by their integer number, starting with 0 for the first FROM instruction. However, you can name your stages, by adding an as <name> to the FROM instruction.</name></p>
</blockquote>
<p>-- <cite>Name your build stages</cite></p>
<p>Basically, I divided the Dockerfile in 3 stages:</p>
<p>1.- Clone</p>
<pre><code>FROM alpine/git as clone 
LABEL maintainer=&quot;Iván Mauricio Montilla Figueroa&quot;
WORKDIR /app
RUN mkdir srv &amp;&amp; cd srv &amp;&amp; \ 
git clone --progress https://github.com/immontilla/OpenID-Connect-Java-Spring-Server.git &amp;&amp; \ cd .. &amp;&amp; mkdir web &amp;&amp; cd web &amp;&amp; \ git clone --progress https://github.com/immontilla/simple-web-app.git
</code></pre>
<p>2.- Build</p>
<pre><code>FROM maven:alpine as build WORKDIR /app
COPY --from=clone /app/srv/OpenID-Connect-Java-Spring-Server /app/srv
RUN cd srv &amp;&amp; mvn -Dmaven.javadoc.skip=true -DskipTests clean install &amp;&amp; \
mkdir ../WARs &amp;&amp; mv openid-connect-server-webapp/target/openid-connect-server-webapp.war ../WARs
COPY --from=clone /app/web/simple-web-app /app/web
RUN cd web &amp;&amp; mvn -DskipTests clean install &amp;&amp; mv target/simple-web-app.war ../WARs
</code></pre>
<p>3.- Deploy</p>
<pre><code>FROM tomcat:alpine WORKDIR /app
COPY --from=build /app/WARs /app
RUN apk add --no-cache --update openssl &amp;&amp; \
cp *.war /usr/local/tomcat/webapps/ &amp;&amp; \
rm -rf /usr/local/tomcat/webapps/ROOT/WEB-INF/ &amp;&amp; \
rm /usr/local/tomcat/webapps/ROOT/* &amp;&amp; \
cd /usr/local/tomcat/webapps/ROOT/ &amp;&amp; \
wget https://raw.githubusercontent.com/immontilla/docker-mitreid-oidc-server/master/index.html
</code></pre>
<p>You can see the full Dockerfile at <a href="https://hub.docker.com/r/immontilla/docker-mitreid-oidc-server/~/dockerfile/" title="Dockerfile" target="_blank">immontilla/docker-mitreid-oidc-server/~/dockerfile/</a></p>
<p>The final result is a 212 Mb image. It is not as small as I originally thought. The reason is, I was not taking in count the uncompressed web app folders sizes.</p>
<p>Let's check the result:</p>
<p>Tomcat:alpine size +<br>
openid-connect-server-webapp.war size +<br>
openid-connect-server-webapp folder size +<br>
simple-web-app.war size +<br>
simple-web-app folder size</p>
<p>113 Mb + 28.3 Mb + 33.4 Mb + 17.9 Mb + 21.1 Mb = 213.7 Mb</p>
<p>If you like to check this result by yourself:</p>
<p>Access the console machine</p>
<pre><code>docker exec -it oidc-srv bash
</code></pre>
<p>Get every file or folder size:</p>
<pre><code>du -sh /usr/local/tomcat/webapps/openid-connect-server-webapp.war
</code></pre>
<pre><code>du -sh /usr/local/tomcat/webapps/openid-connect-server-webapp/
</code></pre>
<pre><code>du -sh /usr/local/tomcat/webapps/simple-web-app.war
</code></pre>
<pre><code>du -sh /usr/local/tomcat/webapps/simple-web-app/
</code></pre>
<p>and sum them.</p>
<h5 id="lessonslearnedalongtheway">Lessons learned along the way</h5>
<ul>
<li>The small image file size, the better.<br><br>
Dividing the image building process in stages reduce its file size. In the final image there is no any java library, compiler files and/or folders and none build/compile utility at all. It is just Tomcat and two web applications.</li>
<li>Latest is not always the most recent version. Usually is the stable version.<br><br>
This is why immontilla/docker-mitreid-oidc-server base image is not tomcat:9.0.1-alpine anymore. In fact, that version is no longer available at <a href="https://hub.docker.com/r/library/tomcat/" title="library/tomcat/" target="_blank">library/tomcat/</a>, it was replaced by the 9.0.2. I chose tomcat:alpine as base image because its version is 8, which is the current Tomcat stable version.</li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>