「Hacker's GATE Presents サービス品質向上しナイト ~みんなでテスト!10年続くチームと品質~ 」を開催しました

どうも!Hacker's GATE運営の石川です。

昨日、株式会社チームスピリットさん、株式会社ウエディングパークさんと共同で、「Hacker's GATE Presents サービス品質向上しナイト ~ みんなでテスト!10年続くチームと品質 ~」を開催しました。 この記事では当日のイベントの模様をお届けします。

willgate.connpass.com

開催の主旨

プロジェクトの規模が小さい状態だと、個人の力量でカバーできたサービスの根幹を支えるサービスの品質も、サービス規模や組織の拡大など、様々な要因で属人化してしまい、品質の担保が難しくなった、といった課題を感じている方もいるのではないでしょうか。

そこで、各社の仕組みや体制づくりなど、自社の経験を役に立ててほしい、という思いで、今回のイベントを開催しました。

当日の様子

3社の組織的な取り組みやQAの仕組み、応募した質問からパネルディスカッションを開催しました。

株式会社ウエディングパーク 斉藤 健太さん

「ウェディングメディアを支えるQAチームの取り組み」

f:id:char1129:20190214150215j:plain

斉藤さんの発表では、開発組織におけるQAチーム発足以前のこと、発足後の導入のお話をしていただきました。 発表中、仕様理解からの改善というアプローチをプロジェクト化して、開発時の品質向上につながったことが印象的でした。 関係各所だけでなく、役員含め関わる人すべてに理解を持ってもらうことで、全員の理解向上、品質が改善する素晴らしい取り組みですね!

f:id:char1129:20190214160637j:plain

当日のスライド speakerdeck.com

株式会社ウィルゲート 鶴飼 吉行

「品質向上に向けた組織改革と成功失敗例」

続いて、ウィルゲートの品質向上に向けた開発での取り組みについて発表をしました。

f:id:char1129:20190214160657j:plain

f:id:char1129:20190214160712j:plain

発表では、2016年当初の開発組織としての課題について、組織としての動きの説明。 各セクションごとの成功・失敗例とともに、説明させていただきました。 この取り組みについては後日記事にしてお届けしようと考えております。

当日のスライド

speakerdeck.com

株式会社チームスピリット 生井 龍聖さん

「チームスピリットにおける品質保証の仕組み」

f:id:char1129:20190214160734j:plain

最後の登壇は、生井さん。 QA組織としての継続的な取り組みや体制作りについてお話しいただきました。 QAの未来像であったり、状況に応じた適応であったり、というのは体制を整えても難しい課題なんですね。

f:id:char1129:20190214160749j:plain

当日のスライド speakerdeck.com

パネルディスカッション

f:id:char1129:20190214160907j:plain

パネルディスカッションでは、事前に募集したアンケートからテーマをピックアップ、登壇してくださった3名に質問してみました。

当日のディスカッションテーマごとに、当日のツイートからまとめてみました。

属人化からの脱却で失敗したエピソード

各社の失敗談いろいろありますね。 やはり、足並みを揃えるときが必要そうですね。

テーマあえて属人化した状態を容認することは?

属人化の許容は、初めは許容しているというWGの回答とともに、ツイッター上でも同じような声がいくつか上がっていました。 ただ、属人化が進めないような仕組みが大切になってきますね。

QA チームとして課題に直面したときに判断軸として大事にしている考え方

f:id:char1129:20190214160849j:plain

ここではチームスピリット・生井さんの障害に対する重要度や発生頻度の考え方について、ツイッター上で多くの共感の声が上がってました。

そして、斉藤さんが行った過去2年分の分析というのはすごいですね。

テストエンジニアやQA はどのようなキャリアパスを描ける?

どのフィールドにおいても、品質を担保できるエンジニアが求められるのはみんな共通の考えなのでしょう。

そして、こんな質問に。

QAを担う人たちの評価がこの時間のトレンド、前日に開催された勉強会でも話題になっていたんですね。

生井さん曰く、テストフェーズにおけるサイクルを評価に加えているようで、現在この評価方法に納得して取り組んでいるということです。

懇親会

f:id:char1129:20190214160936j:plain

f:id:char1129:20190214160953j:plain

懇親会の様子

発表・パネルディスカッションの熱気を保ったまま、懇親会が始まりました。 改めて、品質保証に関するトピックに興味関心ある人が集まった会だったため、各社の取り組みや、チャレンジ、課題相談など、素晴らしい交流の時間になりました。

私自身、懇親会で聴講していた方とお話しさせていただいて、QAの部署の評価について興味があって参加した人や、品質の改善に向けた組織的な取り組みに興味ある人が多い印象で、 有意義な会だったという声をいただけました。

最後に

今回「Hacker's GATE Presents サービス品質向上しナイト ~みんなでテスト!10年続くチームと品質~ 」にご参加いただいた、みなさま、ありがとうございました。 参加していただいた方に「よかった」「いい会だった」という声が多く聞けて、運営として嬉しく思います。

また当日会場を利用させていただいた株式会社チームスピリットさん、 イベント開催にご協力いただいた株式会社ウエディングパークさん、 ご登壇いただいた、斉藤さん、生井さん、ありがとうございました!

Hacker's GATEでは引き続き、エンジニアがワクワクするような、技術交流の場やイベントを提供できるよう、活動していきます。 今後の活動についてもTwitterで告知していきますので、ぜひフォローしてみてください! twitter.com

