序章

管理者は、DigitalOceanメタデータサービスを使用して、新しいサーバーが自動的に構成できるようにする手順を提供できます。 これは便利ですが、多くの組織は、ChefやPuppetなどの構成管理ツール内ですべてのインフラストラクチャ構成を処理することを好みます。

このガイドでは、メタデータサービスとCloudInitを使用してDigitalOceanサーバーをブートストラップし、既存の構成管理展開に接続する方法を示します。 サーバーの実際の構成は、構成管理サービスで処理できます。 ChefノードとPuppetノードの両方をブートストラップする方法を示します。

前提条件

このガイドを完了するには、DigitalOceanメタデータサービスにある程度精通している必要があります。 メタデータサービスに情報を入力したり、メタデータサービスから情報を取得したりする方法の詳細については、このガイドを参照してください。

このガイドでは、次のような種類のスクリプトを活用します cloud-config これは、初回起動時にDropletのCloudInitサービスによって消費され、初回実行構成を実行します。 あなたはいくつかの基本的な知識を得る必要があります cloud-config このガイドに示されているスクリプトを変更する方法をよりよく理解するための、スクリプト、その構文、および動作。 cloud-configスクリプティングの概要はここにあります。 より実用的な例については(フォーマットの制限に関するいくつかの議論とともに)、cloud-configここを使用していくつかの基本的なタスクを実行するためのガイドを読むことができます。

Cloud-Configスクリプトを使用してChefノードをブートストラップする

DigitalOceanメタデータサービスを使用すると、新しいサーバーを既存のChef制御のインフラストラクチャに簡単に接続できます。 cloud-config スクリプト。

このシステムに新しいサーバーを追加するには、新しいサーバーが構成手順を受け取るために接続できるChefサーバーがすでに構成されている必要があります。 Chefサーバーと管理ワークステーションのデプロイについてサポートが必要な場合は、このガイドに従って開始できます。

一般的な計画

新しいサーバーをオンラインにするときは、Chefサーバーの制御下に置く必要があります。 通常、これは、新しいサーバーに接続することで実現できます。 knife 管理コマンドと使用 bootstrap サブコマンド。 これにより、新しいサーバーに接続し、Chefクライアントと、新しいノードがChefサーバーに接続できるようにする検証クレデンシャルをインストールします。 その後、Chefクライアントはサーバーに接続し、自身を検証し、新しいクライアントクレデンシャルを受け取り、サーバーから構成をプルダウンし、自身を目的の状態にするために必要なアクションを実行します。

このガイドでは、 cloud-config 手動のブートストラップ手順を置き換えるスクリプト。これにより、新しいノードがChefサーバーに自動的に接続し、自身を検証し、クライアントクレデンシャルを受け取り、Chefクライアントの初期実行を実行できるようになります。 サーバーは、管理者の手動による支援なしに、最初の起動時にこれを自動的に実行します。

KnifeConfigファイルから必要なデータを収集する

私たちのために cloud-config スクリプトを正常にブートストラップするには、通常使用できる資格情報にアクセスする必要があります。 knife 指図。 具体的には、次の情報が必要です。

  • Chef検証名
  • 検証キー
  • ChefサーバーにアクセスできるURL

この情報はすべて、正しい形式で、 knife Chefインフラストラクチャの管理に使用されるワークステーション上の構成ファイル。 Chefリポジトリ内には、次のような隠しディレクトリがあるはずです。 .chef このファイルが含まれています。

Chefリポジトリがワークステーションのホームディレクトリにあり、 chef-repo、次のように入力して、ファイルの内容を出力できます。

cat ~/chef-repo/.chef/knife.rb

必要な情報を以下に示します。

current_dir = File.dirname(__FILE__)
log_level                :info
log_location             STDOUT
node_name                "jellingwood"
client_key               "#{current_dir}/jellingwood.pem"
validation_client_name   "digitalocean-validator"
validation_key           "#{current_dir}/digitalocean-validator.pem"
chef_server_url          "https://your_server.com/organizations/digitalocean"
syntax_check_cache_path  "#{ENV['HOME']}/.chef/syntaxcache"
cookbook_path            ["#{current_dir}/../cookbooks"]

