<?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: Shobhit🎈✨</title>
    <description>The latest articles on DEV Community by Shobhit🎈✨ (@shobhitic).</description>
    <link>https://dev.to/shobhitic</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%2F62066%2F56ab0b7f-da7c-417a-a255-38a54a7796a6.jpg</url>
      <title>DEV Community: Shobhit🎈✨</title>
      <link>https://dev.to/shobhitic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shobhitic"/>
    <language>en</language>
    <item>
      <title>Psst... I can build this in a weekend!</title>
      <dc:creator>Shobhit🎈✨</dc:creator>
      <pubDate>Tue, 27 Feb 2024 16:10:00 +0000</pubDate>
      <link>https://dev.to/shobhitic/psst-i-can-build-this-in-a-weekend-5b45</link>
      <guid>https://dev.to/shobhitic/psst-i-can-build-this-in-a-weekend-5b45</guid>
      <description>&lt;p&gt;What can you &lt;em&gt;really&lt;/em&gt; build in a weekend?&lt;/p&gt;

&lt;p&gt;The core functionality with happy path? Probably, yes.&lt;/p&gt;

&lt;p&gt;But will it be useful? I doubt it.&lt;/p&gt;

&lt;p&gt;Can you add support for settings so users can customize the workflow in that weekend?&lt;/p&gt;

&lt;p&gt;What about error states when things go awry?&lt;/p&gt;

&lt;p&gt;What about security?&lt;/p&gt;

&lt;p&gt;The mobile or desktop optimized version?&lt;/p&gt;

&lt;p&gt;What about compliances needed to serve?&lt;/p&gt;

&lt;p&gt;And onboarding, so users can actually get some value out of it?&lt;/p&gt;

&lt;p&gt;Admin panel? Customer support tool integration? Handling weird payment flows? Marketing site? &lt;/p&gt;




&lt;p&gt;Converting a weekend hacked up prototype, to a proper functioning business takes a lot of time and effort.&lt;/p&gt;

&lt;p&gt;Yes, you can come up with a prototype that users can use and play around with, and you should to reduce time to feedback!&lt;/p&gt;

&lt;p&gt;But don't belittle other people's work of turning prototypes to a proper business with a flippant attitude.&lt;/p&gt;




&lt;p&gt;Originally written on &lt;a href="https://shobhitic.github.io/weekend-build"&gt;my site&lt;/a&gt;. Would love to hear your opinion! :)&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Building and Deploying an Amber app in 2 days</title>
      <dc:creator>Shobhit🎈✨</dc:creator>
      <pubDate>Fri, 29 Jun 2018 06:54:49 +0000</pubDate>
      <link>https://dev.to/shobhitic/building-and-deploying-an-amber-app-in-2-days-962</link>
      <guid>https://dev.to/shobhitic/building-and-deploying-an-amber-app-in-2-days-962</guid>
      <description>&lt;p&gt;&lt;em&gt;This was originally posted on &lt;a href="https://www.pilanites.com/deployed-amber-crystal/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yesterday night, I deployed my first Amber app to production. It’s a JSON hosting service for your mobile and web apps. I call it &lt;a href="https://jsonkeeper.com/" rel="noopener noreferrer"&gt;JSON Keeper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The app is very simple and straightforward right now. It only has one screen with no user accounts. You simply go to the site, paste your JSON and receive a URL where it’ll be hosted. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxpxfas1z0trfcouywq7s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxpxfas1z0trfcouywq7s.png" alt="JSON Keeper - A simple JSON hosting store for your web and mobile apps" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Building the app was very similar to Rails experience. Amber has the good old MVC structure, and regularly spits out response in microseconds.&lt;/p&gt;

&lt;p&gt;It took me some time to internalize that it is reporting things in microseconds. I kept comparing the response time of Amber app to a Rails app. This was a bit disappointing as I saw 300ms for Rails and 300 µs for Amber app.&lt;/p&gt;

&lt;p&gt;Later when I looked closely at the unit of time did it all make sense.&lt;/p&gt;