SAML 2.0 + LDAP + AWSで複数アカウントのSSOを実現した話

はじめに

こんにちは! インフラチームの高畑です。 最近インフルエンザが流行っていて毎年かかっている私も、もうすぐかかるのではないかと日々怯えながら過ごしています。

今回は SAML 2.0 ID プロバイダ(IdP) と LDAP を連携して複数アカウントで管理している AWS の SSO(シングルサインオン)化についてお話しします!

これまで何が問題だったのか

これまで弊社では AWS コントロールパネルへのログイン情報を社内サーバを使ってオンプレで運用している社内専用 wiki で管理しており、都度該当のアカウント情報をコピーしてログインを行なっていました。

そのため、法令停電などの影響で wiki を見ることができずコントロールパネルに入れないという問題や、サービス毎に AWS のアカウントを分けているため、今後もアカウントが増え続け管理が大変になるといった問題もありました。

これらの問題を解決するため、SAML 2.0 IdP (今回は SimpleSAMLphp を使用)を構築して、元々社内でアカウント管理に使用していた LDAP サーバ と連携した SSO を実現しようと動き出しました。

SAML 2.0 IdP / SP の構築

f:id:tkhttty:20190121152652p:plain
SAML 対応のシングルサインオンについて処理の流れ

SimpleSAMLphp について

SimpleSAMLphp とは、 IdP や サービスページ( SP )を構築できる OSS です。 PHP + Web サーバが動作する環境であれば構築ができ、別途ミドルウェアが立ち上がったりもしないため手軽に導入することができます。

github.com

SimpleSAMLphp のインストール

ダウンロードページより最新版( 2019/01/17 時点での最新版は 1.16.3 )を入手してサーバに配置してください。

[root@hostname ~]# tar xvzf simplesamlphp-1.16.3.tar.gz
[root@hostname ~]# mv simplesamlphp-1.16.3 /var/www/simplesamlphp

SimpleSAMLphp 初期設定

[root@hostname ~]# vim /var/www/simplesamlphp/config/config.php
// SimpleSAMLphp の IdP 機能を有効にする
:
    'enable.saml20-idp' => true,
:

IdP 証明書を作成

