<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alexandre Rousseau</title>
    <description>The latest articles on DEV Community by Alexandre Rousseau (@madeindjs).</description>
    <link>https://dev.to/madeindjs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F54985%2F098c9103-0fd4-4451-adca-9815893809f8.jpeg</url>
      <title>DEV Community: Alexandre Rousseau</title>
      <link>https://dev.to/madeindjs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/madeindjs"/>
    <language>en</language>
    <item>
      <title>Hack protected WPA/WPA2 Wi-fi</title>
      <dc:creator>Alexandre Rousseau</dc:creator>
      <pubDate>Thu, 06 Aug 2020 15:42:54 +0000</pubDate>
      <link>https://dev.to/madeindjs/hack-protected-wpa-wpa2-wi-fi-3ph2</link>
      <guid>https://dev.to/madeindjs/hack-protected-wpa-wpa2-wi-fi-3ph2</guid>
      <description>&lt;p&gt;I decided to hack my &lt;a href="///network/2017/10/11/Installer_bridge_sfr_box-4k.html"&gt;my new router&lt;/a&gt; just to try and have a fun. Spoiler : it was really easy.&lt;/p&gt;

&lt;p&gt;So to make my tests I tried a famous Linux distribution: &lt;a href="https://www.kali.org/"&gt;Kali Linux&lt;/a&gt;. This distribution have many pre-instaled hacking tools who help us.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i4oMCdJg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://rousseau-alexandre.fr/img/blog/kali.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i4oMCdJg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://rousseau-alexandre.fr/img/blog/kali.svg" alt="Logo de Kali Linux"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I installed Kali Linux in &lt;a href="https://fr.wikipedia.org/wiki/Multiboot"&gt;dual-boot&lt;/a&gt; but you can also use it in Live USB mode or with a virtual machine like &lt;a href="https://www.virtualbox.org/"&gt;VirtualBox&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;Here we will use &lt;a href="https://www.aircrack-ng.org/"&gt;Aircrack-ng&lt;/a&gt; which is an open-source software suite used to monitor wireless networks and "break" the WEP and WPA keys of Wi-fi networks. The attack will take place in several phases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Preparation&lt;/strong&gt; of your network card&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analysis&lt;/strong&gt; of the Wi-fi target&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capturing&lt;/strong&gt; a &lt;strong&gt;WPA handshake&lt;/strong&gt; &lt;em&gt;(a connection to the Wi-fi network)&lt;/em&gt; by disconnecting a device on the Wi-fi&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WPA handshake&lt;/strong&gt; password cracking by &lt;em&gt;bruteforce&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Preparation
&lt;/h2&gt;

&lt;p&gt;The first step is to activate the &lt;strong&gt;monitor mode&lt;/strong&gt; of the network card set up. To do this we list the available network cards with &lt;code&gt;airmong-ng&lt;/code&gt;. Open a terminal and type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;airmon-ng
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If your network card does not display, it is not compatible. You have to buy one &lt;em&gt;(a USB Wi-fi dongle is enough)&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In our case we see that we can use our &lt;strong&gt;wlan0&lt;/strong&gt; network card. So we activate the &lt;strong&gt;monitor mode&lt;/strong&gt; with the following command::&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;airmon-ng start wlan0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;From here, the network card &lt;strong&gt;wlan0&lt;/strong&gt; is no longer available &lt;em&gt;(you no longer have internet)&lt;/em&gt;, and a new network card appears. It can be found by doing an &lt;code&gt;ifconfig&lt;/code&gt;. In my case, it is &lt;strong&gt;wlan0mon&lt;/strong&gt;..&lt;/p&gt;

&lt;h2&gt;
  
  
  Analysis
&lt;/h2&gt;

