Libvirt

概要

libvirtは仮想機械の制御を抽象化したライブラリである。
本ライブラリの特徴は、サポート範囲が広いことである。
サポートしている仮想化は、現在Xen、KVM、QEMU、LXC、OpenVZ、UML、VirtualBox、VMware ESX・GSX・Workstation・Player、Hyper-V、そしてクラスタ管理ソフトOpenNebulaである。
更なる対象仮想機械の拡大を目指して例えば、対応やLinux-VServerのサポートをどうするかなどが開発者メーリングリスト上で議論された。
また、様々な版数でのサポートも特徴である。たとえば、Xenのリリースされたさまざまな版（例えばXen3.1.0やXen3.0.3など）で動作する。またUnix系オペレーティングシステムだけでなく、Windows上でもMinGWやCygwinを使えば動作する。
libvirt自体が多くの種類の仮想化をサポートしていても、必ずしもlibvirtを利用しているアプリケーションが全ての仮想化をサポートしているというわけではなく、KVMやXenなどがlibvirtを利用しているアプリケーションのサポートの中心となっている。
またハードウェアプラットフォームに着目すると、CPUの場合、x86、x86-64、IA-64、POWERなどをサポートしており、ビット (32/64) およびエンディアンを問わない。
このような幅広いサポートを行っているため、仮想機械を制御するインタフェースとしては、事実上の標準の地位を築きつつある。
例えば、RHEL5上で仮想機械を管理するためのアプリケーションであるVirtual Machine Managerの実装においても利用されている。
本ソフトウェアのライセンスはLGPLで提供されている。このため、GPLで開発されているXenのライブラリ (libxc) に比べてアプリケーション開発者の視点では使い勝手が良い。
標準提供APIはCとPythonである。またその他の言語 (Perl, OCaml, Ruby, Java) のAPIもオプションパッケージで提供されている。また、運用管理の標準インタフェースであるCIMへの対応もIBMを中心にCMPI CIM Providerとしてlibvirt-CIMの開発が進んでいる。なお、CMPIは、Common Manageability Programming Interfaceの略である。
セキュリティ拡張として、MACアクセス制御との連携を考えたsVirtが検討されている。
本プロジェクトのメンテナーは、Daniel Veillard（通称Daniel）、Daniel Berrange（通称Dan）、Richard W.M.Jones（通称Rich）などレッドハットの開発者である。そのほか、レッドハット以外にもIBMやノベル、富士通の開発者にソースコードの変更権が与えられている。

ソフトウェア構成

libvirtの実装はlibvirt.cを中心としたソフトウェア構成になっている。libvirtのAPIを利用しているアプリケーションとしては、管理コマンドvirshが提供されている。また、Python Bindingsもlibvirt.cの上位に位置する。
一方、各種仮想機械の制御ドライバは、libvirt.cの下に位置する。例えばXenの制御層の実装では、Xen統合管理層 (xen_unified.c) から、それぞれのXenのモジュールを呼び出す形になっている。ハイパーバイザ直接 (xen_internal.c)、管理ツールであるXend (xend_internal.c)、管理データベースであるxenstore (xs_internal.c) を呼び出している。
また、ネットワーク越しの制御に関するコードは、以下の通りである。クライアント側では、remote_internal.cを介してリクエストを発行する。サーバ側では、libvirtd（コード的には、qemudディレクトリ以下）を介して、libvirtAPIを使って制御を行う。

サーバ設定

管理者は、libvirtdの認証方法を、ネットワークソケット毎に設定することが出来る。
この設定は、libvirtdの設定ファイル /etc/libvirt/libvirtd.confで行う。
そして、認証方法は、なし、POLKITそしてSASLの3つから選択することが出来る。
さらに、SASL機構は、将来さまざまなオプションを設定できるようになる予定である。

UNIXドメインソケットによる伝統的権限管理