検証名とChefサーバーのURLは、ファイルからそのまま直接取得できます。 これらの値をコピーして、で使用できるようにします cloud-config ファイル。

The validation_key 実際のキーが保持されている場所を指します。 上記の例では、これはそれがと同じディレクトリにあることを示しています knife.rb ファイルと呼ばれます digitalocean-validator.pem. これは、構成によって異なる可能性があります。

このファイルの内容が必要なので、 cat もう一度コマンドします。 コマンドを変更して、バリデーターキーに指定された場所を指すようにします。

cat ~/chef-repo/.chef/digitalocean-validator.pem

RSA秘密鍵が表示されます。

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA3O60HT5pwEo6xUwcZ8WtExBUhoL3bTjlsvHVXg1JVmBUES+f
V9jLu2N00uSZEDZneCIQyHLBXnqD/UNvWEPNvPzt1ecXzmw2BytB7lPDW4/F/8tJ
vAVrKqC7B04VFGmcFY2zC8gf8BWmX8CNRDQooM7UO5OWe/H6GDGPPRIITerO3GrU

. . .

sWyRAoGBAKNc/ZUM8ljRV0UJxQ9nbdozXRZjtUaNgXMNiw+oP2HYYdHrlkKnGHYJ
Js63rvjpq8pocjE8YI+2H0v4/4uWqW8GEBfrWbLMzGsYPnRyiHR5+hgjCUU50RB3
eFoNbURwLYcq2Z/IAQZpDpJWpofz3OVMpMXtei1cIflrAAd2wtWO
-----END RSA PRIVATE KEY-----

検証キー全体をコピーして、 cloud-config 瞬間的にスクリプト。

基本的なCloud-ConfigChefクライアントのインストール

上記のデータを取得したら、スクリプトを作成できます。 Chefの構成は、専用の cloud-config と呼ばれるモジュール chef. The cloud-config 有効なYAMLが含まれている必要があり、 #cloud-config スクリプトの最初の行として。

最初は、スクリプトは次のようになります。

#cloud-config
chef:

The cloud-config ドキュメントには、Ruby gem、パッケージ、または従来の「オムニバス」インストール方法を使用してChefクライアントをインストールできると記載されています。 ただし、実際には、gemメソッドとpackageメソッドの両方が失敗する傾向があるため、「オムニバス」メソッドを使用します。 通常は必要ありませんが、オムニバスインストーラーの場所も明示的にリストします。

設定します force_install 「false」に。 このように、何らかの理由でChefクライアントがすでにイメージにインストールされている場合(たとえば、スナップショットからデプロイしている場合)、クライアントは再インストールされません。 これまでのところ、スクリプトは次のようになっています。

#cloud-config
chef:
  install_type: "omnibus"
  omnibus_url: "https://www.opscode.com/chef/install.sh"
  force_install: false

次に、Chefインフラストラクチャ内の新しいサーバーの名前を選択するオプションがあります。 node_name 指令。 これを設定しない場合、Chefはサーバーのホスト名を使用するため、これはオプションです。 ただし、これはChef環境で一意である必要があります。

その後、Chefワークステーションから取得したすべての接続情報を追加できます。 設定します server_url Chefサーバーの場所へのオプション knife.rb ファイル。 同じことが当てはまります validation_name オプション。

検証キーには、YAMLパイプシンボルを使用します(|)ワークステーションで見つかった検証キー全体を入力するには:

#cloud-config
chef:
  install_type: "omnibus"
  omnibus_url: "https://www.opscode.com/chef/install.sh"
  force_install: false
  node_name: "new_node"
  server_url: "https://your_server.com/organizations/digitalocean"
  validation_name: "digitalocean-validator"
  validation_key: |
    -----BEGIN RSA PRIVATE KEY-----
    MIIEowIBAAKCAQEA3O60HT5pwEo6xUwcZ8WtExBUhoL3bTjlsvHVXg1JVmBUES+f
    V9jLu2N00uSZEDZneCIQyHLBXnqD/UNvWEPNvPzt1ecXzmw2BytB7lPDW4/F/8tJ
    vAVrKqC7B04VFGmcFY2zC8gf8BWmX8CNRDQooM7UO5OWe/H6GDGPPRIITerO3GrU

    . . .

    sWyRAoGBAKNc/ZUM8ljRV0UJxQ9nbdozXRZjtUaNgXMNiw+oP2HYYdHrlkKnGHYJ
    Js63rvjpq8pocjE8YI+2H0v4/4uWqW8GEBfrWbLMzGsYPnRyiHR5+hgjCUU50RB3
    eFoNbURwLYcq2Z/IAQZpDpJWpofz3OVMpMXtei1cIflrAAd2wtWO
    -----END RSA PRIVATE KEY-----

この時点で、スクリプトには、Chefサーバーに接続してクライアント資格情報を作成するために必要なすべての認証が含まれています。

Chef Environment、run_list、および属性の構成

上記の詳細は、クライアントがChefサーバーに接続するための十分な情報を提供しますが、実際にそれ自体を構成する方法に関する情報をノードに提供していません。 この情報は、 cloud-config スクリプトも。

新しいノードを配置する環境を指定するには、 environment オプション。 これが設定されていない場合、 _default 環境が設定されます。これは、別の環境が与えられていないChefノードの一般的なデフォルトです。

chef:
  environment: "staging"

私たちの run_list クライアントが順番に適用する必要がある項目の単純なリストとして指定できます。 これらは、レシピまたはロールのいずれかです。

chef:
  run_list:
    - "recipe[lamp]"
    - "role[backend-web]"

新しいノードの初期属性は、 initial_attributes 階層。 これにより、初期属性が設定されます。 run_list 適用されます:

chef:
  initial_attributes:
    lamp:
      apache:
        port: 80
      mysql:
        username: webclient
        pass: $#fjeaiop34S

前に接続したとき cloud-config スクリプトの場合、次のようになります。

#cloud-config
chef:
  install_type: "omnibus"
  omnibus_url: "https://www.opscode.com/chef/install.sh"
  force_install: false
  node_name: "new_node"
  server_url: "https://your_server.com/organizations/digitalocean"
  validation_name: "digitalocean-validator"
  validation_key: |
    -----BEGIN RSA PRIVATE KEY-----
    MIIEowIBAAKCAQEA3O60HT5pwEo6xUwcZ8WtExBUhoL3bTjlsvHVXg1JVmBUES+f
    V9jLu2N00uSZEDZneCIQyHLBXnqD/UNvWEPNvPzt1ecXzmw2BytB7lPDW4/F/8tJ
    vAVrKqC7B04VFGmcFY2zC8gf8BWmX8CNRDQooM7UO5OWe/H6GDGPPRIITerO3GrU

    . . .

    sWyRAoGBAKNc/ZUM8ljRV0UJxQ9nbdozXRZjtUaNgXMNiw+oP2HYYdHrlkKnGHYJ
    Js63rvjpq8pocjE8YI+2H0v4/4uWqW8GEBfrWbLMzGsYPnRyiHR5+hgjCUU50RB3
    eFoNbURwLYcq2Z/IAQZpDpJWpofz3OVMpMXtei1cIflrAAd2wtWO
    -----END RSA PRIVATE KEY-----
  environment: "staging"
  run_list:
    - "recipe[lamp]"
    - "role[backend-web]"
  initial_attributes:
    lamp:
      apache:
        port: 80
      mysql:
        username: webclient
        pass: $#fjeaiop34S

出力のリダイレクトとChefクライアント実行の構成

上記のスクリプトには、 chef: セクション。 ただし、他のいくつかを使用して実行する必要がある他のいくつかのことがあります cloud-config モジュール。

まず、すべてのコマンドとサブコマンドからの出力をCloudInitプロセスの出力ログにリダイレクトすることを指定する必要があります。 これはにあります /var/log/cloud-init-output.log デフォルトでは。 私たちはこれを行うことができます output このようなモジュール:

output: {all: '| tee -a /var/log/cloud-init-output.log'}

もう1つ実行したいのは、Chefクライアントをインストールして構成した後、実際に実行するように設定することです。 この記事の執筆時点では、オムニバスのインストール方法はこれを自動的に行いません。