&lt;p&gt;Now we can &lt;em&gt;sniff&lt;/em&gt; the network packets that circulate around us with &lt;code&gt;airodump&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;airodump-ng wlan0mon
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This command will find additional information on Wi-fi including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;strong&gt;BSSID&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;CH&lt;/strong&gt;annel&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;AUTH&lt;/strong&gt;, the mode of authentication&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;ESSID&lt;/strong&gt;, the name of the router&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Among all the lines, my network appears. Remember to write down the information as it will be useful to us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt; BSSID              PWR  Beacons    #Data, #/s  CH  MB   ENC  CIPHER AUTH ESSID

 18:D6:C7:85:7E:A0  -45        6        0    0   2  54e  WPA2 CCMP   PSK  TP-LINK_7EA0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Capturing a WPA handshake
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;WPA handshake&lt;/strong&gt; takes place when a device is connected to the Wi-fi. Our goal is to capture one in order to recover the encrypted password.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sniff the Wi-fi and wait for a device to connect to the Wi-fi&lt;/li&gt;
&lt;li&gt;sniff the Wi-fi and cause a disconnection and wait for the device to reconnect&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In order to test, I will disconnect my &lt;strong&gt;Blackberry&lt;/strong&gt; already connected to it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wi-fi Scan
&lt;/h3&gt;

&lt;p&gt;So we scan the network with the &lt;code&gt;airodump-ng&lt;/code&gt; command and options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-c&lt;/code&gt; options to specify the channel&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--bssid&lt;/code&gt;, my router's ID.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;w&lt;/code&gt; the directory where the output files will be stored
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;airodump-ng &lt;span class="nt"&gt;-c&lt;/span&gt; 10 &lt;span class="nt"&gt;--bssid&lt;/span&gt; 18:D6:C7:85:7E:A0 &lt;span class="nt"&gt;-w&lt;/span&gt; tplink  wlan0mon
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We leave this command in the background, it will produce 3 files, one of which is of type &lt;em&gt;xml&lt;/em&gt;. This is the one we are interested in because it contains more details about the devices connected to the wi-fi. By opening this one, we can find very easily the information of my Blackberry. Here is an extract of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;client-mac&amp;gt;&lt;/span&gt;94:EB:CD:25:E0:C1&lt;span class="nt"&gt;&amp;lt;/client-mac&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;client-manuf&amp;gt;&lt;/span&gt;BlackBerry RTS&lt;span class="nt"&gt;&amp;lt;/client-manuf&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Disconnection
&lt;/h3&gt;

&lt;p&gt;Now that we have all the information, we will send a packet that will &lt;strong&gt;request disconnection&lt;/strong&gt; of my Blackberry. We use &lt;code&gt;aireplay-ng&lt;/code&gt; with the parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-0&lt;/code&gt; to send a de-authentication signal.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-a&lt;/code&gt; To the BSSID of our Wi-fi.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-c&lt;/code&gt; The BSSID of the target&lt;/li&gt;
&lt;li&gt;the network card used
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;aireplay-ng &lt;span class="nt"&gt;-0&lt;/span&gt; 2 &lt;span class="nt"&gt;-a&lt;/span&gt; 18:D6:C7:85:7E:A0 &lt;span class="nt"&gt;-c&lt;/span&gt; 94:EB:CD:25:E0:C1 wlan0mon
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The device disconnects and reconnects automatically. The result is a &lt;strong&gt;WPA Handshake&lt;/strong&gt; which is contained in the &lt;em&gt;tplink.cpa&lt;/em&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cracking
&lt;/h2&gt;

&lt;p&gt;Now that we have obtained a packet containing the &lt;strong&gt;encrypted WPA password&lt;/strong&gt;, we just have to test several combinations until we find a matching one: this is called a &lt;strong&gt;bruteforce&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  the dictionary
&lt;/h3&gt;

&lt;p&gt;To find a password we need... passwords! You can find &lt;a href="http://www.wirelesshack.org/wpa-wpa2-word-list-dictionaries.html"&gt;multi-gigabyte text files of the most commonly used passwords&lt;/a&gt;. In my case, I know that the password of my Wi-fi contains 8 digits. So I'm going to use the &lt;code&gt;crunch&lt;/code&gt; command to generate all the possible combinations. &lt;code&gt;crunch&lt;/code&gt; uses several parameters:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the minimum length &lt;em&gt;(8)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;the maximum length &lt;em&gt;(8)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;the characters to be used &lt;em&gt;(0123...9)&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We're sending it all in a &lt;em&gt;passwords.txt&lt;/em&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;crunch 8 8 12345678 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; passwords.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In a few seconds we get a file of &lt;strong&gt;43046721 lines&lt;/strong&gt; weighing &lt;strong&gt;369 MB&lt;/strong&gt;!!!!&lt;/p&gt;

&lt;h3&gt;
  
  
  The bruteforce
&lt;/h3&gt;

