Medley Developer Blog

株式会社メドレーのエンジニア・デザイナーによるブログです

ユーザー認証とOpenID Connect

こんにちは。開発本部のエンジニアの鶴です。 今回は先月に行った社内の勉強会TechLunchの内容をご紹介させていただきます。

イントロ

Webサービスでは、ユーザーにアカウントを作ってもらい、ログインをしてサービスを利用してもらう、というユーザー認証を利用するサービスも多いかと思います。 Webサービスを開発する側としては、サービスごとに都度ユーザー認証の仕組みを構築する必要がありますが、セキュリティ対策の観点から考慮することが多く、地味に開発の工数がかかってしまいます。

 

また最近では、Amazon CognitoFirebase AuthenticationAuth0など、ユーザー認証サービスがいくつかリリースされ、ユーザー認証の機能をこれらの外部サービスに任せて開発の手間を省くという選択肢も取れるようになってきています。 自分自身、かつて担当したプロジェクトでユーザー認証の仕組みをAmazon Cognitoにまかせてシステムを構築したことがありました。

しかし、当時は特にユーザープールの機能がリリースされて間もないこともあり、SDKの動作やサービスの仕様の理解にかなり手間取ったことを覚えています。

ユーザー認証サービスではOpenID Connectという仕様に準拠していることが多いのですが、おそらく自分にとってこの仕様の理解が疎かだったことが原因の一つだったと思います。

 

そこで今回は、ユーザー認証とOpenID Connectの仕組みについて改めて勉強し直したので、その内容を簡単に解説をさせていただこうと思います。

ユーザー認証とは

ユーザー認証の前に、そもそも認証とはどういう操作のことを指すのでしょうか。 みんな大好きWikipedia先生によると、以下のような記載があります。

 

認証(にんしょう)とは、何かによって、対象の正当性を確認する行為を指す。 認証行為は認証対象よって分類され、認証対象が人間である場合には相手認証(本人認証)、メッセージである場合にはメッセージ認証、時刻の場合には時刻認証と呼ぶ。 単に認証と言った場合には相手認証を指す場合が多い。

 

ユーザー認証はWebサービスにとってリクエストを送信してきた相手の正当性を認証することなので、相手認証の1つですね。 さらに相手認証の認証方法として2通りの方法があります。

 

第1の方法は、被認証者が認証者に、秘密鍵をもっていることによって得られる何らかの能力の証明を行う方法である。第2の方法は、被認証者が認証者に、被認証者の公開鍵に対応する秘密鍵の知識の証明を行う方法である。

 

ユーザー認証の場合、多くはこの第1の方法での認証で、ログイン時にユーザーIDに加えて、この「秘密鍵」としてアカウント作成時に登録しておいたパスワードを入力することでユーザー認証を行っているかと思います。

Webサービスでのユーザー認証

Webサービスで扱う情報の秘匿性が高くなればなるほど、この「秘密鍵」が本当にそのユーザーにしか提供できない情報であることが求められます。

上述のようなパスワードによる認証の場合、パスワードが推測されるなどして悪意のある第三者にアカウントが乗っ取られてしまう事件はよく耳にします。

よりセキュリティを高めるため、パスワード以外の認証や多要素認証などを用いる事が増えてきました。

 

また、セキュリティの観点だけでなく利便性の観点からも、パスワード入力の代わりに指紋認証や顔認証によるログインや、あるいは各種SNSアカウントによるログインも増えてきています。自社の複数のサービスを連携できるようユーザーに共通IDを提供したい、といったケースもあるかもしれません。

 

