Kotaro7750's Gehirn
Home About
  • Home
  • Category
  • About

Hashicorp VaultのSSH OTPを利用してUbuntuマシンへのアクセスをセキュアに保つ

2024-06-22

TL; DR;

宅鯖のVMへの認証情報をリポジトリ内に置かなくて済むようにパスワードレス・Hashicorp Vault SSH OTPによる接続ができるようにしました。 その際、cloud-init・terraformを用いた自動セットアップや、AnsibleでのOTPを使ったログインなど、IaC awareな方法を用いました

モチベーション

我が家の宅鯖環境では、環境の再現性を高めるために、物理マシン上にKVMによる仮想マシンを構築して、その上でKubernetesクラスタを構築しています。 このVMへの接続に用いるユーザーは、VMインストール時にcloud init(正確にはubuntuのauto install)を用いてパスワード作成・SSHアクセスを許可する公開鍵登録を行っているのですが、このやり方だと以下のような問題があります。

  • 認証情報を平文で保存しておりセキュリティ的によろしくない
    • プライベートリポジトリなのでそこまで問題ではないが気持ち悪い
  • 認証情報をローテーションする際に、cloud initの設定ファイル変更に加えてマシンでの変更が必要になる
    • cloud initはインストール時にしか作用しないため
  • マシン毎に異なる認証情報を用いようとするとさらに管理が煩雑になる

これらの問題に対して、本来ならPAMを使って外部のパスワードソースと連携するといったアプローチが考えられますが、インターネットからアクセスできないネットワーク上かつユーザーは自分だけなので、とりあえずパスワードレスとします。

ただしそのままだとSSH接続をセキュアに行うことができないので、SSH接続時の認証に関して以下のような方法を検討し、最終的にHashicorp VaultのSSH OTPを導入することにしました。 機能だけで見るならTeleportですが宅鯖環境での設計は一筋縄ではいかなさそうである一方、SSH OTPなら機密情報管理用にVaultを既に入れていてミニマルに始められそうだったためです。

  • 公開鍵認証
    • メリット
      • 公開鍵を配置するだけで実装可能
    • デメリット
      • 自動化の余地はあるが、接続元の追加・削除の際に全マシンに対して変更する必要がある
  • Hashicorp Vault SSH OTP
    • Vaultが生成したOTPを使うことでそのマシンへのログインに限ったSSHパスワードを行える
    • メリット
      • エージェントをインストールするだけでマシンへの導入が終わる
    • デメリット
      • Hashicorp Vaultをセットアップする必要がある
      • Vaultへの疎通がとれない場合にログインできなくなる
  • Teleport
    • ゼロトラストのアクセス用OSS
    • メリット
      • PAMの提供もしており、セキュリティレベルでは最も高い
    • デメリット
      • 導入・運用の手間が多い
      • 宅鯖でHA構成を取ろうとするとストレージ・LBの選定が難しい

Hashicorp Vault SSH OTPによるログインの流れは図のようになります。 Hashicorp Vault SSH OTPによるログインの流れ

設定

Vault側の設定

公式ドキュメントの手順に従ってTerraformによる設定を行います。

provider "vault" {
  address = "Vaultのエンドポイント"
  ca_cert_file = "ルート証明書"
}

// ssh secret engineを有効化する
resource "vault_mount" "ssh" {
  path = "ssh"
  type = "ssh"
}

// roleを作成する
resource "vault_ssh_secret_backend_role" "virtual-machine-otp" {
  name     = "virtual-machine-otp"
  backend  = vault_mount.ssh.path
  key_type = "otp"
  default_user = "localadmin"
  cidr_list = "172.16.1.0/24"
}

仮想マシン側の設定

公式チュートリアルに従ってcloud-initでのVMセットアップ時に設定を行います。 実際にはubuntuのautoinstallという機能の設定ファイルなので、user-data以下にcloud-initの記法で記述します。

