App Service で KeyVault 参照する手順

この記事は Microsoft Azure Advent Calendar 2018 9日目の記事です。

Azure で好きなサービスは App Service です。
嬉しい機能追加のニュースが入ってきました。

Simplifying security for serverless and web apps with Azure Functions and App Service

Key Vault に保存した情報を App Service の環境変数から簡単に取り出せる仕組みができました。
動作や設定方法を簡単に確認します。

App Service の設定その1

App Service の Windows 版の場合は GUI で設定可能です。
ここでは App Service を Azure Active Directory にアプリケーション登録します。

App Service Register with Azure Active Directory
App Service Register with Azure Active Directory

Linux 版の場合も ドキュメント を読むと GUI で設定できそうでしたが、ポータルのUIが設定できなかったので Azure CLI で設定します。

Cloud Shell を開いてサクッと以下のコマンドを動かします。

az webapp identity assign --name myApp --resource-group myResourceGroup

Key Vault の設定

今回はシークレットを利用します。
Key Vault を開き、シークレット DbPassword を作成します。

keyvault-kv-secrets-list
Key Vault Secret List

シークレットを作成すると URI ができます。

keyvault-kv-uri
Key Vault Secret URI

この Secret Identifier URI は後で使うのでどこかにコピーしておきます。

次にアクセスポリシーを設定します。

Key Vault Add Policy1
Key Vault Add Policy1

Active Directory に登録した App Service をここで設定します。
アクセス権限については、今回はシークレットの読み込みだけなので、Get だけあれば動きます。

Key Vault Add Policy2
Key Vault Add Policy2

これで Key Vault の設定は終わりです。

App Service の設定その2

環境変数からの読み込みを App Settings で設定します。

App Service App Settings
App Service App Settings

以下のフォーマットを Value に設定します。

@Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931)

SecretUri については Key Vault でコピーしておいた文字を入力しましょう。

設定は以上です。

設定がうまくいっていれば値が無事取得できます。

App Service Key Vault 参照成功
App Service Key Vault 参照成功

アクセス権が設定できていなかったり、取得に失敗した場合は以下のように、設定したとおりの値になります。

App Service Key Vault 参照失敗
App Service Key Vault 参照失敗

当然、みんな大好き Kudu でも読み出されたシークレットを確認できます。

App Service Kudu
App Service Kudu

あとがき

この機能は App Service 起動時に読み出し、環境変数に展開しているようです。
というのも、起動後に KeyVault 上のアクセスポリシーを削除してもアプリケーションが値を取得可能だったことからこれに至ります。
そのため、リクエスト毎取得するアプリケーション側の実装するよりもパフォーマンスへの影響を少なくできます。

また、アプリケーションの言語に依存せずに機能を利用できるのがありがたいですね。

参考記事

Azure Blob Storage を使った Static website の DevOps

kheiakiyama.hateblo.jp

以前から Static website 使ってポートフォリオサイト を動かしている。
Travic CI で AzCopy on Linux を使って適当なコンテナにデプロイし、そこから $web に手動コピーしてリリースするという手順を取っていた。

AzCopy がいつの間にか $web に対応していたので完全に自動化した。

Travic CI

サイトでは jekyll を使っているが、_site の部分を読み替えれば他のコンテンツ作成手段でも利用できるはず。

# Require Environment Variables
# - BLOB_CONTAINER_URL 
# - STORAGE_KEY
language: ruby
rvm:
  - 2.5
before_script:
  - chmod +x ./scripts/cibuild
script: ./scripts/cibuild
after_success:
  - sudo apt-get update
  - sudo apt-get install apt-transport-https -y
  - sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main"
  - sudo add-apt-repository "deb http://cz.archive.ubuntu.com/ubuntu xenial main"
  - sudo apt-get update
  - sudo apt-get install libicu55 -y
  - sudo apt-get install libunwind-dev -y
  - wget -O azcopy.tar.gz https://aka.ms/downloadazcopylinux64
  - tar -xf azcopy.tar.gz
  - sudo ./install.sh
  - ls -la ./_site
  - azcopy --version
  - azcopy --source ./_site --destination "$BLOB_CONTAINER_URL" --dest-key $STORAGE_KEY --recursive --quiet --set-content-type
branches:
  only:
    - master
env:
  global:
    - NOKOGIRI_USE_SYSTEM_LIBRARIES=true # speeds up installation of html-proofer

環境変数

$BLOB_CONTAINER_URLhttps://xxx.blob.core.windows.net/$web のような指定になるが、Travis CI では特殊文字エスケープが必要なため、 https://xxx.blob.core.windows.net/\$web とする必要がある。

Environment Variables - Travis CI

デバッグ

最新の AzCopy on Linux を動かすために、Travis CI のデバッグで少し苦労した。

Travis CI で動くエージェントは Docker イメージが用意されているので下のリンクから該当イメージを探して手元で試すと早い。
ただし ruby のイメージは3GB超。。

Common Build Problems - Travis CI

Azure CDN への反映

