行ったことある?スクラム、アジャイル関連のイベント

こんにちは! saber_chica です。 この記事はfreee Developers Advent Calendar 2018 12/24(日付超えてしまいましたが...)の記事です。

本日はスクラム関連のイベントをご紹介したいと思います。 ラグビーの方ではないですよ!(完全に関係ないわけではないですが!)

なんで紹介するの?

スクラムは「複雑で変化の激しい問題に対応するためのフレームワークであり、可能な限り価値の高いプロダクトを生産的かつ創造的に届けるためのもの」とスクラムガイドで定義されています。 私自身はこれを、知り得ない未来の変化と付き合っていくために先人たちが考え抜いた、使わない手はないフレームワークだな〜と日頃考えています。

当然、スクラムやアジャイルが全ての課題を解決してくれるわけではありませんが、客観的に判断するための「現状」を著しくあらわにしてくれるもではあります。 その「現状」を把握した後に何かしらの対策を講じるのか、現状をそのままにするのかはそのプロダクトに関わる全ての人に委ねられるので大きく失敗もできるし、大きな改善にもつながる可能性を秘めています。

ただ、実際やり始めてみるとうまくいかないことが出てきたるするのですが、そんな時にうまくいったやり方を聞く機会としてイベントに参加することで、役に立つことが私自身あったのでご紹介して行きたいと思います!

Scrum Gathering Tokyo

https://2019.scrumgatheringtokyo.org/index.html

直近一番近くに開催される国内最大規模のスクラムのカンファレンスです。 参加者はスクラムの初心者からスクラム戦闘力の高いエキスパートまで、国内外から様々な立場の人々が集まるカンファレンスです。

講演だけでなくワークショップや参加者同士の交流もあり、スクラムを採用し始めてうまくいかないことをダイレクトに戦闘力の高い人たちに相談したり、意見やヒントをもらったりできる貴重な場です。私自身参加した時は、やる気を補充できる場ともなっていました。 そんな Scrum Gathering Tokyo ですが、今年のチケットは売り切れています。 次回行きたいと感じた人は、人気が高くチケットはすぐに売り切れることもしばしばあるので早め(10月ごろにアナウンスされることが多いのでその時期)に購入しておく方が良いです。

Agile Japan

https://www.agilejapan.org/

こちらのカンファレンスも非常に大きなイベントです。

Scrum Gathering Tokyo との違いはスクラム以外のアジャイルに関わる内容が幅広く(Scrum Gathering Tokyo も幅広いのですが!)含まれている点だと感じています。 あとは、Scrum Gathering Tokyo よりもエンタープライズ感が強めかな〜と感じるところも違う点です。 大きな組織でアジャイルな組織を作っていこうとしているときに悩めることがある時は刺さる講演が多くあるかと思います。

Scrum Masters Night!

https://smn.connpass.com/

2~4ヶ月に1回開催されていて、経験豊かなスクラム戦闘力の高い人たちも参加者の中にゴロゴロいて、悩みや困りごとがある人が参加すると得るものが非常に大きいです。 最近参加した際はOST(Open Space Technology)というやり方で進行されていて参加型のイベントです。

OSTとは参加者が熱い想いをもって話し合いたいテーマを持ち寄り、ファシリテーターが中心となりオープンな話し合いしてテーマを決めていくやり方です。 各テーマが決まったら、興味のあるテーマごとに別れディスカッションが始まっていきます。 私自身、スクラムでやっている時もやっていない時も開発プロセスに関わる部分で疑問や腑に落ちない点などが出てきた時はここに行ってヒントを得たりすることがよくあります。

アジャイル・ディスカッション!!!

https://agile-discussion.doorkeeper.jp/

こちらのイベントもOST(Open Space Technology)形式で開催されていました。 Scrum Masters Night!よりも開催頻度が高く、参加しやすいです。 Scrum Masters Night!と同じく、開発現場でコーチをされている人たちがいるので、悩ましいことなどがある時に参加すると突き刺さるものがあります。 私自身悩ましいことがある時は、参加してするようにしているコミュニティです。

アジャイルひよこクラブ

https://agile-hiyoko-club.connpass.com/

こちらのイベントは私自身はじめて参加したアジャイル関連のコミュニティで、非常に参加しやすく感じ参加していくうちに、今では私も運営に関わっています。 開催頻度は2ヶ月に1回です。