&lt;p&gt;Developing this app was a refreshing experience. I was concerned that strong typing will get in the way of productivity but it rarely happened. Although I did run into a weird bug which produced itself only on production, but that’s a story for another time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speed
&lt;/h2&gt;

&lt;p&gt;Yes, any post from a Rubyist trying out new frameworks and languages will invite speed comparison, but it’s true. Crystal is a blanzingly fast language and when deployed by creating an optimized binary, the response time is mind blowing.&lt;/p&gt;

&lt;p&gt;As I had said a few paragraphs ago, Amber is generating a response in less than 1 millisecond. Think about that! A similar Rails app deployed with MRI and passenger takes 200 milliseconds or so to generate a response.&lt;/p&gt;

&lt;p&gt;Needless to say, Crystal (and Amber) is really giving us great speed with a pleasure to work with language.&lt;/p&gt;

&lt;p&gt;“Fast as C, Slick as Ruby” is true!&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment
&lt;/h2&gt;

&lt;p&gt;Deployment experience very nice with Amber. You can build a binary to copy paste (or &lt;code&gt;scp&lt;/code&gt;) to your server and it have all required files, and code to run the server. No need to install and maintain dependencies on your servers any more. This also helps us while sharing our app with others.&lt;/p&gt;

&lt;p&gt;This is pretty similar to how Go lang does it deployment.&lt;/p&gt;

&lt;p&gt;On top of manually building and deploying, Amber gives you some deploy recipes out of the box. Currently it supports Digital Ocean and Heroku, with support for AWS, Azure, GCP coming soon.&lt;/p&gt;

&lt;p&gt;This is kind of like Capistrano integrated in framework itself with native support and the ability to spin up servers. Although, I didn’t use this feature as I wanted to experience the native way of deploying Amber/Crystal apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stability
&lt;/h2&gt;

&lt;p&gt;Stability can be measured on two different parameters – How stable is the server once deployed, and how stable is the framework/language in terms of incorporating breaking changes with new releases.&lt;/p&gt;

&lt;p&gt;The servers seems to be very stable. I did some load testing on it and while Ruby/Node servers start responding slowly, I saw no such issue with Amber.&lt;/p&gt;

&lt;p&gt;The framework and its APIs though are largely work in progress. I myself &lt;a href="https://github.com/amberframework/amber/commits?author=shobhitic" rel="noopener noreferrer"&gt;contributed a couple of commits&lt;/a&gt; to the framework and reading through the code and discussions shows you that the framework, and possible even the language, will have breaking changes in next releases.&lt;/p&gt;

&lt;p&gt;To be fair I’ve used Amber v0.8.0 and Crystal v0.25.0 so these kinds of things are expected.&lt;/p&gt;

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

&lt;p&gt;I am super excited about future of these two little technologies. Writing Crystal is a pleasure and it provides a lot of things which Ruby by its nature cannot. All Crystal (and Amber) now need is a serious corporate backing and they’ll explode in popularity.&lt;/p&gt;

</description>
      <category>crystal</category>
      <category>amber</category>
    </item>
    <item>
      <title>What is the funniest thing a non-developer has asked you about code?</title>
      <dc:creator>Shobhit🎈✨</dc:creator>
      <pubDate>Thu, 31 May 2018 14:46:12 +0000</pubDate>
      <link>https://dev.to/shobhitic/what-is-the-funniest-thing-a-non-developer-has-asked-you-about-code-1inf</link>
      <guid>https://dev.to/shobhitic/what-is-the-funniest-thing-a-non-developer-has-asked-you-about-code-1inf</guid>
      <description>&lt;p&gt;For me, it was a client who was scared about the language I'll use and had to ask this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fqph.ec.quoracdn.net%2Fmain-qimg-f05202b0c652414086a29f2a3c08a011" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fqph.ec.quoracdn.net%2Fmain-qimg-f05202b0c652414086a29f2a3c08a011" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I just couldn't control my laughter. :)&lt;/p&gt;