libvirtがPolkitをサポートしていない場合、UNIXドメインソケットに対するアクセス制御は、伝統的なユーザグループアクセス制御により行われる。
2種類のソケットがあり、ひとつは読み書き可能、もう1つは読みのみ可能となっている。
読み書きソケットは、アクセス制御が厳しく(0700)、ルートユーザのみが使うことが出来る。
読みのみソケットは、アクセス制御がオープン (0777) であり、どのユーザも使うことが出来る。
非特権ユーザにより広いアクセスを許可する場合、libvirtd.confファイルを編集しunix_sock_rw_permsに許可権限を設定し、ユーザグループを、unix_sock_groupに設定する必要がある。例えば、前者の属性を0770にして、後者をwheelグループに設定すると、wheelグループの人全員libvirtdにアクセスできることになる。

Polkitを使ったUNIXドメインソケットの認証

libvirtがPolkit認証をサポートする場合、アクセス制御は、より進んだ形態になる。
この場合、unix_sock_authパラメータは、polkitが標準になる。そして、ファイルアクセス権限は、読み書き権限を含め0777になる。クライアントアプリケーションは、Polkitと連携してアイデンティティを提供し、ソケットに接続する。
現デスクトップセッションのいずれのアプリケーションでも、パスワード認証を行うことが、読み書きソケットの標準ポリシーである。
この方法はsudoコマンドによる認証と似ている。しかし、クライアントアプリケーションは究極的に特権ユーザ（ルート）として動く必要がない。
そして標準ポリシーでは、読み専用ソケットにどのようなアプリケーションも接続できる。
ポリシーは/etc/PolicyKit/PolicyKit.confに置かれたマスター設定ファイルによって管理者が変更出来る。
PolicyKit.conf(5)マニュアルページに設定方法詳細の記述がある。
属性として、2つのlibvirtd操作が設定されている。1つは、読み専用のorg.libvirt.unix.monitorである。もう1つは、読み書き可能なorg.libvirt.unix.manageである。
例として、fredに読み書き権限を与え、joeには管理者パスワードを認証を要求する例を示す。このアクセス制御をするためには、以下の設定を、PolicyKit.confに追記する必要がある。
 <match action="org.libvirt.unix.manage">
   <match user="fred">
     <return result="yes"/>
   </match>
 </match>
 <match action="org.libvirt.unix.manage">
   <match user="joe">
     <return result="auth_admin"/>
   </match>
 </match>

ユーザ名とパスワードによる認証

TCPソケットを平文のまま用いたlibvirtdは、標準でSASLを認証機構として用いる。
SASL機構は、標準では、Digest-MD5を用いる。これは、基本的なユーザ名とパスワード形式の認証である。
データストリームを暗号化する方法も提供している。このため平文のTCPソケットのセキュリティもTLSソケットを使った場合と同等のセキュリティである。このため、UNIXドメインソケット及びTLSソケットをSASL認証するように設定しておくことは望ましい。この設定は、libvirt.conf設定ファイルのauth_unix_ro, auth_unix_rw, auth_tlsでSASL認証するようにしておく。
使い始めの段階では、ユーザアカウントは定義されていない。このためクライアントがTCP接続することが出来ない。
ユーザを追加し、設定を行うためには、saslpasswd2コマンドを使う。
このコマンドを実行するに当たって、アプリケーションがlibvirtであることを明示的に示す必要がある。
この例では、fredをアカウントに追加する例を示している。
 # saslpasswd2 -a libvirt fred
 Password: xxxxxx
 Again (for verification): xxxxxx
全アカウントのリストを見るためには、sasldblistuser2コマンドを使う。このコマンドでは、libvirtのユーザデータベースを指定する必要がある。このデータベースは/etc/libvirt/passwd.dbにある。
 # sasldblistusers2 -f /etc/libvirt/passwd.db
 fred@t60wlan.home.berrange.com: userPassword
最後に、ユーザアクセスを停止する場合、saslpasswd2コマンドを再び使う。
 # saslpasswd2 -a libvirt -d fred

ケルベロス認証

