Automating security updates on AWS and pushing the output to Slack


Hello there! My name is Adam, an aspiring DevOps engineer who joined the Infrastructure team of Linkbal this year in February. My main focuses are optimizing the AWS environments and the server middleware. Occasionally I will make something cool and useful, most likely involving AWS, which I would like to share with you.

Today, I will be detailing how to schedule a security update script to be run on an EC2 Linux instance on a time schedule, then push the output logs to a Slack channel for everyone to see.


First, let’s consider what we want to achieve, so as to determine what the end result should be:

  1. Automatically run security updates on an EC2 Linux instance on a pre-determined schedule.
  2. Be notified of the update and see the output in a Slack channel.
  3. Be able to change the time schedule or turn on/off without having to access the instance.

The 3rd point is important as it adds a layer of convenience to the method. If it ever becomes necessary to stop the updates, we want to be able to do so quickly and easily, without having to remove what we put in place.


  • AWS account with privileges to create a CloudWatch rule and use Systems Manager.
  • EC2 Linux-based instance with AWS CLI installed.
  • IAM role attached to the EC2 instance. 
  • Permission to access the EC2 instance via SSH connection and use root credentials.
  • A Slack account with a channel for receiving the output logs and the permission to create a webhook.

Plan and script

The source code originally came from here: Slack notification via curl
The diagram was drawn using a free account in LucidChart.

# This script runs a security update then pushes the output to Slack.

VAR1=$(sudo yum update --security -y)