&lt;p&gt;What's yours?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>clients</category>
    </item>
    <item>
      <title>Simple String encryption in Rails</title>
      <dc:creator>Shobhit🎈✨</dc:creator>
      <pubDate>Fri, 25 May 2018 07:46:53 +0000</pubDate>
      <link>https://dev.to/shobhitic/simple-string-encryption-in-rails-36pi</link>
      <guid>https://dev.to/shobhitic/simple-string-encryption-in-rails-36pi</guid>
      <description>&lt;p&gt;If you've ever implemented any kind of SSO, you'll have encountered "relay state". Relay state is a parameter you send to your identity party, and they send it back to you without any modification so you can identify the user who just authorized.&lt;/p&gt;

&lt;p&gt;It's a pretty common flow, used by Google as well as many other OAuth providers.&lt;/p&gt;

&lt;p&gt;When I was a new programmer, I simply sent the &lt;code&gt;user_id&lt;/code&gt; of the user as relay state and did a &lt;code&gt;User.find(user_id)&lt;/code&gt; to fetch user.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do I need to encrypt User ID
&lt;/h2&gt;

&lt;p&gt;So, imagine this, if you signed up for my service, and then later wanted to add your Google credentials, you'd click on a button and it'll take you through the whole authorization workflow, in the end making a Webhook request with relay state as your user id, in plain text.&lt;/p&gt;

&lt;p&gt;This was pretty bad as now some user capable of doing Inspect element can change the &lt;code&gt;user_id&lt;/code&gt; from their number to any integer and my application would think the other user has authorized. Now they can use "Login with Google" on the sign in page and simply log in as that other user.&lt;/p&gt;

&lt;p&gt;Insecure af.&lt;/p&gt;

&lt;p&gt;When I was adding a &lt;a href="https://stride.com" rel="noopener noreferrer"&gt;Stride&lt;/a&gt; integration to my app which notifies when a &lt;a href="https://monitorcertificates.com" rel="noopener noreferrer"&gt;certificate is going to expire soon&lt;/a&gt;, I had the same problem as their official docs ask us to add a button where you add a &lt;code&gt;relayState&lt;/code&gt; parameter. Their application sends us a webhook once the user has added our app. The user is not redirected back to our site, unlike Slack.&lt;/p&gt;

&lt;p&gt;So the only way of identifying the user was with that &lt;code&gt;relayState&lt;/code&gt; and leaving it to plan &lt;code&gt;user_id&lt;/code&gt; would mean if you change the button's value and click on it, you will potentially get notified when other user's certificates are going to expire.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encrypting the User ID
&lt;/h2&gt;

&lt;p&gt;To combat this issue, I added two little functions to my helper class and called them &lt;code&gt;encrypt&lt;/code&gt; and &lt;code&gt;decrypt&lt;/code&gt;. The functions looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Assuming your Secret Key Base is in Rails.application.secrets.secret_key_base&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;encrypt&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
  &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_a?&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;

  &lt;span class="n"&gt;len&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MessageEncryptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;key_len&lt;/span&gt;
  &lt;span class="n"&gt;salt&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SecureRandom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hex&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;
  &lt;span class="n"&gt;key&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;KeyGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secret_key_base&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;generate_key&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;
  &lt;span class="n"&gt;crypt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MessageEncryptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;
  &lt;span class="n"&gt;encrypted_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;crypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encrypt_and_sign&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;$$&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;encrypted_data&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decrypt&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
  &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt; &lt;span class="s2"&gt;"$$"&lt;/span&gt;

  &lt;span class="n"&gt;len&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MessageEncryptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;key_len&lt;/span&gt;
  &lt;span class="n"&gt;key&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;KeyGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secret_key_base&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;generate_key&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;
  &lt;span class="n"&gt;crypt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MessageEncryptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;
  &lt;span class="n"&gt;crypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decrypt_and_verify&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How &lt;code&gt;encrypt&lt;/code&gt; works
&lt;/h2&gt;

