Thursday, December 25, 2014

それ、CMISで繋げます(Liferay編その1)

CMISは文書管理リポジトリにアクセスするための仕様ですが、「CMIS対応しているっていうけど、何ができるの?」という質問を最近ときどき頂きます。

何ができるか、という質問に対する答えは、技術的な観点に限定しても、以下の2つの要素に分解できるでしょう。
・CMIS単体で提供される、文書管理機能のセット
・CMISによるシステム間連携

CMISは、連携、あるいはデータやサービスの相互運用性(interoperability)を主眼として策定されたもので、そのために文書管理機能としてはいろんなECMの最大公約数的な機能に絞られています。そういう意味では、CMISで実際にいろいろ繋いだものをお見せするのが、CMISのメリットを理解していただく早道かと思います。
(※最大公約数とはいえ、CMISの提供する文書管理機能にもある種のクセはあるのでその点は機会があれば別途)

 Liferayと繋いでみた

というわけで初回はLiferayと繋いでみましょう。
Liferayでは、そのCMS的な機能のバックエンドとして、バージョン6.1からCMISリポジトリをサポートしています。

ここではLiferay6.2を使用して、弊社製品であるCMIS対応の文書管理リポジトリであるNemakiWareに接続してみます。
NemakiWareを使う理由なのですが、単に弊社製品だからという商売っ気だけでなく、実際にCMIS仕様の遵守率が100%で、他ECMと比較しても現時点で1位にあるからです。
http://cmissync.org/CmisCompat/

NemakiWare自体のインストール・起動はまた別途ご紹介しますが、
インストーラのダウンロード:こちら
インストール・起動方法:こちら
になります。

CMIS接続のための設定は、LiferayのWiki(英語)を参照しました。
 
 

下準備

Liferay側での下準備として、ポータルのプロパティ(portal-ext.propertiesなど、プロパティの上書き機構に準ずる)に
session.store.password=true
company.security.auth.type=screenName 
と設定します。
 
この設定では、Liferay上のログインユーザ持つスクリーン名/パスワードが、CMISリポジトリにログインするためのユーザID/パスワードと一致している必要があります。
LiferayのUIからCMISリポジトリを操作することになるので、Liferayのログインユーザ情報がCMISリポジトリのログインユーザ情報として引き渡されるためです。
もしCMISリポジトリがLDAP認証などに対応していれば、ID/PWDは簡単に統一化できるでしょう。

ここではLiferay、NemakiWareともに、admin/adminユーザでログインするものとします。

リポジトリの追加

AdminメニューのContentを開きます。

左側のペインからDocument and Mediaを開き、AddボタンのドロップダウンメニューからRepositoryを選択します。

新規に追加するリポジトリのために、設定項目を入力します。
重要なのは
RepositoryType
CMISには接続方式として、WebService、AtomPub(およびBrowser)が定義されています。ここではAtomPubが推奨されています。
AtomPub URL
AtomPubで接続する場合のコンテキストURLを入力します。おつかいのCMISリポジトリによって当然異なります。なお、このURLを開こうとするとリポジトリ全体の情報を記述したxmlファイルがダウンロードできます。NemakiWareの場合はデフォルトで
http://localhost:8080/core/atom
です。
RepositoryID
省略可能です。
CMISサーバでは、一番大きな単位としてリポジトリがあり、1つのCMISサーバは複数のリポジトリを持てることになっています。ですが実際は「メイン」リポジトリが1つだけということも珍しくありません。
この値を省略すると、CMISサーバ側で設定されているメインリポジトリが自動的に選択される仕組みになっています。

最後にもう1つ、Permissionという設定項目がありますが、これはLiferay上で、このCMISリポジトリを見られるユーザを制限するものです。CMIS側の権限設定とは関係ありません。
値にはAnyone(Guest Role), Site Members, Ownerがあります。

以上、設定できたらSaveを押したら、リポジトリの追加完了です。

Liferayのスクリーン名/パスワードがCMISリポジトリのそれと一致していない場合は、エラーになります。上手く行かない場合はCMISリポジトリ側のエラーログを見てください。

コンテンツの表示

CMISリポジトリにあるコンテンツに、LiferayのUIからアクセスできることを確認してください。ファイルに対して、コンテキストメニュー的なものも表示されていますね。アクションとしてCheckoutも行えるようです。

Checkout時の挙動については、CMISリポジトリごとに微妙に揺れがあるので、また次回の話題とさせていただきます。

なお、画像にもあるようにリポジトリを追加すると"Access these files offline using Liferay Sync."というメッセージが表示されます。Liferay Syncの説明はここでは省きますが、オフラインのときにした編集でもDropboxライクに同期できる仕組みです。

CMISリポジトリに限っていえば、CMISインタフェースのレベルでCmisSyncというDropboxライクな同期ツールが既に存在していますので、そちらもご検討ください。と陰に陽に自社製品をご紹介させてもらいまして、今回の結びとさせていただきます。


(文:linzhixing)

Monday, December 22, 2014

