astamuse Lab

astamuse Labとは、アスタミューゼのエンジニアとデザイナーのブログです。アスタミューゼの事業・サービスを支えている知識と舞台裏の今を発信しています。

SSL証明書の有効期限一覧を自動生成した話

こんにちは。開発部のtorigakiです。 弊社ではSSL証明書を使ったサイトが300以上ありますが、このSSL証明書の期限をEXCELなどを使って手作業で管理しようとするとなかなか大変な作業となります。

そこで自動的にSSL証明書の有効期限の一覧を生成する仕組みを作ってみましたので、今回はそのお話をさせていただければと思います。

route53からドメインリストを取得する

弊社ではDNS管理にroute53を使っていますので、route53をコマンドラインで使えるツールを使って運用ドメインの一覧を取得します。

ドメイン一覧の取得にはcli53を使用しました。

SSL証明書を使っているFQDNの一覧は以下のように取得します。

  • cli53 list にて運用ドメインを取得。
  • cli53 export ${DOMAIN}にて各ドメインごとのゾーンを取得し、そのゾーン情報からAレコードを取得。
  • Aレコード+ドメイン名からFQDNを取得。

上記で取得したFQDN一覧の中にはSSL運用していないサイトも含まれますので、SSL運用しているサイトに絞り込みます。 絞り込む方法は、opensslコマンドでアクセスし応答の有無で判定します。 opensslコマンドは以下のように実行します。 応答が返ってこないときの対策として先頭にtimeoutをつけて実行します。

timeout 3 openssl s_client -connect ${FQDN}:443 -servername ${FQDN} < /dev/null 2> /dev/null

上記で応答が返ってきたFQDNに対して、以下コマンドで有効期限を取得します。

openssl s_client -connect ${FQDN}:443 -servername ${FQDN} < /dev/null 2> /dev/null | openssl x509 -noout -startdate -enddate | grep notAfter

上記を実行すると以下の結果が得られます。

notAfter=Feb 13 12:00:00 2021 GMT

SSL証明書の発行署名者も一覧に加える場合は、以下コマンドにて発行署名者を取得します。

openssl s_client -connect ${FQDN}:443 -servername ${FQDN} < /dev/null 2> /dev/null | openssl x509 -noout -issuer

上記を実行すると以下の結果が得られます。

issuer= /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=RapidSSL RSA CA 2018

上記3つを取得できたら、FQDN、発行署名者、有効期限 のCSV形式でファイルに出力します。

CSVファイルをHTMLファイルに変換する

ブラウザで一覧を見れるようにするため、生成したCSVファイルをHTMLに変換します。

変換はシェルスクリプトで実行します。変換スクリプトはこちらを参考にさせていただきました。

HTML形式に変換した結果、ブラウザにて以下のように一覧表示できるうようになります。

f:id:astamuse:20191029144212p:plain
SSL

まとめ

以上のように、cli53とopensslコマンドから情報収集してCSV出力し、HTML変換する処理を毎週1回cronで実行するようにしておけば自動的にはSSL証明書の期限管理をできるようになります。

またこの一覧とは別に、証明書期限が30日前になったらSlack宛に通知する仕組みも入れたりしてSSL証明書の更新忘れ防止をしております。

今回はSSL証明書期限管理について工夫した点について紹介させていただきました。 少しでもSSL証明書の運用されている方のお役に立てれば幸いです。

弊社では引き続きエンジニア・デザイナーを募集中ですので、ご興味のある方は下からご応募いただければと思います。

バリアブルフォントで遊ぼう

f:id:astamuse:20191024122921p:plain

はじめまして、フロントエンドエンジニアの minamo です。

趣味は映画鑑賞、特にアクション映画が大好きです。

今年は「イップ・マン外伝マスターZ」、「ジョン・ウィック : パラベラム」、 「HiGH&LOW THE WORST」と最高アクション映画が豊作でうれしいですね。

2月に astamuse にジョインしてから初めてのブログで、好きな映画以外書くことが思い浮かばなかったのですが、最近「バリアブルフォントがおもしろい!」と思ったので、ご紹介します。

バリアブルフォントって何?

バリアブルフォントとは、Adobe・Apple・Google・Microsoftが共同で開発したフォントの規格です。 Variable = 可変フォントとも呼ばれていました。

通常のフォントは字幅やウェイト、斜体などによってファイルが分かれていますが、バリアブルフォントだとそれらが ひとつのフォントファイルで利用できる のが特徴です。

ほとんどはウェイトの調整だけですが、書体によっては傾斜やフォント自体の形状など独自の数値を調整することができます。

f:id:astamuse:20191024123412p:plain
Photoshop の画面。 "VAR" とついているのがバリアブルフォントですね。

Photoshop や Illustrator で利用でき、デザイナー向けの話題と思われがちですが、もちろん Web font としても利用できます。

バリアブルフォントを CSS アニメーションと組み合わせたら楽しいのでは?!と思い、色々遊んでみることにしました。

ドキュメント

まずは MDN Web Doc を読んでみましょう。

Variable フォントガイド