&lt;p&gt;Encrypting a &lt;code&gt;text&lt;/code&gt; requires a &lt;code&gt;key&lt;/code&gt; and &lt;code&gt;salt&lt;/code&gt;. Decrypting an encrypted &lt;code&gt;text&lt;/code&gt; requires the same &lt;code&gt;key&lt;/code&gt; and &lt;code&gt;salt&lt;/code&gt;, otherwise this won't work.&lt;/p&gt;

&lt;p&gt;We generate a salt with these lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;len&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MessageEncryptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;key_len&lt;/span&gt;
&lt;span class="n"&gt;salt&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SecureRandom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hex&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we have our salt, we can use the Rails' &lt;code&gt;secret_key_base&lt;/code&gt; as a "key" to generate a cryptographic key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;key&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;KeyGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secret_key_base&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;generate_key&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using this key, we create an encryption object &lt;code&gt;crypt&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;crypt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MessageEncryptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then we encrypt our text via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;encrypted_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;crypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encrypt_and_sign&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we could have simply returned this &lt;code&gt;encrypted_data&lt;/code&gt; and provided this as a relay state, but since &lt;code&gt;salt&lt;/code&gt; was generated randomly, we would know what it was and so won't be able to decrypt this data.&lt;/p&gt;

&lt;p&gt;I used a trick from Rails' &lt;code&gt;has_secure_password&lt;/code&gt; and &lt;code&gt;bcrypt&lt;/code&gt;, and returned a string which contains &lt;code&gt;salt&lt;/code&gt; and &lt;code&gt;encrypted_data&lt;/code&gt; as you can see from the last line of &lt;code&gt;encrypt&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;$$&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;encrypted_data&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns a string where you have both &lt;code&gt;salt&lt;/code&gt; and &lt;code&gt;encrypted_data&lt;/code&gt; and the user can't change this to other user's ID without knowing your &lt;code&gt;secret_key_base&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How &lt;code&gt;decrypt&lt;/code&gt; works
&lt;/h2&gt;