初心者を対象としているコミュニティで参加者も始めたばかりという人やこれから初めてみたいという人も多くいます。 悩み相談をメインコンテンツとしているので、悩みがあるが初心者すぎる悩みなんじゃないかと不安に思いながらも相談相手が欲しい時にはちょうど良いかと思います。

終わりに

気になるイベントがあった方はぜひ行けるタイミングで行ってみてください! なかった方、こんなのもあるよ!というのをご存知な方はぜひ教えてください。喜びます。

今回は私が参加したことのあるイベントにとどめましたが、プロダクトオーナーなら是非行って欲しいイベントもあるので気になる方がいたらどこかで紹介しようと思います。

最後まで読んでくださりありがとうございました!

明日はいよいよ最終日!とても楽しみです!

Goでスタックトレースを構造化して取り扱う

はじめましてfreee株式会社でソフトウェアエンジニアをしているbudougumi0617ことしみっちょです。普段はGoによるアカウントアグリゲーション機能(銀行同期基盤)の開発に携わっています。

この記事はfreee Developers Advent Calendar 2018 の23日目の記事です。

12月23日と言えば国民の祝日、Perfumeかしゆかさんの誕生日ですね。おめでとうございます。 今回は私が先日参加したPerfume 7th Tour 2018 「FUTURE POP」の感想を書こうと思ったのですが、ツアーが終わるまでネタバレは禁止なのでGoの話をすることにしました。

この記事では私が携わっているプロダクトで行なっているエラーハンドリングの一部とGoでスタックトレースを構造化に扱う方法について紹介します。

なお、文中で利用しているソースコードや出力結果は以下のサンプルリポジトリに用意したコードを利用しています。

github.com

Goのエラーハンドリングについて

Goの標準パッケージから生成されるエラーはそのまま愚直に利用するとエラーメッセージしか持っていない非常なシンプルな情報しか得られません。 プロダクトで利用する上ではスタックトレースやSeverityの仕組みがほしいですね。各社・各人が多様なアプローチをとっており、2018年12月のアドベントカレンダーや勉強会だけでもエラーの扱い方について以下のような投稿・発表がなされています(漏れていたらごめんなさい)。

私のGoのプロダクトではpkg/errorsをラップした独自errorsパッケージを利用しています。

github.com

pkg/errorsを利用すると、エラー情報にスタックトレースをエラー情報に含めることが可能です。 以下はpkg/errors.New関数から生成したエラーをfmt.Printf("%+v",err)と出力した結果に含まれているスタックトレースの引用です。

github.com/budougumi0617/errors-example/errors.NewByPkg
        /Users/budougumi0617/go/src/github.com/budougumi0617/errors-example/errors/errors.go:14
github.com/budougumi0617/errors-example/root/sub.(*Sub).ReturnErrorByPkg
        /Users/budougumi0617/go/src/github.com/budougumi0617/errors-example/root/sub/sub.go:18
github.com/budougumi0617/errors-example/root.secondFuncWithPkg
        /Users/budougumi0617/go/src/github.com/budougumi0617/errors-example/root/root.go:24
github.com/budougumi0617/errors-example/root.FirstFuncWithPkg
        /Users/budougumi0617/go/src/github.com/budougumi0617/errors-example/root/root.go:19
main.main
        /Users/budougumi0617/go/src/github.com/budougumi0617/errors-example/main.go:14
runtime.main
        /usr/local/opt/go/libexec/src/runtime/proc.go:201
runtime.goexit
        /usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1333

呼び出し元の関数名や呼び出された場所のファイル行数などのスタックフレームを出力しているのがわかります。 上記のようにpkg/errorsを使うだけでスタックトレースをエラー情報に含めることができるようになるのですが、私のプロダクトの独自エラー型ではスタックトレースの生成を一部独自に行なっています。

なぜ独自にスタックトレース情報を取り扱うのか?

pkg/errorsで出来る以上ほとんど車輪の再発明なのですが、スタックトレースの取得を独自にすることの利点は、エラートラッキングサービスに加工後のスタックトレース情報を送信できることです。 私が担当しているプロダクトでは、BugSnagを利用してエラー情報のトラッキングをしています。BugSnagはSentryなどと同様のエラートラッキングサービスです。

www.bugsnag.com

そして、私が担当しているGoのプロダクトはos/exec.Cmd経由でRubyのスクリプトに一部の処理を移譲しています。Rubyスクリプトのスタックフレームについては当然Goのランタイムからは取得できません。 そのため、Rubyスクリプトの実行時に例外が発生したとき、Rubyのスタックトレースのフレーム情報ををGoのスタックトレースに追加してからBugSnagに送信しています*1 。ではどのようにすればGoのスタックトレースを操作することが可能なのでしょうか。

