Oracle Audit Vault and Database FirewallにはJavaベースの監査証跡収集プラグインのセットが用意されており、これを使用してカスタム・プラグインを作成することができます。
テンプレートベースの収集プラグインで監査証跡データを簡単に処理できない場合は、Javaベースの収集プラグインを使用できます
カスタム収集プラグインの作成にJava APIを使用すると、収集プラグインをより柔軟に設計できます。
一般的には、次のような必要がある場合にJavaタイプの収集プラグインを使用します。
データベース表またはXMLファイルに書き込まれていない証跡を読み取る。
表またはXMLファイルに書き込まれた複雑な証跡を読み取る。
親トピック: Javaベースの監査証跡収集プラグイン
Javaベースの収集プラグインには、コードをコンパイルおよびテストするためのJDKが必要です。出荷後、収集プラグインはエージェントと同じJVMで実行されるため、エージェントの開始に使用したのと同じJDKを使用することをお薦めします。JDKでクラスをコンパイルするには、javac
コンパイラの-target
オプションを同じバージョンに設定します。詳細は、JDKのドキュメントを参照してください。
親トピック: Javaベースの監査証跡収集プラグイン
収集プラグインは、監査証跡にアクセスして監査証跡から監査レコードおよび関連フィールドを抽出した後、その監査レコードをAudit Vaultイベントにマップし、すべてのフィールドをAudit Vaultフィールドにマップします。次に、収集プラグインは、Audit Vaultイベントとフィールドを収集フレームワークに渡し、これがAudit Vault Serverに情報を送信します。
監査証跡収集の制御プロセスのフローは、次のとおりです。
親トピック: Javaベースの監査証跡収集プラグイン
独自の収集に特に便利な、Oracle Audit Vault Javaベースの収集プラグインのクラスおよびインタフェースについて学習します
次の画像はAuditService、CollectorContextおよびClass AVLoggerのクラスとインタフェース間の関係を示しています。
図4-1 AuditService、CollectorContextおよびClass AVLoggerのクラスとインタフェース
次の図に、Javaベースの収集プラグインを記述する際に必要となる、収集フレームワークの様々なクラスおよびインタフェースを示します。
親トピック: Javaベースの監査証跡収集プラグイン
Oracle Data VaultのJavaベースの収集プラグインの作成と使用に必要なタスクを確認します。
AUD
という名前の表に書き込む仮のソースなどを含めて、Javaベースの収集プラグインの実装例が示されています。 親トピック: Javaベースの監査証跡収集プラグイン
Oracle Audit Vaultのドキュメントには、イベントをAUD
という名前の表に書き込む仮のソースなどを含めて、Javaベースの収集プラグインの実装例が示されています。
Oracle Audit Vault and Database Firewallの実装には、AuditEventCollectorFactory
インタフェースを実装するJavaクラスの記述、およびAudit Vault収集フレームワークの一部であるAuditEventCollector
クラスの拡張が含まれます。同じJavaクラスを使用して、AuditEventCollector
クラスの拡張と、AuditEventCollectorFactory
インタフェースの実装の両方を実行できます。または、個別に2つのクラスを記述することもできます。サンプルは、AuditEventCollectorFactory
インタフェースを実装するSampleEventCollectorFactory
と、AuditEventCollector
クラスから拡張されるSampleEventCollector
の、2つのクラスで構成されます。
親トピック: Javaベースの収集プラグインの作成方法
収集フレームワークはAuditEventCollector
オブジェクトのインスタンスを直接作成しません。かわりに、AuditEventCollectorFactory
クラスのインスタンスを作成し、ファクトリ・オブジェクトを使用してAuditEventCollector
オブジェクトを取得します。これは、収集プラグインでAuditEventCollector
の複数の実装が必要になる可能性があるためです。どの実装を使用するかは、収集プラグインによって実行時に決定されます。そのため、すべての収集プラグインにAuditEventCollectorFactory
が実装されている必要があります。
例4-1では、createAuditEventCollector()
は常にSampleAuditEventCollector
クラスのインスタンスを作成して返します。
例4-1 SampleAuditEventCollectorクラスの作成
public class SampleEventCollectorFactory implements AuditEventCollectorFactory { public AuditEventCollector createAuditCollection( CollectorContext collectorContext) throws AuditEventCollectorException { return new SampleEventCollector(); } }
親トピック: Javaベースの収集プラグインの作成方法
監査証跡の効率的な収集に必要なソースに関する情報をOracle Data Vault収集プラグインに提供するソース属性の使用方法を学習します。
収集フレームワークは、initializeCollector
メソッドを使用して、CollectorContext
クラスのインスタンスを収集プラグインに渡します。収集プラグインは、このインスタンスを問い合せて、ソースが生成した監査証跡の収集に必要な情報を取得します。
親トピック: Javaベースの収集プラグインの作成方法
監査証跡収集を正常に取得するために、収集プラグインにOracle Audit Vault and Database Firewallのソースに関する情報を提供する基本ソース属性があります。
Oracle Audit Vault and Database Firewallの基本ソース属性には、ユーザー名、パスワードおよび接続文字列が含まれます。これらの属性は、それぞれgetSecuredTargetUser
、getSecuredTargetPassword
およびgetSecuredTargetLocation
の各メソッドにより返されます。他のソース属性はgetAttributes
を使用して取得できます。
Oracle Audit Vault管理者がソースを登録する場合、Oracle Audit Vault管理者に必要な情報をソース属性の形式で指定するように要求できます。Oracle Audit Vaultでは、これらの属性はOracle Audit Vault Serverリポジトリに保存され、起動時にコレクタ・コードに提供されます。
一部の収集プラグインではソースへの接続が不要であり、その場合、収集フレームワークはこれらのメソッドにnullを返します。
関連トピック
チェックポイントおよび証跡名の属性は、Oracle Audit Vault and Database Firewallで取得される基本属性です。
チェックポイントの属性はgetCheckpoint
メソッドによって返され、証跡名の属性はgetTrailLocation
メソッドによって返されます。これらの属性は収集プラグインで次のように使用されます。
返されたチェックポイントは、収集プラグインが最後に実行されたときに、この証跡用に設定した最後のチェックポイントです。収集プラグインは、イベント時間がチェックポイント以降であるレコードのみの送信を開始します。収集プラグインを初めて開始する場合、収集プラグインはこの値をnullとして受け取ります。この場合、収集プラグインはレコードを最初から送信する必要があります。
証跡名は、監査イベントが含まれるターゲットを示しており、通常は表またはディレクトリの名前です。
他の証跡属性はgetAttributes
を使用して取得できます。
関連トピック
AVLoggerおよびAuditService属性をOracle Audit Vaultコレクタで使用する方法を学習します。
AVLogger
およびAuditService
は、それぞれgetLogger
メソッドおよびgetAuditService
メソッドによって返されます。これらの属性はコレクタで次のように使用されます。
AVLogger
インスタンスは様々なメッセージを記録します。
AuditService
インスタンスはチェックポイントおよびメトリックをAudit Vault Serverに送信します。
これらのメソッドがnullを返すことはありません。
コレクタに必要なその他の属性は、属性名をgetAttribute
メソッドに渡すことによって返されます。
たとえば、監査データを収集するために、ソースにSourceVersion
が必要である場合、ソースのコレクタはcollectorContext.getAttribute('SourceVersion')
を呼び出して、SourceVersion
の値を取得します。
属性が存在する場合、getAttribute
メソッドは属性値を文字列として返します。そうでない場合、メソッドはnullを返します。
必須の属性にnullまたは無効な値を受け取った場合、コレクタはinitializeCollector
メソッドからAuditEventCollectorException
例外をスローします。その後、収集フレームワークは停止します。
関連項目:
収集プラグイン属性の実行時変更の詳細は、「Audit Vault and Database Firewall属性の実行時変更」を参照してください
これらの例は、Javaベースの収集プラグインを初期化する方法と、Oracle Audit Vault and Database Firewallを使用してイベントの収集を開始する方法を理解する場合に使用します。
収集スレッドの開始後に収集フレームワークが最初に行うことは、コレクタの初期化です。
収集フレームワークは、AuditEventCollector
クラスのinitializeCollector()
メソッドを呼び出します。コレクタは環境を適切に設定し、監査イベントの収集を開始できるようにします。たとえば、データベース表の収集プラグインの場合、このメソッドはデータベースに接続します。XMLファイルの収集プラグインの場合、このメソッドはファイル・マスクを解析し、開始する特定のファイルを開きます。収集プラグインはまた、このときに様々な属性をコレクタ・コンテキストから取得する場合があります。環境の設定中にエラーが発生した場合、このメソッドは適切なエラー・メッセージとともにAuditEventCollectorException
をスローします。
例4-2 Javaベースの収集プラグインの初期化
次に、Javaベースの収集プラグインを初期化する方法の例を示します。
private AVLogger m_logger; private CollectorContext m_collectorContext; private long m_timeZoneOffset; private AuditService m_auditService; private Timestamp m_previousCheckpoint; public void initializeCollector(CollectorContext collectorContext) throws AuditEventCollectorException { m_collectorContext = collectorContext; m_auditService = m_collectorContext.getAuditService(); m_previousCheckpoint = m_collectorContext.getCheckpoint(); m_logger = m_collectorContext.getLogger(); // Get other attributes of the Source. String offset = m_collectorContext.getAttribute("TimeZoneOffset"); if (offset != null) { m_timeZoneOffset = getTimeZoneOffsetInMs(offset); } connectToSource(); }
例4-3 ConnectionManagerユーティリティを使用したデータベースの接続と監査レコードの取得
監査レコードを取得するためにコレクタをデータベースに接続する必要がある場合は、Oracle Audit Vaultで提供されるConnectionManager
ユーティリティAPIを使用する必要があります。次の例は、ConnectionManagerユーティリティの使用方法を示しています。
private ConnectionManager m_connectionManager; private void connectToSource() throws AuditEventCollectorException { m_logger.logDebugMethodEntered(); // Get connection information from collector context. String user = m_collectorContext.getSecuredTargetUser(); String password = new String(m_collectorContext.getSecuredTargetPassword()); String connectionString = m_collectorContext.getSecuredTargetLocation(); // Create a ConnectionManager object. try { m_connectionManager = new ConnectionManagerImpl(connectionString, user, password.toCharArray()); m_connection = m_connectionManager.getConnection(); } catch (AuditException ex) { throw new AuditEventCollectorException( ErrorCodes.FAILED_CONNECT_TO_SOURCE, new Object[] { connectionString }, ex); } m_logger.logDebugMethodExited(); }
初期化後、収集フレームワークは、内部的にfetchEvents()
メソッドを呼び出す、コレクタのhasNext()
メソッドを繰り返し呼び出します。このメソッドでは、コレクタは監査証跡から監査レコードをResultSet
の形式でフェッチします。
フェッチされる範囲は、現在の時間に近く、終了したばかりの時点から開始します。次のフェッチは、現在のResultSet
を使い果たしたときに実行されます
収集プラグインは、1つのResultSet
の処理が終了すると、次が始まる前にチェックポイントを設定します。このタイミングは重要です。収集プラグインがTimestamp
t
でチェックポイントを設定した場合、t
より前のイベント時間を持つすべてのレコードが収集フレームワークにすでに送信されていることを確認する必要があります。ただし、ResultSet
ではレコードに特定の順序付けを行わないため、ResultSet
の終了前にチェックポイントを設定するのは正しくありません。また、収集プラグインでは現在の時間を範囲の上限として使用せず、現在の時間からデルタ時間を引いた時間を使用します。これにより、イベントの生成とイベントを表に挿入するまでの間の遅延が許容されます。収集プラグインが問合せを実行した場合、上限までのすべてのイベントがResultSet
にフェッチされ、チェックポイント・コントラクトが履行されます。5秒の遅延時間(デルタ)によって、上限までのすべてのレコードがすでに表にあることを確認できます。
例4-4に示すように、コレクタが必要とする場合は常にConnectionManager
からConnection
を取得できる必要があります。
例4-5では、hasNext()
メソッドは、例4-4で定義したfetchEvents()
メソッドを実行して、レコードのフェッチとチェックポイントの設定を行います。
例4-4 ResultSetのフェッチおよびチェックポイントの設定
private ResultSet m_resultSet; private Timestamp m_nextCheckpoint; private void fetchEvents() throws AuditEventCollectorException { m_logger.logDebugMethodEntered(); if (m_nextCheckpoint != null) { m_auditService.setCheckpoint(m_nextCheckpoint); m_previousCheckpoint = m_nextCheckpoint; } // It is not good to hold on to the Connection for long. As this is the // only place we can release the connection, we release and reacquire the // connection. try { if (m_connection != null) { m_connectionManager.releaseConnection(m_connection); } } catch (AuditException ex) { throw new AuditEventCollectorException( ErrorCodes.FAILED_TO_RELEASE_CONNECTION_TO_DB, null, ex); } try { m_connection = m_connectionManager.getConnection(); } catch (AuditException ex) { throw new AuditEventCollectorException( ErrorCodes.FAILED_TO_GET_CONNECTION_TO_DB, null, ex); } // This is the upper bound which is current time minus 5 seconds. m_nextCheckpoint = new Timestamp(System.currentTimeMillis() - 5000); String query = null; try { if (m_previousCheckpoint == null) { query = "select * from AUD where EVENT_TIME <= ?"; m_preparedStatement = m_connection.prepareStatement(query); m_preparedStatement.setTimestamp(1, m_nextCheckpoint); } else { query = "select * from AUD where EVENT_TIME > ? and EVENT_TIME <= ?"; m_preparedStatement = m_connection.prepareStatement(query); m_preparedStatement.setTimestamp(1, m_previousCheckpoint); m_preparedStatement.setTimestamp(2, m_nextCheckpoint); } m_resultSet = m_preparedStatement.executeQuery(); } catch (SQLException ex) { throw new AuditEventCollectorException( ErrorCodes.ERROR_GETTING_DATA_FROM_SOURCE, new Object[] { query }, ex); } m_logger.logDebugMethodExited(); }
例4-5 hasNextを使用したレコードのフェッチ
public boolean hasNext() throws AuditEventCollectorException { boolean hasMore; try { if(m_resultSet == null) { fetchEvents(); return m_resultSet.next(); } hasMore = m_resultSet.next(); if (!hasMore) { fetchEvents(); hasMore = m_resultSet.next(); } } catch (SQLException ex) { throw new AuditEventCollectorException( ErrorCodes.ERROR_GETTING_DATA_FROM_SOURCE, null, ex); } return hasMore; }
親トピック: Javaベースの収集プラグインの作成方法
Oracle Audit Vault収集プラグインがソース・イベント値をいつどのようにしてOracle Data Vault値に変換するかについて学習します。
コレクタは、ソースから特定のフィールドの値を取得します。一部のフィールドについては、値を取得するだけでなく、特定の方法で値を変換する必要があります。この項では、すべてのソース・タイプに対して必要な変換について説明します。
親トピック: Javaベースの収集プラグインの作成方法
イベント時間はUTCタイムゾーンでのみ送信できます。そのため、値を返す前にソース・タイムゾーンからUTCタイムゾーンに変換する必要があります。ソース・データベースの列でタイムゾーンが認識される場合、この変換は必要ありません。
例4-6 EventTimeのソース・タイムゾーンからUTCへの変換
public Timestamp getEventTimeUTC() throws AuditEventCollectorException {
try {
Timestamp eventTime = m_resultSet.getTimestamp("EVENT_TIME");
// As the method name suggests, the timestamp must be returned only in
// UTC timone.
return new Timestamp(eventTime.getTime() - m_timeZoneOffset);
} catch (SQLException ex) {
throw new AuditEventCollectorException(
ErrorCodes.ERROR_GETTING_DATA_FROM_SOURCE, null, ex);
}
}
各ソース・イベント名は、1つのAudit Vaultイベント名にマップされます。getCommandClass()
メソッドは、ソース・イベント名をAudit Vaultが受け入れられる値に変換します。
例4-7 ソース・イベント名からAudit Vaultイベント名へのマッピング
private static final Map<Integer, String> eventNameMap = new HashMap<Integer, String>(); static { eventNameMap.put(1, "CREATE"); eventNameMap.put(2, "INSERT"); eventNameMap.put(3, "SELECT"); eventNameMap.put(4, "CREATE"); eventNameMap.put(15, "ALTER"); eventNameMap.put(30, "AUDIT"); eventNameMap.put(34, "CREATE"); eventNameMap.put(35, "ALTER"); eventNameMap.put(51, "CREATE"); eventNameMap.put(52, "CREATE"); } public String getCommandClass() throws AuditEventCollectorException { try { int eventId = m_resultSet.getInt("ACTION"); return eventNameMap.get(eventId); } catch (SQLException ex) { throw new AuditEventCollectorException( ErrorCodes.ERROR_GETTING_DATA_FROM_SOURCE, null, ex); } }
関連項目:
Audit Vaultイベント名の一覧は、Oracle Audit Vault and Database Firewallフィールドを参照してください。
一部のソースでIDとしてレポートされるイベントは、ユーザーがIDを熟知していなければ意味を持ちません。そのため、ソース・イベントIDをわかりやすいソース・イベント名にマップするのが最良の方法です。監査レコード自体にわかりやすいイベント名が付けられている場合は、マッピングせずに直接返すことができます。ソース・イベント名はオプションであるため、情報がない場合、収集プラグインはnullを返します。
例4-8では、ソース・イベントIDをわかりやすいソース・イベント名にマップします。
例4-8 ソース・イベントIDからソース・イベント名へのマッピング
private static final Map<Integer, String> sourceEventMap = new HashMap<Integer, String>(); static { targetTypeMap.put(1, "OBJECT:CREATED:TABLE"); targetTypeMap.put(2, "INSERT INTO TABLE"); targetTypeMap.put(3, "SELECT FROM TABLE"); targetTypeMap.put(4, "OBJECT:CREATED:TABLE"); targetTypeMap.put(15, "OBJECT:ALTERED:TABLE"); targetTypeMap.put(30, "AUDIT OBJECT"); targetTypeMap.put(34, "OBJECT:CREATED:DATABASE"); targetTypeMap.put(35, "OBJECT:ALTERED:DATABASE"); targetTypeMap.put(51, "OBJECT:CREATED:USER"); targetTypeMap.put(52, "OBJECT:CREATED:ROLE"); } public String getEventName() throws AuditEventCollectorException { try { int eventId = m_resultSet.getInt("ACTION"); return sourceEventMap.get(eventId); } catch (SQLException ex) { throw new AuditEventCollectorException( ErrorCodes.ERROR_GETTING_DATA_FROM_SOURCE, null, ex); } }
ターゲット・タイプは、イベントが発生したオブジェクトのタイプです。たとえば、イベントが表のSELECT
操作である場合、ターゲット・タイプは表です。一部のソースでは、ソース・イベント名およびIDでターゲット・タイプを表している場合があります。たとえば、イベント名select table
では、ターゲット・タイプが表であることを示しています。この場合、ソース・イベント名またはIDをターゲット・タイプにマップする必要があります。ターゲット・タイプはオプションのフィールドであるため、そのような情報がない場合、収集プラグインはnullを返します。
例4-9では、ソース・イベントIDをAudit Vaultターゲット・タイプにマップしています。
例4-9 ソースIDからターゲット・タイプへのマッピング
private static final Map<Integer, String> targetTypeMap = new HashMap<Integer, String>(); static { targetTypeMap.put(1, "TABLE"); targetTypeMap.put(2, "TABLE"); targetTypeMap.put(3, "TABLE"); targetTypeMap.put(4, "CLUSTER"); targetTypeMap.put(15, "TABLE"); targetTypeMap.put(30, "OBJECT"); targetTypeMap.put(34, "DATABASE"); targetTypeMap.put(35, "DATABASE"); targetTypeMap.put(51, "USER"); targetTypeMap.put(52, "ROLE"); } public String getTargetType() throws AuditEventCollectorException { try { int eventId = m_resultSet.getInt("ACTION"); return targetTypeMap.get(eventId); } catch (SQLException ex) { throw new AuditEventCollectorException( ErrorCodes.ERROR_GETTING_DATA_FROM_SOURCE, null, ex); } }
EventStatus
に許可される値は3つのみです。SUCCESS
、FAILURE
およびUNKNOWN
です。例4-10に示すように、ソース値をこれらの値のいずれかにマップする必要があります。
例4-10 ソース値からAudit Vault EventStatus値への変換
public EventStatus getEventStatus() throws AuditEventCollectorException {
try {
int status = m_resultSet.getInt("STATUS");
if (status == 1) {
return EventStatus.SUCCESS;
} else if (status == 0) {
return EventStatus.FAILURE;
} else {
return EventStatus.UNKNOWN;
}
} catch (SQLException ex) {
throw new AuditEventCollectorException(
ErrorCodes.ERROR_GETTING_DATA_FROM_SOURCE, null, ex);
}
}
変換の必要がないフィールドについては、収集プラグインはソースから取得した値を返します(例4-11ではユーザー名を取得し、これを返しています)。
例4-11 変換不要の値を返す
public String getUserName() throws AuditEventCollectorException {
try {
return m_resultSet.getString("USER_ID");
} catch (SQLException ex) {
throw new AuditEventCollectorException(
ErrorCodes.ERROR_GETTING_DATA_FROM_SOURCE, null, ex);
}
}
親トピック: Javaベースの収集プラグインの作成方法
Oracle Audit Vault and Database Firewall管理者は、Audit Vault and Database FirewallコンソールまたはAVCLI
コマンドライン・ツールを使用して、ソース属性などの属性を実行時に更新できます。
コレクタが監査証跡を収集しているときに更新が発生した場合、Audit Vault ServerはコレクタのsetAttribute
メソッドを呼び出して、実行中のすべてのコレクタに対して動的に通知を行います。その後、収集プラグインはただちに新しい値を使用して開始する必要があります。収集プラグインが属性を認識できない、または使用できない値である場合、コレクタはSetAttributeException
をスローします。
例4-12では、収集プラグインは、以降のすべてのイベントでEventTime
からUTCタイムゾーンに変換する際に使用する、新しいタイムゾーン・オフセットを受け取り、処理します。これは、例4-6で発生するタイムゾーン・オフセットの変換に影響を与えます。
関連項目:
属性とその初期化方法の詳細は、「Javaベースの収集プラグイン作成時のCollectorContextクラスの使用」を参照してください。
収集プラグインでの例外の使用については、「収集プラグインでの例外の使用」を参照してください。
例4-12 Audit Vault and Database Firewall属性の変更
public void setAttribute(String name, String value)
throws SetAttributeException {
if (name.equalsIgnoreCase("TimeZoneOffset")) {
m_timeZoneOffset = getTimeZoneOffsetInMs(value);
} else {
throw new SetAttributeException(ErrorCodes.INVALID_ATTRIBUTE_NAME,
new Object[] { name, value }, null);
}
}
親トピック: Javaベースの収集プラグインの作成方法
AVDF属性と同じように、カスタム属性を実行時に変更することができます。
カスタム属性を変更する場合は、次のメソッドを実装して、setAttribute
メソッドで使用する前にカスタム属性を検証する必要があります。
例4-13 カスタム値の変更
private static final String[] s_attributes = new String[] { "av.collector.configureParameter1", "av.collector.configureParameter2" }; public String[] getAttributeNames() throws AuditEventCollectorException { return s_attributes.clone(); } public void setAttribute(String name, String value) throws SetAttributeException { if (name.equalsIgnoreCase("configureParameter1")) { // use value }else if (name.equalsIgnoreCase("configureParameter2")) { // use value }else { throw new SetAttributeException(ErrorCodes.INVALID_ATTRIBUTE_NAME, new Object[] { name, value }, null); } }
親トピック: Javaベースの収集プラグインの作成方法
拡張フィールドには、ユーザーが関心を持っていているがコア・フィールドまたはラージ・フィールドのいずれにも対応していない、ソース・イベントのすべてのフィールドが含まれます。コレクタには、これらの追加フィールドの名前と値を含む文字列が1つ構成されている必要があります。この文字列の書式は収集プラグインで決定できます。収集フレームワークがこの文字列を解析することはありません。例4-14では次の書式を使用し、必要に応じて繰り返します。
<field_name>=<field_value>;
例4-14では、拡張の一部として3つのフィールドを送信します。
例4-14 拡張フィールドの作成
public String getExtension() throws AuditEventCollectorException { try { StringBuilder sb = new StringBuilder(); sb.append("DB_ID=" + m_resultSet.getString("DB_ID") + ";"); sb.append("INSTANCE=" + m_resultSet.getString("INSTANCE") + ";"); sb.append("PROCESS=" + m_resultSet.getString("PROCESS")); return sb.toString(); } catch (SQLException ex) { throw new AuditEventCollectorException( ErrorCodes.ERROR_GETTING_DATA_FROM_SOURCE, null, ex); } }
親トピック: Javaベースの収集プラグインの作成方法
一部の監査レコード・フィールドは非常に大きく、文字列として返すことができない場合があります。そのため、これらのフィールドに対応するメソッドは、Reader
タイプのオブジェクトを返します。ソース・フィールドがCLOB
である場合、clob.getCharacterStream()
を使用してReader
を取得できます。
ノート:
Reader
は、ソースへの接続が活動状態である間のみ有効です。
リーダーを使用するすべてのイベントがAudit Vault Serverに送信されるまで、ソースへの接続が活動状態に維持されるように、収集プラグインを設計する必要があります。
コレクタでソースへのConnection
をリセットする場合は、チェックポイントの設定直後に行う必要があります。これは、収集フレームワークがレコードのバッチを送信してからチェックポイントを設定するため、すべてのレコードが確実にAudit Vault Serverに送られているのはこの時点のみであるからです。この他にも、レコードがAudit Vault Serverに送信されている状況はありますが、チェックポイントを含めるとこの場合のみであることに注意してください。
Reader
インスタンスを直接取得できない場合は、コレクタがReader
を作成して返す必要があります。
例4-15 ラージ・フィールドの作成
public Reader getCommandText() throws AuditEventCollectorException {
try {
Clob clob = m_resultSet.getClob("SQL_TEXT");
return clob.getCharacterStream();
} catch (SQLException ex) {
throw new AuditEventCollectorException(
ErrorCodes.ERROR_GETTING_DATA_FROM_SOURCE, null, ex);
}
}
親トピック: Javaベースの収集プラグインの作成方法
コレクタは、収集フレームワークがレコードを一意に識別するために使用するマーカーを生成する必要があります。
コレクタは、特定の証跡の各レコードに一意のマーカーを生成する必要があります。マーカーの作成には2つ以上のイベント・フィールドを使用できます。テンプレートベースの収集プラグインでない場合は、表名、ファイル名、ファイル作成時間などの、監査イベントに含まれていない情報を使用することもできます。作成にかかる時間が短く、リカバリ・フェーズでのスペースが少なく、また一致時間が短くなるため、小さいサイズのマーカーが推奨されます。マーカーは、最後のチェックポイント後に送信されたレコードをフィルタする必要があるような、特にリカバリ・フェーズの特定のシナリオに有用です。収集プラグインはイベントの収集を開始する場合、最後の実行の最後のチェックポイントから開始します。ただし、そのチェックポイントの後に一部のレコードが収集され、Audit Vault Serverに送信されている可能性があります。重複を避けるために、収集フレームワークはレコード・マーカーを使用して、受信レコードとAudit Vault Serverにある既存のレコードを比較します。
例4-16では、マーカーのSession
_ID
およびEntry
_ID
を使用します。
例4-16 マーカーの作成
public String getMarker() throws AuditEventCollectorException { // ENTRY_ID will identify an audit event uniquely with in a session. Hence // ENTRY_ID along with SESSION_ID will uniquely identify an audit event // across sessions. try { return m_resultSet.getString("SESSION_ID") + ":" + m_resultSet.getString("ENTRY_ID"); } catch (SQLException ex) { throw new AuditEventCollectorException( ErrorCodes.ERROR_GETTING_DATA_FROM_SOURCE, null, ex); } }
親トピック: Javaベースの収集プラグインの作成方法
Javaベースの収集プラグインを閉じるプロセスは、収集フレームワークが特定の監査証跡の収集を停止するコマンドを受信したときに開始され、収集フレームワークはclose()
メソッドを使用してコレクタにこれを通知します。このメソッドでは、コレクタはデータベース接続またはファイル処理の終了などのクリーンアップ・タスクを実行します。close()
メソッドから収集フレームワークに制御が戻されると、収集スレッドは終了します。
このメソッドが例外をスローすることは予期されていません。例4-17に示すように、例外が発生した場合はエラー・メッセージが記録されます。
例4-17 クローズの呼出しおよびリソースの解放
public void close() {
try {
if (m_resultSet != null) {
m_resultSet.close();
m_resultSet = null;
}
if (m_connectionManager != null) {
m_connectionManager.destroy();
m_connectionManager = null;
}
m_previousCheckpoint = null;
m_nextCheckpoint = null;
m_logger = null;
} catch (SQLException ex) {
m_logger.logError("SampleEventCollector", "close",
"SQLException occurred. ", ex);
} catch (AuditException ex) {
m_logger.logError("SampleEventCollector", "close",
"AuditException occurred. ", ex);
}
}
親トピック: Javaベースの収集プラグインの作成方法
コレクタは、次の2つのチェック済例外をスローします。AuditEventCollectorException
およびSetAttributeException
。setAttribute
メソッドは、新しい値を設定できない場合にSetAttributeException
例外をスローします。この例外が受信されると、場合によってはコレクタが収集フレームワークによって停止されます(例4-12を参照)。close
メソッド以外のすべてのメソッドはAuditEventCollectorException
をスローします。この例外は、回復不能な条件が発生した場合にのみスローされるようにします。この例外を受信すると、収集フレームワークはコレクタを停止します。コレクタを停止する前に、収集フレームワークはclose
メソッドを呼び出します。これらの例外を作成しスローするサンプル・コードについては、前の項を参照してください。
親トピック: Javaベースの収集プラグインの作成方法
収集フレームワークに加えて、Oracle Audit Vault APIにはコレクタの記述タスクを簡単にするJavaユーティリティAPIが含まれています。
ConnectionManager
APIを使用してデータベースへの接続を管理する必要があります。EventLog
APIを使用できます。 AVLogger
APIを使用できます。親トピック: Javaベースの監査証跡収集プラグイン
Javaで記述されたOracle Audit Vault and Database Firewallのコンポーネント(コレクタ、エージェントおよびサーバー)はすべて、ConnectionManager
APIを使用してデータベースへの接続を管理する必要があります。
ConnectionManager
APIを使用して、Oracle Database、Microsoft SQL Server、Sybase Adaptive Server、およびIBM DB2などのソース・データベースへの接続を管理します。
ConnectionManager APIを使用する利点
データベース・サーバーのリソースの使用率が下がります。
クライアント側の操作がより正常になり、クライアントがハングしたり突然強制終了されることはなくなります。
これによりパフォーマンスが改善されます。
接続プールの設定に必要となる適切なパラメータが設定された、接続マネージャの具体的な実装をインスタンス化する必要があります。いくつかのコンストラクタを使用できます。呼出し元によって指定されないオプション・パラメータはすべて、次に示すようにOracle Audit Vault固有のデフォルト値になります。
CONNECTION_FACTORY_CLASSNAME=oracle.jdbc.pool.OracleDataSource
MIN_POOL_SIZE=0
INACTIVE_CONNECTION_TIMEOUT=1800
INITIAL_POOL_SIZE=0
VALIDATE_CONNECTION_ON_BORROW=true
親トピック: Javaベースの収集プラグインのユーティリティAPIの例
ConnectionManager APIを使用してデータベースへのOracle Audit Vault and Database Firewall Javaコンポーネント接続を管理する方法を確認してください。
ConnectionManager
APIは、データベース接続を管理するための取得、使用および解放モデルに基づいています。Javaで記述されたOracle Audit Vault and Database Firewallのコンポーネント(コレクタ、エージェントおよびサーバー)はすべて、ConnectionManager APIを使用してデータベースへの接続を管理する必要があります。例4-18 接続マネージャを使用した接続プールの処理
//Connection Manager ConnectionManager cManager = null; try { /* * Connection Pool Properties. * Set the pool properties such as URL * Initial pool size, Min pool size, etc. * The set of supported connection pool properties are * documented in the Oracle UCP documentation */ Properties pProps = new Properties(); pProps.put(URL, "jdbc:oracle:thin:@hostname:port:sid"); /* * Connection Properties * * Set the connection properties here. * The set of connection properties that can be set * depends on the driver. To enable SSL using the * the oracle jdbc driver, you need to set the following * Properties cProps = new Properties(); * String walletLoc = "/path/to/walletdirectory/cwallet.sso"; * cProps.setProperty("oracle.net.authentication_services","(TCPS)"); * cProps.setProperty("javax.net.ssl.trustStore", walletLoc); * cProps.setProperty("oracle.net.ssl_server_dn_match", "true") ; * cProps.setProperty("javax.net.ssl.trustStoreType","SSO"); * cProps.setProperty("javax.net.ssl.keyStore", walletLoc); * cProps.setProperty("javax.net.ssl.keyStoreType","SSO"); */ Properties cProps = new Properties(); cManager = new ConnectionManagerImpl(pProps, cProps); String username; char[] passwd; Connection conn = null; /* Do something */ ... /* Retrieve and set the username and password for user1 */ username = "user1"; passwd = "user1passwd".toCharArray(); /* Get a connection as "user1"*/ conn = cManager.getConnection(username, passwd); /* Use the "user1" connection and do something useful */ ... /* Release the connection */ cManager.releaseConnection(conn); /* Retrieve and set the username and password for user2 */ username = "user2"; passwd = "user2passwd".toCharArray(); /* Get a connection as "user2" */ conn = cManager.getConnection(username, passwd); /* Use the "user2" connection and do something useful */ ... /* Release the connection */ cManager.releaseConnection(conn); } catch (Exception e) { /* Take appropriate action here */ } finally { if (cManager != null) { try { cManager.destroy(); } catch (AuditException ae) { /* Take appropriate action here */ } }
ConnectionManager
APIは、呼出し元が異なるユーザー資格証明を使用していつでもデータベース接続を取得し解放できるように設計されています。たとえば、呼出し元はalice
のデータベース資格証明を使用して接続を取得し、その後robert
のデータベース資格証明で同じ接続マネージャを使用して接続を取得できます。
ノート:
呼出し元は次のことを行わないでください。
これらの要件によって、接続プールは次のような動作の接続を自動的に回復できるようになります。
TIME_TO_LIVE
時間制限を超過した。関連トピック
親トピック: Javaベースの収集プラグインのユーティリティAPIの例
Microsoft Windowsイベント・ログを解析するには、Microsoft WindowsのEventLog
APIを使用できます。
Windows EventLog
APIは、Windowsイベント・ログにアクセスするWindows API上のラッパーです。このAPIは、監査レコードの抽出が必要なコレクタを対象として、Windowsプラットフォーム上でのみ使用可能です。
次の図は、Windowsイベント・ログの解析に使用できるクラスを示しています。
EventLogRecord
クラスによって、イベント・ログに1つのレコードを格納できます。EventLogReader
クラスによって、イベント・ログ・レコードを1つずつフェッチできます。演算子クラスによって、イベント・ログ・レコードをフィルタできます。演算子は、イベント・ログ・レコードの特定のフィールドで動作し、フィールドの値に基づいてレコードをフィルタするかどうかを決定します。たとえば、Equals
演算子を使用して、フィールドの値が指定した値と等しくないすべてのイベント・ログ・レコードをフィルタできます。InRange
演算子およびOutsideRange
演算子は三項演算子です。その他は二項演算子です。
イベント・ログ・レコードを収集するには、次のステップを実行します。
関連トピック
親トピック: Javaベースの収集プラグインのユーティリティAPIの例
イベントのメタデータを取得するには、このMicrosoft Windows Metadata Java APIプロシージャを使用できます。
Microsoft Windowsでは、バージョン2008以降、イベントのメタデータを取得できる新しいAPIが提供されています。パブリッシャ名を指定すると、このAPIは各イベントのメタデータを取得します。次の図は、Windows Metadata JavaがWindows API上のラッパーであることを示しています。
EventMetaDataRecord
には、1つのイベントのメタデータが含まれます。EventMetaDataReader
を使用すると、イベント・メタデータ・レコードを1つずつフェッチできます。このAPIは次のように使用します。
親トピック: Javaベースの収集プラグインのユーティリティAPIの例
エラー、警告、情報、デバッグ・メッセージをOracle Audit Vault and Database Firewallログに記録するには、AVLogger
APIを使用できます。
例4-19 AVLogger APIの使用
import oracle.av.platform.common.util.AVLogger; import oracle.av.platform.common.exception.AuditException; import oracle.av.platform.common.AuditErrorCodes; public class Test { public static void main(String[] args) { /* Logger objects */ AVLogger myModule = null; try { /* get Logger instances; this will auto-create the logger instance */ /* if one does not exist */ myModule = AVLogger.getLogger("someModule"); /* print INFO level message */ /* check log level if you are concatenating strings to avoid expensive */ /* string operations */ if(myModule.isInfoEnabled()) { avServer.logInfo("Testing INFO level message...." + "another String" + "one more string"); } /* No need to check the log level if there is no string concatenation */ myModule.logInfo("Testing INFO level message for another component...."); /* changing the log level dynamically */ myModule.setLogLevel(AVLogger.AV_LOG_LEVEL_DEBUG); myModule.logWarn("Testing WARN level message ...."); myModule.logDebug("Testing DEBUG level message ...."); /* Reset the log level back to INFO */ myModule.setLogLevel(AVLogger.AV_LOG_LEVEL_INFO); /* Testing Exceptions: For now on, all exceptions will have */ /* an OAV-XXXX error code printed out automatically as long as */ /* they derive from AuditException object */ throw new AuditException (ErrorCodes.INTERNAL_ERROR, null, null); } catch (Exception e) { myModule.logError(e); } } }
関連トピック
親トピック: Javaベースの収集プラグインのユーティリティAPIの例
収集を開発している場合、Oracle XML Developer's Kitを使用してXMLファイルを解析し、そこから監査レコードを抽出できます。
Oracle XML Developer's Kitは含まれており、収集の開発に使用できます。
関連項目:
詳細は、『Oracle XML Developer's Kitプログラマーズ・ガイド』を参照してください。
親トピック: Javaベースの収集プラグインのユーティリティAPIの例
監査証跡のクリーンアップは、アーカイブされた後に監査レコードを削除するために一部のソースが提供する機能です。このタイプの機能がソースに存在する場合、Audit Vault収集プラグインが統合して、ソースに監査証跡がアーカイブされた範囲を通知できます。これにより、ソースはそのポイントまでの監査証跡をクリーンアップ(元の監査データを削除)でき、これを認識しているとデータを損失しません。Audit Vault収集プラグインは、データが収集された最後のポイントのチェックポイントに関するクリーンアップ・ユーティリティ情報を提供します。
収集プラグインは、この情報を、agent_home
\av\atc
ディレクトリの証跡固有の名前のファイルに、次の構文を使用して書き込みます。SecuredTargetName_TrailId
.atc
(oracl_1.atc
など)。
atc
ファイルの内容は次のようなものです。
securedTargetType=Oracle
SecuredTargetName=orcl
TrailType=TABLE
TrailName=sys.aud$
2016-04-15 10:26:53.7
(このタイムスタンプは、これらの設定の最後のチェックポイントを表します。)
セキュア・ターゲットのクリーンアップ・ユーティリティは、atc
のチェックポイントを解析し、このタイムスタンプまでの監査レコードを監査証跡から削除します。
たとえば、Oracle DatabaseソースはこのタイプのユーティリティをDMBS_AUDIT_MGMT
PL/SQLパッケージで提供します。Oracle Databaseの事前パッケージ済収集プラグインをこのパッケージと統合することで、監査証跡のクリーンアップ操作が使用可能になります。
親トピック: Javaベースの監査証跡収集プラグイン
監査レコードを抽出するための接続が必要となるデータベースなどのソースについて、このタスクの実行に必要な権限を正しく文書化することは、開発者の責任です。接続に使用するアカウントには、ジョブに必要な最小限の権限のみを付与することをお薦めします。追加の権限を付与することは、セキュリティ上の問題になる可能性があります。
また、入力監査レコードを正しく解析し、Oracle Audit Vault and Database Firewallを悪意のあるデータから保護する必要があります。たとえば、監査レコードは、監査証跡にSQLまたはHTMLを挿入するように作成されており、これによってAVDFに保存されているデータに攻撃が加えられる危険があります。受信するすべての監査レコードは、収集フレームワークに渡される前に正しくサニタイズされる必要があります。
親トピック: Javaベースの監査証跡収集プラグイン