[root@hostname ~]# openssl req -newkey rsa:2048 -new -x509 -days 3652 -nodes -out server.crt -keyout server.pem
Generating a 2048 bit RSA private key
............................................+++
.............+++
writing new private key to 'server.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:国名
State or Province Name (full name) []:都道府県名
Locality Name (eg, city) [Default City]:市名
Organization Name (eg, company) [Default Company Ltd]:組織名
Organizational Unit Name (eg, section) []:部署名
Common Name (eg, your name or your server's hostname) []:IdPドメイン
Email Address []:メールアドレス
 
[root@hostname ~]# mv server.* /var/www/simplesamlphp/cert/

証明書、認証方法の設定

[root@hostname ~]# vim /var/www/simplesamlphp/metadata/saml20-idp-hosted.php
:
        'privatekey' => 'server.pem',
        'certificate' => 'server.crt',
:
        'auth' => 'ldap',
:

接続先LDAPの設定

LDAPに関する設定を /var/www/simplesamlphp/config/authsources.php に追記

[root@hostname ~]# vim /var/www/simplesamlphp/config/authsources.php
: //↓新規追加
    'ldap' => array(
        'ldap:LDAP',
 
        // Give the user an option to save their username for future login attempts
        // And when enabled, what should the default be, to save the username or not
        //'remember.username.enabled' => FALSE,
        //'remember.username.checked' => FALSE,
 
        // The hostname of the LDAP server.
        'hostname' => 'ldaps://LDAPドメイン',
 
        // Whether SSL/TLS should be used when contacting the LDAP server.
        'enable_tls' => FALSE,
 
        // Whether debug output from the LDAP library should be enabled.
        // Default is FALSE.
        'debug' => FALSE,
 
        // The timeout for accessing the LDAP server, in seconds.
        // The default is 0, which means no timeout.
        'timeout' => 0,
 
        // The port used when accessing the LDAP server.
        // The default is 389.
        'port' => port,
 
        // Set whether to follow referrals. AD Controllers may require FALSE to function.
        'referrals' => TRUE,
 
        // Which attributes should be retrieved from the LDAP server.
        // This can be an array of attribute names, or NULL, in which case
        // all attributes are fetched.
        'attributes' => NULL,
 
        // The pattern which should be used to create the users DN given the username.
        // %username% in this pattern will be replaced with the users username.
        //
        // This option is not used if the search.enable option is set to TRUE.
        'dnpattern' => 'uid=%username%,ou=people,dc=example,dc=org',
 
        // As an alternative to specifying a pattern for the users DN, it is possible to
        // search for the username in a set of attributes. This is enabled by this option.
        'search.enable' => TRUE,
 
        // The DN which will be used as a base for the search.
        // This can be a single string, in which case only that DN is searched, or an
        // array of strings, in which case they will be searched in the order given.
        'search.base' => 'Base DN',
 
        // The attribute(s) the username should match against.
        //
        // This is an array with one or more attribute names. Any of the attributes in
        // the array may match the value the username.
        'search.attributes' => array('uid'),
 
        // Additional LDAP filters appended to the search attributes
        'search.filter' => '特定の属性を持っていれば許可する等のフィルタを記述',
 
        // The username & password the SimpleSAMLphp should bind to before searching. If
        // this is left as NULL, no bind will be performed before searching.
        'search.username' => 'Bind DN',
        'search.password' => 'password',
 
        // If the directory uses privilege separation,
        // the authenticated user may not be able to retrieve
        // all required attribures, a privileged entity is required
        // to get them. This is enabled with this option.
        'priv.read' => FALSE,
 
        // The DN & password the SimpleSAMLphp should bind to before
        // retrieving attributes. These options are required if
        // 'priv.read' is set to TRUE.
        'priv.username' => NULL,
        'priv.password' => NULL,
 
    ),
:

SP 側の設定

[root@hostname ~]# vim /var/www/simplesamlphp/config/authsources.php
:
    'default-sp' => array(
:
        'entityID' => 'https://SPドメイン/simplesaml/module.php/saml/sp/metadata.php/default-sp',
        'idp' => 'https://IdPドメイン/simplesaml/saml2/idp/metadata.php',
:

管理画面ログイン用アカウントのパスワードを変更

[root@hostname ~]# vim /var/www/simplesamlphp/config/config.php
:
    'auth.adminpassword' => 'P@ssw0rd',  // 初期値123
:

Apache の設定をする

[root@hostname ~]# vim /etc/httpd/conf.d/vhost.conf
<VirtualHost *:443>
    ServerName IdPドメイン
    DocumentRoot /var/www/simplesamlphp/www
 
    ErrorLog /var/log/httpd/idp-error.log
    CustomLog /var/log/httpd/idp-access.log combined
 
    Alias /simplesaml /var/www/simplesamlphp/www
</VirtualHost>
 
<VirtualHost *:443>
    ServerName SPドメイン
    DocumentRoot /var/www/simplesamlphp/www
 
    ErrorLog /var/log/httpd/sp-error.log
    CustomLog /var/log/httpd/sp-access.log combined
 
    Alias /simplesaml /var/www/simplesamlphp/www
</VirtualHost>

https://SPページのドメイン/simplesaml にアクセスができればOKです!

【管理者ユーザID】admin

【パスワード】設定したもの

管理者ログインできることも確認しましょう!

IdP、SP のメタデータを設定

(1) 上記URLより管理者でログイン

(2) 連携タブを開くと下図のようになっているか確認

f:id:tkhttty:20190121160128p:plainSAML 2.0 SP メタデータ」と「SAML 2.0 IdP メタデータ」の両方が表示されていない場合は設定が抜けているので再確認しましょう!

(3) それぞれのメタデータをコピーし、「XML を SimpleSAMLphp メタデータに変換」から変換し、

IdPメタデータ → /var/www/simplesamlphp/metadata/saml20-idp-remote.php

SPメタデータ → /var/www/simplesamlphp/metadata/saml20-sp-remote.php

にそれぞれ記載

AWS 側での設定

(1) IAMのページからIDプロバイダーを作成

f:id:tkhttty:20190121160457p:plain

(2) プロバイダータイプは「SAML」、プロバイダ名は適宜、メタデータドキュメントはsimpleSAMLphpのメタデータを選択

f:id:tkhttty:20190121160616p:plain

(3) IAMロールを作成

SAMLプロバイダーは (2) で作成したプロバイダを選択し、「プログラムによるアクセスとAWSマネジメントコンソールによるアクセスを許可する」にチェック f:id:tkhttty:20190121160832p:plain

アタッチするポリシーでは「AdministratorAccess」を選択 ※実際には許可するポリシーを選択してください f:id:tkhttty:20190121161135p:plain

ロール名に分かりやすい名前を入力

SAML認証した後に表示されるロールの選択画面で表示される名前なので、サービス名など分かりやすい名前にしましょう! f:id:tkhttty:20190121161416p:plain

作成したロールの arn をコピーしておく(simpleSAMLphpの設定で使用します) f:id:tkhttty:20190121161548p:plain

SimpleSAMLphp でロール、プロバイダの設定を行う

[root@hostname ~]# vim /var/www/simplesamlphp/config/config.php
 
 857     'authproc.idp' => array(
                  // n は連番でよしなに
                  // https://aws.amazon.com/SAML/Attributes/Role の部分は、 ロールのarn,SAMLプロバイダのarn      ←カンマ区切りにするのを忘れずに!
                 n => array(
                     'class' => 'core:AttributeAdd',
                     'https://aws.amazon.com/SAML/Attributes/Role' => array('コピーしたロールのarn,arn:aws:iam::アカウントID:saml-provider/プロバイダ名')
                 ),
                :
                :
                複数アカウントがあれば同様にここへ追記
                :
                :

以上で設定が完了です! https://SPドメイン/simplesaml/saml2/idp/SSOService.php?spentityid=urn:amazon:webservices にアクセスして LDAP ユーザで認証ができれば OK !

認証が問題なければ以下のようなロール選択画面に移動するので、ログインしたい AWS アカウントのロールを選択してログインができます! f:id:tkhttty:20190121162609p:plain

SSOを導入してみて

今回 SAML 認証を利用して AWS の SSO を設定したことで、複数アカウントの管理が楽になり、停電などの影響も受けなくなりました!

常日頃利用している LDAP のユーザ ID とパスワードで AWS のコンソールにログインすることができるので、一々 ID やパスワードを確認する必要がなくなりちょっとだけ負担を軽くすることに成功したと思っています。

同じようなことで悩んでいる方がいらっしゃれば参考になると幸いです。

Gmailストレージ容量との戦い~GoogleAppsScriptを使った効果的な取捨選択~

開発グループPMO(プロジェクトマネジメントオフィス)の大嶋です。 実はウィルゲートのエンジニアでは最古参なことに最近気づきました。

そんなわけ(?)で、今回は組織の在籍期間が長くなってくると遭遇しがちな情報資産の氾濫という側面から「一足遅いですがこれを大掃除して新年を迎えよう!」というテーマでGmail資産の整理についてお伝えします。

GoogleAppsの容量が逼迫している

ウィルゲートでも、かねてより業務上のメールやファイル共有を中心にGoogleAppsを活用してきています。 近年ではSlackなどチャットサービスへの移行によりメールによるコミュニケーションは減ってきているものの、「フォーマルな連絡はメール」であったり「社内外のシステムからの通知はメール」といった形で、Gmailを使う機会はまだまだあるのではないでしょうか。

GoogleAppsは他のストレージサービスと比べても普通に使うには十分なストレージ容量がありますが、長く在籍しているとどうしても容量上限との戦いになってきます。 GoogleAppsは通常で30GB(無償版は15GB)の容量があり、追加で月額課金の形式で容量を増やすことはできるので短期的には「物理あるいは札束で殴る」的な解決をすることも可能です。

f:id:oshima106:20180907150822p:plain

ですが、仕事をやりくりできる人は得てして限られた時間の中で取捨選択してうまくやりくりしているのではないかと思います。 そこで限られた容量の中でGmailを効果的に運用する方法について考えてみます。

容量を逼迫させる原因

Gmail容量を逼迫させる原因であり、削除するべき対象は大きく分けて以下の2つと考えられます。

  1. 単独で大きなサイズを占めている
    • メールに添付ファイルや解像度の高い画像がついているようなもの
  2. 一つ一つは小さくても同様の内容が大量に存在している
    • メルマガやシステムアラート通知など

このあたりはデータや画像を圧縮して処理したり、N+1問題のような実装を避ける、といったシステム開発における 性能改善の考え方にも通じるものを感じます。

サイズの大きなものを特定

Gmailでは条件を指定したメールの検索ができるので、これを活用して特定していきます。

  • 『larger:3m』のようなサイズ指定で探す
    • この例では、主に添付ファイルを含む3MB以上のサイズのメールが抽出されます
    • 自身の業務に関連性が低いものを中心に削除していきます
  • 『filename:pptx』 のような拡張子で探す
    • 必要な添付ファイルは個別にローカルに保存するなどしてメールは削除してしまうのも一つの手です

これらを『before:2018/01/01』のような日付指定と組み合わせて抽出することで、過去のサイズの大きなファイルをまとめて削除する、といったこともできます。

f:id:oshima106:20190109174756p:plain

1つ1つが小さくても件数がかさんでいるものを特定

こちらが今回の本題です。 サイズや拡張子であたりを付けられる探し方に比べると、特定が難しいことがあります。

主なあたりの付け方としては、メールタイトル、送信元、送信先メーリングリスト)で検索して大量に来ていないかを調べることになります。 あたりをつけるのが難しい場合は、直近何日かの期間に来ているメールを対象に絞って傾向を調べてみましょう。

とはいえざっと見ても数100通くらいはあって目視ではシンドいのと、この先毎回同じことをするのも避けたいので、GoogleAppsScript のコードを実行することで集計してみました。 この例では、ここ5日以内に送信されたメールを対象に送信元アドレスごとの件数をカウントしています。

/**
 * 所定の条件でメールを検索して送信元ごとの件数を集計する
 */
function processMailFromCount() {
  // メールの検索条件を設定(5日前より新しいメール)
  var SEARCH_CONDITION =  "newer_than:5d";

  // Gmailを指定条件で検索する
  var resultThreads = GmailApp.search(SEARCH_CONDITION);

  var resultCounts = {};  // 送信元アドレスごとのカウント用配列
  var messagesInThread  = {};  // スレッド内のメッセージ取得用配列
  var mailFrom = "";  // 送信元メールアドレス
  
  // 見つかった件数を記録
  Logger.log('検索条件:' + SEARCH_CONDITION);
  Logger.log('対象スレッド件数:' + resultThreads.length);
  Logger.log('========集計開始========');
  
  // 検索結果で取得したスレッドを順に処理し、送信元アドレスごとの件数を集計
  for each(var thread in resultThreads){
    messagesInThread = thread.getMessages();
    // スレッド内のメッセージを順に見て送信元アドレスを取得
    for each(var message in messagesInThread){
      mailFrom = message.getFrom();
      var mailAddress = mailFrom.match(/<.*@.*>/); // 送信者名 <hogehoge@gmail.com> 形式のメールアドレス部分を抽出
      if (mailAddress != null){
        mailFrom = mailAddress[0].substring(1,mailAddress[0].length - 1); // 角括弧を除いて整形
      }
     // 送信元アドレスごとの件数をカウントアップ
      if (mailFrom in resultCounts) {
          resultCounts[mailFrom] += 1;
      } else {
        resultCounts[mailFrom] = 1;
      }
    }
  }
  
  // 件数を降順にソートする
  var keys=[];
  for(var key in resultCounts){
    keys.push(key);
  }
  keys.sort(function(a,b){
    return resultCounts[b]-resultCounts[a];
  });
  
  // ログに送信元:件数 のフォーマットで書き出す
  for (key in keys){
    Logger.log(keys[key] + ': ' + resultCounts[keys[key]]);
  }

  Logger.log('========集計終了========');
};

結果どのくらい減らせたのか

直近5日(GoogleAppsScriptの仕様で一度に最大500件)を対象にメールの送信元を集計すると、自社メディアサービス「Milly」のシステムから送信されているものをはじめ、システムから通知されているものが大多数を占めていることが判明。

f:id:oshima106:20190109182339p:plain

実際に来ていた内容は外部API連携処理のエラー通知や、広告運用状況の通知など。特定の画面にアクセスする際に出力されるランタイムエラー情報のアラート通知など直接的な悪影響がないため対策が後回しになっているものでした。 StackTraceログがメールに貼り付けられているものもあるため、メール1通あたりのサイズもそこそこ大きくなっていました。

これらを順に削除していくことで、1.5GBくらいの容量を空けることができました。大掃除というにはちょっと物足りないですが、当面半年くらいはやりくりできそうです。

f:id:oshima106:20190109190057p:plain

おわりに

今回は日常業務にちょっとしたエンジニアリングを活用した事例のご紹介でした。 今後もウィルゲートではこういったライトなものから、現場のコアな技術のことまで引き続きお伝えできればと思います。

【スライド・動画あり】PHP Conference 2018 で Laravel × レイヤードアーキテクチャについて発表しました

PHP Conference 2018 / Laravel × レイヤードアーキテクチャを実践して得られた知見と反省

10 月から開発グループ直下の所属となりました。岡田(okashoi)です。

先日 12/15(土)に開催された PHP Confernece 2018 にて「Laravel × レイヤードアーキテクチャを実践して得られた知見と反省」というテーマで登壇させていただきました。

PHP Conference 2018 の様子

f:id:okashoi:20181217103911j:plain
PHP Conference 2018 のテーマは「GROWTH

今年は「GROWTH」をテーマに合計 38 のセッション + 10 を超える LT がありました。

どのセッションも興味深い内容であり、当日の来場者はおよそ 1000 人にものぼったそうで、たいへん盛り上がりました。

当日の盛り上がりは twitter からも見て取れると思います。

twitter.com

発表内容

www.slideshare.net

youtu.be

今年度に取り組んだ 2 つのプロジェクトでレイヤードアーキテクチャを実践した振り返りが主たる内容です。

レイヤードアーキテクチャを実践したことについてすべてが上手く言ったとは思いません。というより、反省点はたくさんありました。

ですが、実践の中で得られた知見/成長がたくさんあり、結果として組織にとってプラスになった取り組みだと信じています。

この発表の締めくくりには「不正解」を選ぶことを恐れるあまり挑戦を避けるのではなく、自分たちが選んだ選択肢を自分たちの手で「正解」に変えていきましょう、というメッセージを込めました。

時間の関係で具体的な実装レベルの話をするのは避けましたが、そちらについてはどうにか別の機会を得て話したいと思っています。

おわりに

私個人として、PHP Conference への登壇はの 2018 年の大きな目標のひとつでした。

この目標を達成できたことについて、一緒にレイヤードアーキテクチャに向き合って試行錯誤してくれたプロジェクトメンバー、発表資料のクオリティ向上に協力してくれた開発室のみなさん、そして何より PHP Conference 運営に携わるすべてのみなさまに感謝を述べたいと思います。

本当に、ありがとうございました!

新卒から1年半でチームリーダになるまでに経験したこと

こんにちは!ウィルゲート開発室執行役員の鶴飼です。 本日は、入社して1年半でリーダに昇格した吉田君にインタビューしたいと思います。 ウィルゲートでは複数事業とプロダクト開発を行っているので、挑戦機会がたくさんあります。 そんな挑戦機会を得て成長してきた吉田君が、実際どのような事を経験し、成長してきたかを紹介したいと思います。

入社前と入社後のイメージって1年半経った今、改めて感じる事ってありますか?

f:id:m_yokomichi:20181206132454j:plain ▲左がインタビューする鶴飼 右がそれに答える吉田

入社前の印象としては、漠然と「色々な事が出来る雰囲気はある」という感じでした。 実際何が出来るのかや具体的な仕事のイメージはあまり無かったのですが、裁量は大きく持たせて貰える雰囲気は感じ取れました。 入社後はメディアチームに配属され、主にフロントエンド開発を中心にサービス開発を行っていました。 もちろんフロントエンドとしても技術的なチャレンジもあり、先輩の技術に追いつくだけでも精一杯ですが、少しづつ出来る部分が増えるとそれに合わせて、踏み込んだ開発をさせて貰えるようになってきました。

入社して3ヵ月ぐらいで、テストコード導入の推進してたよね?

そうですね、メディアチームではグロースが多い為、小さい開発をリリースする事がたくさんあります。 その為、品質担保の為のテストコードの導入が検討が進んでいたのですが、その際に私が研修で作成した実装方針でおこなう事が決まったので、 チームでのテストコード導入を推進しました。 実際にチームで導入していく際に、実装方針に漏れが多々あり、それらをチームで話し合いながら決めていけたので勉強になりました。 また同時に、そこまで考えていなかった自分の甘さに気づきました。

チームで話し合って決めた事って何を決めたの?

どういったテストを書くべきか。具体的には共通化や定数化のルールを決め、過去のテスト漏れや障害から、何を最優先で担保すべきかを決めていきました。 そのように共通の認識を取り始めると、コストを掛けてでもテストコードを書くべきか、過剰になるのか、いかに使いまわせるかなどのディスカッションができたので 自分だけで考えたよりも深く練り込まれたテストコードの導入推進ができたと思います。 また、上流工程でしっかりと考えておかないと実装の際に手戻りが発生してしまうことを身をもって経験しました。

導入した事でメリットはあった?

特に改修の多い画面や、ログイン系はテスト仕様書に沿って各人にお願いするより圧倒的に速度も上がりましたし、自分がやっているテスト以上の品質が担保されているので、安心してリリースできるようになりました。

新規メディアのプロジェクトマネージャも新卒の時だよね

今年の初めからは花時間というメディアのプロジェクトマネージャを任してもらえました。 元々、上長にはチャンスがあればプロジェクトマネジメントをやりたいと言っていたので、新規メディアの話が上がった時に真っ先に手を上げました。 規模も大きすぎず、メンバーも経験豊富な方を入れていただきながら新卒の1年目からPMを任せてもらえて、今までとは違う視点で開発業務に取り組むことができるようになりました。 今までは振られたタスクを納期までに実装するというスタイルでしたが、PMを経験したことで、なぜその機能が必要なのか、他の実装方法はないのかを常に考えるようになりました。 また、他のメンバーのタスクも管理していたので、スケジュールの管理の大切さを学びました。

スケジュール管理の大切さってどういう所かな?

当初予定していた通りに進められれば良かったのですが、途中でメンバーが別のプロジェクトのトラブルで時間を割けなくなってしまいました。 その時に、全体のスケジュールを見直してタスクの割り振りを変え、優先度を再定義する事で新しく入ってくるメンバーがやりやすい場所を作る事ができ、 全体のスケジュールを変えずに完了する事ができました。 スケジュール管理は進捗管理だけではなく、流動的にメンバー配置を変えたりするのにも重要な役割を果たすと感じています。

2年目に入って新しくチャレンジした事ってある?

これまでアプリの開発を行なったことがありませんでした。そんな私ですが、暮らしニスタのアプリのプッシュ通知を任せてもらえました。 会社にアプリのコードをかける人が1人しかいなかったことも挑戦の機会をもらえるきっかけになりました。 いざ実装に着手するとわからない点ばかりだったので、会社の先輩に聞きながらどんな処理が書かれているのかを理解するところから始めました。 また、アプリの技術顧問の方に週に1度質問をすることができるので、実装方法で不明な点を質問しながら進めました。 周りのサポートの体制が充実しているので、初心者でもプッシュ通知の機能の実装を完成させることができました。

プッシュ通知作ってみてユーザの反応はどうですか?

今まで全体に対するプッシュ通知はありましたが、今回は個別のプッシュ通知を送信できる仕組みを導入した事もあり開封率はかなり高いです。 暮らしニスタのアプリをインストールしてログインしてくれているユーザに毎日アプリを開くきっかけを作れたのは良かったです。

他にも業務でやっている事あるかな?

ウィルゲートが運営しているメディアはフルスクラッチで作成しているものが多いですが、WordPressで動いているサービスもあります。 これまでWordPressはほとんど触ったことがなかったですが、運用保守を任せてもらえています。 趣味程度のものは作ったことがありましたが、業務レベルとなると求められている部分が違うなと感じています。

f:id:m_yokomichi:20181206132937j:plain ▲色々と深ぼって聞く様子

趣味と業務で求められる事の違いってどんな事?

先ずはセキュリティ周りが大きく違います。趣味レベルで作っていた時には管理者用ログイン画面も特にIP制限やベーシック認証などかけずにいましたが、そんな簡単な事からも違いを感じています。 また、プラグインの選定に関しても、自分で作っているものは自分が使いたいように選べばよかったものに対し、事業部やクライアントが扱いやすいものを選定したり、更新が止まっているものは選定から落としたり、使う人の目線で構築するというのも新しかったです。 とはいえ、ユーザファーストでの考え方が業務を通じて身に染みているので当たり前にやらなければいけない事ですね

目まぐるしく色々経験しているけど、何が一番印象深い?

花時間のPMが印象深いです。 メンバー2人(先輩と年上)にしっかりコミュニケーションを取る事、先輩だろうとしっかり言わないといけない事もあるという気付きを得たました。

初めてのPMは上手くいった?

初めての時は何とか上手くできたと思います。どちらかというとやったに近いのかもしれません。 とはいえ、先ほども言った通り規模も大きすぎず経験豊富なエンジニアアサインなど上長が行ってくれたので、 プロジェクトが複雑になった時の対応力とかまだまだ経験してない事がたくさんあり、これからも経験を積んでいきたいと思います。

PM今後もやりたいですか?

LDRとPMはしっかりやっていきたいと思っています。同じように見えてどっちも違うと感じます。 LDRはメンバマネジメント中心、PMはプロジェクトマネジメント中心なので、近しいと思いますがどちらも経験してチームに貢献していきたいと思います。

1年半を振り返って

f:id:m_yokomichi:20181206133106j:plain これまで1年半とは思えないほど色々な学びを得ることができました。 10月からはチームリーダとして更なる高みを目指していきたいと思います。 今まではプロダクトの成長を考えるだけでしたが、今後は人も見る必要があります。 人を見て、人を活かし、どうやって成長させてあげられるかを考えるのもリーダの仕事の一つだと思います。

課題は見えてる?

まだまだ足りない事ばかりですが、とにかく情報量が足りないです。 業務に関する事だけではなく、事業の事や組織の事それらのインプット量を増やしていく事で、良いアウトプットが出来ると思います。

最後に3年後はどうなっていたい?

フロントエンドが元々メインなので、技術キャッチアップは忘れずにスペシャリストと会話が出来る状態でありたいし、自分でもコードが書ける状態で居続けたいです。 上長がサイト責任も行っているので、事業も作れるエンジニアになっていきたいです。

ウィルゲートはやりたい!と手を上げればどんどん挑戦することができる環境がそろっています。 挑戦することで今までになかった知識や技術が身についていくと思うので、これからの1年も新たな挑戦をたくさんしていきたいと思います。

Web開発経験ゼロの新卒が入社半年を経て気付いてしまったこと

こんにちは、18年度新卒の田島です。前回は新人研修の模様についてお話しさせていただきましたが、今回は私が入社半年を経て気付いたことについてまとめたいと思います。

はじめに

私は現在メディアユニットに配属し、Milly や暮らしニスタなどの運用保守や機能改善を行っています。Web メディアという媒体の特性上開発するべき機能は大きくないものの大量に存在するため、常に優先順位付けを行いつつ着手しています。リリースしたものから順に効果検証を行い、更なる変更や改善を行うこともあります。そのため、非常にスピード感のあるアジャイル開発といってもよいのかもしれません。

そんなめまぐるしい環境で学んだことの中から特に感じたことを、設計や開発の観点から3つ紹介いたします。

コーディング規約の重要性

入社前私は個人で Java などのコーディングを行っていたのですが、入社前と入社後で最も大きく違いを感じたのはチーム開発であることによるコーディングに対する意識の違いでした。特に、コーディング規約が開発スピードや成果物の質に非常に影響を及ぼすということに気付きました。コーディング規約が守られているコードはそうでないコードと比べて読みやすさが段違いであり、読んでいてとても理解しやすいものでした。また機能拡張を行う際にどのような場所にどのようにコーディングすれば良いのか明確であるために実装もとても捗ることが分かりました。

入社当初はその重要性に気づかず、正直なところ周りのコードに合わせてなんとなく規約に違反しないよう実装するだけでしたが、最近はソースコードやモデルの持つ役割を考えて適した実装ができるように心がけています。またこれは余談ですが、レスポンスの変数名や形式などが統一されていない外部 API に苛立ちが湧くようになりました。

f:id:tajima-ryo:20181205173725p:plain

プルリクエストのテンポ感

次に強く感じていることは、コードレビューのためのプルリクエストは早く出せば出すほど良いということです。もちろんプルリクエストを出す前に規約違反やつまらないミスなど、レビュアーに指摘されると恥ずかしい(+そもそもレビュアーの時間を取らせてしまい申し訳ない)点を修正する確認作業は必要です。しかし、指摘を恐れて必要以上に自分のコードを点検したりプルリクエストを出すのをためらうのは良くないことだと気付きました。

入社から数ヶ月経ち最近は自分自身も他の人のプルリクエストをレビューするようになりました。そこで特に感じることは、レビュアーがコードレビューに取れる時間やタイミングは限られているということです。プルリクエストを遅らせることはレビューのタイミングを遅らせることになり、アドバイスの数やタイミングも遅くなってしまいます。特に期日が明確なタスクではテンポ感を大事にしていきたいと感じました。

f:id:tajima-ryo:20181205173753p:plain

テストの難しさと重要性

そして、最後の気付きはテストの難しさと重要性についてです。十分なテストは非常に難しく、フロント側のテストはある程度フォーマット化して進めようとしても抜け漏れが発生してしまう場合があります。また API に対してはテストコードを書いているのですが、想定されるデータや考えるべき状況を把握しなければならないのは非常に大変です。

しかしテストを十分に行うことで、リリース後に不具合が発生することを抑えられるのはもちろん、実装した機能が今後拡張された際にうまく動かなくなるということを避けることができます。そのため、テストを行うことは非常に意味のあることだと感じました。まだまだ自分のテストには抜け漏れが多いのですが、今後も継続的に取り組むことで解消していきたいです。

終わりに

今回まとめたことは熟達したエンジニアの方々にとっては当たり前のことかもしれません。しかし、こういった当たり前の気付きを自分の実体験として重ねていくことでエンジニアとして一歩一歩成長できるものと考えております。今後もこういった当たり前の気づきを糧に成長できるように努力を続けていきます。それでは、次回もよろしくお願いいたします!

HTTPS の Wordpress を AWS LightSail に移行

経緯

弊社で運用している一部のサーバはクラウド事業者の VPSWordPress 環境を構築し、そこに証明書を入れて HTTPSWordPress を運用していました。 ただ、VPS の月額料金や証明書の更新に関わる購買や更新手続きといったコストといった点が問題視されていました。

無料の証明書である Let's Encrypt も考えましたが、できるだけ仕掛けを作らずに証明書の更新作業を自動化したいと考えました。 VPS の月額コスト見直しのタイミングもあったので、AWS LightSail に移行し証明書を自動更新する仕組みに切り替えました。

AWS LightSail とは

LightSail とは、AWS が提供する VPS サービスで、SSL アクセラレータ機能のあるロードバランサー(以下 LB )も使えます。 この LB には DNS 認証による無料の SSL/TLS 証明書を簡単に組み込むことができます。

SSL アクセラレータとは

SSL アクセラレータとは通信を TLS/SSL で暗号化する際に、暗号化や複合化の処理を専門に行う機能のことです。

  • 証明書管理の一元化
  • 負荷分散

といった効果があります。

今回の通信経路を図にすると以下のようになります。

f:id:kobayashi-ryotaro:20181127155450j:plain

LightSail ロードバランサー 作成

  1. AWS のコントロールパネルから LightSail のホーム画面に入ります。 f:id:kobayashi-ryotaro:20181127163621p:plain
  2. 「ネットワーク」→「ロードバランサーの作成」と進みます。 f:id:kobayashi-ryotaro:20181127164020p:plain
  3. 作成画面でリージョンや名前を設定して「ロードバランサーの作成」を押下します。HTTPS の設定は後で行います。 f:id:kobayashi-ryotaro:20181127164345p:plain
  4. ロードバランサー管理画面の「インバウンドトラフィック」で証明書の設定を行います。必要な項目を設定してください。 f:id:kobayashi-ryotaro:20181127165554p:plain
  5. ドメインの認証が終われば証明書の組み込みが完了します。 f:id:kobayashi-ryotaro:20181127165948p:plain

LightSail インスタンス作成

  1. ホーム画面から「インスタンス」→「インスタンスの作成」を押下します。 f:id:kobayashi-ryotaro:20181127170755p:plain
  2. 今回はWordPressの移行ということでバージョンの差異を懸念し、インスタンスイメージは「 OS のみ」「Amazon Linux」にしました。 f:id:kobayashi-ryotaro:20181127171149p:plain
  3. インスタンスプランを選んで名前を設定し、「インスタンスの作成を」押下してしばらくお待ちください。 f:id:kobayashi-ryotaro:20181127171316p:plain
  4. 作成が完了したら、先ほど作成したロードバランサーのターゲットインスタンスとして設定してください。 f:id:kobayashi-ryotaro:20181127172335p:plain
  5. 作成されたインスタンスにはパブリック IP で SSH 接続ができます。 f:id:kobayashi-ryotaro:20181127172544p:plain

WordPress の移行

WordPress はデフォルトだと ApachephpMySQL ですが、今回の環境は nginx+php-fpm + MySQL です。 各ミドルウェアのインストールや設定は割愛します。

移行に関しては基本的に

を移行すれば大丈夫です。

WordPressHTTPS

設定を間違えるとリダイレクトループしたりレイアウトが崩れるので注意してください。

リダイレクトループ対策

リダイレクトループとは、以下のようなループ現象です。

  1. LB が http で受ける
  2. LB が Web サーバに http で渡す
  3. Web サーバが301を返して https にリダイレクト
  4. LB が https で受ける
  5. LB が Web サーバに http で渡す
  6. Web サーバが301を返して https にリダイレクト
  7. 4に戻る

これを避けるために、nginx のコンフィグの server ディレクティブに以下の設定を追記します。 証明書に関する記述があれば削除してください。

   if ($http_x_forwarded_proto != https) {
      return 301 https://$host$request_uri;
    }

世の多くの LB や CDN は、自身を通過したときに http の拡張ヘッダである http_x_forwarded_proto に値を入れます。 これは配下のサーバが、もともとのアクセスが http なのか https なのかを判断可能にするためです。

この値を利用することで以下のような流れになり、ループを回避できます。

  1. LB が http でリクエストを受ける
  2. LB が http_x_forwarded_proto に http を入れて Web サーバに http で渡す
  3. Web サーバが http_x_forwarded_proto を評価し、http なので301を返して https にリダイレクト
  4. LB が https でリクエストを受ける
  5. LB が http_x_forwarded_proto に https という値を入れて、Web サーバに http で渡す
  6. Web サーバが http_x_forwarded_proto を評価し、 https なのでバックエンドにリクエストを渡す

WordPress の設定

こちらは設定を間違えるとレイアウトが崩れたりします。

wp-config.php に以下の設定を追記します。 php のアプリケーションは $_SERVER['HTTPS'] を評価してプロトコルを判定していることが多いためです。WordPress も例外ではありません。

  if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
      $_SERVER['HTTPS'] = 'on';

WordPressCSS の作成で自己参照することがあるのですが、こうすることでレイアウト崩れを防ぐことができます。

効果

証明書の自動更新機能で運用コストの削減ができました。 また DNS サービスである Route 53 を使えば AWS アカウントですべて管理でき、とても便利です。

まとめ

nginx や wordpress の移行作業が手間ではありますが、今回の移行により証明書の管理から解放されました。 手軽に HTTPSWordPress を作成したい場合は LightSail を検討してはいかがでしょうか。