Windows下Libvirt Java API使用教程(三)
突兀的出來一個libvirt的教程三,您可能會覺得奇怪,其實這是OneCoder以前寫的一個小系列教程,原來發在51cto的部落格上,前兩篇已經發了過來,考慮到完整性,就把第三篇也發過來。前兩篇地址:
之前已經介紹過了libvirt api的上手使用方式,這裡再補充一些細節問題。
TLS安全認證訪問:
之前我們給出的例子都是直接用tcp訪問的,這就需要被訪問的伺服器開放tcp訪問的埠,也就是說,任何機器只要知道了伺服器的ip,都是可以訪問上面的libvirt介面的。這是十分危險的,在生產環境中是不可取的。
所以,libvirt支援基於tls認證的安全訪問協議。連線格式如下:
qemu+tls://10.4.54.10 或者 qemu://10.4.54.10(因為預設就是走tls的)
要想正常訪問,必須在客戶端和服務端配置證書,下面就介紹一個這個配置過程。
- 首先自然是證書生成工具的安裝。libvirt官方推薦的工具是:GnuTLS。不過可惜,官網給出的地然居然不正確。GnuTLS專案,官網地址如下:
下載頁面為:
這裡介紹的windows環境下配置,所以進入頁面:
下載即可。
- 解壓下載的工具。通過命令列進入\bin目錄(或者將該bin目錄配置到環境變數的path即可在任意路徑訪問):
- 首先為你的證書生成私鑰:
Create a private key for your CA:
certtool --generate-privkey > cakey.pem
然後,為你證書進行自簽名。
and self-sign it by creating a file with the signature details called ca.info containing:</p>
cn = Name of your organization
ca
certsigningkey
certtool --generate-self-signed --load-privkey cakey.pem --template ca.info --outfile cacert.pem (Y)
先在當前路徑下建立一個叫ca.info的檔案,裡面寫上如上第一段內容,
然後執行第二段引用所示命令:
報錯。這下頭疼了。。筆者翻箱倒櫃,翻江倒海找了一通。。實在沒有找到答案。。。考慮到證書的製作過程中沒有與機器相關的資訊,所以,決定求助筆者非常不熟悉的linux。掏出putty,登入,重新執行上面第一個命令。生成私鑰:
然後同樣按照上面的方式進行簽名,果然輕鬆成功!
此時已經可以刪除ca.info檔案了。繼續生成證書,接下來開始生成服務端私鑰:
certtool --generate-privkey > serverkey.pem
然後簽名:
certtool --generate-certificate --load-privkey serverkey.pem --load-ca-certificate cacert.pem --load-ca-privkey cakey.pem --template server.info --outfile servercert.pem
同樣是依靠一個叫做server.info的檔案。先建立改檔案,寫入如下格式內容:
organization = Name of your organization
cn = oirase
tlswwwserver
encryptionkey
signingkey
這裡只有cn這個屬性需要注意,他應該是當前主機的主機名:(
only the CN field matters, which as explained above must be the server's hostname)- (The CN must match the hostname which clients will be using to connect to the server. In the example below, clients will be connecting to the server using a URI of xen://oirase/, so the CN must be "oirase".)
如果不知道主機名,用ip當然也是可以的。那麼你的訪問就是通過IP訪問了。:)
成功。
將服務端證書拷貝伺服器的相應位置:
Finally we have two files to install:
serverkey.pem is the server's private key which should be copied to the server only as /etc/pki/libvirt/private/serverkey.pem.
servercert.pem is the server's certificate which can be installed on the server as /etc/pki/libvirt/servercert.pem.
最後是客戶端的證書,過程類似,這裡只列出主要過程和命令:
1、建立私鑰:
certtool --generate-privkey > clientkey.pem
2、建立client.info模版檔案:
country = GB
state = London
locality = London
organization = Red Hat
cn = client1
tlswwwclient
encryptionkey
signingkey
然後簽名:
certtool --generate-certificate --load-privkey clientkey.pem \
--load-ca-certificate cacert.pem --load-ca-privkey cakey.pem \
--template client.info --outfile clientcert.pem
3、拷貝證書到客戶端的指定位置(linux):
cp clientkey.pem /etc/pki/libvirt/private/clientkey.pem
cp clientcert.pem /etc/pki/libvirt/clientcert.pem
其中client.info中國家等資訊可根據你的情況指定。
至此,需要的證書已經都準備好了。證書有了,服務端也部署了。但是windows的客戶端不知道該部署到什麼地方?因為網上的說明給出的都是linux檔案路徑,沒說windows下的情況。不過筆者相信libvirt的錯誤日誌:)於是:
怎麼樣,位置有了吧。趕緊拷貝過去試試。</p>
有的同學可能發現,這裡只給出了一個位置,我們有三個證書呢。別急,你看這個路徑,比照網上給出的linux的路徑格式:
Location | Machine | Description | Required fields |
---|---|---|---|
/etc/pki/CA/cacert.pem | Installed on all clients and servers | CA's certificate (more info) | n/a |
/etc/pki/libvirt/ private/serverkey.pem | Installed on the server | Server's private key (more info) | n/a |
/etc/pki/libvirt/ servercert.pem | Installed on the server | Server's certificate signed by the CA. (more info) | CommonName (CN) must be the hostname of the server as it is seen by clients. |
/etc/pki/libvirt/ private/clientkey.pem | Installed on the client | Client's private key. (more info) | n/a |
/etc/pki/libvirt/ clientcert.pem | Installed on the client | Client's certificate signed by the CA (more info) | Distinguished Name (DN) can be checked against an access control list (tls_allowed_dn_list). |
其實基本已經可以猜出windows下的目錄組織了。linux在的/etc目錄,就想當於我們這裡的..\libvirt目錄,子目錄的組織相同即可。
沒猜出來也不用擔心,最多我們複製一個證書嘗試一次,錯誤資訊會依次告訴你所有的路徑的:)
再訪問一下,成功~
補充說明一下關於動態連結檔案的問題:
之前介紹的時候,筆者只提到說呼叫libvirt Java api需要一個virt.dll檔案,這個檔案筆者是拷貝的libvirt-0.dll檔案改名而來,然後訪問成功。
筆者後來發現,原來libvirt 安裝目錄的bin資料夾下的所有檔案,其實都是該dll檔案的依賴檔案,當筆者將其他檔案刪除或轉義的時候,依然會報找不到virt.dll檔案的錯誤。所以,如果呼叫libvirt Java API開發,可以將所有的dll拷貝到一個指定位置,然後指定jna.library.path到該位置即可。