バリアブルフォントを CSS で設定するときのプロパティ font-variation-settings も合わせて。

ウェイトや斜体の数値をこのプロパティで設定していくようです。

font-variation-settings

バリアブルフォントの対応状況

caniuse によるとブラウザでの対応状況はこのとおり。 ほとんど対応できています。

f:id:astamuse:20191024124014p:plain
https://caniuse.com/#search=variable%20fonts

バリアブルフォントをアニメーションさせてみよう

実際に動かしてみました。 まずはかんたんに font-weight のアニメーションから。

f:id:astamuse:20191024145111g:plain
League Spartan Variable

ソースはこちら

// HTML
<h1 class="zycon">
  astamuse
</h1>

// CSS
@font-face {
  font-family: 'LeagueSpartan';
  src: url('/LeagueSpartanVariable.woff2') format('woff2-variations');
}

.leagueSpartan {
  font-family: 'LeagueSpartan';
  display: block;
  font-size: 100px;
  color: #35495e;
  letter-spacing: 1px;
  animation: weight 2000ms infinite alternate;
}

@keyframes weight {
  0% {
    font-weight: 200;
  }
  100% {
    font-weight: 900;
  }
}

もうちょっとバリアブルフォントっぽいことがしたい!

font-weight 以外も動かしてみましょう。

さきほどの font-variation-settings でバリアブルフォント独自の数値を設定することができます。

f:id:astamuse:20191024145650g:plain
Handjet

// HTML
<h1 class="handjet">
  astamuse
</h1>

// CSS
@font-face {
  font-family: 'Handjet';
  src: url('/Handjet-VF.woff2') format('woff2-variations');
}

.handjet {
  font-family: 'Handjet';
  display: block;
  font-size: 100px;
  color: #35495e;
  animation: digit 2000ms infinite alternate;
}

@keyframes digit {
  0% {
    font-variation-settings: 'wght' 1, 'wdth' 400, 'opsz' 100;
  }
  100% {
    font-variation-settings: 'wght' 80, 'wdth' 400, 'opsz' 100;
  }
}

wght = font-weight のこと、など独自の値があります。

Dingbats(装飾記号)のバリアブルフォントもあるので、こっちの方がおもしろいかも。

f:id:astamuse:20191024145636g:plain
Zycon

// HTML
<h1 class="zycon">
  🐈
</h1>

// CSS
@font-face {
  font-family: 'Zycon';
  src: url('/Zycon.ttf');
}

.zycon {
  font-family: 'Zycon';
  display: block;
  font-size: 100px;
  color: #35495e;
  animation: meow 2000ms infinite alternate;
}

@keyframes meow {
  0% {
    font-variation-settings: 'T1  ' 0;
  }
  100% {
    font-variation-settings: 'T1  ' 1;
  }
}

ねこちゃんかわいいですねえええええ!!

ローディングアニメーションにもいいんじゃないでしょうか!

f:id:astamuse:20191024145705g:plain
いぬもかわいいです!

バリアブルフォントで遊べるサイト紹介

現在公開されているバリアブルフォントを閲覧できるサイトがあります。

数値をグリグリ調整してるだけで飽きずに遊べちゃいますよ。

Variable Fonts

数が多いですが、調子にのって遊んでいると重くなります。

Font Playground -- Play with variable fonts!

直感的な UI で数値をいじれます。

お気に入りのバリアブルフォント

f:id:astamuse:20191024144205p:plain
Fit

見たまま・超・カッコイイです。ラグランパンチっぽいですね。

f:id:astamuse:20191024144212g:plain
Pappardelle Party

ペカペカできて楽しい!かわいい!

未来へ

和文のバリアブルフォントはあるの?ということが気になると思います。日本人なので。

現時点(2019年10月)で調べた限り、ちょっと見つかりませんでした。。 バリアブルフォントでドープな日本語のサイトを作れる日はまだのようです。

モリサワの「タイプデザインコンペティション 2019」でもバリアブルフォント部門の募集があったそうですが、受賞作品…該当なし!ないんかい!

なんだかしまらないですが、astamuse ではいつでもエンジニア&デザイナーを募集しています。

日本語のバリアブルフォントあるよ!というツッコミのついででも良いので、おきがるにどうぞ!

Akka HTTPプロジェクトでSwagger Specificationを出力する。

お久しぶりです。開発部のyanagitaです。

以前、Play FrameworkプロジェクトでSwaggerを導入した記事を本ブログで投稿させていただきました。

執筆は、開発部のNishikawa氏 lab.astamuse.co.jp

今回は、Akka HTTPを使用したプロジェクトでSwagger Specification(以下、Swagger Spec)を出力したいと思います。

使用するライブラリ

今回はswagger-akka-http/swagger-akka-httpを使用します。

github.com

サンプルプロジェクトがあるのでそちらで解説を入れていきます。

github.com

build.sbtへライブラリ追加

build.sbtに以下を追加します。