この動作を強制するには、 chef-client コマンドを呼び出す前に、実行可能ファイルがサーバーにインストールされます。 シンプルな bash ループします。5秒ごとにこのファイルの存在を確認します。 見つかったら実行します chef-client 指定した初期構成を実装するため。

The runcmd モジュールを使用して、任意のコマンドを発行できます。 それは私たちにとって理想的な場所です bash ループ:

runcmd:
  - while [ ! -e /usr/bin/chef-client ]; do sleep 5; done; chef-client

また、オプションで、別のものを追加できます cloud-config 最初の起動後にメタデータエンドポイントをnullルーティングするディレクティブ。 これは、ユーザーデータに秘密鍵を入れるので便利です。 メタデータエンドポイントをヌルルーティングしないと、サーバー上のすべてのユーザーがこれにアクセスできます。 次を追加してこれを実装します。

disable_ec2_metadata: true

これらをこれまでに作成したスクリプトと組み合わせると、ノードをブートストラップしてChefインフラストラクチャに接続するために必要な完全なスクリプトを取得できます。

#cloud-config
chef:
  install_type: "omnibus"
  omnibus_url: "https://www.opscode.com/chef/install.sh"
  force_install: false
  node_name: "new_node"
  server_url: "https://your_server.com/organizations/digitalocean"
  validation_name: "digitalocean-validator"
  validation_key: |
    -----BEGIN RSA PRIVATE KEY-----
    MIIEowIBAAKCAQEA3O60HT5pwEo6xUwcZ8WtExBUhoL3bTjlsvHVXg1JVmBUES+f
    V9jLu2N00uSZEDZneCIQyHLBXnqD/UNvWEPNvPzt1ecXzmw2BytB7lPDW4/F/8tJ
    vAVrKqC7B04VFGmcFY2zC8gf8BWmX8CNRDQooM7UO5OWe/H6GDGPPRIITerO3GrU

    . . .

    sWyRAoGBAKNc/ZUM8ljRV0UJxQ9nbdozXRZjtUaNgXMNiw+oP2HYYdHrlkKnGHYJ
    Js63rvjpq8pocjE8YI+2H0v4/4uWqW8GEBfrWbLMzGsYPnRyiHR5+hgjCUU50RB3
    eFoNbURwLYcq2Z/IAQZpDpJWpofz3OVMpMXtei1cIflrAAd2wtWO
    -----END RSA PRIVATE KEY-----
  environment: "staging"
  run_list:
    - "recipe[lamp]"
    - "role[backend-web]"
  initial_attributes:
    lamp:
      apache:
        port: 80
      mysql:
        username: webclient
        pass: $#fjeaiop34S
output: {all: '| tee -a /var/log/cloud-init-output.log'}
runcmd:
  - while [ ! -e /usr/bin/chef-client ]; do sleep 5; done; chef-client
disable_ec2_metadata: true

上記のスクリプトは、インフラストラクチャ内の新しいサーバーごとに必要に応じて調整できます。

Cloud-Configスクリプトを使用してPuppetノードをブートストラップする

インフラストラクチャが構成管理をPuppetに依存している場合は、 puppet 代わりにモジュール。 Chefの例のように、Puppetノードのブートストラップには cloud-config 新しいサーバーを既存の構成管理インフラストラクチャに接続します。

開始する前に、インフラストラクチャ用にPuppetマスターサーバーを構成する必要があります。 Puppetサーバーの起動と実行についてサポートが必要な場合は、このガイドを確認してください。

一般的な計画

新しいPuppetサーバーがオンラインになると、Puppetエージェントがインストールされ、Puppetマスターサーバーと通信できるようになります。 このエージェントは、ノードの望ましい状態を指示する情報を受信して適用する責任があります。 これを行うには、エージェントはマスターに接続し、自身に関するデータをアップロードし、目的の状態を説明する現在のカタログをプルダウンして、その状態に到達するために必要なアクションを実行します。