Goでスタックトレース(スタックフレーム)を構造化して操作する

まず、pkg/errorsはどのようにスタックトレースを取得しているのでしょうか。pkg/errorserrorを生成するerrors.Newなどは以下のような実装をしています。

https://github.com/pkg/errors/blob/2233dee583dcf88f3c8b22cb7a33f05a499800d8/errors.go#L100-L107

// New returns an error with the supplied message.
// New also records the stack trace at the point it was called.
func New(message string) error {
    return &fundamental{
        msg:   message,
        stack: callers(),
    }
}

このstackフィールドに入っている情報がスタックトレースの情報なのですが、実際に格納するオブジェクトを返しているcallers関数の実装は以下です。

https://github.com/pkg/errors/blob/059132a15dd08d6704c67711dae0cf35ab991756/stack.go#L133-L139

func callers() *stack {
    const depth = 32
    var pcs [depth]uintptr
    n := runtime.Callers(3, pcs[:])
    var st stack = pcs[0:n]
    return &st
}

この中のruntime.Callers関数で取得した[]uintptrがスタックトレースの各フレーム情報になります。pkg/errorsでは独自型のpkg/errors.Frame(type Frame uintptr)に格納して情報を取得しています。
なお、Go1.7以降ではruntimeパッケージ内にスタックトレース情報を模すruntime.Framesと、runtime.Callers関数で取得したuintptrをからFramesを取得するruntime.CallersFrames関数が追加されているのですが、こちらを利用すると加工が少し面倒なため、今回は利用しません。 (runtime.CallersFramesの利用方法はruntimeパッケージのExampleをご覧ください。)

本稿では以下のような独自型を定義します。

// Frame はスタックフレームを表現する独自構造体
type Frame struct {
    // File はそのスタックが発生した開始されたファイル
    File string
    // LineNumber はそのスタックが開始されたファイル行数
    LineNumber int
    // Name はそのスタックが開始された関数・メソッド名
    Name string
    // ProgramCounter は元データ
    ProgramCounter uintptr
}

そしてこのFrame構造体にruntime.Func構造体を介して各スタックフレーム情報を格納してきます。*runtime.Funcオブジェクトはruntime.Callersで取得したスタックフレーム情報のuintptrからruntime.FuncForPC関数を使って取得できます。*runtime.Funcオブジェクトを介してスタックフレーム情報を[]Frameに格納し直すコードが以下になります。

func callers() []uintptr {
    const depth = 32
    var pcs [depth]uintptr
    n := runtime.Callers(3, pcs[:])
    return pcs[0 : n-2]
}

// NewFrame はスタックトレースの各スタックフレームをFrameに格納する
func NewFrame(pcs []uintptr) []Frame {
    frames := []Frame{}

    for _, pc := range pcs {
        frame := Frame{ProgramCounter: pc}
        fn := runtime.FuncForPC(pc)
        if fn == nil {
            return frames
        }
        frame.Name = trimPkgName(fn)

        frame.File, frame.LineNumber = fn.FileLine(pc - 1)
        frames = append(frames, frame)
    }
    return frames
}

// package名を取り除く
func trimPkgName(fn *runtime.Func) string {
    name := fn.Name()
    if ld := strings.LastIndex(name, "."); ld >= 0 {
        name = name[ld+1:]
    }
    return name
}

あとはerrorインターフェースを満たす構造体に[]Frameを保持しておけば、スタックトレース情報を含んだ独自errorの定義の完成です(fmt.Stringerfmt.Formatterインターフェースも実装しておくとよいでしょう)。 次の出力は大雑把にError()メソッドを実装したMyErrorの出力です。

大雑把にスタックトレースを出力する独自error:
Cause: custom error
Trace:
/Users/budougumi0617/go/src/github.com/budougumi0617/errors-example/root/sub/sub.go:15 ReturnError
/Users/budougumi0617/go/src/github.com/budougumi0617/errors-example/root/root.go:16 secondFunc
/Users/budougumi0617/go/src/github.com/budougumi0617/errors-example/root/root.go:11 FirstFunc
/Users/budougumi0617/go/src/github.com/budougumi0617/errors-example/main.go:12 main

私のプロダクトでは[]Frameに更にRubyから取得したスタックトレース情報を付与したりしています。