コンテンツ更新するため、キャッシュを一旦削除した。

Azure CDN エンドポイントの消去 | Microsoft Docs

ドキュメントに載っていないが、Microsoft CDN のパージは3分くらいだったように感じる。

Go lang で SSL チェックするプログラム

書いた。

github.com

感想

badssl.com を使って TLS Version のテストケース書くなどした。

大量にリクエストを送って動作確認する実装なので、テスト実行するときは気をつけたい。

Go言語による並行処理

Go言語による並行処理

GKE 上で Pub/Sub 動かすサンプルアプリ

コンテキスト

今年は GCP を触っていくと決めていたのにしばらくぶりになってしまった。
前回が半年以上前。

Azure 系エンジニアから見た GAE 〜Google App Engine編〜 - ぐだぐだ言ってないでコードを書けよ、ハゲ。

本題

今回はサービス評価ではないが、以下のサービスを触っているという近況報告。

k8s 上の Deployment で Pub/Sub の Subscriber を常駐させつつ、CronJob で Publisher を動かすサンプルアプリを書いた。

github.com

感想

k8s はだんだんしっくり気始めて、基本的な概念理解からようやく Secret や Config など現場で使う技術に手が出始めた段階。
やはり実サービスで自分で使っていかないと身につかない。
デバッグやアップデートどうするんだっけ、という現場で当たり前のテクニックがないとマズイなと思った次第。

所感としては、特につまづくことがなかったので、よく出来てるなあという印象。
公式を見て順番に理解していけば進められる。

Kubernetes Documentation - Kubernetes

YAML Hell については Kustomizeがkubectrlに統合されていくらしいので、はじめから使っていけばいいかなという感じ。

ほか

個人サービスで使っていくことで理解が深まりそうなので、どのクラウドで使うかはわからないがいろいろ試していきたい。

Kubernetes完全ガイド (impress top gear)

Kubernetes完全ガイド (impress top gear)

SharePoint Online の REST API を PowerShell から叩いてハマったことへの対処

SharePoint Online の REST API を PowerShell から叩いてみる - からめもぶろぐ。
MVP の方の記事をほぼそのまま試していましたが、多少ハマったのでその補足を備忘録として残します。

グループのタイトルの取得

サイトのタイトルは元記事の通り、以下。

$uri = $resourceUri + "/_api/web/title"

グループのタイトルは以下。

$uri = $resourceUri + "/sites/(group_name)/_api/web/title"

類推した通りに動きます。

グループのドキュメント一覧の取得

サイトのドキュメント一覧は元記事の通り、以下。

$uri = $resourceUri + "/_api/web/GetFolderByServerRelativeUrl('/Shared%20Documents')/files"

グループのドキュメント一覧は以下。

$uri = $resourceUri + "/sites/(group_name)/_api/web/GetFolderByServerRelativePath(decodedurl='/sites/(group_name)/Shared%20Documents')/files"

パスの指定が重要ですね。

一度許可したアクセス許可を削除する

SharePoint の話題ではありませんが。
Azure AD 内で登録したアプリケーションに対してアクセス許可をしますが、許可した対象によって登録される先が違います。

f:id:khei-fuji:20181011165541p:plain

組織の代理として同意する にチェックがある場合は Azure AD、ない場合は個人の Office365 に登録されます。

参考記事

ひと目でわかる SharePoint Server 2016

ひと目でわかる SharePoint Server 2016

Azure DevOps Pipelines で Go の Docker コンテナを Heroku に継続的デプロイする

kheiakiyama.hateblo.jp

フロント部分は Nuxt.js で作っているアプリですが、バックエンドのAPIは Heroku にデプロイすることにしました。
どうせなら Firebase にデプロイしたかったのですが Firebase Function はまだ Go や Docker に対応していません。残念です。

実装方法

Heroku

Rails アプリを動かす PaaS と思ってましたがいつの間にか Docker コンテナを動かせるようになってました。

コンテナを動かすための手順はこのあたりにあります。
Container Registry & Runtime (Docker Deploys) | Heroku Dev Center

Dockerfile を書く上での制約がいくつかあるので気をつけたいところです。
引っかかりそうな部分は下記2点あたりです。

The web process must listen for HTTP traffic on $PORT, which is set by Heroku. EXPOSE in Dockerfile is not respected, but can be used for local testing. Only HTTP requests are supported.

(意訳)EXPOSE は無視します。$PORTトラフィックを流すのでよろしくね。

CMD is required. If CMD is missing, the registry will return an error CMD will always be executed by a shell so that config vars are made available to your process; to execute single binaries or use images without a shell please use ENTRYPOINT

(意訳)CMD は必ず指定してね。

Azure DevOps Pipelines

kheiakiyama.hateblo.jp

上の昨日の記事にも書きましたが DevOps Pipelines ではYAMLファイルで設定できます。
Agent-pool は Hosted Ubuntu 1604 を使います。

azure-pipelines.yml

pool:
  vmImage: 'Ubuntu 16.04'
  