Alfresco勉強会#25でAlfrescoのアップグレードについて発表しました

こんにちは、かわべです。
12月17日に弊社オフィスで第25回Alfresco勉強会が開催されました。
寒い中ご参加いただいた皆様、ありがとうございます!

発表振り返り

今回は発表が2つありましたが、発表ごとに別の記事としています。
私はAlfrescoのアップグレードについて発表しました。
発表資料はこちら

Alfrescoのアップグレードは、コンテンツ実体(ファイルシステム)とメタデータ(データベース)のコールドバックアップデータを新しいAlfrescoに移行することで実行できます。ただし、カスタムモジュールなどが移行対象のバージョンでも期待通り動作するか、事前に検証することも大切です。
という発表の最後に、デモとして4.2.fから5.0.cへのアップグレードをお見せした…の で す が!

うまくいきませんでした…
(3回ぐらい練習したのに…)

時間を掛けた割に、ちゃんとしたものをお見せできなくてすみませんでした。
検証したところ、SQLのdumpを書き戻すときにデータベース名を指定する部分を飛ばしてしまったようです。
あのあと一旦DBをドロップして、再作成してから書き戻すとちゃんと移行できました。
勉強会が終わるまでに解決できなかったのが心残りですが、資料の手順は間違っていないはずなので参考にしてみてください。

告知1

次回のAlfresco勉強会は2015年2月18日(水)に開催予定です。
たくさんの方のご参加をお待ちしております!参加登録はこちらからお願いします。
また、「こういうテーマの発表が聞きたい」などのご意見があれば、ぜひconnpassのフィードなどでご連絡ください。

告知2

こちらは勉強会ではなく、弊社セミナーのご案内です。
2015年1月20日(火) 19時〜20時、Alfrescoの基本的な機能や使い方についての少人数セミナーを開催いたします。
(勉強会の終わりではWebinarだとお伝えしてしまいましたが、弊社オフィスで行うようです)
詳細や申し込み、お問い合わせは以下のリンクからお願いします。
基礎からわかるAlfrescoセミナー
ご都合が合えば、こちらもぜひご参加ください。

Thursday, December 18, 2014

Alfresco勉強会#25でワークフローについて話しました

とたにです。

久しぶりにAlfresco勉強会でしゃべりました。
今回はAlfrescoのワークフローについて、どういった機能が用意されているのか、また新しくワークフローを追加するにはどんな作業が必要なのかを具体的にイメージしてもらえることをゴールにして、入門レベルの内容を準備しました。

ワークフローはAlfrescoの活用方法によっては重要な位置づけとなる機能ですが一方で全く利用するつもりのない方もいるので、勉強会の題材としては少しささる人が少ない、狭い話題を選んでしまったかも、という反省をしつつこのブログを書いています。

アドバンストワークフローでは最低限必要な2つのファイルのみを作って、Alfrescoにワークフローを追加する方法について説明したのですが、説明後に「もっと簡単にワークフローを開発する方法はありますか?」という質問を頂きました。アドバンストワークフローはactivitiというBPMエンジンを採用していてプロセスの記述能力は非常に高いのですが、その反面、開発者レベルのスキルが要求されるのも事実です。このあたりは勉強会で理解いただくというアプローチのほかに、手軽に利用できるワークフローのセットを公開して選択して使っていただく、というアプローチもいいかもしれないと思いました。

また日本型ワークフロー(という言葉があるかどうかは知らないですが)では、必ず期待される機能として承認フロー上の承認者としてユーザの上司を自動でアサインしたい、というものがあり、それについても質問されたのですが、標準のAlfrescoにはそのような組織モデルが実装されていないので実現するためには、Alfresco内もしくは外部にそのような組織モデルおよび取得のサービスを実装する必要があります。

第25回Alfresco勉強会ワークフロー入門編
サンプルコードはこちら

ワークフローの開発は細かいTipsがたくさんあるので応用編として書ける内容もまだまだあるのですが、やはり少し題材として狭いので勉強会で取り上げるかは現時点では未定です。他のネタが思いつかなければ取り上げるかもしれません。

Wednesday, December 17, 2014

Alfresco 5.0とActive DirectoryでNTLM SSOを設定する

こんにちは。おおたにです。今回はActive Directory(以下AD)と連携してAlfrescoでSSOを実現する方法を紹介したいと思います。


何が実現できるのか


AlfrescoとADのSSO設定を行うと、ADで管理された端末からユーザID/パスワードを入力することなくAlfrescoにアクセスできるようになります。

端末上のWindowsにログインする際に利用した認証情報(ADによって管理されているユーザに関するもの)を利用し、Alfrescoへのアクセス時に自動的に認証を行います。認証方法としてはNTLM v1とKerberosの2種類がありますが、以下ではNTLM v1を使ったSSOの設定手順を説明します。


必要なもの