function post_to_slack () {
    SLACK_URL={Slack web hook} # Replace this with your own web hook, without the braces

    case "$2" in

curl -X POST --data "payload={\"text\": \"${SLACK_ICON} ${SLACK_MESSAGE}\"}" ${SLACK_URL}
post_to_slack "Result of security update for $IP: $VAR1" "INFO"
exit 0


  1. Create a Slack web hook for the channel you want to receive the log output in. Paste the web hook into the script as the value for SLACK_URL (without the {} braces).
  2. Upload script to the instance (take a note of the path). This can be done from the command line as such:
    $ scp -i /path/to/key.pem ec2-user@{IPv4 DNS}:path/to/file
    Or you can SSH connect to the instance, make a new file and paste the code in there:
    $ ssh -i /path/to/key.pem ec2-user@{IPv4 DNS}
    $ vi /path/to/file/
    It doesn’t matter were the file goes, so long as you know where it is.
    Be sure to change the permissions on the script so that it can be executed.
    $ chmod 775 /path/to/file/
    Install the AWS SSM agent: (installed by default on AWS Linux 1 AMIs since 2017.9 and on all AWS Linux 2 AMIs)[Manually install SSM agent on Amazon EC2 Linux instances]
    Add the policy “AmazonEC2RoleforSSM” policy to the role being use by the EC2 instance.
  3. Go to CloudWatch, select “Rule” on the left toolbar and then “Create rule”. Set the time expression by either a fixed rate or a cron expression. Note that the time will be in UTC, so depending on your timezone you will need to adjust the hour and possible day values. As an example, to update at 2am UTC Monday-Friday, the expression would be:
    0 2 ? * MON-FRI *
    For help with cron expressions in AWS, please see: AWS CloudWatch – How to schedule events
    Select “SSM Run Command”.
    Select the document “AWS-RunShellScript (Linux)”
    Target key = InstanceIds (can choose a different target, if you prefer)
    Target values = {Instance ID} i.e. i-a1b2c3d4e5
    Click on the “Configure parameters” drop down.
    Commands = ./
    WorkingDirectory = /path/to/file/
    ExecutionTimeout = 100
    Select “Create a new role for this specific resource”
    Click on “Configure details”. Give it a name and a description.
  4. The CloudWatch Rule uses AWS Systems Manager to call the SSM Agent which runs the script.  The script will run the update, then pass the output to a post function which uses the Slack web hook to post the output in your channel.
    Even if there are no updates due, the message will still be sent.
  5. Success! You can customize the name and image of the web hook in the Slack settings menu.



We have now configured for security updates to run on the AWS EC2 Linux instance on a specific time schedule, with the result of the update being sent to a channel in Slack. The script can be turned on/off easily from the AWS console (or by the AWS CLI) and we can change the time schedule there as well.
Let us now consider the advantages and disadvantages of this method.


  • Quick and simple to set up.
  • The script is reusable; can be used on most if not all Linux instances on AWS. Only the Slack web hook would have to be changed if a different channel was required, otherwise no need to edit the script.
  • Only a basic understanding of AWS is required.
  • Virtually zero cost.


  • CloudWatch rule must be stopped manually. Could set up a trigger with SMS and Lambda to stop the rule without the need for human intervention.
  • Only works for Linux instances. Windows would require something different.
  • Root privileges are required to set up (possibly avoidable with AWS Systems Manager).
  • Would be easier to understand if more details concerning the instance were put into the script, such as the name tag. (Can use ec2-metadata to obtain a lot of this information, but tags are not included in this list. Could use AWS CLI to get the instance name tag.)

Overall we have achieved what we set out to do. There are ways we could improve the script, but for now this is more than suitable.

I hope you have enjoyed this post, it’s a simple start with many more things to come. See you next time!


  1. Source code:
  2. LucidChart:
  3. AWS CloudWatch – How to schedule events:
  4. AWS EC2 – Manually install SSM Agent on AWS EC2 Linux instance:
  5. Manually install SSM agent on Amazon EC2 Linux instances :









Progressive Web Apps – Part 1


Hi! I’m Dennis and I’ve been working at Linkbal as a software engineer since October 2017.

This is the first part in a series of articles about Progressive Web Apps or PWAs. I am currently taking the following course at Udemy and I am writing these articles to help me consolidate the earned knowledge: Progressive Web Apps (PWA) – The Complete Guide

What are Progressive Web Apps

As you can notice by reading articles such as Seriously, though. What is a progressive web app?, it is very difficult to describe what a PWA actually is, but I will give it a try.

Progressive Web Apps (PWAs) are web applications that behaves like native mobile applications. They do so by using a set of techniques and technologies to provide end-users with features they usually find on native apps, such as:

  • Background synchronization
  • Push notifications
  • Offline accessibility
  • Location based behavior
  • Device camera access
  • Application shortcut in the home screen

It’s difficult to define PWAs as there is not a single specific criteria to consider an app a PWA, so it is even more difficult (if not impossible) to call an app a “perfect” PWA. Because some of the recommended enhancements rely on modern web browser capabilities and new capabilities will surely create new recommended enhancements in the future, I believe it is not absurd to consider the goal of a “perfect” PWA unattainable. Not only that, but depending on the nature of your application, implementing some of the enhancements proposed for PWAs may not even make sense.

That said, as written in the article mentioned previously, there are three baseline criteria to qualify an app as a PWA:

  1. It must run under HTTPS.
  2. It must include a Web App Manifest.
  3. It must implement a service worker.

The first criteria is quite straightforward and we will cover the other two later.

I’m not sure if it’s completely accurate to consider an app a PWA once these three criterias are satisfied, but I like to think so, as it gives us an objective way to make this judgement. Even after we can call our app a Progressie Web App, we will always be striving to reach the goals proposed for PWAs, such as making our apps more reliable, faster and more engaging [1].

Core Building Blocks

Now that we have an idea of what Progressive Web Apps are, let’s take a look at their core building blocks, or the core techniques and technologies we need to use to build a PWA.

Service Workers

Service workers are basically JavaScript code that runs in a background process, separately from the main browser thread, even if the application is not open in the browser. It is a technology well supported by modern web browsers 2 and a building block that provides a lot of the features that PWAs can provide.

Service workers can intercept network requests and cache those requests to improve performance. This cache can then also be used to provide offline access when the network is not available [3].

Because they run in the background, they are capable of providing some features that make web applications work like native apps, such as:

  • Background Sync
  • Push Notifications

Other Characteristics

There are a couple more characteristics to service workers that are consequences of their role in a PWA and the fact that they are independent from the application they are associated with:

  • Because a service worker is not blocking, synchronous XHR and localStorage cannot be used.
  • Service workers can’t access the DOM directly, so they need to use a messaging system to communicate with the page.
  • As they can intercept network requests and modify responses, service workers only run over HTTPS to prevent “man-in-the-middle” attacks.
  • Service workers become idle when not in use and restart when needed.

Application Manifests

An application manifest makes it possible for a web application to be added to mobile device homescreens. It is a simple JSON file that also describes how it should behave when “installed”. Among other things, it specifies the icon to be used, the URL to access when the app is launched and the background color of the splash screen displayed while the app is loading.

Responsive Design

At this point, responsive web design is a topic that does not need introduction, but it can be considered a core bulding block of PWAs because one of the goals is to create an application that fits any form factor [4].

PWAs and SPAs (Single Page Applications)

There’s one important confusion that is frequently seen regarding SPAs and PWAs, that the techniques and technologies to progressively enhance web applications to turn them into PWAs can only be applied to single page applications. The reality is that any web application can become a progressive web app no matter it is a SPA or a traditional multiple pages application.

Application Manifests

An application manifest is a JSON file that describes how a web app should behave once it is “installed” in the user’s device. For example, the browser uses that information to determine the icon to display when the application is added to the device’s homescreen.

Adding a Manifest File

Adding a manifest file to a project is as simple as creating a file named manifest.json and linking it in the “ of all the pages of the web app:

<link rel="manifest" href="/manifest.json">

Content of the Manifest File

Below, there’s an example content for an application manifest file:

  "name": "PWApp - Progressively Enhanced App",
  "short_name": "PWApp",
  "start_url": "index.html",
  "scope": ".",
  "display": "standalone",
  "background": "#5cb4f7",
  "theme_color": "#5cb4f7",
  "description": "A web app progressively enhanced to become a PWA",
  "dir": "ltr",
  "lang": "en-US",
  "orientation": "portrait",
  "icons": [
      "src": "/assets/images/icons/icon-36.png",
      "type": "image/png",
      "sizes": "36x36"
      "src": "/assets/images/icons/icon-48.png",
      "type": "image/png",
      "sizes": "48x48"
  "related_applications": [
      "platform": "play",
      "url": "",
      "id": "com.example.app1"
      "platform": "itunes",
      "url": ""
  • name: specifies a long name for the app, displayed in the app install prompt[5], for example.
  • short_name: short name for the app that may be used, for example, in a device homescreen where there is insufficient space to display the full name.
  • start_url: URL that is loaded when the app is launched through the icon added to the homescreen.
  • scope: determines the pages the application manifest applies to. “.” applies to all pages.
  • display: defines the preferred display mode for the website [6]. Using standalone will make the app look and feel like a standalone app, for example.

A PWA launched browser mode (left), standalone mode (middle) and fullscreen mode (right). Image: New in Chrome 58

  • background_color: sets the background color used in the splashscreen displayed while the app is loading.
  • theme_color: this color is shown, for example, in the browser toolbar and in the top bar on Android’s task switcher, what increases the sense of OS integration even more.
  • description: this field is used whenever the browser needs some description for an app.
  • dir: specifies the text direction for name, short_name and description.
  • lang: together with lang, it helps to display right-to-left languages.
  • orientation: sets the default orientation, but bear in mind users prefer selecting the orientation themselves.

Portrait and landscape orientation options for the app manifest. Image:The Web App Manifest

  • icons: icons to be displayed in the homescreen. Multiple icons with different sizes can be provided in the array and the browser will determine the “best” icon depending on the device.
  • related_applications: array of native applications that can be installed through the applications stores of the respective platforms.


In this first part of the series about the course on PWAs I am taking on Udemy, I tried to define what Progressive Web apps are, presented their building blocks and an introduction to application manifests. In the next part, we are going to go deeper into the subject of application manifests and start talking about service workers.


  1. Progressive Web Apps – Google Developers
  2. Service Workers – Can I use
  3. Introduction to Service Worker – Google Developers
  4. Your First Progressive Web App
  5. The Web App Manifest – Google Developers
  6. Web App Manifest #display – MDN

Host a Website on GitHub with Jekyll – Part 1

Hi! I’m Dennis and I’ve been working at Linkbal as a software engineer since October 2017. In Part 1 of this article, I will introduce Jekyll and show how to create a new website and make it available publicly.


Jekyll is an open-source static site generator. Its GitHub repository README shows a very simple description: “Think of it like a file-based CMS, without all the complexity.” With Jekyll, we can create our website structure using HTML, CSS and Liquid Templates. After the structure is in place, we can focus on updating the website’s content, by just creating files using Markdown.

It is an intermediate solution that sits between static websites and web applications. We can add a little bit of dynamic behavior when generating the website but, in the end, it is served as a completely static website.

Jekyll is also the engine behind GitHub Pages, which can be used to host websites from GitHub repositories. Because we are not dealing with a database, updating a website is a matter of editing files and pushing the changes to GitHub,  This article is an introduction on how to work with Jekyll to create a website and how to host it on GitHub Pages.

Repository Creation

Our final goal is to have our website hosted on GitHub Pages. To achieve this, we need to upload our Jekyll project to a GitHub repository. We can have a exclusive repository for our website, but we can also store our project source in a folder of an existing repository. This last option is particularly useful for creating documentation websites for open-source software projects as it allows us to manage both the project and its documentation sources as a single project, making it easier to keep the later updated.

In this article, I am going to create a repository called ‘jekyll_website’ to be used exclusively to host the website by following the steps in the following link:

Jekyll Installation

In this article, I won’t cover Jekyll’s installation process. It is very well documented in the Jekyll documentation and I assume you are going to follow that, but I will try to present some guidelines. I also assume you have a working Git installation.

Jekyll is distributed as a Ruby Gem and can be installed on most systems. It is recommended to work on a Unix-based system such as macOS or Linux, but you should not have problems working on Windows as well. By the way, this article was written on a Windows machine with Windows Subsystem for Linux enabled. You can take a look at the official documentation if you choose to go this path too.

Whatever system you choose to work on, the requirements are the same. You are going to need to have Ruby, RubyGems and build tools (GCC and Make) installed. If you, like me, are a Rails developer and already have a Ruby development environment installed, you should be good to go after installing Jekyll with the following commands (we are also installing bundler, a gem that helps us manage other Ruby gems in our project):

$ gem install jekyll bundler

New Project

Now, we are going to create a new Jekyll project:

$ jekyll new jekyll_website --skip-bundle

We passed the option --skip-bundle because we don’t want to install our dependencies system-wide. Instead, we want the installation of our dependencies to be limited to our project. But first, as we know we are going to host our website on GitHub, we want to setup up our project accordingly. First, open the Gemfile file created on your project’s root folder.

And remove the line declaring the dependency of the jekyll gem. It may differ depending on the version of the software you are working with, but in my case, I removed the following line:

gem "jekyll", "~> 3.6.2"

And uncomment the following line:

# gem "github-pages", group: :jekyll_plugins

Dependencies Installation

We can now install or dependencies locally with the following command:

$ cd jekyll_website

$ bundle install --path vendor/bundle

Local Server Startup

After that we can serve our website with the following command:

$ bundle exec jekyll serve

But, it’s highly recommended to use the command below instead:

$ bundle exec jekyll serve --livereload

This way the website will automatically build and reload each time changes are saved. This is particularly useful when we are writing articles and want to see how it is looking. You can stop the jekyll process at any time by pressing “Cmd (Ctrl) + C”.

Just open a browser and access the following address:


Great! We already have a working website. You can see Jekyll comes with a pre-defined look & feel. Jekyll supports themes and it uses a theme called minima by default. You can check this fact by opening the Gemfile file, where there is a line setting the minima gem as a dependency:

gem "minima", "~> 2.0"

In this article, I will show you some examples on how we can start customizing our website. Although we can start our website from scratch, without a theme at all, it is probably easier to have a starting point, at least when using Jekyll for the first time.

But, before that, let’s add our website to GitHub to manage the changes in our website. You will see that, in the case of a Jekyll website, adding the project to GitHub not only means that we are controlling its versions, but also means that we are deploying our website for public access.


To start the deployment process, let’s first enable GitHub Pages. To do so, access the settings of your repository and scroll to the GitHub Pages section. Let’s change the Source option from “None” to “master branch”. By doing that, GitHub will run Jekyll to build the website and serve it whenever we push changes to the master branch.

Now we can push our project to GitHub. But, before doing that, let’s edit our .gitignore file. The Jekyll project already comes with a .gitignore to prevent unnecessary files to be commited. But, as installing the gems locally is an optional step, it does not include entries to ignore the installed packages. So, let’s add the following lines to the .gitignore file:



Now we can push our files to GitHub as usual:

$ git init
$ git add .
$ git commit -m "First commit"
$ git remote add origin
$ git push -u origin master


You can now access your website at the URL provided by GitHub. In my case, it is: If you still can’t see your website, it may take some time for GitHub to build it.

Creating a Post

Now that we have a website running, we can create our first blog post. To do so, add a new file to the _posts folder. I will name it “2019-02-28-my-first-post.markdown”.

The first thing we need to do then is to add the front matter section to this file. It is YAML block containing some metadata about our post. Let’s add the lines below to the file:

layout: post
title: "My First Post!"
date: 2019-02-28 08:26:44 +0900
categories: first post

After that, we just need to write our post using markdown syntax. Jekyll uses kramdown as its markdown converter. Let’s just add some content to test it:

A **formatted** line of *text*.

> A nice blockquote

## Code

{% highlight ruby %}
puts ‘Hello Jekyll!’
{% endhighlight %}

You should be able to see the new posted listed in the home page and access its content.


In this article we could see how to create a new Jekyll website and make it available for the public. In the part 2 of the series, I am going to show some examples on how we can use some of Jekyll’s features to customize our website structure.







数学は、高校数学の微分積分を半分くらいしか復習できなかったものの、log x を微分すると 1/x になる、という程度は思い出せた。ちなみに、いまお世話になっている数学の教科書は、これだ。



GitLabの導入(Backlog + GitHub からの移行)

いま、社内に GitLab を導入中です。数ヶ月かけて、これまで利用していた Backlog と GitHub を、GitLab に置きかえていく予定です。

Backlog は課金額がユーザ数に依存しません。そこで、いろいろな人が関わる課題管理には Backlog を利用しています。過去の履歴を見ると、2013年から 5年以上もお世話になっています。現在のアクティブユーザー数は120名ほど。

一方 Backlog の Gitリポジトリ機能はそれほど魅力的ではないため、コード管理には GitHub を利用しています。しかし GitHub はユーザ毎にお金がかかるため、コードを書く人に限定して使っています。現在のアクティブユーザー数は50名ほど。



  1. 誰かが「○○をやりたい」と提案する。誰が何を提案してもいい。要点をまとめて Backlog に proposal(提案)として登録する。
  2. やるか、やらないか、優先度はどうするか、を毎朝のミーティングで決める。
  3. やることになった案件は planning(企画)フェーズに移行し、ディレクター、デザイナー、エンジニアなど案件毎に適切な人が仕様を決める。
  4. planningフェーズの仕様をレビューして問題がなければ、dev フェーズに移行させる。課題の優先度は毎朝の会議で決める。
  5. 優先度高の課題の中から好きなものを、手が空いたエンジニアが自分で取っていく。
  6. 開発が終わったら、提案者やディレクターがテストする。問題がなければリリース待ちとなる。
  7. リリースする。「街コンジャパン」の場合、少ない日で 1件、多い日で 10件くらいのリリースをする。ただし、売上が一番多いのが土日祝であるため、休みの前日のリリースはなるべく避ける。

開発組織の育て方 – エンジニア3人から30人へ



当時、うまくいかなかった要因はいくつもありました。年間数十億円を販売するECサイトなのに WordPress で作られているから関心を示すエンジニアが少ない。「チャラい若者で溢れる出会い系企業」だから自分には合わないとエンジニアから敬遠される。当時の人事部が問題を抱えていて人材紹介会社からの評判が悪かった。超絶技巧的に WordPress を使いこなしていた影響で、保守だけで精一杯になり、新しいことに目を向ける余裕がなかった、など。


AWS re:Invent 2018 参加レポート : 海外カンファレンスについて

リンクバル技術部の川畑です。AWS re:Invent 2018の全日程が終了しました。。
ちなみに私は海外カンファレンスはAWS re:Inventしか参加したことないので、AWS re:Invent寄りの内容になることをご了承ください。


AWS re:Invent 2018 参加レポート : 4日目

リンクバル技術部の川畑です。AWS re:Invent 2018に参加するためラスベガスに来ています。本日もKeynoteでLambdaでのRubyサポート、そしてCOBOLも使えるようになるなど衝撃的な新サービスの発表がありました。
本日はそのLambdaのセキュリティ観点を学ぶために「Securing Serverless Applications and AWS Lambda」というワークショップを受けてきたので、その内容を簡単に共有させて頂きます。


AWS re:Invent 2018 参加レポート : 3日目

リンクバル技術部の川畑です。「AWS re:Invent 2018」に参加するためラスベガスに来ています。Amazon Web ServicesのCEO Andy Jassy氏による Keynote に参加してきました。毎年新たなサービスが発表されるのが恒例となっているようです。朝8時に開始にもかかわらず、朝7時に到着した時点ではすでに300メートルの10列ぐらいの行列ができていました。それでも何とか中にはスムーズに入ることができました。この辺りの誘導は手慣れたものだなと思いました。