libraryDependencies ++= Seq(
  "javax.ws.rs" % "javax.ws.rs-api" % "2.0.1", 
  "com.github.swagger-akka-http" %% "swagger-akka-http" % "2.0.4", 
  "com.github.swagger-akka-http" %% "swagger-scala-module" % "2.0.5",
  "com.fasterxml.jackson.module" %% "jackson-module-scala" % jacksonVersion,
  "io.swagger.core.v3" % "swagger-core" % swaggerVersion,
  "io.swagger.core.v3" % "swagger-annotations" % swaggerVersion,
  "io.swagger.core.v3" % "swagger-models" % swaggerVersion,
  "io.swagger.core.v3" % "swagger-jaxrs2" % swaggerVersion,
  "com.typesafe.akka" %% "akka-http" % akkaHttpVersion,
  ...
)

Swagger Spec生成に必要なライブラリは以下です。
javax.ws.rs-api → サンプルではリクエストメソッドの指定で使用します。
com.github.swagger-akka-http %% swagger-xxx → Swagger Specを生成するライブラリセットです。
io.swagger.core.v3 % swagger-xxx → Swaggerアノテーションを使用するためのライブラリセットです。

ルート定義とSwagger Spec情報定義

まずはAPIの定義から入ります。
参考コードはHelloService.scalaからの抜粋ですが、一部修正を入れています。

 // 44行目から  
  // アノテーション定義がSwagger Spec生成の情報定義になります。
  @Path("/hello/{name}")
  @GET
  @Operation(summary = "Return Hello greeting", description = "Return Hello greeting for named user",
    parameters = Array(new Parameter(name = "name", in = ParameterIn.PATH, description = "user name")),
    responses = Array(
      new ApiResponse(responseCode = "200", description = "Hello response",
        content = Array(new Content(schema = new Schema(implementation = classOf[Greeting])))),
      new ApiResponse(responseCode = "500", description = "Internal server error"))
  )
  // 以下はルート定義
  def getHelloSegment =
    path("hello" / Segment) { name =>
      get {
        complete { (hello ? Hello(name)).mapTo[Greeting] }
      }
    }

結果が先に来てしまうのですが、上記定義で生成されるSwagger Specの定義が以下になります。

  /hello/{name}:
    get:
      summary: Return Hello greeting
      description: Return Hello greeting for named user
      operationId: getHelloSegment
      parameters:
      - name: name
        in: path
        description: user name
        required: true
        schema:
          type: string
      responses:
        "200":
          description: Hello response
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/Greeting'
        "500":
          description: Internal server error

Swagger SpecのAPI定義に当たる箇所はすべてアノテーションで定義します。
一見、アノテーション定義は複雑に見えますが、Swagger Specを記述されたことがある方はどのアノテーション定義がSwagger Spec上の記述となるか簡単に紐づくと思います。Swagger Specが初見の方は一度Swagger Specの理解から入られるとアノテーションの理解が早まると思います。

Swagger Spec生成サービスの追加

swagger-akka-httpでは、リクエストに対してSwagger Specを返却する仕組みとなているため、Swagger Sepcを生成するサービス作成とルート追加が必要となります。

SwaggerDocService.scala

object SwaggerDocService extends SwaggerHttpService {
  override val apiClasses = Set(classOf[AddService], classOf[AddOptionService], classOf[HelloService], EchoEnumService.getClass)
  override val host = "localhost:12345"
  override val info = Info(version = "1.0")
  override val externalDocs = Some(new ExternalDocumentation().description("Core Docs").url("http://acme.com/docs"))
  //override val securitySchemeDefinitions = Map("basicAuth" -> new BasicAuthDefinition())
  override val unwantedDefinitions = Seq("Function1", "Function1RequestContextFutureRouteResult")
}

SwaggerDocServiceは、SwaggerHttpServiceを継承しSwagger Specに出力する情報を定義します。
最低限必要な定義はapiClasses、hostになります。apiClassesは、Swagger Specに掲載するAPIクラス(Swaggerアノテーションを定義したクラス)を羅列します。(apiClassesに含まないクラスはSwagger Specに出力されません。)hostはSwagger UIからAPI実行するためのエンドポイントのホスト情報として必要となります。
あとはAkkaのルーティングにSwaggerDocService(SwaggerDocService.route)を追加して終わりです。
Swagger Specの出力形式はjson形式、yaml形式の両方があります。アプリを起動し、以下のでURLにアクセスすれば出力可能です。

json形式はこちら → http://localhost:12345/api-docs/swagger.json
yaml形式はこちら → http://localhost:12345/api-docs/swagger.yaml

※ アクセスのパスの「/api-docs/」はSwaggerDocService内の定義で変更可能です。

まとめ

以上、サンプルをベースにAkka HTTPプロジェクトからSwagger Specを出力するコードを紹介しました。
アノテーションの定義が多く面倒に感じる部分がありますが、導入コストは非常に低く制限も少ないので導入は容易だと感じました。

PR

アスタミューゼではたくさんのエンジニア&デザイナをまだまだまだ募集しています。 気になる方は下からご応募下さい!新しい出会いをメンバー一同お待ちしてます!

Copyright © astamuse company, ltd. all rights reserved.