TCPソケットを平文のまま用いたlibvirtdは、標準でSASLを認証機構として用いる。
SASL機構は、標準では、Digest-MD5を用いる。これは、基本的なユーザ名とパスワード形式の認証である。
ケルベロス (Kerberos) 認証のシングルサインオンを有効にするには、libvirt用SASL設定ファイルを変更する必要がある。そのファイルは、/etc/sasl2/libvirt.confである。そして、mech_listパラメータは、digest-md5の代わりにgssapiに変更する必要がある。
もし、UNIXドメインソケットやTLSソケットに対してSASLが有効になっている場合、Kerberosは、SASLを使うことが出来る。DIGEST-MD5のように、ケルベロス認証機構は、セッションのデータ暗号化機構を提供する。
ディストリビューションによっては、SASL-Kerberosプラグインをデフォルトでインストールしない。この場合、cyrus-sasl-gssapiなどのパッケージをインストールすることが必要になる。
ケルベロス認証プラグインがインストールされているかどうか調べるためには、pluginviewerを実行して、gssapiがリストされるか確認する必要がある。
 # pluginviewer
 ...snip...
 Plugin "gssapiv2" [loaded],     API version: 4
         SASL mechanism: GSSAPI, best SSF: 56
         security flags: NO_ANONYMOUS|NO_PLAINTEXT|NO_ACTIVE|PASS_CREDENTIALS|MUTUAL_AUTH
         features: WANT_CLIENT_FIRST|PROXY_AUTHENTICATION|NEED_SERVER_FQDN
次に、ケルベロス認証のレルムの管理者は、プリンシプルをlibvirtサーバ用に発行する必要がある。
プリンシプルは、ホスト毎に、libvirtdに対応して一つ割り当てる必要がある。
そして、プリンシプルは、libvirt/full.hostname@KERBEROS.REALMと名づける必要がある。
この作業は、通常kadmin.localコマンドをケルベロス認証サーバで実行して行われる。しかしながらケルベロス認証サーバによっては、サービスプリンシプルを設定するために他の方法が必要な場合もある。
一度生成されると、プリンシプルは、キータブとしてエクスポートされる。そしてlibvirtd向けには、/etc/libvirt/krb5.tabに設定される。
 # kadmin.local
 kadmin.local: add_principal libvirt/foo.example.com
 Enter password for principal "libvirt/foo.example.com@EXAMPLE.COM":
 Re-enter password for principal "libvirt/foo.example.com@EXAMPLE.COM":
 Principal "libvirt/foo.example.com@EXAMPLE.COM" created.
 
 kadmin.local:  ktadd -k /root/libvirt-foo-example.tab libvirt/foo.example.com@EXAMPLE.COM
 Entry for principal libvirt/foo.example.com@EXAMPLE.COM with kvno 4, encryption type Triple DES cbc mode with HMAC/sha1     added to keytab WRFILE:/root/libvirt-foo-example.tab.
 Entry for principal libvirt/foo.example.com@EXAMPLE.COM with kvno 4, encryption type ArcFour with HMAC/md5 added to keytab WRFILE:/root/libvirt-foo-example.tab.
 Entry for principal libvirt/foo.example.com@EXAMPLE.COM with kvno 4, encryption type DES with HMAC/sha1 added to keytab WRFILE:/root/libvirt-foo-example.tab.
 Entry for principal libvirt/foo.example.com@EXAMPLE.COM with kvno 4, encryption type DES cbc mode with RSA-MD5 added to keytab WRFILE:/root/libvirt-foo-example.tab.
 
 kadmin.local: quit
 
 # scp /root/libvirt-foo-example.tab root@foo.example.com:/etc/libvirt/krb5.tab
 # rm /root/libvirt-foo-example.tab
ケルベロス認証するlibvirtに接続したいアプリケーションがユーザプリンシプルを取得するためにkinitを実行する必要はほとんどない。
PAMがケルベロス認証向けに設定されている場合、デスクトップセッションにログインした時点で自動的に取得しているためである。

リモートドライバ

ネットワーク越しのハイパーバイザを管理することが出来る。