以下の説明での前提条件、事前に準備が必要なものは以下のとおりです。なお、筆者はAlfresco 5.0.b、Windows Server 2012 (AD)、Windows 7 Professional (Client)という構成で動作確認を行いました。
  • Alfresco 5.0 (3.2以上であれば基本的に同様の手順で設定可能です)
  • Active Directoryサーバ
    • サーバ名もしくはサーバIP (ここでは kate とします)
    • ドメイン名 (ここでは aegif.local とします)
    • LDAPサービスでユーザ/グループ情報の取得権限を持つユーザ名 (ここではAdministrator を使います)
    • 上記ユーザのパスワード (ここでは thepassword とします)
    • ユーザ情報格納先のベースDN (ここでは cn=Users,dc=aegif,dc=local とします)
    • グループ情報格納先のベースDN (ここでは cn=Users,dc=aegif,dc=local とします)
    • ドメインに所属するクライアントPC(テストに利用します)

Alfrescoの設定


まずAlfrescoをダウンロード、インストールします。インストーラが提供されているのでインストール自体はそんなに難しくありませんが、こちらの記事が参考になると思います。インストールが完了したら、 ブラウザで http://localhost:8080/share にアクセスし、adminユーザでログインできることを確認しておいてください。

Alfrescoが正しくインストールされたら、alfresco-global.propertiesに以下の設定を追記します。

<tomcat_dir>/shared/classes/alfresco-global.properties :
authentication.chain=passthru1:passthru,ldap-ad1:ldap-ad,alfrescoNtlm1:alfrescoNtlm
ntlm.authentication.sso.enabled=true

ldap.authentication.active=false
ldap.authentication.userNameFormat=%s@aegif.local
ldap.authentication.java.naming.provider.url=ldap://kate:389

ldap.synchronization.active=true
ldap.synchronization.java.naming.security.principal=Administrator@aegif.local
ldap.synchronization.java.naming.security.credentials=thepassword
ldap.synchronization.groupSearchBase=cn\=Users,dc\=aegif,dc\=local
ldap.synchronization.userSearchBase=cn\=Users,dc\=aegif,dc\=local
synchronization.import.cron=0 0 * * * ?

passthru.authentication.useLocalServer=false
passthru.authentication.domain=aegif.local
passthru.authentication.servers=aegif.local\\kate
passthru.authentication.defaultAdministratorUserNames=Administrator

ドメイン名、サーバ名、LDAP認証情報、ベースDN等は環境に合わせて設定してください。以下、上記設定の説明です。
  • authentication.chain でAlfrescoログインのための認証チェーンを指定します。passthruがSSO認証、ldap-adがAD認証(ユーザ/パスワード入力タイプ)、alfrescoNtlmがAlfrescoが管理するユーザ情報での認証です。認証チェーンとは、複数の認証方式を連鎖させるもので、ここでは、SSO→AD認証→Alfresco認証の順に認証をトライします。
  • ntlm.authentication.sso.enabled=true でNTLM SSOが有効になります。
  • ldap.authentication.active=false でldap-adの認証機能を無効化し、ldap.synchronization.active=true でldap-adのユーザ/グループ同期機能を有効化します。
    • ここではAD認証自体は行わず、AD上のユーザ/グループ情報をAlfrescoに同期させる(定期的に差分情報をインポートする)ことのみを行います。
  • synchronization.import.cron で同期周期を設定します。デフォルトでは1日1回0時に実行されます(上記例では毎時0分に実行されます)。
  • passthru.authentication.useLocalServer でADサーバ上でAlfrescoが稼働しているか否かを指定します。falseの場合は passthru.authentication.domain, passthru.authentication.servers を指定する必要があります。
  • passthru.authentication.defaultAdministratorUserNames にAlfrescoの管理者権限を与えたいユーザ名を列挙します。

次に、share-config-custom.xmlの設定を変更します。デフォルトでは以下のSSO向けの設定がコメントアウトされていますので、コメントアウトのタグを外して設定を有効にします。

<tomcat_dir>/shared/classes/alfresco/web-extension/share-config-custom.xml :
   <config evaluator="string-compare" condition="Remote">
      <remote>
         <keystore>
             <path>alfresco/web-extension/alfresco-system.p12</path>
             <type>pkcs12</type>
             <password>alfresco-system</password>
         </keystore>
         
         <connector>
            <id>alfrescoCookie</id>
            <name>Alfresco Connector</name>
            <description>Connects to an Alfresco instance using cookie-based authentication</description>
            <class>org.alfresco.web.site.servlet.SlingshotAlfrescoConnector</class>
         </connector>
         
         <connector>
            <id>alfrescoHeader</id>
            <name>Alfresco Connector</name>
            <description>Connects to an Alfresco instance using header and cookie-based authentication</description>
            <class>org.alfresco.web.site.servlet.SlingshotAlfrescoConnector</class>
            <userHeader>SsoUserHeader</userHeader>
         </connector>

         <endpoint>
            <id>alfresco</id>
            <name>Alfresco - user access</name>
            <description>Access to Alfresco Repository WebScripts that require user authentication</description>
            <connector-id>alfrescoCookie</connector-id>
            <endpoint-url>http://localhost:8080/alfresco/wcs</endpoint-url>
            <identity>user</identity>
            <external-auth>true</external-auth>
         </endpoint>
      </remote>
   </config>