ただし、これが発生する前に、最初の実行時に、エージェントは自分自身をマスターサーバーに登録する必要があります。 証明書署名要求を作成し、それをマスターに送信して署名します。 通常、エージェントは証明書が署名されるまで定期的にマスターに再接続しますが、環境に適している場合は、特定の特性を持つ着信要求に自動的に署名するようにPuppetを構成できます(これについては後で説明します)。

私たちの使用 cloud-config スクリプトでは、マスターに初めて接続するために必要な情報を使用して新しいサーバーを構成します。 その時点で、Puppetマスターサーバーからカタログの形式で構成の詳細を取得できます。

パペットマスターから必要なデータを収集する

構築する前に最初に行う必要があること cloud-config ファイルは、接続する必要があるPuppetマスターサーバーからデータを収集します。 必要な情報はほんのわずかです。

まず、Puppetマスターサーバーの完全修飾ドメイン名(FQDN)を取得する必要があります。 これを行うには、次のように入力します。

hostname -f

ほとんどの場合、次のようなものが返されます。

puppet.example.com

Puppetマスター構成ファイルをチェックして、 dns_alt_names オプションが設定されています:

cat /etc/puppet/puppet.conf
. . .

dns_alt_names = puppet,puppet.example.com

. . .

これらのオプションを設定した後にPuppetマスターのSSL証明書が生成された場合は、それらも使用できる可能性があります。

収集する必要があるもう1つのアイテムは、Puppetマスターの認証局証明書です。 これはどちらかで見つけることができます /var/lib/puppet/ssl/certs/ca.pem また /var/lib/puppet/ssl/ca/ca_crt.pem:

sudo cat /var/lib/puppet/ssl/certs/ca.pem

結果は次のようになります。

-----BEGIN CERTIFICATE-----
MIIFXjCCA0agAwIBAgIBATANBgkqhkiG9w0BAQsFADAcMRowGAYDVQQDDBFQdXBw
ZXQgQ0E6IHB1cHBldDAeFw8xNTAyMTkxOTA0MzVaFw0yMDAyMTkxOTA0MzVaMBwx
GjAYBgNVBAMMEVB1cHBldCBDQTogcHVwcGV0MIICIjANBgkqhkiG9w0BAQEFAAOC

. . .

arsjZT5/CtIhtP33Jl3mCp7U2F6bsk4/GDGRaAsFXjJHvBbL93NzgpkZ7elf0zUP
rOcSGrDrUuzuJk8lEAtrZr/IfAgfKKXPqbyYF95V1qN3OMY+aTcrK20XTydKVWSe
l5UfYGY3S9UJFrSn9aBsZzN+10HXPkaFKo7HxpztlYyJNI8UVSatcRF4aYYqt9KR
UClnR+2WxK5v7ix0CVd4/KpYH/6YivvyTwxrhjF2AksZKg==
-----END CERTIFICATE-----

証明書全体をコピーします。 これを私たちの cloud-config 新しいサーバーが正しいPuppetマスターに接続していることを確認できるようにファイルします。

これらの情報を入手したら、構築を開始できます cloud-config 新しいサーバーが既存のPuppetインフラストラクチャにプラグインできるようにファイルします。

基本的なCloud-ConfigPuppetノードのインストール

The cloud-config 新しいPuppetノードの構成は非常に簡単です。 すべてのPuppet固有の構成は、 puppet: ファイルのセクション。 すべてのように cloud-config ファイルの場合、最初の行に含まれている必要があります #cloud-config そのままで:

#cloud-config
puppet:

この下には、2つのサブセクションしかありません。 最初は ca_cert 鍵。 これはパイプ文字を使用してYAMLテキストブロックを開始し、CA証明書全体をインデントされたブロックとして指定できるようにします。