今回は独自定義のFrame型を用意しましたが、例えばBugSnagを利用している場合、bugsnag-go/errors.StackFrame構造体にフレーム情報を格納し、bugsnag-go/errors.ErrorWithStackFramesインターフェースを実装すれば「細工したスタックトレース」をBugSnagのWebビューに表示することもできます。

// bugsnag-go/errors.StackFrame の定義
type StackFrame struct {
    File           string
    LineNumber     int
    Name           string
    Package        string
    ProgramCounter uintptr
}

// bugsnag-go/errors.ErrorWithStackFrame の定義
type ErrorWithStackFrames interface {
    Error() string
    StackFrames() []StackFrame
}

終わりに

今回はGoでエラーハンドリングを行なう際に自前でスタックトレースを取り扱う方法を紹介しました。

最後にfreeeでは一緒に働けるGopherを募集中です。 www.wantedly.com

明日は人事労務とスクラムに精通するエンジニア、そーださんです。お楽しみに。

*1:もちろん、Rubyスクリプト側からStderrPipe経由などで情報をGoに送り込む「仕込み」は必要です。

システム障害のおわびとまなび

はじめに

こんにちは、freee株式会社でCDO(最高開発責任者)をしている平栗です。 2018年10月31日に、freeeで起こしてしまったシステム障害について、その原因と対策、障害からの学びについて共有したいと思います。 この記事はfreee Developers Advent Calendarの22日目になります。

おわび

まず、約2時間半にわたりfreeeの全サービスを停止し、皆様に多大なるご迷惑をおかけしましたことを、改めてお詫び申し上げます。 今回の障害を大きな学びと成長の機会とし、今後の再発防止と業務改善に取り組んでまいります。

障害の経緯

2018年10月31日12時34分~15時00分の2時間26分の間、freeeの全サービスを一時停止し、すべてのサービスがご利用できなくなりました。 以下、復旧までの経緯です。

  • 11時24分 特定の機能が利用できなくなっていると、社内から不具合報告があがり、エンジニアチームで調査を開始
  • 11時30分 サポートチームからも、お客様から問い合わせがきていると共有
  • 11時56分 多くのリリースフラグ(リリースフラグについては後述)がオフになっていることに気づく
  • 12時34分 リリースフラグオフが原因と判断し、ただちに影響範囲を把握することが困難であったため、お客様のデータ保護のため全サービスを一時停止
  • 15時00分 影響範囲調査の結果、お客様のデータの毀損・漏洩がないことを確認し、サービスを再開

お客様のデータへの影響

お客様のデータ保護の観点からサービスを停止しましたが、変更されたリリースフラグの影響をすべて調査した結果、お客様のデータの漏洩・毀損等は一切ございませんでした。

リリースフラグとは

リリースフラグとは、システムの機能オン/オフを機動的に切り替えるための仕組みで、主に新機能のリリース管理に利用しています。 リリース直後の機能について不具合があった場合に、再度デプロイ作業をすることなく、システムの管理画面上から機動的にフラグをオフにして即座に切り戻すことができます。 基本的には、新しい機能が使えるかどうか以外システムへの影響はなく、リリースフラグはオンでもオフでもシステムは正常に作動するように設計されています。

障害の原因

システム障害の最初の原因は、リリースフラグ変更作業上のオペレーションミスでした。それにより意図せず多くのリリースフラグがオフになってしまい、お客様のデータへの影響がないと即座に判断することができず、データ保護を最優先に考え、サービスを一時停止しました。

原因の深掘りと対策

なぜオペレーションミスが起こったか

前述の通り、リリースフラグ自体は、本来オンでもオフでもシステムは正常に動作するように設計されています。リリースの切り戻しをより素早く行えるよう、システムの管理画面上で簡単に変更できるようにしていました。

具体的には、管理画面上ではリリースフラグが一覧表示になっており、フラグを変更するボタンをクリックして確認するだけで、変更可能でした。 意図したリリースフラグと一行ずれたものを押してしまうミスが起こりやすい状態になっていました。 対策として、一覧画面での変更をやめ、個別のリリースフラグの画面に遷移した上で変更をするようにし、変更する際にはリリースフラグの名前の入力をするようにしました。

オペレーション上も、リリースフラグの誤操作によるリスクは低いと考えていたので、作業時の確認を徹底するフローができていませんでした。 これに関しては、フォーム画面に必要事項を入力すると、作業上の注意項目がのった手順書が自動で作成される仕組みをつくり、月次モニタリング運用を行うことにしました。 また、手順書をつくる対象作業の見直しとその結果の周知も実施しました。