#cloud-config
autoinstall:
  version: 1
  locale: ja_JP.UTF-8
  user-data:
    users:
      - name: localadmin
        # パスワードを指定しないことでパスワードレスにできる
        # パスワードレスでsudoができるように設定
        sudo: "ALL=(ALL) NOPASSWD:ALL"
        shell: /bin/bash
    runcmd:
      - apt update
      - apt install -y unzip
      # vault-ssh-helper(エージェント)のインストール
      - wget "https://releases.hashicorp.com/vault-ssh-helper/0.2.1/vault-ssh-helper_0.2.1_linux_amd64.zip"
      - unzip -q vault-ssh-helper_0.2.1_linux_amd64.zip -d /usr/local/bin
      - rm vault-ssh-helper_0.2.1_linux_amd64.zip 
      - chmod 0755 /usr/local/bin/vault-ssh-helper
      - chown "root:root" /usr/local/bin/vault-ssh-helper
      - mkdir /etc/vault-ssh-helper.d
      # vault-ssh-helperの設定
      - |
          tee /etc/vault-ssh-helper.d/ca.crt << EOF
          ルート証明書の内容を記載
          EOF

      - |
          tee /etc/vault-ssh-helper.d/config.hcl <<EOF
          vault_addr = "Vaultのエンドポイント"
          tls_skip_verify = false
          ca_cert = "/etc/vault-ssh-helper.d/ca.crt"
          ssh_mount_point = "ssh"
          allowed_roles = "*"
          EOF
      # sshdのPAM設定でvault-ssh-helperを使うように変更する
      - sed -r -i "s/(^@include common-auth)/#\1/" /etc/pam.d/sshd
      - |
          tee -a /etc/pam.d/sshd <<EOF
          auth requisite pam_exec.so quiet expose_authtok log=/var/log/vault-ssh.log /usr/local/bin/vault-ssh-helper -config=/etc/vault-ssh-helper.d/config.hcl
          auth optional pam_unix.so not_set_pass use_first_pass nodelay
          EOF
      # sshdの設定でvault-ssh-helperを使うように変更する
      - sed -r -i "s/(^UsePAM no)/#\1/" /etc/ssh/sshd_config
      - sed -r -i "s/(^KbdInteractiveAuthentication no)/#\1/" /etc/ssh/sshd_config
      - sed -r -i "s/(^PasswordAuthentication yes)/#\1/" /etc/ssh/sshd_config
      - |
          tee -a /etc/ssh/sshd_config <<EOF
          # For Hashicorp vault ssh helper
          KbdInteractiveAuthentication yes
          UsePAM yes
          PasswordAuthentication no
          EOF
      - systemctl restart sshd
      - vault-ssh-helper -verify-only -config /etc/vault-ssh-helper.d/config.hcl
  timezone: "Asia/Tokyo"
  ssh:
    install-server: true

この設定を投入してVMを作成すると、自動でSSH OTPのエージェントのインストール・設定が完了します。

ログイン

ターミナルからのログイン

VaultのUIから、OTPを発行し、そのOTPをSSH時に求められるパスワードとすることでログインできます。 OTPの発行

パスワードレスの設定をしているので、sudoをする際にはパスワードを求められることはありません。

また、いちいちUIにアクセスするのは面倒ですが、自動で行えるコマンドも紹介されています。

Ansibleによるログイン

IaCを実践するために、kubernetesノードとしてのセットアップなどはAnsibleで行っていますが、OTPなのでinventoryに直接書くことができません。

そこで、inventoryでOTPを動的に作成してそれを認証情報として使えるようにします。

仕組みとしては簡単で、community.hashi_vault.vault_write lookupプラグインを用いて、OTPを取得しているというだけです。

all:
  vars:
    ansible_user: localadmin
    ansible_password: "{{ lookup('community.hashi_vault.vault_write', 'ssh/creds/virtual-machine-otp', url='Vaultのエンドポイント', ca_cert='ルート証明書のパス', data={'ip': lookup('community.general.dig', inventory_hostname)})['data']['key'] }}"

  children:
    servers:
      hosts:
        VM1のFQDN:
        VM2のFQDN:
        ...

今後の改善点

当初実現したかったことは達成でき当面はこれで行こうかと思いますが、パスワードレスにしたゆえにセキュリティ的に少し気持ち悪いという課題は残ります。

Teleportはここらへんをうまく解決してくれそうなので、検証をしていきたいです。

Related Posts

スケーラブルなOpenTelemetry CollectorパイプラインをKubernetes上に構築する

スケーラブルなOpenTelemetry CollectorパイプラインをKubernetes上に構築する

2025-04-14

OpenTelemetry Certified Associate ( OTCA ) を取得した

OpenTelemetry Certified Associate ( OTCA ) を取得した

2025-04-13

KorbでKubernetesの既存PVのStorage Classを変更する

KorbでKubernetesの既存PVのStorage Classを変更する

2024-12-15

New Posts

スケーラブルなOpenTelemetry CollectorパイプラインをKubernetes上に構築する

スケーラブルなOpenTelemetry CollectorパイプラインをKubernetes上に構築する

2025-04-14

OpenTelemetry Certified Associate ( OTCA ) を取得した

OpenTelemetry Certified Associate ( OTCA ) を取得した

2025-04-13

Golangのnet/httpの実装からHTTP1.1クライアントでのTCPコネクションの挙動を確かめる

Golangのnet/httpの実装からHTTP1.1クライアントでのTCPコネクションの挙動を確かめる

2025-03-21

ToC

  • TL; DR;
  • モチベーション
  • 設定
  • Vault側の設定
  • 仮想マシン側の設定
  • ログイン
  • ターミナルからのログイン
  • Ansibleによるログイン
  • 今後の改善点

Ads

Ads

Privacy Policy