#cloud-config
puppet:
  ca_cert: |
    -----BEGIN CERTIFICATE-----
    MIIFXjCCA0agAwIBAgIBATANBgkqhkiG9w0BAQsFADAcMRowGAYDVQQDDBFQdXBw
    ZXQgQ0E6IHB1cHBldDAeFw8xNTAyMTkxOTA0MzVaFw0yMDAyMTkxOTA0MzVaMBwx
    GjAYBgNVBAMMEVB1cHBldCBDQTogcHVwcGV0MIICIjANBgkqhkiG9w0BAQEFAAOC
    
    . . .
    
    arsjZT5/CtIhtP33Jl3mCp7U2F6bsk4/GDGRaAsFXjJHvBbL93NzgpkZ7elf0zUP
    rOcSGrDrUuzuJk8lEAtrZr/IfAgfKKXPqbyYF95V1qN3OMY+aTcrK20XTydKVWSe
    l5UfYGY3S9UJFrSn9aBsZzN+10HXPkaFKo7HxpztlYyJNI8UVSatcRF4aYYqt9KR
    UClnR+2WxK5v7ix0CVd4/KpYH/6YivvyTwxrhjF2AksZKg==
    -----END CERTIFICATE-----

証明書全体を開始マーカーと終了マーカーとともに含め、適切にインデントするようにしてください。

下の2番目のセクション puppet: 傘は conf: セクション。 これは、ジェネリックに追加されるキーと値のペアを指定するために使用されます puppet.conf ファイル。 キーと値のペアは、セクションヘッダーの下に配置する必要があります。 puppet.conf ファイル。

たとえば、少なくとも、新しいサーバーはPuppetマスターサーバーのアドレスを知っている必要があります。 の中に puppet.conf ファイル、これは下にあります [agent] このようなセクション:

. . .

[agent]
server = puppet.example.com

. . .

これをで指定するには cloud-config 構文では、これをこれまでのところに追加します。

#cloud-config
puppet:
  ca_cert: |
    -----BEGIN CERTIFICATE-----
    MIIFXjCCA0agAwIBAgIBATANBgkqhkiG9w0BAQsFADAcMRowGAYDVQQDDBFQdXBw
    ZXQgQ0E6IHB1cHBldDAeFw8xNTAyMTkxOTA0MzVaFw0yMDAyMTkxOTA0MzVaMBwx
    GjAYBgNVBAMMEVB1cHBldCBDQTogcHVwcGV0MIICIjANBgkqhkiG9w0BAQEFAAOC
    
    . . .
    
    arsjZT5/CtIhtP33Jl3mCp7U2F6bsk4/GDGRaAsFXjJHvBbL93NzgpkZ7elf0zUP
    rOcSGrDrUuzuJk8lEAtrZr/IfAgfKKXPqbyYF95V1qN3OMY+aTcrK20XTydKVWSe
    l5UfYGY3S9UJFrSn9aBsZzN+10HXPkaFKo7HxpztlYyJNI8UVSatcRF4aYYqt9KR
    UClnR+2WxK5v7ix0CVd4/KpYH/6YivvyTwxrhjF2AksZKg==
    -----END CERTIFICATE-----
  conf:
    agent:
      server: "puppet.example.com"

に注意してください conf: セクションは、 ca_cert セクションであり、子要素ではありません。 これは、Puppetマスターに接続するために最低限必要なものです。 にある追加の構成アイテム puppet.conf 同様の方法で、最初にセクション名のレベルを作成し、次にキーと値のペアを定義することで追加できます。

この後、今後のすべての出力をにリダイレクトする必要があります cloud-init-output.log ファイルを追加し、 runcmd Chef構成用に追加した行に相当する行。 これにより、Puppetエージェントがインストールされるまで待機してから、有効にして再起動します。 Chefセクションで行ったように、最初の実行後にメタデータエンドポイントをnullルーティングすることもできます。 これらの行 cloud-config ディレクティブは、他のモジュールセクションの外側に配置する必要があります。

. . .

  conf:
    agent:
      server: "puppet.example.com"
output: {all: '| tee -a /var/log/cloud-init-output.log'}
runcmd:
  - while [ ! -e /usr/bin/puppet ]; do sleep 5; done; puppet agent --enable; service puppet restart
disable_ec2_metadata: true

この情報を使用して、新しいサーバーはPuppetマスターサーバーに接続し、マスターに転送するためのクライアント証明書署名要求を生成できます。 デフォルトでは、クライアント証明書はPuppetマスターで手動で署名する必要があります。 これが完了すると、次のPuppetエージェントの更新間隔(デフォルトでは30分ごと)で、ノードはPuppetマスターから構成をプルダウンします。 この遅延を回避するために、比較的安全な自動署名メカニズムを実装する方法については、少し後で説明します。