リリースフラグ自体は、今後も素早い切り戻しのために必要だと考えていて、その中でいかにミスの起こりにくい仕組みを実現できるかが難しいポイントだと思っています。 今後運用していく中で、リスクを適切に評価しながら改善していきたいと思っています。

なぜ影響範囲を即座に判断できなかったか

繰り返しになりますが、リリースフラグ自体は、本来オンでもオフでもシステムは正常に動作するように設計されています。それなのに影響範囲をすぐに判断できなかったのは、以下の3点がネックになったからでした。

1点目は、意図せずオフになったフラグが多かったことです。数が多いことで、すぐに影響範囲を正確に判断することが難しくなっていました。

2点目は、どのフラグがオフになったのかすぐにわからなかったことです。リリースフラグの変更はリスクが低いと考えていたこと、頻繁に操作するものではなかったことから、どのフラグがいつ・どう変更されたのかが、管理画面上ですぐわかるようになっていませんでした。activity_logや、直前のDBの状態を調べる必要がありました。

3点目は、古いリリースフラグが残っていたことでした。リリースフラグは主にリリース直後の切り戻しに使うのですが、リリース後経過観察をした上で削除する場合もあり、そのまま消されずに残っていたものが多くありました。そして負債化し、そのフラグの影響範囲を読むことが難しくなっていました。

対策として、1点目については、リリースフラグの大掃除大会を実施し、リリースフラグの数を大幅に減らすことにしました。数年間の負債が溜まり続けた結果、簡単に終わる作業ではないですが、障害を契機にエンジニアチーム全体で取り組んでいます。

2点目については、リリースフラグが変更されたときに、変更ログを自動的に社内SNS (slack) に飛ばす仕組みを作り、変更履歴をすぐに追えるようにしました。

3点目については、リリースフラグの管理体制を作ることにしました。リリースフラグの目的、残存期間の目安、期間を超過した場合のアクション、残存させ続ける条件等を定め、月次モニタリング運用に組み込むことにしました。

障害からのまなび

障害からの大きな学びは、開発上のリスクをサービスの成長とともに適切に評価しなおしていくことの大事さと難しさでした。 今回のシステム障害の原因となったリリースフラグでは、使いだした当初は障害につながるリスクは低いと思っていましたが、数年たつうちに、あっという間にリリースフラグもそれを扱うエンジニアも大きく増え、潜在的にリスクが増していました。 リリースフラグだけでなく、サービス全体としても、ユーザーさんの数、ユーザーさんの質、扱うデータの性質がどんどん変化していく中で、それらの変化を適切に捉えた上で、開発全体のリスク評価をしなければいけません。

10月31日のシステム障害から2ヶ月がたち、障害の原因分析とすぐに行う対策の完了に目処がついてきたので、来月からは改めて開発全体のリスクの再評価に取り組む予定です。 社内においてこれまで見落としてきたリスクがなぜ見落とされたのかを分解整理しつつ、社外の知見も借りながら、年単位で開発プロセスを振り返り、リスクを最小化していく努力を続けていきたいと思っています。

最後に

重ねて、利用者の皆様にシステム障害によりご迷惑、ご心配をお掛けしましたことをお詫び申し上げるとともに、お客様への価値を安全に、かつ最大最速で届けられるようfreeeの開発体制を進化させ続けていきたいと思います。

つきましては、freeeの開発基盤を進化させていくエンジニアを募集しております。 興味があれば、ぜひご連絡ください!

jobs.jobvite.com

明日は、freeeの銀行同期基盤を支えるgoエンジニア、しみっちょです!

freeeのプロダクトセキュリティを高めるための取り組み

この記事はfreee Developers Advent Calender 2018 21日目の記事です。

 

こんにちは、freeeでCSIRTとソフトウェアエンジニアの二足のわらじを履く liva です。

社内では「攻撃する人」で通ってます。日常の本人は至って無害です。

 

早いものでもう年末で、この記事が公開される日は会社の忘年会です。

きっと今年もどんちゃん騒ぎです。お酒は好きですが酒に呑まれてインシデントを起こさないように気をつけたいところです。

 

freeeのプロダクトは日々様々な機能開発が行われ、短いスパンで各種リリースされ、プロダクト自体が大きくなっています。

それに伴って外部からの侵入や情報漏洩を狙った攻撃を受ける可能性が増えてきています。