&lt;p&gt;We're taking action. Here we're going to brute force the password. To do this we use &lt;code&gt;aircrack-ng&lt;/code&gt; which will encrypt the passwords one by one and check if it matches the password of the network packet we captured (Get yourself a coffee as it can be long).&lt;/p&gt;

&lt;p&gt;To do this we use &lt;code&gt;aircrack-ng&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;aircrack-ng &lt;span class="nt"&gt;-a2&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; 18:D6:C7:85:7E:A0 &lt;span class="nt"&gt;-w&lt;/span&gt; /root/Desktop/passwords.txt /root/Desktop/tplink.cap
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And after a while::&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nthKMGR1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fynlzv1ig5di2w1tqat7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nthKMGR1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fynlzv1ig5di2w1tqat7.png" alt="Success"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Through this little test we see that it is very easy to "crack" a Wi-fi with a WPA password. The tools at our disposal are easy to access and no specific hardware is required. However by applying some simple rules we can avoid this kind of risk.&lt;/p&gt;

&lt;p&gt;Remember, the password used was only 8 numeric characters. The number of combinations fit into a 380 MB file. If the password had included alphabetic characters, the dictionary would have exceeded the terabyte. The bruteforce would certainly have lasted several weeks.&lt;/p&gt;

&lt;p&gt;So by applying a more complex password, we reduce the risk. By changing it regularly, it is not possible to crack the combination quickly enough.&lt;/p&gt;

&lt;p&gt;Furthermore it is possible to adapt the wi-fi signal so that it is not visible in the whole building.&lt;/p&gt;

&lt;p&gt;As soon as possible, use the Ethernet cable, which is still the most secure solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://rousseau-alexandre.fr/en/hacking/2020/08/06/hack-password-wpa-wifi.markdown.html"&gt;Original article&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.aircrack-ng.org/"&gt;Aircrack-ng&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kali.org/"&gt;Kali Linux | Penetration Testing and Ethical Hacking Linux Distribution&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>hack</category>
      <category>kali</category>
      <category>wifi</category>
      <category>wpa</category>
    </item>
    <item>
      <title>Deploy a fullstack application on Google Cloud Plateform with Gitlab CI</title>
      <dc:creator>Alexandre Rousseau</dc:creator>
      <pubDate>Thu, 06 Aug 2020 08:14:05 +0000</pubDate>
      <link>https://dev.to/madeindjs/deploy-a-fullstack-application-on-google-cloud-plateform-with-gitlab-ci-1n91</link>
      <guid>https://dev.to/madeindjs/deploy-a-fullstack-application-on-google-cloud-plateform-with-gitlab-ci-1n91</guid>
      <description>&lt;p&gt;I deployed a Fullstack application (i.e. Frontend / Backend) on Google Cloud Platform with Kubernetes. And since &lt;a href="https://www.forbes.com/sites/forbestechcouncil/2018/01/08/developers-are-lazy-and-thats-usually-a-good-thing/"&gt;developers are lazy&lt;/a&gt;, I automated everything with Gitlab CI.&lt;/p&gt;

&lt;p&gt;It's a far cry from PHP deployed by hand on an Apache server. If you're interested in moving up a gear and see how it works, read on.&lt;/p&gt;

&lt;h2&gt;
  
  
  My application
&lt;/h2&gt;

&lt;p&gt;My project I'm currently working on is divided into three parts: &lt;em&gt;Frontend&lt;/em&gt;, &lt;em&gt;Backend&lt;/em&gt;, &lt;em&gt;Job Queue&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Each part runs in separate &lt;em&gt;containers&lt;/em&gt; Docker. So they all have a `Dockerfile':&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the &lt;em&gt;frontend&lt;/em&gt; uses a Node.js image that builds &lt;strong&gt;Angular 9&lt;/strong&gt; and then a NGINX image that serves the static files&lt;/li&gt;
&lt;li&gt;the &lt;em&gt;backend&lt;/em&gt; uses a &lt;strong&gt;Node.js&lt;/strong&gt; image that launches a web server on port 3000&lt;/li&gt;
&lt;li&gt;the &lt;em&gt;job_queue&lt;/em&gt; also uses a Node.js image that launches a &lt;strong&gt;Node.js&lt;/strong&gt; script that communicates with the Postgres database and performs offline actions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So my project has the following structure:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
├── backend&lt;br&gt;
├── docker&lt;br&gt;
├── docker-compose.yml&lt;br&gt;
└── frontend&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So I wanted to build these images automatically during a &lt;code&gt;git push&lt;/code&gt; and publish it on Google Cloud Platform with Kubernetes. For this, I used &lt;strong&gt;Gitlab CI&lt;/strong&gt; but the logic must be identical with Github's Circle CI.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Postgres database is independent of Kubernetes and runs on a [Google Cloud SQL for PostgreSQL] service (&lt;a href="https://cloud.google.com/sql/docs/postgres"&gt;https://cloud.google.com/sql/docs/postgres&lt;/a&gt;). I won't talk about it here..&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Automation with Gitlab CI
&lt;/h2&gt;