ノードの証明書名の定義

新しいサーバーに配置できる値の1つ puppet.conf ファイルはユニークなケースです。 の中に cloud-config ファイル、 certname オプションは、特定の変数が指定されている場合、環境からの値を置き換えることができます。 次の変数が認識されます。

  • %i :サーバーのインスタンスID。 これはから取得されます http://169.254.169.254/metadata/v1/id サーバーが作成されたとき。 これは、液滴を一意に識別するために使用される液滴IDに対応します。
  • %f :サーバーのFQDN。

これを念頭に置いて、一般的な certname 設定は次のようになります。

#cloud-config
puppet:

. . .

  conf:
    agent:
      server: "puppet.example.com"
      certname: "%i.%f"

これにより、 certname これに似たパターンで:

   |-Droplet ID
   |
   |            |-Fully Qualified Domain Name
   |            |
|-----||-------------------|
123456.testnode.example.com

の一部として液滴IDを持っている certname 次のセクションで説明するように、安全なPuppet自動署名を構成するのに役立ちます。

Puppet証明書の自動署名を実装する

管理者の介入の必要性を回避するために証明書自動署名システムを実装したい場合は、いくつかのオプションがあります。 最初にPuppetマスターサーバーでこれを設定する必要があります。

の中に puppet.conf Puppetマスターサーバー上のファイル、あなたは設定することができます autosign 下のオプション [master] ファイルのセクション。 これは、いくつかの異なる値を取ることができます。

  • true :これにより、Puppetマスターサーバーは、チェックを行わずに、着信するすべての証明書要求に署名するように指示されます。 これは実際の環境では非常に危険です。どのホストもCSRに署名して、インフラストラクチャに入ることができるからです。
  • :2番目のオプションは、ホストまたはホスト正規表現のホワイトリストとして機能するファイルを指定することです。 Puppetマスターは、このリストに対して証明書署名要求をチェックして、証明書に署名する必要があるかどうかを確認します。 証明書名は簡単にスプーフィングされる可能性があるため、これもお勧めしません。
  • :3番目のオプションは、証明書署名要求に署名する必要があるかどうかを判断するために実行できるスクリプトまたは実行可能ファイルを指定することです。 Puppetは、引数としてcertnameを渡し、標準入力を介してCSR全体を渡します。 終了ステータス0が返された場合、証明書は署名されています。 別のステータスが与えられた場合、証明書は署名されません

ポリシーベースの自動署名は、自動キー署名を実装するための最も安全な方法です。これにより、正当な要求と非正当な要求を区別する方法を任意に複雑にすることができます。

ポリシーベースの自動署名を示すために、 certname あなたに可変 cloud-config それを含む %i インスタンスID変数。 我々は使用するだろう %i.%f 選択したホスト名も含まれるようにします。

#cloud-config
puppet:
  conf:
    agent:
      server: "puppet.example.com"
      certname: "%i.%f"
  ca_cert: |

   . . .

あなたの完全な cloud-config これで、次のようになります。

#cloud-config
puppet:
  conf:
    agent:
      server: "puppet.example.com"
      certname: "%i.%f"
  ca_cert: |
    -----BEGIN CERTIFICATE-----
    MIIFXjCCA0agAwIBAgIBATANBgkqhkiG9w0BAQsFADAcMRowGAYDVQQDDBFQdXBw
    ZXQgQ0E6IHB1cHBldDAeFw8xNTAyMTkxOTA0MzVaFw0yMDAyMTkxOTA0MzVaMBwx
    GjAYBgNVBAMMEVB1cHBldCBDQTogcHVwcGV0MIICIjANBgkqhkiG9w0BAQEFAAOC
    
    . . .
    
    arsjZT5/CtIhtP33Jl3mCp7U2F6bsk4/GDGRaAsFXjJHvBbL93NzgpkZ7elf0zUP
    rOcSGrDrUuzuJk8lEAtrZr/IfAgfKKXPqbyYF95V1qN3OMY+aTcrK20XTydKVWSe
    l5UfYGY3S9UJFrSn9aBsZzN+10HXPkaFKo7HxpztlYyJNI8UVSatcRF4aYYqt9KR
    UClnR+2WxK5v7ix0CVd4/KpYH/6YivvyTwxrhjF2AksZKg==
    -----END CERTIFICATE-----