最近ではパスワードレス認証やWebAuthnも注目されていますね。今回は紹介は割愛しますが、パスワードレス認証の一つであるFIDO認証は、前述の「被認証者が認証者に、被認証者の公開鍵に対応する秘密鍵の知識の証明を行う方法」を利用した認証方式のようです。(ref1, ref2

 

このように、セキュリティの観点やユーザー利便性の観点などにより、Webサービスにおけるユーザー認証機能は1回作ったら終わりではなく、時流に応じて適宜改修する必要が出てくることもあるかと思います。

 

しかし、特にユーザー認証がメインのサービスと密結合している場合などでは、認証の前後など認証処理そのものだけでなくその周辺の処理への影響範囲も無視できない場合もあり、ユーザー認証の改修に工数が思ったよりかかってしまったり、対応が滞ってしまうこともあるかもしれません。

 

そんなとき、認証サービスをメインのサービスと切り離すことでより柔軟なユーザー認証手段を提供できるよう、OpenID Connectの導入を検討してみても良いかもしれません。

OpenID Connectとは

OpenID Connect(以降、OIDC)について、本家サイトでは以下のように説明されています。

 

OpenID Connect 1.0 は, OAuth 2.0 プロトコルの上にシンプルなアイデンティティレイヤーを付与したものである. このプロトコルは Client が Authorization Server の認証結果に基づいて End-User のアイデンティティを検証可能にする. また同時に End-User の必要最低限のプロフィール情報を, 相互運用可能かつ RESTful な形で取得することも可能にする.

この仕様は, OpenID Connect の主要な機能である OAuth 2.0 上で End-User の情報伝達のためにクレームを用いる認証機能を定義する. この仕様はまた, OpenID Connect を利用するための Security, Privacy Considerations を説明する.

 

日本語, 英語

 

個人的には、メインのサービスと認証サービスを切り離して運用することを想定して仕様が規定されている点が重要と考えます。 OIDCを利用することで、ユーザー認証をより柔軟に改修したり新しい認証方法に対応したりすることがしやすくなることが期待されるからです。

 

なお、OIDCの仕様には認証手段自体(パスワード認証や多要素認証など)に関しては規定されておらず、あくまで認証サービスによる認証結果の取得方法や扱い方についてが規定されています。

また、様々なユースケースに対応できるよういくつかの処理フローやオプショナルな設定が提供されていますが、その反面セキュリティの確保は実装者に委ねられており、ユースケースに応じて適切な実装を行う必要があります。

 

前述したユーザー認証サービスであるAmazon CognitoやFirebaseAuthenticationなどは、認証手段が標準でいくつか提供されており、加えてバックエンドとSDKにOIDC固有のセキュアな実装が施されてあるため、開発者は最小限の設定だけでユーザー認証機能が利用できるようになります。便利ですね。

処理フローの解説

さて、OIDCの具体的な処理について解説していこうと思います。


まず登場人物です。

  • OpenID Provider(OP):認証認可を行うサービス。ユーザー認証情報(識別子やパスワードなど)を管理したり、認証に関するユーザー属性情報(氏名やユーザー名など)を保持する。
  • RelyingParty(RP): アクセス元のユーザーの認証とユーザー属性情報を要求するサービス。ユーザーからのリクエストに対しOPによる認証結果を信頼(rely)してリソースへのアクセスを許可する(例えばマイページを表示するなど)。
  • EndUser:ログインをしてサービスを利用しようとしているユーザー。

 

基本的な用語も先に簡単に紹介しておきます。

  • クライアントID:OpenID Providerで管理する、RelyingPartyの識別情報。
  • クライアントシークレット:OpenID ProviderがRelyingPartyごとに発行する秘密鍵
  • 認証コード:後述するAuthorizationCodeFlowでOpenID Providerが発行する短命のパスワードのようなもの。
  • IDトークン:OpenID Providerから発行される、ユーザーによる認証を行った証明情報。JSON Web Token(JWT)で表現され、検証により改ざん検知することができる。認証の内容(OpenID Provider、ユーザー識別子、RelyingPartyのクライアントID、有効期限など)やユーザー属性情報が格納される。
  • アクセストークン:OpenID Providerが保持するユーザー属性情報に対しアクセスするためのOAuth2の認可トークン。

OIDCの処理フローは大きく分けて3種類が規定されています。

  • AuthorizationCodeFlow:認証成功時にOpenID ProviderがRelyingPartyに対し認証コードを発行し、RelyingPartyはこれを用いてOpenID ProviderからIDトークン等を取得する。RelyingPartyがサーバーサイドアプリケーションで、OpenID Providerから発行されるクライアントシークレットを安全に管理することができる場合などに用いられる。
  • ImplicitFlow:認証コードを使わず認証結果のレスポンスでIDトークン等を取得する。RelyingPartyがクライアントアプリケーションの場合など、クライアントシークレットが安全に管理できない場合などに用いられる。
  • HybridFlow:AuthorizationCodeFlowとImplicitFlowの組み合わせ。

これらのフローの違いは以下の表のとおりです。

 

f:id:medley_inc:20190426141901p:plain

公式より引用

 

今回は、公式こちらの解説記事などを参照しながら、基本の処理フローであるAuthorizationCodeFlowについて解説します。

 

簡略化のため、イメージ重視で登場人物は「ユーザー」「(ユーザーにサービスを提供する)Webサービス」「認証サービス」と表現することにします。

f:id:medley_inc:20190426141939p:plain

大まかには以下のステップで処理が行われます。

  1. ユーザーからのアクセスに対し、Webサービス認証サービスにユーザー認証を要求する
  2. 認証サービスはユーザー認証を行い、認証コードを発行して、ユーザーWebサービスにリダイレクトさせる
  3. Webサービスは2で取得した認証コードを用いて認証サービスにIDトークン等をリクエストする
  4. Webサービスは3で取得したIDトークンを検証し、ユーザーの識別子を取得する

Step.0 : 事前準備

あらかじめWebサービス認証サービスからクライアントIDとクライアントシークレットを取得し保持しておきます。

f:id:medley_inc:20190426142007p:plain

Step.1: ユーザー認証の要求

ユーザーWebサービスに対し一般的なログインの流れでログインを要求すると、Webサービス認証サービスにリクエストをリダイレクトします。

f:id:medley_inc:20190426142502p:plain

Webサービスから認証サービスへのリダイレクトのURLは以下のような感じです。

HTTP/1.1 302 Found
Location: https://server.example.com/authorize?
   response_type=code
   &client_id=s6BhdRkqt3
   &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
   &scope=openid%20profile
   &state=af0ifjsldkj

 

response_type でOIDCのどの認証フローを使うかを指定します。

redirect_uri は、認証サービスでの認証が成功したときのWebサービスにコールバックするURLです。これは事前に認証サービスに登録しておく必要があります。

scopeには認証の内容を設定します。openidは必須で、他にはOAuth2のアクセストークンを使って取得できるユーザー属性情報を指定します。

scopeで指定できるユーザー属性情報は以下のとおりです。

 

f:id:medley_inc:20190426142232p:plain

公式より引用

 

ユーザーの認証でよく使われそうな「氏名」や「メールアドレス」など基本的な属性情報が定義されています。

 

state はCSRF対策などのためのランダム値です。認証フローを開始するたびにWebサービスが発行し、リクエストとコールバックの間で値が維持されます。

 

他にもいくつかのパラメータ(nonce など)が定義されており、必要に応じて利用します。

Step.2: ユーザー認証と認証コードの発行

認証サービスでは認証手段に応じてログインID・パスワードの入力フォームなどを表示し、ユーザーから認証情報を取得して認証処理を行います。

f:id:medley_inc:20190426142212p:plain

認証サービスはユーザーの認証に成功すると、認証コードを発行し、ユーザーWebサービスにリダイレクトさせます。

 

HTTP/1.1 302 Found
Location: https://client.example.org/cb?
   code=SplxlOBeZQQYbYS6WxSbIA
   &state=af0ifjsldkj

 

リダイレクト先について、認証サービスはStep.1で受け取った redirect_url を認証サービスに予め登録されているURLと合致することを検証する必要があります。Webサービスのなりすましを防ぐためです。

またWebサービス側で認証サービスからのレスポンスであることを確認できるよう、state もパラメータに含めます。

 

なお、認証に失敗した場合は下記のように認証エラーした内容をパラメーターに加えてWebサービスにリダイレクトさせます。

HTTP/1.1 302 Found
Location: https://client.example.org/cb?
   error=invalid_request
   &error_description=
     Unsupported%20response_type%20value
   &state=af0ifjsldkj

Step.3: 認証結果の取得

Step.2 でWebサービス認証サービスからのリダイレクトを受け、認証コードを取得すると、この認証コードを利用して認証サービスに対して認証結果情報(IDトークンなど)を取得します。

f:id:medley_inc:20190426142612p:plain

Webサービスから認証サービスへの認証結果取得リクエストは以下のような形式になります。

 

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
 
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
  &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

 

認証コードを送信する必要があるため、POST メソッドでリクエストします。またクライアントIDとクライアントシークレットによるBASIC認証を行います。

このリクエストでクライアントシークレットが必要になるのですが、これは認証サービスにとってWebサービスの正当性を検証するための重要なパラメータであり、安全に管理される必要があります。

SinglePageApplicationのようにユーザー側にあるアプリケーションでOIDCを処理する場合には、このクライアントシークレットが安全に管理される保証がないため、AuthenticationCodeFlowではなくImplicitFlowなどを利用する必要があります。

 

Webサービスからのリクエストを受け取った認証サービスは grant_type にStep.1で指定した処理フローに該当する情報を渡し、認証コード( code )と合わせて認証サービスにリクエストの検証をさせます。

認証サービスはリクエストの検証に成功すると、Webサービスに対し認証結果としてIDトークン等を返却します。

 

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-cache, no-store
Pragma: no-cache
 
 {
  "access_token":"SlAV32hkKG",
  "token_type":"Bearer",
  "expires_in":3600,
  "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
  "id_token":"eyJ0 ... NiJ9.eyJ1c ... I6IjIifX0.DeWt4Qu ... ZXso"
 }

 

access_token は認証サービスで管理しているユーザー属性情報を取得するためのOAuth2トークンです。

refresh_tokenは認証サービスからaccess_tokenを再発行する際に利用します。

Step.4: 認証結果の検証

Webサービス認証サービスから取得したIDトークンを検証します。IDトークンは前述の通りJWTで表現されており、認証サービスの公開鍵を用いて検証することができます。

手順は こちら をご確認ください。他にも参考リンクを紹介しておきます。

下記はIDトークンに含まれる認証情報の例です。

 

{
  "iss": "https://server.example.com",
  "sub": "24400320",
  "aud": "s6BhdRkqt3",
  "exp": 1311281970,
  "iat": 1311280970
}

 

このうち sub が認証サービスで管理されているユーザーの識別子です。

iss認証サービス、audはWebサービスのクライアントIDになります。

exp、iatはそれぞれ認証の有効期限と認証したタイムスタンプです。

 

WebサービスはIDトークンが正しい内容であることが確認できれば、これをログインセッションと紐づけて保管します。

以上で認証処理は完了です。

ユーザー属性情報の取得

ユーザー認証後、Webサービスがユーザー名などのユーザー属性情報が必要になった場合、Step.3 で取得した access_token を利用し認証サービスに対してユーザー属性情報をリクエストします。

 

GET /userinfo HTTP/1.1
Host: server.example.com
Authorization: Bearer SlAV32hkKG

 

このリクエストにより、Step.1の scope で指定したユーザー属性情報が取得できます。

まとめ

以上少し長くなりましたが、ユーザー認証とOpenID Connect、特に基本のAuthenticationCodeFlowについて解説しました。限られた発表時間の中での解説のため厳密さより雰囲気を重視した内容となりましたが、お気づきの点などあればお知らせいただければと思います。

 

サービスの要件やフェーズによってOIDCを取り入れるかどうかは様々ですが、ユーザー認証の実装を自前で実装、メンテナンスしていくだけでなく、Amazon Cognitoなどの便利な認証サービスを利用していくことも選択肢の一つとして検討してみても良いかもしれません。

 

そしてそれら便利な認証サービスをうまく使いこなすためにも、その背景にあるOIDCの仕様や思想、そもそも認証の仕組みについて立ち返ってみると、理解が一段と深まるかとおもいます。

 

RubyKaigi 2019にメドレーがBreakfast Sponsorとして参加しました

こんにちは。開発本部のエンジニア・新居です。

メドレーは4/18〜4/20に開催されたRubyKaigi 2019にBreakfast Sponsor(朝食スポンサー)として協賛させていただきました(一昨年のRuby Sponsor昨年のLightning Talks Sponsorに続き、3年目の協賛です)。
2017年のレポート
2018年のレポート
2019年は福岡県の福岡国際会議場での開催でした。会場に向かう途中の博多駅ではさっそくRubyKaigiのポスターに迎えられ、RubyKaigiムードが高まっておりました。

RubyKaigi

博多駅ではさっそくRubyKaigiのポスターがお出迎え
ということで、今年RubyKaigiの様子をレポートさせていただきます。

Breakfast Sponsorの様子

今回はBreakfast Sponsorとしての協賛で、RubyKaigi2日目と3日目の朝8時30分から10時までの時間帯で、RubyKaigiに参加されるみなさんに朝食をご提供させていただきました。
 
朝食会場は福岡国際会議場内の1Fにあるレストラン ラコンテさん。朝食の内容はビュッフェ形式で、焼き魚やオムレツなどの定番おかずと、福岡名産の辛子明太子や辛子高菜をたらふく食べられる朝食でした。

入り口でみなさんをお出迎えするエンジニア稲本

おしゃれなテラス席

ビュッフェに並ぶおかず

フルーツもたくさん

「辛子明太 & 辛子高菜」乗せごはん

福岡名産の辛子明太子と辛子高菜を白ごはんに添えてたらふくいただきました

会場の様子、大盛況でした

テラス席はグローバルな感じ


Twitterでも朝食の様子を話題にしていただけたりと、ご満足いただけた様子が伺えました。
ご来場いただいた人数は、RubyKaigi2日目(朝食1日目)は379名、3日目(朝食2日目)は411名でした。
 
朝食会場の出入り口でご案内していると「美味しかったです、ありがとうございました!」というお声を直接いただけたりと、みなさんにご満足いただけたようで良かったです。
 
Breakfast Sponsorでの参加は初めてでしたが、みなさんが満足気に朝食会場を後にする姿を見ているとこちらも嬉しい気持ちになりました。
 
朝食をご利用いただいたみなさん、本当にありがとうございました。
 
今年はBreakfast Sponsorという形でしたが、RubyRubyコミュニティの発展のため、今後も様々な形で貢献していければと思います。

RubyKaigi 2019の様子

今年も毎年恒例のMatzさんのKeynoteから始まりました。
今年は「The Year of Concurrency」というテーマで、Ruby 3についての発表でした。
 
Ruby 3のStatic Analysis、Performance、Concurrencyあたりの話を中心に、Rubyの今後の展望について語られました。普段Rubyを使って仕事をしている身として、MatzさんからRuby 3の話を聞けたのは貴重な時間でしたし、改めてRubyの進化を実感できるセッションでした。

MatzさんのKeynote

その他のセッションスケジュールについてはこちら。

2階にはブースゾーンがあり、セッションの合間にはたくさんの参加者で溢れかえっていました。

ブースゾーンは大盛況

ブースゾーンの出入り口付近には各社のノベルティ

Ruby関連書籍の展示も

会場5階(最上階)にはハックスペースが用意されていました。
ここで各々休憩したり、黙々と作業したり、仲間と談笑したりと、様々な用途に使われていました。

ハックスペース入り口

ハックスペースの中(このときはセッション中だったので空いてました)

福岡開催ならではの屋台スペースも用意されていました。
ランチタイムには屋台ラーメンなどが振る舞われ、めちゃくちゃ混み合っていましたが、こういう地域特有の催しはRubyKaigiを盛り上げてくれるので良いですね。

ランチ前になるとゾロゾロと人集りが

ランチタイムの屋台は大行列

屋台でラーメンを食らう参加者を羨むエンジニア中畑


メドレーブースの様子

また、2階のブースゾーンにはメドレーのブースも出展しました。

今回参加したメンバー全員で
ノベルティーにはメドレーロゴ付きのうちわ、ステッカー、お水、そして恒例の絆創膏を用意しました。
 
RubyKaigi 2018でもらったメドレーの絆創膏が、子供が怪我したときに役に立ったよ〜という嬉しいお声をいただいたりもしました。
靴擦れや擦り傷を負ったとき、お子さんが転んだときとかに役に立つので、今度見かけた際はぜひお持ち帰りください。

メドレーの絆創膏
ブースではメドレーの会社説明やメドレーが提供するサービスの説明などを行いました。
 
スポンサーとして初参加だったRubyKaigi 2017に参加したときよりもメドレーのことを知っている人が増えているなあと実感しました

ブースで対応するエンジニア達(中畑、稲本、橋本)

Matzさんにも来ていただきました!

福岡の様子

そして福岡といえば美味しいごはんですよね。
 
1日目の夜はRubyKaigi 2019 Official Partyが開催され、中洲川端商店街を半貸切にして日本酒やうどん、ラーメンや地鶏などが振る舞われました。

RubyKaigi 2019 Official Partyの会場・中洲川端商店街のGuide Map

大樽に入って日本酒が配られてました

日本酒のラインナップ

f:id:medley_inc:20190424143021j:plain

うどんを前に満面の笑みの広報・深澤

夜は福岡の美食を求めて街に繰り出しました。

絶品イカの活造り

定番モツ鍋

出汁が最高の水炊き

会場近くの某有名ラーメン店のきくらげラーメン

あまりのうまさに昇天するエンジニア中畑

また、RubyKaigi初参加の2017年から続けている神社参拝にも行ってきました。
今回は警固神社(けごじんじゃ)に参拝してきました。
 

警固神社入り口

参拝するエンジニア中畑


さいごに

2017年から3度目となるRubyKaigiの協賛の様子をお届けしました。
 
Breakfast Sponsorとして、RubyKaigi参加者のみなさんにご満足いただけて本当に良かったなあと思います。
繰り返しになりますが、RubyRubyコミュニティの発展のため、今後も様々な形で貢献していければと思います。
 
来年2020年は長野県松本市での開催ということで、またみなさんとお会いできることを願って、レポートを締めたいと思います。

rubykaigi.org

お知らせ

メドレーでは医療業界に存在する課題にITを駆使して取り組んでいきたいメンバーを、デザイナー・エンジニアを中心に全職種絶賛募集中です。皆さまからのご応募お待ちしております。

www.medley.jp

RubyKaigi 2019に朝食スポンサーとして協賛します

みなさん、こんにちは。開発本部の平木です。

2017年から、RubyKaigiにスポンサーとして参加していましたが、今年も朝食スポンサーとして協賛することになりました! f:id:medley_inc:20190412183606p:plain

(去年とおととしの参加レポート)

developer.medley.jp

developer.medley.jp

会場である、福岡国際会議場内の1Fにあるレストラン ラコンテさんでビュッフェ形式の朝食を楽しむことができます。

会期中の4/19~20日の8:30 ~ 10:00で開催しています。当日はメドレーメンバーがご案内する予定になっていますので、ぜひお気軽に話かけてください!目印として、メンバーはメドレーパーカーを着用しています。

f:id:medley_inc:20190412183045j:plain

メニューは和洋それぞれ用意があり、福岡ならではのメニューも入っていますので、1日の始まりにぜひおいしい朝食を食べて元気にセッションに臨んでください。

また、スポンサーブース内にもメドレーブースが常設されており、エンジニア4人も行く予定となっていますので、ぜひお立ち寄りいただいて、みなさんと交流できればと思います。

それでは、RubyKaigiという大きなイベントでまた皆様にお会いできるのを楽しみにしています!!

電子処方箋実証事業におけるFHIRの活用と標準化の展望

こんにちは。CLINICS事業部の児玉です。

今回は、メドレーが2018年12月に厚生労働省から受託した「電子処方箋の本格運用に向けた実証事業」で、医療情報標準規格のFHIRを基盤とした電子処方箋管理システムを構築しましたので、その内容についてご紹介します。

FHIRとは

FHIR(Fast Healthcare Interoperability Resources)とは、医療情報交換の国際標準規格であるHL7(Health Level 7)の中で最も新しい規格であり、インターネットテクノロジーをベースとした、シンプルで効率的にシステム間での情報共有を可能にする「次世代の医療情報標準規格」として世界各国で注目されています。

HL7は、世界に30以上の国際支部を有しており、日本では1998年に日本HL7協会が設立されました。そして、現在流通しているHL7規格には、データ交換に利用されるHL7v2と、医用文書の記述に利用されるCDA(Clinical Document Architecture)が存在します。

電子処方箋とは

電子処方箋とは、従来の紙に印刷された処方箋ではなく、医療機関調剤薬局が電子データを用いて処方内容をやりとりする仕組みです。単純にペーパーレス化することだけが目的ではなく、患者個人の服薬履歴を電子的に管理して、重複投薬の適正化を図るといった目的もあります。

実証事業の背景と概略

2016年3月の法令改正で、処方箋の電子的な交付が可能となり、運用ガイドラインも策定されました。しかし、法令改正から数年が経過した現在においても、実運用での課題が払拭できずに、電子処方箋の全国的な普及は進んでおりません。

f:id:medley_inc:20190328142501p:plain
ガイドラインに定められた運用フロー(電子処方せんの運用ガイドラインより転載)

元来、処方箋には医師の記名押印、または署名が必要であると医師法で定められています。現行のガイドラインは、この規則を踏襲して設計されていますので、紙の処方箋の代替としてCDAで記述された静的ファイルを必要とし、記名押印の代替としてHPKIを使用した電子署名が必要となります。

また、クライアント端末で生成された静的ファイルが、インターネットに流通するフローとなっていますので、改ざんの検知を可能とするために電子タイムスタンプを付与する必要があります。

このように複雑化された運用フローが、電子処方箋の普及を阻害する要因の1つであると考えられます。

こうした状況を踏まえ、現行のガイドラインに縛られず、円滑な運用ができる仕組みを検討するために、実際の医療機関調剤薬局を使用したフィールド実験を実施しました。


実証事業概略

  • 実施目的:電子処方箋の運用の仕組みの検討・実証・考察
  • 実施期間:2019年2月4日 - 2019年3月17日
  • 実証エリア:東京都港区
  • 協力施設:2医療機関 / 6薬局
  • 利用実績:64件

電子処方箋管理システムの概要

以下に示すのは、今回の実証事業で開発した評価システムです。本システムは「処方箋管理システム」「医療機関システム」「薬局システム」「PHRアプリ」の4つのシステムから構成されています。

f:id:medley_inc:20190328140004p:plain
システム概観


  • 処方箋管理システム

    医療機関システム、薬局システム及びPHRアプリから接続され、各システムからの処理要求を受けて、処方データと調剤データの返答、作成、編集、及び削除を行う。

  • 医療機関システム

    診療結果としての処方データを処方箋管理システムに登録し、その結果として返される処方箋アクセスコードを患者に共有する。処方箋アクセスコードはQRコードの活用を想定し、QRコードを印字した紙又は電子データを患者に共有する。

*「QRコード」は株式会社デンソーウェーブの登録商標です。
  • 薬局システム

    訪問してきた患者の本人確認を行った上で、処方箋アクセスコードを受け取り、処方箋管理システムにアクセスし処方データを参照する。処方後は調剤データを処方箋管理システムに格納する。

  • PHRアプリ

    患者がオンライン診療やお薬手帳の機能を利用するためのアプリ。処方箋管理システムへのアクセスが許可され、医療機関システムから受け取った処方箋アクセスコードを元に、調剤結果を参照することを可能にする。


医療機関システムは、メドレーのクラウド電子カルテ「CLINICSカルテ」を利用しましたが、システム連携に関わる部分については、他の電子カルテなどでも活用できるよう、疎に結合した設計を意識しました。

処方箋管理システムは、前述の通りFHIRインターフェイスを基盤として構築しました。これは現行のガイドラインには記載されていない新たな試みです。

HPKIを利用したSSO(Single Sign On)による本人資格確認と、FHIRインターフェイスを利用したクラウドベースでのデータフローを実現することが可能であれば、複雑化の要因となっている静的ファイル、電子署名、タイムスタンプは不要であると考えました。

データ設計

FHIRには「リソース」と呼ばれるデータセットが定められています。リソースは、Patient(患者)、Practitioner(施術者)、Organization(組織)といった粒度で設計されており、リソース単位でのデータ交換が可能です。

FHIRを利用するためには、その目的に応じたリソースの選定と、リソースの下位概念であるフィールドに設定する具体的な値を定義する必要があります。

例えば、日本では人名を記述する際に、漢字氏名とカナ氏名を併記することが一般的ですが、グローバル・スタンダードではありません。このような国の事情に応じて、ローカライズされた記述ルールを定める必要があります。

実証事業で使用したリソース

リソース 説明
Patient 患者
Practitioner 施術者(処方医/薬剤師)
PractitionerRole 施術者役割
Organization 組織(医療機関調剤薬局
MedicationRequest 投薬要求
MedicationDispense 調剤実施
Coverage 保険

FHIRを使用した所感

FHIRの改版はon-Goingで行われています。実証事業のための開発を始めた頃は、STU3(Standard for Trial Use 3)が公式バージョンでした。しかし、あるとき急にFHIRのホームページが接続不安定になり困っていたところ、翌日にはR4(Release 4)に更新されていたということもありました。

このように、日進月歩のFHIRをプロダクトに組み込むには、タイミングの見極めと、アップデートに追従する「覚悟」を決めることが大切だと思います。

f:id:medley_inc:20190328210514p:plain
2018年12月27日にR4がCurrent Versionになりました

FHIRの利点は、従来のHL7規格と比較した実装容易性にあると考えます。REST(REpresentational State Transfer)のように、Webサービスでは一般的に普及している概念を標準として取り込んでいるため、実装者は特別な知識を習得する必要がありません。また、FHIRを実装するためのオープンソースライブラリが豊富に提供されており、これらを活用することによって、本当に必要な処理に注力して開発することが可能となります。

臨床概念モデルとしての観点では、CDAのベースとなっているHL7v3-RIM(Reference Information Model)と比較すると、クラス、継承のようなオブジェクト指向の概念が廃止されています。あらゆる臨床概念をモデリング可能とすることを目指したRIMと比べると、さすがに表現可能な範囲は狭まると思われますが、網羅性は実用域のレベルには達しているのではないでしょうか。

また、1:1のシステム連携におけるデータ交換では、すでに稼働しているv2インターフェイスを、無理してFHIRに置き換える必要は無いと思います。用途に応じて、既存の規格と共存していくのが大切であると考えます。

実運用へ向けての課題

FHIRリソースは、臨床概念としてユニバーサルに利用可能なものを中心に構成されています。保険情報のような各国の医療制度に応じて異なるものや、調剤技法に対する「一包化」や「粉砕」などの細かな指示情報に関しては、ある程度アドホックマッピングするしかありませんでした。実装者によるマッピングのブレが生じないようにするためには、指標となるガイドラインの策定が必要になります。

また、リソースにマッピングする医薬品や用法のマスターコードについては、厚生労働省標準マスターの利用が望まれます。しかしながら、満遍なく普及しているとは言い難い状況ですので、標準マスター利用の推奨も併せてガイドラインに明記することが必要です。

ガイドラインは、メドレー1社で策定することが可能なものではなく、医療情報システムの開発に関わる多くの開発者にFHIRを利用していただき、実装方法についての議論を交わす必要があります。しかし、現時点での日本国内におけるFHIRの活用事例は、残念ながらほとんど見られません。

次にご紹介するのは、FHIRを使用した簡単なコードのサンプルと、ローカル環境でFHIR Serverを簡易的に動かす方法です。実装者の方がFHIRに触れるきっかけになればと思って書きましたので、ご参考にしていただけますと幸いです。

FHIRの実装サンプル

FHIRを理解するためには、実際にコードを書いて動かしてみるのが一番だと思います。ここでは、ローカル環境でFHIR Serverを起動して、リソースを登録する簡単なプログラムを書いてみました。(オープンソースの恩恵を最大限に享受しています。)

実行環境

FHIR Server

DockerコンテナでFHIR Serverを起動します。簡単に動かせるように、DockerHubに公開されているHAPI-FHIRのコンテナイメージを利用します。

HAPI-FHIRとは、カナダのトロントにある医療研究機関のUHN(University Health Network)が立ち上げたプロジェクトで、FHIRのオープンソースライブラリを提供することを目的に活動しています。

Dockerコンテナイメージの取得

$ docker pull petersonjared/hapi-fhir
$ docker run -d -p 8080:8080 --name=fhir petersonjared/hapi-fhir:dstu3
$ docker exec -it fhir /docker-entrypoint.sh java -jar /usr/local/jetty/start.jar

Dockerをインストールするのが面倒な人は、HAPI-FHIRがグローバルに公開しているテストサーバーを利用することも可能です。ただし、世界中の人がテストに利用しているサーバーですので、機微な個人情報は登録しないよう注意が必要です。

FHIR Client

FHIR Clientは、Rubyで動かします。以下のGemを利用します。

$ gem install fhir_client
$ gem install fhir_models

Rubyのコードです。Patientリソースを作成してFHIR Serverに登録します。

patient.rb

require 'fhir_client'

client = FHIR::Client.new("http://localhost:8080/baseDstu3")
FHIR::Model.client = client
    
patient = FHIR::Patient.new

# 患者ID
identifier = FHIR::Identifier.new
identifier.value = '12345678'
patient.identifier = identifier
    
# 患者氏名
human_name = FHIR::HumanName.new
human_name.family = 'Kodama'
human_name.given = 'Yoshinori'
patient.name.push(human_name)

# 性別
patient.gender = 'male'

patient.create
puts patient.id

上記のコードを実行すると、FHIR ServerにPatientリソースが登録されます。ここでリソースを一意に特定するリソースIDが採番されます。今回は 19953 が採番されました。(puts patient.idで確認)

このリソースIDを利用して、FHIR ServerにHTTPリクエストを送ります。

$ curl http://localhost:8080/baseDstu3/Patient/19953

そうすると、先ほど登録したリソースがJSON形式で取得できます。

{
  "resourceType": "Patient",
  "id": "19953",
  "meta": {
    "versionId": "1",
    "lastUpdated": "2019-03-21T09:12:44.660+00:00"
  },
  "text": {
    "status": "generated",
    "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><div class=\"hapiHeaderText\">Yoshinori <b>KODAMA </b></div><table class=\"hapiPropertyTable\"><tbody><tr><td>Identifier</td><td>12345678</td></tr></tbody></table></div>"
  },
  "identifier": [
    {
      "value": "12345678"
    }
  ],
  "name": [
    {
      "family": "Kodama",
      "given": [
        "Yoshinori"
      ]
    }
  ],
  "gender": "male"
}

もちろん、患者IDなど利用して検索することも可能です。

$ curl http://localhost:8080/baseDstu3/Patient?identifier=12345678

さいごに

今回の実証事業では、FHIRのインターフェイスを活用することにより、シンプルなアーキテクチャとシームレスなフローで、迅速に処方箋管理システムの構築ができ、電子処方箋の運用評価を行うことができました。本実証事業の最終成果報告書は厚生労働省のサイトに公開されていますので、詳細について興味のある方はこちらをご参照ください。

www.mhlw.go.jp

メドレーは、実証事業で得られた知見を可能な限りオープンにして電子処方箋の普及推進に取り組むことはもちろん、インターネットを活用したオープンな技術の普及活動に積極的に取り組み、医療機関と患者の双方にとってより良い医療の実現を目指してまいります。

お知らせ

今回の電子処方箋実証事業の成果と、システム開発に活用したFHIRについて共有するイベントを、以下のとおり4月23日(火)に開催します。お時間ある方はぜひご参加ください。

techplay.jp

また、メドレーでは医療業界に存在する課題にITを駆使して取り組んでいきたいメンバーを、デザイナー・エンジニアを中心に全職種絶賛募集中です。皆さまからのご応募お待ちしております。

www.medley.jp

フロントエンドエンジニアがUI設計〜実装で考えていること

おはこんばんちは、開発本部エンジニアの大岡です。

先日、TechLunchという社内勉強会で「フロントエンジニアがUI設計〜実装で考えていること」という内容で発表しました。UI設計から実装の細かい話ではなくどういう気持ちで望んでるかという話で、基本的なことしか書いていませんが紹介させていただければと思います。

UI設計

UI設計をデザイナーがして、それをエンジニアが実装する場合とエンジニアが単独でUI設計から実装までする場合があります。今回はそれぞれのケースで、フロントエンドエンジニアがどういうことを考えてるかを紹介します。

とその前に、他人とUIについて話すときに気をつけてる言葉で分かりやすくまとまっているツイートがあったので紹介します。

  • 普通はそうする
  • 直感的にわかる
  • 使いやすい
  • わかりやすい

これらの言葉は誰にとってなのか?やそれまでの経験によって意味合いが変わってきてしまうので対象を明確にしないと相手と話が噛み合わなくなることもあるので気をつけています。今回何ヶ所か使っていますが実際UIについて話すときは使わないように心がけています

デザイナーから画面仕様をもらう場合

デザイナーが優秀であればあるほど、もらった画面仕様を元に早く手を動かしたくなります。ですがここはグッと堪えます。落ち着いて以下のようなことを考えてます。

  • なぜこの課題がうまれたのか
  • 解決したい課題の本質はなんなのか
  • 他の解決策はないのか
  • この機能を追加してしまうことにより他に影響がでてしまわないか
  • 追加ではなく他の機能を落とすことにより解決できないのか
  • そもそも必要なのか

など、この段階で理解できないことはチームで話したりして解決しておきます。次に画面仕様に目を向けまた考えます。

  • 似たようなコンポーネントがあったら統一できないか
  • より使いやすくできないのか
  • 操作感が他と明らかに違わないか
  • 操作に対して予想した動きになっているか
  • 表示されている情報に意味があるのか

など、画面仕様からは理解できないことや疑問点などはデザイナーとコミュニケーションをとり齟齬がでないようにします。

手を動かす前にある程度ユーザが解決したい課題を精度高く汲み取り落としこめるように努力してます。

自分でUI設計をする場合

「デザイナーから画面仕様をもらう場合」に書いたことをまずは考えています。

それらを踏まえ、すでに実装済みのUIで似たようなものがあれば似たように作ります。理由としては既にユーザが学習済みのUIのため新たに追加した機能だとしても比較的学習コストが低くなるのではないかと考えるからです。

似たようなUIがなく新たに作らなければならないときは以下を意識しています。

  • 表示する情報の精査
  • 表示する情報はリストなのか詳細表示なのか
  • 表示する情報に対しての操作はどんなものがあるのか
  • 操作に対してのレスポンス・納得感はどうすれば得られるのか
  • エラー表示をどうするのか
  • 表示する情報が多すぎて収まり切らない場合どうするのか
  • 表示する情報がない場合どうするのか
  • 画面サイズ毎に適切に表示できるか
  • 状態(クリックやホバーなど)を表現できてるか
  • リストの場合デフォルトの順番は適切なのか

などをざっくりノートなどに書き出し詳細を詰めていっています。行き詰まったら迷わずデザイナーに相談しにいきます笑

実装

細かい実装部分というよりはもっと大枠の基本的なことですが紹介します。

  • 何も考えずにコピペしない
    • 修正が大変になるので一箇所になるべくまとめる
  • 用途にあったコンポーネントを使う
    • 似てるからと使い回すとコンポーネント修正時に思わぬ変更が加わる可能性があるかも
  • コンポーネント間の関係が疎になるようにする
    • 密接な関係だと気を使い合わなくてはならず修正が大変
  • コンポーネントを作成する際に無理に汎用性をもたせない
    • 修正が困難になり逆に汎用性がなくなる場合が多い
  • Reduxに管理させるステートの粒度は適切か
  • なんでもかんでもReduxに状態を管理させてしまっていないか
  • 無駄な再レンダリングをしていないか
  • 無駄な通信をしていないか
  • 非同期通信のレスポンスが遅い場合にサーバー側の処理に問題がないか
  • 関数や変数は適切な命名で適切な場所に書かれているか
  • マジックナンバーを使ってしまっていないか
    • 使ってると修正大変
  • なるべく簡単に書けないか
  • エラー・例外時の動きは適切か

など細かいことを言い出したらキリがないですが、こんなこと意識してます。

よりよいものを届けるために

いろいろと書きましたがUI設計から実装完了まではなるべく早く終わらせようと意識しています。1サイクルを

  1. UI設計
  2. 実装
  3. 触る
  4. フィードバック

とした場合に、このサイクルをリリースまでに多く回すことによってより多くの気づきが得られるからです。基本的には一回作ってうまくいくことは希かと思っているからです。

ただ、フィードバックの段階で本当に色々な意見がでてきます。心が折れかけることやイライラすることもあるかもしれません。ですが、プロダクトとして必要なのか、今必要なのか、対象とする利用者としてなのか、ただの愚痴なのか等を見極め軸をぶらさないことが大切です。

フロントエンドのUIやパフォーマンス系は事業的に見ると優先度が低い場合が多い印象を受けます。優先度が上がるときは強い競合、数字的な上昇が見られなくなった時など危機感がでてきたときかなと。。。足りない機能を追加しないといけないし、そもそも人的リソースが足りないなどしょうがないことなのかなとも思っています。

初回リリース時に時間が足りなくても精度の高いものを作りたいという気持ちがあるため先ほどのサイクルを多く回し一人でも多くの人に触ってもらい気付ける回数を増やすことは大事なことだと思っています。

さいごに

あくまで私個人が考えてることなのでフロントエンジニア全てにあてはまるわけではありません。出来てないこと抜けてしまう時や本質的に理解していないことも多々あると思いますが、自分はこんなことを考えているという紹介でした。最後までお読みいただきありがとうございました。

 

▼メドレーで働くクリエイターたちのストーリーはこちら

www.medley.jp

改めてBigQueryのPartitioned tablesと戯れた話

こんにちは、開発本部の宍戸です。先日のメドレー社内勉強会「TechLunch」で、BigQueryのPartitioned tableについて発表しましたので、その話について書きたいと思います。

なぜ今Partitioned table?

ある案件でユーザーの操作ログを扱う必要があり、データ保管先にBigQueryを利用しようと考えていました。その際に、「以前はβ版だった分割テーブル、そういえば今使えるよね」という話になり色々調べてみた、というのが今回このテーマを選んだ背景です。

なぜ分割テーブルを使おうと思ったのか

ユーザーの行動/操作ログの確認についてはAPIサーバーのアクセスログで、ある程度その目的を果たすことができていました。

しかし、APIアクセスログですと今回対象にしたい”ユーザーの操作”以外にも多くの操作ログ(通知の取得ログなどをはじめとする各種データ参照など)を抱えてしまっているため、必要な情報を抽出するためには無駄が発生してしまう状態でした。無駄なスキャンで無駄なコストが発生するのは嫌ですよね。

ということで目的に即したデータに限定して保存/閲覧できるように、行動/操作ログは新しくPartitioned tableに保存することにしました。

また、新しいテーブルに保存する対象となる操作に関しては、これまで保存していた過去分のアクセスログのデータも新しいテーブルへ移行したいというニーズもあり、既存のデータを取得し加工をしたうえでデータを移行するというタスクも行いました。

分割テーブルの各種方法について

まずひとくちに「分割テーブル(Partitioned table)」と言っても、BigQueryではいくつかの実現方法があります。

  • 「取り込み時間で分割」されたテーブル
  • 「特定のカラムに基づいて分割」されたテーブル
  • 「時間ベースの命名方法を使用して分割」したテーブル

前述のとおり今回は過去データの移行なども同時に行いたい背景があったため「取り込み時間で分割」されたテーブルではなく、「特定のカラムに基づいて分割」されたテーブルを利用するようにしました。こちらのテーブルは分割するための列としてDATE型またはTIMESTAMP型を指定することで利用することができます。

こうして作られた分割テーブルは、パーティションと呼ばれるセグメントに内部的にさらに分割されており、参照するパーティションを限定することで、効率の良いアクセス(スキャン対象データ量の限定、高速化)が可能になります。

注意点として公式ドキュメントにもありますが、クエリの記述方法によっては期待したパーティションの絞り込みがされないことがあります。また分割テーブルへのクエリにはレガシーSQLを利用することができないため、標準SQLを利用する必要があります。

クエリキャッシュ

分割テーブルを使うときに気になるコストについてですが、クエリキャッシュの仕組みを利用することでコスト削減が見込めます。そこで今回利用する分割テーブルで、過去のパーティションに対するアクセスはクエリキャッシュが効くのかどうか確認してみました。

そもそも、クエリキャッシュの仕組み上「対象のテーブルがストリーミングバッファを添付されている状態ではクエリの結果はキャッシュに保存されない」という制約(例外)があります。

今回の私達の用途ですと断続的に書き込みが発生する状況になるため、テーブルがストリーミングバッファを持たなくなる状況というのは発生しづらいです。この状態ではフェッチしたいデータ(パーティション)がいかに過去のものであってもテーブルは一つであるため、前述の制約が残り続けてしまいます。

そのため残念ながらクエリキャッシュが有効になるケースは稀そうだなという結論に至りました。(ストリーミングバッファが付いているかどうかは、WebUIのテーブル情報の詳細タブから確認できます)

f:id:medley_inc:20190315130255p:plain

データ移行

前述の要件の中に「過去のアクセスログから一部データを新しいテーブルに移行したい」という話がありました。こちらの作業内容としては以下のようなものになります。

  • access_yyyymm」的なテーブルから、移行用のデータを取得
  • 必要なデータを付与
  • 移行先のテーブルにデータをinsert

とてもシンプルですね。データが少なければ適当なスクリプトで簡単に移行できそうです。

やってみた

まずは試しに google-cloud-ruby を使って、ストリーミングインサートを利用した移行プログラムを作って、実行してみたところ...

「You can only stream to date range within 7 days in the past and 3 days in the future relative to the current date.」

と、怒られてしまいました。

分割テーブルの制限としてストリーミングインサートは、過去7日までしか書き込むことができないようでした。・・・と!発表当時は公式ドキュメントにも書いてあったと思ったのですが、改めて公式ドキュメント(パーティショニング オプションの比較)見てみると、過去1年まで扱えるようになっている!?ようです。この辺りは定期的にアップデートされているようなので、実際に作業する前にきちんと公式情報を確認しておく必要がありそうです。

最終的に

前述のようなストリーミングに関する話もあり、また移行対象データの量もかなり多かった為、ストリーミングの方式は諦めて、GCSにインポート用のファイルを用意してそちらからインポートする形にし、無事移行することができました。

作業当初はデータ移行を行う手段としてEmbulkを利用することも検討していました。Embulkさまざまなストレージ、データベース、NoSQL、クラウドサービス間のデータ転送を支援してくれる並列バルクデータローダーです。しかし今回は簡易的な方法で移行できそう、との思惑から利用を見送っていました。

あとから気になったので、Embulkのプラグインであるembulk-output-bigqueryを調べてみると、やはりストリーミングインサートは実装しておらず、またGCS経由でのデータインポートができるなど、結果的には独自手法でやったことはまさにこのプラグインが提供してくれる機能そのものでした。こちらを最初から利用していればよかったかも...という気持ちで今はいっぱいです ( ꒪⌓꒪)

まとめ

今更ながらBigQueryのPartitioned table周りについて調べてみたこと、やってみたことを発表しました。なんとなく知ってるような気がする、という感じだったコスト周り、分割テーブル、クエリキャッシュなどの項目に対する理解を私自身少し深めることができたと思います。また、弊社では色々な場面でBigQueryを利用しているため、このネタが他チームでの今後の活用に何か役に立てば嬉しいなと思います。

今回のデータ移行を行った後あたりにClustered Table(beta)のことを知りましたが、こちらも対応することでさらにスキャン量の削減、高速化が期待できそうです。

また、TechLunchでの発表後、今回のような用途に対して、先日公開された Amazon QLDB あたりも使えるのでは?と同僚から教えてもらいました。監査機能などを目的としたログデータについては、QLDBはより適した用途のように思いますので、こちらも今後検証していきたいと思います。



JAWS DAYS 2019にメドレーがランチサポーターとして協賛しました

こんにちは。開発本部エンジニアの平木です。

去る2019/02/23(土)に開催されたJAWS-UG(AWS User Group – Japan)主催の全国規模での交流イベントであるJAWS DAYS 2019にメドレーが‌ランチサポーターとして協賛させていただきましたので、当日の様子などをお伝えしていきます。

f:id:medley_inc:20190228122657j:plain

会場の様子

自分はこちらのイベントに初参加だったのですが、来場者数がかなり多い!ということに圧倒されました。会場のTOC五反田メッセはイベント会場としては大分広い方でしたが、セッションの合間などでは移動するのも中々大変な位でした。日本全国からAWSユーザが集まるイベントの規模の大きさが伺えました。

f:id:medley_inc:20190228122724j:plain

公式発表で1,900人の来場だったということで、歴史があるユーザグループの凄さを実感しました。このため、大体のセッションも満席か立ち見が出ているのが印象的でした。

f:id:medley_inc:20190228122752j:plain

セッションもバラエティに富んだラインナップで見たいものが若干カブってしまっていた位で、大変有意義なものでした。

またこちらは、アマゾンウェブサービスジャパン株式会社さんが後援しているイベントということで、JAWS-UG公式Twitterに負けず劣らず、アマゾンウェブサービス公式Twitterでイベントの様子をTweetしていたのは、さすがだなと思わされました。

メドレーのスポンサー活動

さて、そんな活気に包まれていたJAWS DAYS 2019での弊社のスポンサーとしての取り組みについてですが、今回は‌ランチサポーターとして協賛させていただきました

企業サポーターブース

まずは企業サポーターブースで弊社のエンジニア・デザイナー採用パンフレットと、ノベルティとしてロゴ入りの絆創膏を設置させてもらいました!この絆創膏ですが、十分な数かと思っていたのですが、おかげさまで朝にセッティングしたところお昼までには無くなってしまいました。もっと持っていけば良かったと反省しています。

f:id:medley_inc:20190228122821j:plain

パンフレットを置かせていただいていたのは、会場内で2番目くらいに大きい場所でしたがこちらも各サポーター企業さんのブースや同人誌即売コーナーなどで人が溢れんばかりでした。

f:id:medley_inc:20190228122855j:plain

f:id:medley_inc:20190228122904j:plain

ランチセッション

そして、ランチサポーターとしてランチセッションで弊社の田中がAWSマネージドサービスをフル活用して医療系システムを構築・運用するためのノウハウと題したセッションでお話させていただきました。

f:id:medley_inc:20190228123004j:plain

メドレーで運営しているサービスであるCLINICSカルテをAWSを使って、国で定められたガイドラインにきちんと準拠しながら構築・運用するために今まで行なったことを中心に、AWSの各サービスをどのように使っているか?というお話をさせていただきました。

f:id:medley_inc:20190228123035j:plain

詳細としては

  • 医療情報システムを構成する際に準拠しなければならない3省3ガイドラインの抜粋
  • CLINICSカルテでガイドラインがシステム構成に影響を与えた部分
    • 日本国内法の適用が及ぶ場所へのシステムの設置
    • ユーザである医療機関の使用するアプリ側でTLSクライアント認証を実施
    • ユーザアカウント毎の権限管理と各種操作ログの管理
  • AWS東京リージョンへの移行や、システム構成をAWSの各サービス(ECSfargateNLBなど)を使いながらTLSクライアントに対応していった話 セキュリティを強固にするためにAWSサービス群をどのように使用しているかの話

といった内容の発表でした。 来場していただいた方々の関心も高いようで、写真を撮りながら聞いていただいて大変ありがたかったです。セッションが終了したあとも参加していただいた方々に個別に話を聞きに来ていただいたりと、情報交換という意味でも大変有意義なセッションとなりました。

f:id:medley_inc:20190228123114j:plain
セッションが終わって一安心した田中

最後に

イベントを運営していただいたスタッフの方々、そして参加者の皆さまありがとうございました!

メドレーではこの他にもエンジニア・デザイナー向けのイベントのスポンサーを積極的にしております。スポンサーを募集しているイベント主催者の方などいらっしゃいましたら、お気軽にお問い合わせいただければと思います。