&lt;p&gt;Once you understand the &lt;code&gt;encrypt&lt;/code&gt; method, &lt;code&gt;decrypt&lt;/code&gt; id fairly straightforward.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;decrypt&lt;/code&gt; method accepts a &lt;code&gt;text&lt;/code&gt; parameter, from which it extracts &lt;code&gt;salt&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt; (or rather &lt;code&gt;encrypted_data&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"$$"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have the salt with us, we create the &lt;code&gt;crypt&lt;/code&gt; object, just like we did in the &lt;code&gt;encrypt&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;len&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MessageEncryptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;key_len&lt;/span&gt;
&lt;span class="n"&gt;key&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;KeyGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;secret_key_base&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;generate_key&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;
&lt;span class="n"&gt;crypt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MessageEncryptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then, we decrypt the data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;crypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decrypt_and_verify&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which we return back from the method.&lt;/p&gt;

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

&lt;p&gt;This is a pretty simple method of encrypting and decrypting a &lt;code&gt;user_id&lt;/code&gt; or any other data.&lt;/p&gt;

&lt;p&gt;In an ideal scenario, you would create a table and keep a user's token for an application, which you would send as a &lt;code&gt;relayState&lt;/code&gt; and use it again to identify the user back. It takes time to get that perfect, so this simple encryption and decryption works amazing to get up and running as quickly as possible.&lt;/p&gt;

&lt;p&gt;But in the long run, you'd build out a table to keep all this information secure and more robust. That's what I've done with my app. :)&lt;/p&gt;




&lt;p&gt;If you're an expert in security, could you tell me if there's something that I've done here which would make it unsecure? Thanks!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>encryption</category>
    </item>
    <item>
      <title>Monitor your HTTPS certificate expiry with this script</title>
      <dc:creator>Shobhit🎈✨</dc:creator>
      <pubDate>Sat, 19 May 2018 08:26:15 +0000</pubDate>
      <link>https://dev.to/shobhitic/monitor-your-https-certificate-expiry-with-this-script-1k02</link>
      <guid>https://dev.to/shobhitic/monitor-your-https-certificate-expiry-with-this-script-1k02</guid>
      <description>&lt;p&gt;Last year's new years eve, I got a call from my client. They said their website was infected by a virus and no one can access it.&lt;/p&gt;

&lt;p&gt;Now, my client runs a juice shop, and had no idea about how the web technically works, so I discarded the "virus" issue but he said site can't be accessed so I fired up Firefox in my phone and I saw the &lt;code&gt;Your connection is not secure&lt;/code&gt; page.&lt;/p&gt;

&lt;p&gt;Ever since Let's Encrypt came out of beta, I've used it to convert all my and my clients' sites to secure connections via HTTPS. I had set up a cron as instructed by &lt;a href="https://certbot.eff.org/" rel="noopener noreferrer"&gt;certbot&lt;/a&gt; to renew the certificates regularly, but it used to fail every once in a while because I didn't update the python packages, or something like that. Let's Encrypt is kind enough to send a mail before expiring, but initial installations were done by an employee.&lt;/p&gt;

&lt;p&gt;Since it was 31st of December, I was at a party and no where near my machine with which I could ssh into the server and slay this beast. I had JuiceSSH on my phone using which I SSHed into the server (thank god I had added my keys as authorized), updated the packages and renewed the certificates.&lt;/p&gt;

&lt;p&gt;All this while people around me were counting backwards from 10.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not taking a pledge
&lt;/h2&gt;

&lt;p&gt;This wasn't even the first time this was happening so I decided then and there that I am going to solve this problem for myself. I carefully chose not to make it my new year's resolution otherwise I'll be telling the same story next year.&lt;/p&gt;

&lt;p&gt;So on 1st January, I wrote a Ruby script (more about which in a minute) and kept improving it to catch all sorts of red flags with HTTPS installations including if a certificate is revoked, affected by the &lt;a href="https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html" rel="noopener noreferrer"&gt;Symantec mess&lt;/a&gt;, is self-signed or is past/near the expiry date, validating the chain of trust, etc. The script eventually converted into a nice little piece of web app called &lt;a href="https://monitorcertificates.com/" rel="noopener noreferrer"&gt;Monitor Certificates&lt;/a&gt;, but let's get back to talking about the script now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting the certificate
&lt;/h2&gt;

&lt;p&gt;First thing you'll need to do is procure the certificate from a domain. Surprisingly, this was difficult to achieve. I am a big fan of &lt;a href="https://github.com/jnunemaker/httparty/" rel="noopener noreferrer"&gt;&lt;code&gt;HTTParty&lt;/code&gt;&lt;/a&gt; for making requests with Ruby, but unfortunately I couldn't find a way to get it to return certificates.&lt;/p&gt;

&lt;p&gt;So I went one layer down the abstraction and used &lt;code&gt;Net::HTTP&lt;/code&gt;. To get a certificate, you have to run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'net/http'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'openssl'&lt;/span&gt;

&lt;span class="n"&gt;domain_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"example.com"&lt;/span&gt;

&lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTPS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;host: &lt;/span&gt;&lt;span class="n"&gt;domain_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:use_ssl&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;peer_cert&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you an object of certificate in the &lt;code&gt;cert&lt;/code&gt; variable. This variable is of the type &lt;code&gt;OpenSSL::X509::Certificate&lt;/code&gt;. These are called &lt;a href="https://en.wikipedia.org/wiki/X.509" rel="noopener noreferrer"&gt;X.509 certificates&lt;/a&gt;, and they are the standard for public key certificates.&lt;/p&gt;

&lt;p&gt;X.509 certificates give us a lot of details about the certificate including who issued it, when it was issued, when it will expire, how to find if it is revoked, and a plethora of other useful information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding the expiry dates
&lt;/h2&gt;

&lt;p&gt;To find the date when the certificate will be invalid, you just need to call &lt;code&gt;cert.not_after&lt;/code&gt;. This returns a Time object which tells us when the certificate will expire.&lt;/p&gt;

&lt;p&gt;So if you want to be notified everyday for 2 weeks before the certificate is supposed to expire, your script will look like -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'net/http'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'openssl'&lt;/span&gt;

&lt;span class="n"&gt;domain_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"example.com"&lt;/span&gt;

&lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTPS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;host: &lt;/span&gt;&lt;span class="n"&gt;domain_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:use_ssl&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;peer_cert&lt;/span&gt;

&lt;span class="n"&gt;two_weeks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;86400&lt;/span&gt; &lt;span class="c1"&gt;# 14 * One Day&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;two_weeks&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;not_after&lt;/span&gt;
  &lt;span class="c1"&gt;# send reminders&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reminding your self
&lt;/h2&gt;

&lt;p&gt;You can use lots of things to send these reminders. I've now implemented SMS, Emails (to multiple people), Slack and Stride in &lt;a href="https://monitorcertificates.com" rel="noopener noreferrer"&gt;my app&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have some friends who use this script to push mobiles notifications to themselves (using Pusher), web notifications, geckoboard updates, adding to To-Do lists, adding to trello boards, etc. Any communication platform is fair game.&lt;/p&gt;

&lt;p&gt;For example, if you're on a Mac, there's a &lt;a href="https://apple.stackexchange.com/questions/57412/how-can-i-trigger-a-notification-center-notification-from-an-applescript-or-shel/115373#115373" rel="noopener noreferrer"&gt;neat little command&lt;/a&gt; you can use to send a notification to yourself.&lt;/p&gt;

&lt;p&gt;So I'll incorporate that command in our script to send us notifications.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'net/http'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'openssl'&lt;/span&gt;

&lt;span class="n"&gt;domain_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"example.com"&lt;/span&gt;

&lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTPS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;host: &lt;/span&gt;&lt;span class="n"&gt;domain_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:use_ssl&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;peer_cert&lt;/span&gt;

&lt;span class="n"&gt;two_weeks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;86400&lt;/span&gt; &lt;span class="c1"&gt;# 14 * One Day&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;two_weeks&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;not_after&lt;/span&gt;
  &lt;span class="n"&gt;time_remaining&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;not_after&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;days_remaining&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time_remaining&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;86400&lt;/span&gt;

  &lt;span class="sb"&gt;`osascript -e 'display notification "Certificate for &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;domain_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; will expire in &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;days_remaining&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; days. Please renew soon." with title "&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;domain_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;"'`&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I removed the &lt;code&gt;if&lt;/code&gt; condition and ran the script and the output looks like this today &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1sje31dykunh9t1dky6p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1sje31dykunh9t1dky6p.png" alt="dev.to certificate expiry reminder" width="756" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now all you need to do is add it to your crontab and it'll keep reminding you when your certificates are getting close to renewal.&lt;/p&gt;

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

&lt;p&gt;Obviously, the script that I've shown you isn't the most elegant piece of software but it gets the job done. If you want to monitor multiple domains, just turn the script into a method and run the method against each element of your array of &lt;code&gt;domain_names&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We've just scratched the surface here but it's a solid start to build your monitoring infrastructure and more features here to make sure your certificate hasn't been revoked, or if it's a paid certificate, who is the issuer.&lt;/p&gt;

&lt;p&gt;I have added all this and more in &lt;a href="https://monitorcertificates.com" rel="noopener noreferrer"&gt;my app&lt;/a&gt; to help keep on top of HTTPS issues.&lt;/p&gt;

&lt;p&gt;Hope this was helpful for people like me who keep breaking their Let's Encrypt automation, or forgetting that a cert is up for renewal and management forgot to tell you that they are getting mails from vendors to issue a new one. 😁&lt;/p&gt;

&lt;p&gt;For the next post, would you like me to show you how browsers determine if a certificate they are receiving has been compromised or revoked?&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
      <category>ssl</category>
      <category>ruby</category>
      <category>monitoring</category>
      <category>devops</category>
    </item>
    <item>
      <title>Why I am not going to attend Hackathons anymore</title>
      <dc:creator>Shobhit🎈✨</dc:creator>
      <pubDate>Tue, 17 Apr 2018 13:25:57 +0000</pubDate>
      <link>https://dev.to/shobhitic/why-i-am-not-going-to-attend-hackathons-anymore-2896</link>
      <guid>https://dev.to/shobhitic/why-i-am-not-going-to-attend-hackathons-anymore-2896</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://www.pilanites.com/no-more-hackathons/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There was a Hackathon by our local government a few days back and the whole situation was insane. They almost brought me to tears.&lt;/p&gt;

&lt;p&gt;It was a 36-hour Hackathon and it felt like torture for the participants. Some of them fainted, some of burned out, and I could see the “passion for coding” vanish from their eyes.&lt;/p&gt;

&lt;p&gt;I had a follow-up discussion, two days after the event with the participants and most of them were of the opinion that they don’t want to code for some time. They burned out.&lt;/p&gt;

&lt;p&gt;Was it really worth it? If you kill yourself to haphazardly finish a project in X hours, and then burnout and be unproductive for the next month, is it really justified to do so?&lt;/p&gt;

&lt;h2&gt;
  
  
  Problems with Hackathons
&lt;/h2&gt;

&lt;p&gt;1. &lt;strong&gt;The toxic culture&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hackathons promote a toxic culture where you’re supposed to write code because you’re passionate about coding, in a highly caffeinated, intoxicated environment. This not how you work daily, in a sustainable manner.&lt;/p&gt;

&lt;p&gt;You need proper sleep to work well, and create something worthwhile, of good quality.&lt;/p&gt;

&lt;p&gt;You need good food in your stomach, and a clear focused mind to complete your project.&lt;/p&gt;

&lt;p&gt;Hackathons are the exact opposite of these. They provide you with access to lots of Pizza, Beer, and Coffee. Alcohol and Caffeine might help you focus in the short term, but they are diuretics and you lose more water in the long term.&lt;/p&gt;

&lt;p&gt;2. &lt;strong&gt;Exclusive&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s not really inclusive because only young developers, with no responsibilities and ample of free time can manage to participate.&lt;/p&gt;

&lt;p&gt;Women tasked with the household responsibility won’t be able to participate. Senior developers, with kids waiting for them don’t participate. Developers with back-pain, who are not allowed to sit for a long time, won’t participate.&lt;/p&gt;

&lt;p&gt;Only the naive junior developers, with no previous burnout experience are the people I’ve seen participating and enjoying Hackathons.&lt;/p&gt;

&lt;p&gt;3. &lt;strong&gt;Social and distractions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I can either code or I can be social and meet other people. I can’t do both at the same time, or else I won’t be able to do anything well.&lt;/p&gt;

&lt;p&gt;If you want me to socialize, create a social event where expectations are clear, and if you want me to code, create a distraction free environment. The current system doesn’t give me the freedom to focus on anything, consequently making it a waste of time.&lt;/p&gt;

&lt;h2&gt;
  
  
  In conclusion
&lt;/h2&gt;

&lt;p&gt;Hackathons really screw up your health and lead you to a burnout, mess with you sleep cycles, and create bad code quality. Most of the projects made in a hackathon go nowhere.&lt;/p&gt;

&lt;p&gt;As I start getting older (and hopefully wiser), I realize that a sustainable work rate is always better than this burst of code.&lt;/p&gt;

&lt;p&gt;Hackathon’s most powerful idea is to do focused work on something other than your daily job. I think that’s Hackathon organizers should embrace that, but their motives are very different.&lt;/p&gt;

&lt;p&gt;A Hackathon I’d like to organize would give people time constraint, and allow them to do other things during the event. Work for 8 hours on a new thing, and then done, go home.&lt;/p&gt;

&lt;p&gt;After all, Hackathons are a wordplay on Marathons, then why do they feel like an unsustainable sprint?&lt;/p&gt;

</description>
      <category>hackathon</category>
      <category>discuss</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