この記事ではそういったことを防ぐために社内で行ってる取り組みを紹介します。

1週間前に公開されたeijiさんの記事よりはプロダクト寄りのお話になります。

developers.freee.co.jp

 

 

商用ツールを利用した脆弱性診断

freeeのプロダクトは大規模でとてもじゃないけど人が全部見切れる量ではありません。そこで脆弱性診断に特化した商用のツールを利用して日々スキャンをかけています。いわゆる内製化です。1年かけてようやくメインプロダクト1つを完了させられました。巨大すぎるぞ。

ツールは「現状どうなっているか」を把握するために利用しています。検出されてきた脆弱性は以下の観点で対応要/不要のハンドリングを行っています。

  • その脆弱性の存在確認
  • その脆弱性を突かれた場合の被害と影響範囲

ツールは機械判定なため、どうしても誤検知の問題があります。そのため、まずはその脆弱性が本当に存在するのかを確認します。誤検知であることがわかった場合は、そこで対応は終了です。

存在していることがわかった場合、その脆弱性による被害と影響範囲を調査します。ここで言う「被害」とは金銭的であったり、社会的信用であったり、様々です。情報が漏洩する場合は社会的信用が、サービスダウンを引き起こす場合は金銭的な被害と社会的な信用が失われます。被害を想定し、その影響範囲を想定し、対処する/しないの判断を行っています。

対処する場合、機能によっては私が修正することもありますが、そのコードを実装した人にお願いすることもあります。現状は私が修正を行うことが多いです。

 

外部ベンダーへの脆弱性診断依頼

ツールだけではが存在するのでそれの対応として外部のセキュリティベンダーに依頼することもあります。第三者の専門家に依頼するため、私が業務の合間に片手間で探すより安心感があります。

依頼時は

  • 実施時期
  • 対象プロダクト
  • 仕様書や関係ドキュメント

の3点をまず伝えて、ざっと診断の規模を測ってもらいます。ざっくり出してもらった後は規模の調整をして、環境準備やベンダーから送られてきたヒアリングシートへの記入等を行い、診断を実施してもらいます。あとは報告書を受け取って内容を吟味します。修正の要否をざっと出した後、開発チームに脆弱性の修正を依頼、終わったところで再診断を実施します。このあたりはどこのセキュリティベンダーも同じ流れでしょう。

特定の期間中、第三者に見てもらえるのでとても助かります。

 

     

 

商用ツールは主に既存プロダクト、外部ベンダーは新規プロダクトと使い分けています。

プロダクトの性質によっては新規プロダクトであっても商用ツールを利用して回すこともあり、その場合の手動で見る箇所は私が担当しています。私は元々セキュリティベンダーで脆弱性診断をやっていたので、このあたりは慣れています。ある程度管理できる環境で攻撃を試せるので、第三者の立場でやっていた頃に比べて、とても気楽にやっています。

 

     

 

脆弱性診断以外で進めていることとして、開発者向けに脆弱性診断のTips集を作成して、PRレビュー時の動作確認に活かしてもらおうという試みが進行中です。その第1段としてTips集を作成しているのですが、この記事を書きながら並列で進めています。この記事が公開される頃には社内にも公開されているでしょう(多分)。

開発者にやってほしいという理由としては、コストと手戻りの省力化です。脆弱性診断を実施する頃になるとプロダクトはほぼ完成していてリリースを待っている状態です。そこで脆弱性を検出し、修正を行うとなると多大な手戻りが発生します。時間やコストの無駄になるため、PRを出した段階で最低限確認してほしい項目を出して、それを開発者に確認してもらい、必要なら修正してもらおうと考えています。

このあたりはまだ固まっていないので年始から本格的に検討していく予定です。

 

また、社内エンジニア向けのイベントとしてQ毎にhardeningというのをやっています。

悪いこと考えるおじさん’sがわざとセキュリティホールを作ったサーバーとプロダクトを用意して、参加者に配ります。2日間でセキュリティホールを探して修正、修正期間が終わるとおじさん’sが攻撃を仕掛けます。

今年の新卒で入社したエンジニアとバリバリの現役エンジニアを対象に2回実施して、概ね好評でした。

こちらは過去に本ブログで記事が公開されているのでよかったらどうぞ。

developers.freee.co.jp

 

freeeでは一緒に働ける人を募集中です。

jobs.freee.co.jp

 

CSIRTエンジニアも募集中です。

www.wantedly.com

 

明日は弊社の第1号社員平栗さんです。