&lt;p&gt;Gitlab allows you to define a workflow of things to do when you push code through a &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; file. This is often useful for launching a &lt;em&gt;pipeline&lt;/em&gt; (a sequence of actions) that will run unit tests, linter code, etc...&lt;br&gt;
`&lt;br&gt;
In my case, I created the following actions :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;`test': launch unit tests&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;publish&lt;/code&gt;: creation of a Docker image and publication in the GCloud's private image registry&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deploy&lt;/code&gt;: tells the GCloud to deploy the images previously &lt;em&gt;uploaded&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So the structure of the `.gitlab-ci.yml' file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .gitlab-ci.yml&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;publish&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="s"&gt;job:test:backend:&lt;/span&gt;
  &lt;span class="s"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
  &lt;span class="s"&gt;# ...&lt;/span&gt;

&lt;span class="s"&gt;job:publish:backend:&lt;/span&gt;
  &lt;span class="s"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;publish&lt;/span&gt;
  &lt;span class="s"&gt;# ...&lt;/span&gt;

&lt;span class="s"&gt;job:deploy-develop:backend:&lt;/span&gt;
  &lt;span class="s"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy&lt;/span&gt;
  &lt;span class="s"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;I only kept the jobs that involve "backend" to simplify.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'll walk you through the steps. Here we go.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;test&lt;/code&gt;: running unit tests
&lt;/h2&gt;

&lt;p&gt;This is the easiest step. I won't spend too much time on it because a lot of tutorials exist and that's not the subject of this article.&lt;/p&gt;

&lt;p&gt;So we start two jobs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;job:test:backend&lt;/code&gt; will initialize the application, connect a Postgres database and run &lt;code&gt;yarn test&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="s"&gt;job:test:backend:&lt;/span&gt;
  &lt;span class="s"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
  &lt;span class="s"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres:12.3-alpine&lt;/span&gt;
  &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;database&lt;/span&gt;
    &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user&lt;/span&gt;
    &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;password&lt;/span&gt;
    &lt;span class="na"&gt;POSTGRES_HOST_AUTH_METHOD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;trust&lt;/span&gt;
  &lt;span class="na"&gt;before_script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cd backend&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cp .example.env .env&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;yarn install&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;job:test:frontend&lt;/code&gt; will initialize the application and run &lt;code&gt;yarn test&lt;/code&gt; but from an image containing a Chrome driver to emulate navigation.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;job:test:frontend:&lt;/span&gt;
  &lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;weboaks/node-karma-protractor-chrome:alpine&lt;/span&gt;
  &lt;span class="s"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
  &lt;span class="s"&gt;before_script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cd frontend&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;yarn install&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There you go.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;publish&lt;/code&gt;: creating a Docker image and publishing it in the private image registry of the GCloud.
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;publish&lt;/code&gt; step will build docker images of the different applications and publish them to &lt;a href="https://cloud.google.com/container-registry"&gt;GCloud - Container Registry&lt;/a&gt;. To do this, we will create a job for each image to be published (frontend, backend and worker).&lt;/p&gt;

&lt;p&gt;In order to build the images and publish them, we need to use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the image &lt;a href="https://hub.docker.com/r/google/cloud-sdk/"&gt;&lt;code&gt;google/cloud-sdk&lt;/code&gt;&lt;/a&gt; which allows to communicate with GCloud and publish the images.&lt;/li&gt;
&lt;li&gt;the [Docker-in-Docker] service (&lt;a href="https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor"&gt;https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor&lt;/a&gt;) which allows you to use Docker commands in a Docker container.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is then possible to use the :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;gcloud auth&lt;/code&gt; to connect to Gcloud in the container.&lt;/li&gt;
&lt;li&gt;gcloud auth configure-docker to connect Docker to GCloud&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker buil/push&lt;/code&gt; to create the image and publish it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One last thing to know: to connect to the GCloud in Gitlab CI, you must first log in. To do so, you need to add the GCloud credentials in the Gitlab CI settings in the "Settings &amp;gt; Variables" section. Once this is done, it is possible to log into the job using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$GCLOUD_SERVICE_KEY&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/gcloud-service-key.json
gcloud auth activate-service-account &lt;span class="nt"&gt;--key-file&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/gcloud-service-key.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Bellow the final result for &lt;code&gt;job:publish:backend&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;job:publish:backend:&lt;/span&gt;
  &lt;span class="s"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;publish&lt;/span&gt;
  &lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;google/cloud-sdk:latest&lt;/span&gt;
  &lt;span class="s"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;on_success&lt;/span&gt;
  &lt;span class="s"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker:dind&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;dind&lt;/span&gt;
  &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;DOCKER_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tcp://docker:2375&lt;/span&gt;
    &lt;span class="na"&gt;DOCKER_TLS_CERTDIR&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
  &lt;span class="na"&gt;before_script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cd backend&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cp .develop.env .env&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo $GCLOUD_SERVICE_KEY &amp;gt; ${HOME}/gcloud-service-key.json&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;gcloud auth activate-service-account --key-file ${HOME}/gcloud-service-key.json&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;gcloud auth configure-docker&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker build --compress -t us.gcr.io/${PROJECT_NAME}/${APP_NAME}-backend:${CI_COMMIT_SHA} .&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker push us.gcr.io/${PROJECT_NAME}/${APP_NAME}-backend:${CI_COMMIT_SHA}&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker image rm -f us.gcr.io/${PROJECT_NAME}/${APP_NAME}-backend:${CI_COMMIT_SHA}&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "us.gcr.io/${PROJECT_NAME}/${APP_NAME}-backend:${CI_COMMIT_SHA} image build with success and pushed"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;I skip over the details of the other two because they're very similar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;deploy&lt;/code&gt;: ask GCloud to deploy the images previously &lt;em&gt;uploaded&lt;/em&gt;.
&lt;/h2&gt;

&lt;p&gt;To use &lt;code&gt;kubectl&lt;/code&gt; we will also use the &lt;a href="https://hub.docker.com/r/google/cloud-sdk/"&gt;&lt;code&gt;google/cloud-sdk&lt;/code&gt;&lt;/a&gt; image which contains the Kubernetes utility.&lt;/p&gt;

&lt;p&gt;But before we start coding the script, we need to create three &lt;strong&gt;deployment&lt;/strong&gt; :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;dpl-my-app-frontend&lt;/code&gt; on &lt;a href="https://my-app/"&gt;https://my-app/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dpl-my-app-backend&lt;/code&gt; at &lt;a href="https://api.my-app/"&gt;https://api.my-app/&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dpl-my-app-worker&lt;/code&gt; that is not exposed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To create them, you can use the GCloud interface or use &lt;code&gt;kubectl&lt;/code&gt; directly on your PC (don't forget to &lt;a href="https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl?hl=fr"&gt;configure cluster access for kubectl&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;For the command line version, use &lt;code&gt;kubectl create deployment&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create deployment dpl-develop-data-frontend &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us.gcr.io/mazen-158916/data-k8s-frontend
kubectl create deployment dpl-develop-data-backend &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us.gcr.io/mazen-158916/data-k8s-backend
kubectl create deployment dpl-develop-data-worker &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us.gcr.io/mazen-158916/data-k8s-worker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;We can check that everything went well with &lt;code&gt;kubectl get deployments&lt;/code&gt; which should list our three new deployments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then, we just have to create the jobs that will update the &lt;em&gt;containers&lt;/em&gt; on these deployments and specify the port forwarding.&lt;/p&gt;

&lt;p&gt;To do this you also need to use &lt;code&gt;gcloud auth&lt;/code&gt; as you saw before. Then, just call the methods :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;kubectl set image&lt;/code&gt; to update the container image.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl patch deployment&lt;/code&gt; to update container information (e.g. change metadata)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the full version for &lt;code&gt;job:deploy-develop:backend&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;job:deploy-develop:backend:&lt;/span&gt;
  &lt;span class="s"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy&lt;/span&gt;
  &lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;google/cloud-sdk:latest&lt;/span&gt;
  &lt;span class="s"&gt;before_script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo $GCLOUD_SERVICE_KEY &amp;gt; ${HOME}/gcloud-service-key.json&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;gcloud auth activate-service-account --key-file ${HOME}/gcloud-service-key.json&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;gcloud config set compute/zone us-east1-c&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;gcloud config set project ${GCLOUD_PROJECT_NAME}&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;gcloud container clusters get-credentials ${K8S_CLUSTER_NAME}&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;gcloud auth configure-docker&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;kubectl set image deployment/${APP_NAME}-backend data-k8s-backend=us.gcr.io/${PROJECT_NAME}/${APP_NAME}-backend:${CI_COMMIT_SHA}&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;kubectl patch deployment ${APP_NAME}-backend -p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"date\":\"`date +'%s'`\"}}}}}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There you go.&lt;/p&gt;

&lt;p&gt;Then just go to the GCloud interface in the "Kubernetes Engine &amp;gt; Workloads" section, find the corresponding workloads and create the DNS entries on your domain name provider and point them to the corresponding deployments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;For my part I found the Google Cloud Platform approach very confusing but quite well documented. The time invested in learning this technology seems to me well invested because the architecture is really &lt;em&gt;scalable&lt;/em&gt; and allows to reduce the infrastructure costs.&lt;/p&gt;

&lt;p&gt;The only black point could be that we lock ourselves in a provider but I think that Amazon Web Service or Microsoft Azure share the same terminology because their technology is also based on Kubernetes in my opinion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://rousseau-alexandre.fr/en/programming/2020/08/05/gcloud-deploy-with-gitlabci.html"&gt;Original post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/kubernetes-engine/docs/tutorials/hello-app?hl=fr"&gt;Deploying a Containerized Web Application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://shinesolutions.com/2018/10/25/deploying-a-full-stack-application-to-google-kubernetes-engine/"&gt;Deploying a full stack application to Google Kubernetes Engine - Shine Solutions Group&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/access-application-cluster/connecting-frontend-backend/"&gt;Connect a Front End to a Back End Using a Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Building Docker images with GitLab CI/CD](&lt;a href="https://docs.gitlab.com/ee/ci/docker/using_docker_build.html"&gt;https://docs.gitlab.com/ee/ci/docker/using_docker_build.html&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>gcloud</category>
      <category>gitlabci</category>
      <category>docker</category>
    </item>
    <item>
      <title>Api on Rails 6</title>
      <dc:creator>Alexandre Rousseau</dc:creator>
      <pubDate>Mon, 19 Aug 2019 11:48:21 +0000</pubDate>
      <link>https://dev.to/madeindjs/api-on-rails-6-5f21</link>
      <guid>https://dev.to/madeindjs/api-on-rails-6-5f21</guid>
      <description>&lt;p&gt;Dear Ruby community,&lt;/p&gt;

&lt;p&gt;I just finished rewriting my &lt;a href="https://leanpub.com/apionrails6"&gt;API on Rails book&lt;/a&gt; for the brand new version of &lt;a href="https://rubygems.org/gems/rails"&gt;Rails 6&lt;/a&gt; released last Friday. This book discusses of bests practices for building a scalable API with Rails 6.&lt;/p&gt;

&lt;p&gt;I didn't just adapt the content, but I also chose to simplify some examples and use tools that seem more current to me, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;authentication tokens with &lt;a href="https://jwt.io/"&gt;JWT&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;compliance with &lt;a href="https://jsonapi.org/"&gt;JSON:API specifications&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;unit and functional tests with &lt;a href="https://github.com/seattlerb/minitest"&gt;Minitest&lt;/a&gt; instead of &lt;a href="http://rspec.info/"&gt;Rspec&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It took a lot of work on my part, so don't hesitate to &lt;a href="https://leanpub.com/apionrails6"&gt;take a look at Leanpub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The book is also available in &lt;a href="https://github.com/madeindjs/api_on_rails/releases"&gt;open-source on Github&lt;/a&gt; so feel free to fork and suggest improvements. I built the book using &lt;a href="https://asciidoctor.org/"&gt;Asciidocotr&lt;/a&gt; so it's really easy to contribute. You can also translate in your language and sell it on your preferred platform.&lt;/p&gt;

&lt;p&gt;Thank you for reading.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>api</category>
    </item>
  </channel>
</rss>