以上でAlfrescoの設定は終わりです。設定を反映させるため、Alfrescoを再起動します。


Active Directoryサーバの設定


次に、ADサーバ上での設定を行います。AlfrescoのNTLM SSOはNTLMv1だけでNTLMv2に対応していないため、AD配下のクライアントのLAN Manager認証レベルを変更する必要があります(セキュリティレベルを落としたくない場合はKerberos認証の利用をお勧めします)。

まずは、Win+R を押して gpmc.msc を実行します。「グループポリシーの管理」コンソールが起動するので、目的のドメインのデフォルトグループポリシーを編集します。


以下のエディタが表示されるので、コンピューターの構成→ポリシー→Windowsの設定→セキュリティの設定→ローカルポリシー→セキュリティオプションをクリックし、「ネットワークセキュリティ:LAN Manager認証レベル」をダブルクリックします。


以下のダイアログが表示されるので、「このポリシーの設定を定義する」にチェックを入れて、「LMとNTLMを送信する(ネゴシエートした場合NTLMv2セッションセキュリティを使う)」を選択してOKをクリックします。


以上でADサーバ上での設定は完了です。


クライアントPCの設定


以下の設定は全てのクライアントPCで設定する必要があります。クライアントのログイン情報をAlfrescoに渡すためには、AlfrescoのURLがイントラネットゾーン判定される必要があるため、インターネットオプションのセキュリティ設定にAlfrescoのURLを追加します。

Internet Explorerのインターネットオプションを開き、ローカルイントラネットにAlfrescoのURLを追加します。HTTPでアクセスする場合は「このゾーンは…」のチェックを外します。



テストしてみよう