variables:
  HEROKU_API_KEY: YOUR_API_KEY
  HEROKU_APP: YOUR_APP_NAME

steps:
- script: |
   #!/bin/bash
   heroku container:login
   heroku container:push web --app $HEROKU_APP
   heroku container:release web --app $HEROKU_APP
    
  displayName: 'deploy to heroku'

Heroku CLIHosted Ubuntu 1604 にインストールされているのでスクリプト一つで済みます。
Heroku CLI の認証は環境変数HEROKU_API_KEY があればそれで行えるので、 heroku auth:token とかで取得、適宜作成します。
おそらく Secret 用の指定方法はあるのですが、まだ調べてないのでそれはまた今度。

heroku container:pushdocker build && docker push が走るようで、若干気持ち悪さがあります。
タグを意識させないためでしょうか。

感想

ということで無料の範囲で DevOps パイプラインまで作成することができました。
サクッと Docker コンテナの PaaS が使える Heroku はやはりよいですね。

久しぶりに使ったので変なところにハマってしまいましたが無事動きました。

これで Nuxt.js のバックエンドAPIが動かせそうです。

Nuxt.jsビギナーズガイド―Vue.js ベースのフレームワークによるシングルページアプリケーション開発

Nuxt.jsビギナーズガイド―Vue.js ベースのフレームワークによるシングルページアプリケーション開発

Azure DevOps Pipelines で Nuxt.js アプリを Firebase に継続的にデプロイする

kheiakiyama.hateblo.jp

Nuxt.js で書いたアプリですが、デプロイが煩わしい状態でしたので、最近話題の Azure DevOps を使って継続的デプロイを設定しました。

Azure DevOps Pipelines について

まずは公式リンク。

azure.microsoft.com

なぜ Azure DevOps(Pipelines) を使うかというと、プライベートリポジトリを使う場合の CI/CD サービスで Travis CI や CircleCI を使うとそこそこの費用が発生するためです。
(私は GitHub はプライベートリポジトリを使っています)
ギョーム開発であれば有償サービスを使うべきかとは思いますが、Azure DevOps Pipelines は月1,800分の無償枠があります。(2018/9/14 現在)
個人開発で何かを作るにはこの枠を有効に使えるのではないでしょうか。

実装方法

Azure DevOps Pipelines

DevOps Pipelines では GUI で設定する方法とYAMLファイルで設定する方法がある。
GUI で作ったものは後からYAMLを確認できるので、まずは GUI から入るとよい。
ここでは結果のみ書く。

以下の yamlリポジトリ直下に置き、Agent-pool は Hosted Ubuntu 1604 を使う。

azure-pipelines.yml

pool:
  vmImage: 'Ubuntu 16.04'
  
variables:
  firebaseToken: '********'

steps:
- script: |
   #!/bin/bash
   npm install firebase-tools firebase-functions firebase-admin
  displayName: 'Install firebase-cli'

- task: Npm@1
  displayName: 'npm install'
  inputs:
    verbose: false

- script: |
   #!/bin/bash
   npm run build
   npm run copyassets
   node_modules/.bin/firebase deploy --token $(firebaseToken)
  displayName: 'Run npm deploy'

パイプライン内では npm のグローバル環境下に Firebase CLI をインストールする権限がないため、firebase はローカルにインストールしています。
そのため firebase deploy はパス指定して動かす苦肉の策で実行しています。

このYAML についてのドキュメントはまだまだ充実してません。
サンプルコードが以下に紹介されており、GitHub を漁ると iOSAndroid のサンプルも見つかるので参考になれば。

Create your first pipeline | Microsoft Docs

Node 部分

package.json

  "scripts": {
    "dev": "nuxt",
    "build": "npm run clean && nuxt build",
    "clean": "rm -rf dist && rm -rf functions/nuxt",
    "deploy": "npm run build && npm run copyassets && firebase deploy", // for local only
    "start": "nuxt start",
    "generate": "nuxt generate",
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
    "precommit": "npm run lint",
    "copyassets": "mkdir -p dist/assets && npm run copydist && npm run copystatic",
    "copydist": "cp -R functions/nuxt/dist/ dist/assets",
    "copystatic": "cp -R static/ dist"
  },

Nuxt.js 部分

nuxt.config.js

module.exports = {
  buildDir: "functions/nuxt",
  build: {
    publicPath: "/assets/",
  }

感想

Microsoft-Hosted Agent の Docker Image に Firebase CLI を入れる PullRequest 書いたら通るのでしょうか。
後で気が向いたら試してみようと思います。
GitHub - Microsoft/vsts-agent-docker: Visual Studio Team Services (VSTS) Agent Docker Images

Self-Hosted Agent を作るのは結構敷居が高い印象あるので、Travis CI のように Agent に使う Docker Image を指定できると 一番理想的です。

Nuxt.jsビギナーズガイド―Vue.js ベースのフレームワークによるシングルページアプリケーション開発

Nuxt.jsビギナーズガイド―Vue.js ベースのフレームワークによるシングルページアプリケーション開発