output: {all: '| tee -a /var/log/cloud-init-output.log'}
runcmd:
  - while [ ! -e /usr/bin/puppet ]; do sleep 5; done; puppet agent --enable; service puppet restart
disable_ec2_metadata: true

Puppetマスターサーバーで、検証スクリプトを設定する必要があります。 RubyはすでにPuppetにインストールされているので、簡単なRubyスクリプトを作成できます。

使用しているので %i.%f のフォーマット certname、最初の部分が certname (最初のドットの前の部分)は、アカウントの有効なドロップレットIDに対応します。 これは単なるチェックであり、実際にはホワイトリストファイル以上のことはしません。 ただし、必要に応じて、このアイデアをさらに複雑にすることができます。

これを行うには、DigitalOceanコントロールパネルの「Apps&API」セクションからの個人用アクセストークンが必要になります。 また、DigitalOceanRubyライブラリの1つをインストールする必要があります。 以下に、BargeおよびDropletKitDigitalOceanRubyクライアントを使用するいくつかの簡略化されたスクリプトを示します。

Bargeクライアントを使用する場合は、次のように入力して、Puppetマスターにgemをインストールします。

sudo gem install barge

次のスクリプトを使用して、 certname 証明書署名要求では、有効なドロップレットIDに対応しています。

#!/usr/bin/env ruby

require 'barge'

TOKEN = 'YOUR_DIGITALOCEAN_API_TOKEN'

droplet_ids = []
certname = ARGV[0]
id_string = certname.slice(0...(certname.index('.')))
id_to_check = id_string.to_i

client = Barge::Client.new(access_token: TOKEN)
droplets = client.droplet.all

droplets.droplets.each do |droplet|
        droplet_ids << droplet.id
end

Kernel.exit(droplet_ids.include?(id_to_check))

代わりに、DigitalOceanの公式RubyクライアントであるDropletKitを使用する場合は、次のように入力してgemをインストールできます。

sudo gem install droplet_kit

DropletKitgemはRuby2.0以降でのみ有効であるため、Puppetに付属しているバージョンのRubyを使用している場合はこれが不可能な場合があることに注意してください。

DropletKitのスクリプトは、次のように調整できます。

#!/usr/bin/env ruby

require 'droplet_kit'

TOKEN = 'YOUR_DIGITALOCEAN_API_TOKEN'

droplet_ids = []
certname = ARGV[0]
id_string = certname.slice(0...(certname.index('.')))
id_to_check = id_string.to_i

client = DropletKit::Client.new(access_token: TOKEN)
droplets = client.droplets.all

droplets.each do |droplet|
        droplet_ids << droplet.id
end

Kernel.exit(droplet_ids.include?(id_to_check))

インストールしたgemに対応するスクリプトをというファイルに配置できます。 /etc/puppet/validate.rb 次のように入力して、実行可能としてマークします。

sudo chmod +x /etc/puppet/validate.rb

次に、以下を追加できます puppet.conf ファイル(にあります /etc/puppet/puppet.conf オープンソースパペットを使用している場合):

. . .

[master]
autosign = /etc/puppet/validate.rb

. . .

Apacheサービスを再起動して、新しい署名ポリシーを実装します。

sudo service apache2 restart

これで、証明書署名要求がPuppetマスターによって受信されると、証明書名の最初の部分がアカウント内の有効なドロップレット名に対応しているかどうかがチェックされます。 これは、実行可能ファイルを使用してリクエストを検証する方法の大まかな例です。

結論

レバレッジによって cloud-config スクリプトを使用すると、新しいサーバーを簡単にブートストラップして、既存の構成管理システムに渡すことができます。 これにより、管理ソリューションの範囲外で重要な変更を行う前に、既存のツールを使用してインフラストラクチャをすぐに制御できます。