では、ADユーザでログインしたクライアントPCを利用し、Alfrescoにアクセスしてみましょう。先ほどイントラネットゾーンに追加したURLを使ってアクセスしてください(先のスナップショットの例ですと、http://alfresco.aegif.jp:8080/share となります)。ログイン画面が表示されず、直接ダッシュボード画面が表示されればテスト成功です。


トラブルシューティング



うまくいかない場合は以下のことを試してみてください。
  • alfresco.log, catalina.out等に出力されているExceptionを確認してみる
  • ユーザ/グループの同期が正常に行われているか(AD上のユーザ/グループがAlfresco上にも生成されているか)を確認してみる
  • LDAPクライアントを使ってユーザ/グループの検索ベースDNを実際に確認してみる
  • passthru.authentication.domain, passthru.authentication.servers あたりのプロパティ値から.localを省略してみる

今回の紹介は以上です。AD環境がある場合は是非ADとの連携、SSO設定を試してみてください。

Wednesday, December 10, 2014

CmisSync on Raspberry Pi: The Internet of Things meets document management

Raspberry Pi is a tiny board (the size of a credit card) that allows you to create any kind of robot or fun hardware:


Examples:
- Santa detectors
- Sandwich carriers
- Ultra-cheap laptops (UNICEF)
- Industrial robots
- Audit sensors

And guess what? CmisSync runs on Raspberry Pi!
CmisSync is a file synchronization tool compatible with any document management server (Alfresco/SharePoint/FileNet/Documentum/etc) thanks to the CMIS protocol.
Imagine for instance a tiny sensor measuring air pollution and sending a weekly report directly to your document server over Wi-Fi.

A South African company is already embedding CmisSync in office scanners, so that scanned documents get automatically synchronized to Alfresco or another ECM server:



Compare that with the pain it is to achieve the same thing using a normal scanner, and you can easily feel the need for such intelligent hardware based on open standards.

Raspberry Pi + CmisSync can also be used in environments with no permanent network connection, for instance fleets of trucks travelling in uncovered areas and sending reports (load/unload/sleep) when network becomes available. CmisSync makes the Internet of Things survive Internet cuts.
Nicolas Raoul

Tuesday, November 25, 2014

Alfresco 5.0とSolr 4を手動インストールしてみた(Alfresco 5.0.b以降)

こんにちは。大谷です。

以前、「Alfresco4.2をインストールしてみよう(手動インストール編)」という記事を書いたのですが、先ごろリリースされたAlfresco Community 5.0.bで構成に大きな変更があったので、改めて手動インストールの方法を紹介しようと思います。

※ なお、インストーラを利用したインストールは以前と変わっていませんので、「Alfresco4.0をインストールしてみよう(インストーラ編)」を参照してください。インストーラを使うとウィザードに沿っていくつかの設定項目を入力するだけでAlfrescoがインストールできますので、てっとり早く試してみたい場合はインストーラの利用をお勧めします。

「大きな変更」とはSolr 4への対応のことで、これまでの手順に加えてSolr 4のセットアップが新たに必要になりました。これまでは検索エンジンとしてLuceneを使ったインストール手順を紹介していましたが、Alfresco Community 5.0.bからはLuceneをサポートしなくなっています。なお、本記事では以下のような構成を想定しています。
  • OS : Windows
  • Java : JDK7
  • Alfresco : Alfresco Community 5.0.b
  • アプリケーションサーバ : Tomcat 7
  • RDBMS : MySQL Community Server 5.6
  • Solr 4はAlfrescoと同じTomcatインスタンス上にデプロイ
  • Alfresco - Solr間は非SSL通信


JDKのインストール


  1. こちらのサイトからJDK7をダウンロードします。Alfresco 5.0ではJDK7が必要になります。
  2. ダウンロードしたファイルを実行し、JDKをインストールします。


Tomcatのインストール


  1. Alfresco用のディレクトリを作成します。ここでは、Cドライブ直下にalfresco50bというディレクトリを作成し、以下ではALF_HOMEと表記します(ALF_HOME = C:/alfresco50b)。
  2. Apache TomcatのサイトからTomcat 7をダウンロードします。
  3. ダウンロードしたファイルをALF_HOMEに展開します。展開するとALF_HOME以下にapache-tomcat-<バージョン番号>という名前のディレクトリが作成されますので、このディレクトリをTOMCAT_HOMEと表記します(TOMCAT_HOME = C:/alfresco50b/apache-tomcat-7.0.xx)。


MySQLのインストール


  1. MySQL Developer ZoneからMySQL Community Server 5.6をダウンロードし、インストールします。また、後ほど利用するMySQL Connector/J 5.1(JDBCドライバ)をここからダウンロードします。


Tomcatの設定


  1. Alfresco Community Editionのダウンロードサイトにアクセスし、Alfresco 5.0.b Community -> alfresco-community-5.0.b.zipをダウンロードします。
  2. ダウンロードしたファイルを適当なディレクトリに展開します。このうち、alf_data, amps, bin, solr4ディレクトリをALF_HOMEにコピーし、web_serverディレクトリの中身をTOMCAT_HOMEにコピーします(webapps等既存フォルダへのファイル追加も行われます)。
  3. JDBCドライバをTomcatのクラスパスに配置します。先ほどダウンロードしたMySQL Connector/Jを展開し、mysql-connector-java-5.1.xx-bin.jarを<TOMCAT_HOME>/libにコピーします。
  4. Tomcatの設定を変更します。<TOMCAT_HOME>/conf/catalina.properties のshared.loaderプロパティを以下のように変更します。
  5. shared.loader=${catalina.base}/shared/classes,${catalina.base}/shared/lib/*.jar
  6. <TOMCAT_HOME>/conf/server.xml の8080番ポートのConnector設定を以下のように変更します。AJPを利用する場合は8009番についてもURIEncoding設定を追加します。
  7. <Connector port="8080" protocol="HTTP/1.1" URIEncoding="UTF-8"
               connectionTimeout="20000"
               redirectPort="8443" />
  8. <TOMCAT_HOME>/bin/catalina.bat に以下の行を追加してJVMの設定を変更します。JRE_HOMEや最大/最小ヒープサイズ等はPCの設定・スペックに応じて変更してください。alfresco.homeは<ALF_HOME>のパスを指定します。
  9. set JRE_HOME=C:\Program Files\Java\jdk1.7.0_xx\jre
    set JAVA_OPTS=-Xms1024m -Xmx2048m -XX:MaxPermSize=512m -server -Dalfresco.home=C:/alfresco50b -Dcom.sun.management.jmxremote
  10. <ALF_HOME>/solr4/context.xml を <TOMCAT_HOME>/conf/Catalina/localhost/solr4.xml にリネーム/コピーし、環境変数の値を環境に応じて設定します。
  11. <Environment name="solr/home"        type="java.lang.String" value="C:/alfresco50b/solr4" override="true"/>
    <Environment name="solr/model/dir"   type="java.lang.String" value="C:/alfresco50b/alf_data/solr4/model" override="true"/>
    <Environment name="solr/content/dir" type="java.lang.String" value="C:/alfresco50b/alf_data/solr4/content" override="true"/>


データベースの作成


Alfrescoはコンテンツのメタデータをデータベースで管理し、コンテンツのファイル実体をファイルシステムで管理します。データベースについてはAlfrescoが起動時に必要なテーブルを自動生成するため、まずはデータベース(とユーザ)を作成しておくだけで構いません。
  1. コマンドプロンプトで以下のコマンドを実行し、MySQLにログインします。
  2. mysql -u root -p
  3. 以下のコマンドでMySQLにAlfresco用のデータベースを作成します。この例では、データベース名をalfrescoとし、ユーザ名/パスワードもalfresco/alfrescoとなります。
  4. create database alfresco default character set utf8 collate utf8_bin;
    grant all on alfresco.* to 'alfresco'@'localhost' identified by 'alfresco' with grant option;


Solrの設定


  1. <ALF_HOME>/solr4/workspace-SpacesStore/conf/solrcore.properties と <ALF_HOME>/solr4/archive-SpacesStore/conf/solrcore.properties のdata.dir.rootプロパティ(インデックス格納先)とalfresco.secureCommsプロパティ(SSL通信か否か)を以下のように変更します。パスは環境に応じて変更してください。
  2. data.dir.root=C:/alfresco50b/alf_data/solr4/index
    alfresco.secureComms=none


外部ツールのインストール


次に、Alfrescoが利用する外部ツールのインストールを行います。ここではLibreOffice, ImageMagick, Ghostscript, SWFTools(pdf2swf)について説明します。この4つのツールの用途は以下のとおりですので、必要に応じてインストール、設定を行ってください。
  • LibreOffice : Alfrescoでファイルフォーマット変換を行う際に使います。PDF変換機能などを利用する場合に設定する必要があります。(手元の環境では少し古い4.1.0.4を利用)
  • ImageMagick : コンテンツのサムネイルやプレビューを生成する際に使います。(手元の環境では6.8.6.9を利用)
  • Ghostscript : ImageMagickが間接的に利用します。(手元の環境では9.10を利用)
  • SWFTools : 一部コンテンツのプレビューを生成する際に使います。(手元の環境では0.9.0を利用)


Alfrescoの設定


続いて、Alfrescoの設定を行います。大きく分けると、データベース接続設定、ファイルシステムの設定、外部ツール連携設定の3つがあります。
  1. <TOMCAT_HOME>/shared/classes/alfresco-global.properties.sample をalfresco-global.propertiesにリネームします。以下のプロパティ設定は全てalfresco-global.propertiesに行います。
  2. データベース接続設定、ファイルシステムの設定について、以下のように設定します(全てデフォルトでコメントアウトされているので、コメントアウトを外して環境に合わせて設定変更してください)。
  3. #
    # Sample custom content and index data location
    #
    dir.root=C:/alfresco50b/alf_data
    
    #
    # Sample database connection properties
    #
    db.username=alfresco
    db.password=alfresco
    
    #
    # MySQL connection
    #
    db.driver=org.gjt.mm.mysql.Driver
    db.url=jdbc:mysql://localhost/alfresco?useUnicode=yes&characterEncoding=UTF-8
  4. 検索エンジンとしてSolr 4を使い、Alfrescoとの通信を非SSL化するために以下の設定を追記します。
  5. index.subsystem.name=solr4
    solr.secureComms=none
  6. 外部ツールとの連携について、環境に合わせて以下のように設定します(コメントアウトされているものもあるので適宜コメントアウトを外すなりして設定変更してください)。
  7. ooo.exe=C:/Program Files (x86)/LibreOffice 4/program/soffice
    ooo.enabled=true
    img.root=C:/Program Files/ImageMagick-6.8.6-Q16
    img.exe=${img.root}/convert.exe
    img.gslib=C:/Program Files/gs/gs9.10/lib
    swf.exe=c:/SWFTools/pdf2swf.exe


Alfrescoの初回起動と追加の設定


最後に、一度Alfrescoを起動してWARファイルを展開し、その展開されたファイルの設定を修正します。
  1. <TOMCAT_HOME>/bin/startup.bat を実行してAlfrescoを起動します。
  2. コンソールの出力内容(もしくはalfresco.logやcatalina.out)をチェックします。初回起動時はデータベースにテーブルを追加する作業やwarファイルを展開する作業がありますので時間がかかりますが、最終的にはExceptionが断続的に出力される状態となります(一部SSL通信の設定が残っているため)
  3. <TOMCAT_HOME>/bin/shutdown.bat を実行してAlfrescoを停止します。
  4. <TOMCAT_HOME>/webapps/alfresco/WEB-INF/web.xml を編集し、SSL設定に関する以下の箇所をコメントアウトします。
  5. <security-constraint>
       <web-resource-collection>
          <web-resource-name>SOLR</web-resource-name>
          <url-pattern>/service/api/solr/*</url-pattern>
       </web-resource-collection>
    
       <auth-constraint>
          <role-name>repoclient</role-name>
       </auth-constraint>
    
       <user-data-constraint>
          <transport-guarantee>CONFIDENTIAL</transport-guarantee>
       </user-data-constraint>
    </security-constraint>
    
    <security-constraint>
       <web-resource-collection>
          <web-resource-name>SOLR</web-resource-name>
          <url-pattern>/s/api/solr/*</url-pattern>
       </web-resource-collection>
    
       <auth-constraint>
          <role-name>repoclient</role-name>
       </auth-constraint>
    
       <user-data-constraint>
          <transport-guarantee>CONFIDENTIAL</transport-guarantee>
       </user-data-constraint>
    </security-constraint>
    
    <security-constraint>
       <web-resource-collection>
          <web-resource-name>SOLR</web-resource-name>
          <url-pattern>/wcservice/api/solr/*</url-pattern>
       </web-resource-collection>
    
       <auth-constraint>
          <role-name>repoclient</role-name>
       </auth-constraint>
    
       <user-data-constraint>
          <transport-guarantee>CONFIDENTIAL</transport-guarantee>
       </user-data-constraint>
    </security-constraint>
    
    <security-constraint>
       <web-resource-collection>
          <web-resource-name>SOLR</web-resource-name>
          <url-pattern>/wcs/api/solr/*</url-pattern>
       </web-resource-collection>
    
       <auth-constraint>
          <role-name>repoclient</role-name>
       </auth-constraint>
    
       <user-data-constraint>
          <transport-guarantee>CONFIDENTIAL</transport-guarantee>
       </user-data-constraint>
    </security-constraint>
    
    <login-config>
       <auth-method>CLIENT-CERT</auth-method>
       <realm-name>Repository</realm-name>
    </login-config>
    
    <security-role>
      <role-name>repoclient</role-name>
    </security-role>
  6. <TOMCAT_HOME>/webapps/solr4/WEB-INF/web.xml を編集し、SSL設定に関する以下の箇所をコメントアウトします。
  7. <security-constraint>
        <web-resource-collection>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>repository</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
    
    <login-config>
        <auth-method>CLIENT-CERT</auth-method>
        <realm-name>Solr</realm-name>
    </login-config>
    
    <security-role>
       <role-name>repository</role-name>
    </security-role>


動作確認


以上で設定は完了です。Alfrescoを起動して動作確認してみましょう。

  1. <TOMCAT_HOME>/bin/startup.bat を実行してAlfrescoを起動します。
  2. コンソールの出力内容(もしくはalfresco.logやcatalina.out)をチェックします。正常に起動すると、コンソールもしくはログに"Server startup in xxxxxx ms"と表示されます。
  3. 、ブラウザで http://localhost:8080/share にアクセスします。管理者ユーザのデフォルトユーザ名/パスワードは、admin/adminになりますのでそれを入力します。

  4. ログインに成功し、ユーザダッシュボード画面が表示されたら動作確認完了です!

  5. 念のため、Solrにもアクセスしてみましょう。URLは http://localhost:8080/solr4 です。以下の画面が表示されたらOKです。

以上がAlfresco 5.0(5.0.b以降)をインストールする手順となります。本番環境構築の際には、Solr 4の別建てやAlfresco - Solr間のSSL化など、さらに考慮する必要のある事項がありますが、本質的にはこの手順でいけると思います。

Alfresco 5.0の新機能については本ブログの記事「Alfresco 5.0.bの機能紹介」をチェックしてみてください。また、基本的な使い方については「Alfresco 4.2の使い方 - ユーザ管理・グループ管理」、「Alfresco 4.2の使い方 - リポジトリとサイトの準備をしよう」あたりが参考になるかと思いますので是非ご一読ください。

Tuesday, November 18, 2014

Alfrescoでリアルタイムウイルススキャンを実装する


こんにちは。おおたにです。

今回は、Alfrescoでファイルアップロード時にウイルススキャンを行うようなカスタムモジュールを作ってみたいと思います。想定している環境は、以下のとおりです。Alfrescoについては、多分このままもしくは多少の修正で5.0.xでも動くと思います。
  • Alfresco : Alfresco Community Edition 4.2.f
  • OS : CentOS 6系
  • ウイルススキャンツール : Clam AntiVirus


準備


まずは、AlfrescoとClam AntiVirusをインストールします。AlfrescoのインストールはAlfresco4.0をインストールしてみよう(インストーラ編)Alfresco4.2をインストールしてみよう(手動インストール編)あたりを参考にしてください。

次に、Clam AntiVirusをインストールします。CentOSへのインストールはこちらの記事が参考になります。基本的にはファイルアップロードのタイミングでスキャンコマンドを実行するだけなので、自動起動や定期実行の設定は必要ありません。clamscanコマンドがパス指定なしで実行できるようになっていればOKです。


カスタムモジュールの開発


では、早速コードを見てみましょう。今回作ったコード/設定ファイルは以下の4つになります。なお、サンプルコードはこちらからダウンロードすることができます。
  • VirusScanActionExecuter.java : ウイルススキャン処理の実装
  • VirusDetectException.java : ウイルス検知時に投げるException
  • VirusScan.java : OnContentUpdatePolicyを利用したコンテンツ実体更新フック
  • alfresco-virusscan-sample-context.xml :VirusScanActionExecuterとVirusScanのSpring bean定義ファイル

VirusScanActionExecuter.java

ウイルススキャン処理を、ActionExecuterとして実装します。ActionExecuterとして実装するとActionServiceから名前を指定するだけで処理をキックできるため、Alfresco内での再利用性が高まります。具体的には、ActionExecuterAbstractBaseのexecuteImplに処理を実装します。

public class VirusScanActionExecuter extends ActionExecuterAbstractBase {
...
    @Override
    protected void executeImpl(Action action, NodeRef nodeRef) {
        String fileName = (String) fileFolderService.getFileInfo(nodeRef).getName();
        LOGGER.debug("Virus scan start : " + fileName);

        // Output content to temporary file
        ContentReader contentReader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
        File targetFile = null;
        try {
            targetFile = TempFileProvider.createTempFile(contentReader.getContentInputStream(), "virusscan_", ".bin");
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }

        // Execute virus scan
        Map<String, String> properties = new HashMap<String, String>();
        properties.put("target", targetFile.getAbsolutePath());
        ExecutionResult result = virusScanCommand.execute(properties);

        // Check result and delete infected file.
        int exitValue = result.getExitValue();
        if (exitValue == 0) {
            LOGGER.debug("Virus not detected : " + fileName);
        } else if (exitValue == 1) {
            fileFolderService.delete(nodeRef);
            throw new VirusDetectException("Virus detected and cleaned up : " + fileName);
        } else {
            LOGGER.error("Unable to scan : " + result);
        }
    }
...
}

VirusScan.java

OnContentUpdatePolicyを利用して、コンテンツ実体更新時(正確にはそのトランザクションのコミット時)にウイルススキャン処理をキックします。

public class VirusScan extends TransactionListenerAdapter implements OnContentUpdatePolicy, InitializingBean {
...
    @Override
    public void onContentUpdate(NodeRef nodeRef, boolean newContent) {
        if (!nodeService.getType(nodeRef).equals(ContentModel.TYPE_CONTENT) || nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT) == null) {
            return;
        }
        AlfrescoTransactionSupport.bindListener(this);
        AlfrescoTransactionSupport.bindResource(NODE_KEY, nodeRef);
    }

    @Override
    public void beforeCommit(boolean readOnly)
    {
        final NodeRef nodeRef = AlfrescoTransactionSupport.getResource(NODE_KEY);
        String fileName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);

        LOGGER.debug("beforeCommit start : " + fileName + ", readonly : " + readOnly);
        actionService.executeAction(actionService.createAction("virus-scan-action"), nodeRef);
        LOGGER.debug("beforeCommit end : " + fileName);
    }
}

alfresco-virusscan-sample-context.xml

上記2つの実装をSpring beanとして定義します。VirusScanActionExecuterはvirus-scan-actionという名前で登録し、Java APIやJavaScript API、REST APIからこの名前でウイルススキャン処理を実行できるようになります。

コマンドの中身はLinux用になっているのでOSに応じて変更もしくはOSごとに指定してください。

<bean id="virus-scan-action" class="jp.aegif.alfresco.sample.action.executer.VirusScanActionExecuter" parent="action-executer">
   <property name="contentService">
      <ref bean="ContentService" />
   </property>
   <property name="fileFolderService">
      <ref bean="FileFolderService" />
   </property>
   <property name="virusScanCommand">
      <bean class="org.alfresco.util.exec.RuntimeExec">
         <property name="commandsAndArguments">
            <map>
               <entry key=".*">
                  <list>
                     <value>clamscan</value>
                     <value>--stdout</value>
                     <value>--no-summary</value>
                     <value>${target}</value>
                  </list>
               </entry>
            </map>
         </property>
      </bean>
   </property>
</bean>


テストしてみよう


では、カスタムモジュールを適用し、ウイルススキャン機能をテストしてみましょう。

JavaクラスファイルはalfrescoVirusScanSample.jarなどにパッケージングして<tomcat_dir>/webapps/alfresco/WEB-INF/lib/にコピーし、alfresco-virusscan-sample-context.xmlは<tomcat_dir>/shared/classes/alfresco/extension/にコピーします。もちろんAlfrescoを再起動する必要があります。

そして、クライアントPCはリアルタイムスキャンが無効になっていることを確認します。クラ イアントPCにリアルタイムスキャンが設定されていると、テスト用のウイルスファイルが自動除去されてしまってテストができません。そして、テスト用のウイルスファイルをこちらからダウンロードしておきます。

Alfrescoが起動したら、Alfrescoにログインして先ほどのテスト用ウイルスファイルをアップロードします。以下のようにアップロードに失敗し、ウイルスが検知された旨が表示されればOKです。




さらに、catalina.out等のログにはVirusDetectExceptionが出力されているはずです。

ERROR [extensions.webscripts.AbstractRuntime] [http-bio-8080-exec-19] Exception from executeScript - redirecting to status template error: 10120029 Virus detected and cleaned up : eicar.com.txt
 jp.aegif.alfresco.sample.action.executer.VirusDetectException: 10120029 Virus detected and cleaned up : eicar.com.txt
 at jp.aegif.alfresco.sample.action.executer.VirusScanActionExecuter.executeImpl(VirusScanActionExecuter.java:68)
 ...

まとめ


テストはうまくいきましたでしょうか?以上でウイルススキャンを行うカスタムモジュールの基本的な部分ができたかと思います。実際に利用するにあたっては、さらに以下のようなことを考慮する必要があるかもしれません。
  • 1トランザクションで複数のファイル(ノード)が作成されるような場合には対応していない
    • ウイルススキャンアクション呼び出し部分に工夫が必要
  • clamscanはパフォーマンスが良くない
    • ウイルス定義を予めメモリに展開しておくclamdscanの利用
    • Clam AntiVirus以外のウイルススキャンツールの利用
  • ファイルアップロード時ではなく、アクションメニューから手動で実行したい
    • ウイルススキャンをActionExecuterとして実装しているので簡単に実現できます(何人かが既に実装して公開しています)