LoginSignup
8
3

More than 5 years have passed since last update.

Oracle Functions で Let's Encrypt を使用した、自動SSL証明書更新をつくってみた

Last updated at Posted at 2019-03-02

はじめに

Oracle Functions を使用して、自動的にSSL証明書を発行する自動化(oci-lego-sslupdate)を作りました。
Let's Encrypt からSSL証明書を発行し、OCIのLoadBalancerに設定し、ObjectStorageへ保存することが出来ます。
Oracle Functions を使用しているので、ComputeInstanceを必要としないサーバレスなアーキテクチャとなっています。

この記事では、使い方と、技術的な解説を書きます。
作成した自動化(oci-lego-sslupdate)は、GItHubにアップロードしているので、適宜ご利用ください。
https://github.com/Sugi275/oci-lego-sslupdate

概要

architecture.png

  • OCIR (Docker Registry) にアップロードしている、自動化用の DockerImage を Oracle Functions に Pull
  • Fn 上でDockerImageを実行
  • Let's Encryptから新たなSSL証明書を取得
  • OCIのLoadBalancerに、新たなSSL証明書を設定
  • OCIのObjectStorageに、新たなSSL証明書と、SSL証明書に紐づく秘密鍵を保存

使い方

前提条件

  • 取得したいSSL証明書のドメインを、OCIのDNSにあるZoneで管理していること。設定方法例はこちら を参照 (Let's Encryptの認証方式をDNS-01としているため)

  • OCI上にLoadBalancerを作成して、SSL用のListenerを作成していること

  • Oracle Functions を使用可能なこと。設定方法はこちらを参照

oci-lego-sslupdateを Oracle Functions に設定

Gitからoci-lego-sslupdateをclone

git clone https://github.com/Sugi275/oci-lego-sslupdate.git

Oracle Functions 用の設定ファイルを、必要に応じて変更します

> cat func.yaml
schema_version: 20180708
name: oci-lego-sslupdate     <=== Functionの名前を変更したい場合は変更する
version: 0.0.20              <=== バージョンも変更したい場合は変更する
runtime: docker
entrypoint: ./func
format: http-stream
timeout: 120

Oracle Functions のコンソール画面で、適当なアプリケーション(枠組み)を作成します。今回の例では、env-app という名前を使用しています。
アプリケーションを作成後、fn deploy コマンドで、Oracle Functions にデプロイします

fn --verbose deploy --app env-app

function 一覧を確認します。oci-lego-sslupdate が存在していることを確認します

> fn ls functions env-app
NAME                    IMAGE                                                                   ID
custom_runtime          phx.ocir.io/<tenancy>/oracle-function/custom_runtime:0.0.2             ocid1.fnfunc.oc1.phx.aaaaaaaaadizxuar3gv6ubeoztffm5l2nfnujna6vbnkc67g7td2c722jg2a
env-print               phx.ocir.io/<tenancy>/oracle-function/env-print:0.0.7                  ocid1.fnfunc.oc1.phx.aaaaaaaaadu6qtn6zyn754zbiqi3boavtunsdbkwfllggixg7hkwjihfo5ma
oci-lb-list             phx.ocir.io/<tenancy>/oracle-function/oci-lb-list:0.0.24               ocid1.fnfunc.oc1.phx.aaaaaaaaaaialw3wgcnm2ytn7cveaaqmlmtaniilu3qy7k2bmxkbn2tgnpiq
oci-lego-sslupdate      phx.ocir.io/<tenancy>/oracle-function/oci-lego-sslupdate:0.0.21        ocid1.fnfunc.oc1.phx.aaaaaaaaaaz4bvn4oz2sp4d3zzfuaefkui2be7b5vp4cgayrdmltj6f7yeuq <=== 表示されていればおk
test                    phx.ocir.io/<tenancy>/oracle-function/test:0.0.6                       ocid1.fnfunc.oc1.phx.aaaaaaaaaatajmkauwajgxbjjm2p23kiu2do7nz76psxcldwv5w2palfatpq

function に環境変数を設定します。以下に例を記載します。適宜環境に合わせて変更をする必要があります
bashの場合

# oci
export OCI_PRIVKEY_BASE64=`base64 $HOME/.oci/oci_api_key.pem`
fn config func env-app oci-lego-sslupdate OCI_PRIVKEY_BASE64 $OCI_PRIVKEY_BASE64
# fnでは値が空白だと、反映されない。パスフレーズを指定する場合はコメントアウトを外して指定
# fn config func env-app oci-lego-sslupdate OCI_PRIVKEY_PASS ""
fn config func env-app oci-lego-sslupdate OCI_TENANCY_OCID 'ocid1.tenancy.oc1..secret'
fn config func env-app oci-lego-sslupdate OCI_USER_OCID 'ocid1.user.oc1..secret'
fn config func env-app oci-lego-sslupdate OCI_PUBKEY_FINGERPRINT '00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00'
fn config func env-app oci-lego-sslupdate OCI_REGION 'us-phoenix-1'
fn config func env-app oci-lego-sslupdate OCI_COMPARTMENT_OCID 'ocid1.tenancy.oc1..secret'

# lego (let's encrypt client)
fn config func env-app oci-lego-sslupdate OCI_TTL 1
fn config func env-app oci-lego-sslupdate OCI_PROPAGATION_TIMEOUT 120
fn config func env-app oci-lego-sslupdate OCI_POLLING_INTERVAL 10
fn config func env-app oci-lego-sslupdate LETSENCRYPT_DOMAINS 'sugi.tokyo,*.sugi.tokyo'
fn config func env-app oci-lego-sslupdate LETSENCRYPT_MY_MAILADDRESS 'myaddress@mail.com'
# fn config func env-app oci-lego-sslupdate LETSENCRYPT_CA_URL 'https://acme-staging-v02.api.letsencrypt.org/directory'

# oci lb 
fn config func env-app oci-lego-sslupdate OCI_LB_OCID 'ocid1.loadbalancer.oc1.phx.secret'
fn config func env-app oci-lego-sslupdate OCI_LISTENERS 'listener1,listener2'

# oci ObjectStorage
fn config func env-app oci-lego-sslupdate OCI_OS_NAMESPACE '<tenancy>'
fn config func env-app oci-lego-sslupdate OCI_OS_BUCKETNAME 'lego-certificate4'

fishの場合は、若干書式を変更する必要があります

# oci
set IFS
set -x OCI_PRIVKEY_BASE64 (base64 $HOME/.oci/oci_api_key.pem)
set IFS \n" "\t
# fnでは値が空白だと、反映されない。パスフレーズを指定する場合はコメントアウトを外して指定
# fn config func env-app oci-lego-sslupdate OCI_PRIVKEY_PASS ""
fn config func env-app oci-lego-sslupdate OCI_PRIVKEY_BASE64 $OCI_PRIVKEY_BASE64
fn config func env-app oci-lego-sslupdate OCI_TENANCY_OCID 'ocid1.tenancy.oc1..secret'
fn config func env-app oci-lego-sslupdate OCI_USER_OCID 'ocid1.user.oc1..secret'
fn config func env-app oci-lego-sslupdate OCI_PUBKEY_FINGERPRINT '00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00'
fn config func env-app oci-lego-sslupdate OCI_REGION 'us-phoenix-1'
fn config func env-app oci-lego-sslupdate OCI_COMPARTMENT_OCID 'ocid1.tenancy.oc1..secret'

# lego (let's encrypt client)
fn config func env-app oci-lego-sslupdate OCI_TTL 1
fn config func env-app oci-lego-sslupdate OCI_PROPAGATION_TIMEOUT 120
fn config func env-app oci-lego-sslupdate OCI_POLLING_INTERVAL 10
fn config func env-app oci-lego-sslupdate LETSENCRYPT_DOMAINS 'sugi.tokyo,*.sugi.tokyo'
fn config func env-app oci-lego-sslupdate LETSENCRYPT_MY_MAILADDRESS 'myaddress@mail.com'
# fn config func env-app oci-lego-sslupdate LETSENCRYPT_CA_URL 'https://acme-staging-v02.api.letsencrypt.org/directory'

# oci lb 
fn config func env-app oci-lego-sslupdate OCI_LB_OCID 'ocid1.loadbalancer.oc1.phx.secret'
fn config func env-app oci-lego-sslupdate OCI_LISTENERS 'listener1,listener2'

# oci ObjectStorage
fn config func env-app oci-lego-sslupdate OCI_OS_NAMESPACE '<tenancy>'
fn config func env-app oci-lego-sslupdate OCI_OS_BUCKETNAME 'lego-certificate4'

環境変数について

各環境変数の説明を記載します

Key 内容 必須 or 任意 Default値
OCI_PRIVKEY_BASE64 OCIに接続するための秘密鍵をbase64でエンコードした文字列 必須 なし
OCI_PRIVKEY_PASS 秘密鍵のパスフレーズ 必須 なし
OCI_TENANCY_OCID 操作するテナンシーのOCID 必須 なし
OCI_USER_OCID OCIで公開鍵を設定した、ユーザのOCID 必須 なし
OCI_PUBKEY_FINGERPRINT 公開鍵のフィンガープリント 必須 なし
OCI_REGION リージョン名 必須 なし
OCI_COMPARTMENT_OCID コンパートメントのOCID 必須 なし
OCI_TTL Let's Encryptでdns-01認証をする際に、一時的に作成するレコードのTTL 任意 30
OCI_PROPAGATION_TIMEOUT Let's Encryptでdns-01認証をするときの、タイムアウト 任意 60
OCI_POLLING_INTERVAL Let's Encryptでdns-01認証をするときの、インターバル 任意 2
LETSENCRYPT_DOMAINS SSL証明書を取得したいドメイン名。カンマ区切りで複数指定可能 必須 なし
LETSENCRYPT_MY_MAILADDRESS SSL証明書に紐づくメールアドレス 必須 なし
LETSENCRYPT_CA_URL Let's Encrypt を始めとしたCA URLを指定。動作確認をするときには、stagingを指定すると便利 任意 https://acme-v02.api.letsencrypt.org/directory
OCI_LB_OCID SSL証明書を設定したいLoadBalancerのOCID 必須 なし
OCI_LISTENERS SSL証明書を設定したいLoadBanancerに所属している、ListenerのOCID 必須 なし
OCI_OS_NAMESPACE ObjectStorageのネームスペース名 必須 なし
OCI_OS_BUCKETNAME ObjectStorageにSSL証明書や秘密鍵を保存するときのバケット名。指定したバケットが存在しない場合は、自動的にPrivateバケットを作成 任意 lego-cert

loggingの設定 (任意)

現在、Oracle Functions は Limited Available となっており、logを確認したい場合は、logging用のsyslogを用意する必要があります。
Papertrail というサービスを使うことで、簡単に無料でsyslogを表示することが出来ます。
設定方法などは、こちらを参照してください。

今回の自動SSL設定は、2分くらい実行時間が必要なので、loggingしておくと進捗がわかって便利です。

Functionの実行

fn invoke コマンドで、Functionを実行できます。実行してから2分弱ほど経過すると、成功した旨のメッセージが表示されます。
また、実行中の経過はloggingを確認するとよいです。

fn invoke env-app oci-lego-sslupdate

なお、現在のOracle Functions では、定期実行することは制限されていて出来ませんが、GAされれば定期実行できるため、非常にお手軽にSSL証明書を自動的に更新し続けることが出来ます。

8
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3