9 JDBCクライアント側セキュリティ機能
この章では、JDBC OCIおよびJDBC ThinドライバのOracle Advanced Securityのオプション機能に関して、Autonomous Databaseに対するIAM認証、ログイン認証、ネットワーク暗号化および整合性のサポートについて説明します。
ノート:
- サーバー側内部ドライバを介したすべての通信が完全にサーバー内で行われるため、この説明はサーバー側内部ドライバには関係しません。
- パラメータ
SQLNET.CRYPTO_CHECKSUM_TYPES_CLIENTおよびSQLNET.CRYPTO_CHECKSUM_TYPES_SERVERを指定したSHA-1(Secure Hash Algorithm 1)の使用は、このリリースでは非推奨であり、将来のリリースではサポートされなくなる可能性があります。DBMS_CRYPTOでのSHA-1暗号の使用も非推奨になりました(HASH_SH1、HMAC_SH1)。SHA1を使用するのではなく、SHA-1暗号にかわるより強力なSHA-2暗号の使用を開始することをお薦めします。
以前Advanced Networking Option (ANO)またはAdvanced Security Option (ASO)と呼ばれていたOracle Advanced Securityは、業界標準に基づくネットワーク暗号化、ネットワーク整合性、サード・パーティ認証、シングル・サインオンおよびアクセス認可の機能を提供します。JDBC OCIドライバとJDBC Thinドライバは、どちらもOracle Advanced Security機能のすべてをサポートしています。
ノート:
JDBC ojdbc.policyのセキュリティ・ポリシー・ファイルを使用する場合、次のリンクからファイルをダウンロードできます。
http://www.oracle.com/technetwork/index.html
ojdbc.policyファイルには、Javaセキュリティ・マネージャの制御環境でアプリケーションを実行する必要がある付与された権限が含まれます。このファイル自体をJavaポリシー・ファイルとして使用するか、このファイルからコンテンツを取得してJavaポリシー・ファイルのコンテンツを追加できます。このファイルには、次のような権限が含まれます。
-
権限
java.util.PropertyPermission "user.name", "read";などの常に必要ないくつかの必須権限 -
いくつかのドライバ固有の権限(たとえば、JDBC OCIドライバでは権限
java.lang.RuntimePermission "loadLibrary.ocijdbc12";が必要です) -
XA、XDB、FCFなどに関連する権限などのいくつかの機能ベースの権限
要件に応じてファイルに記述されているシステム・プロパティまたは権限のダイレクト値を設定できます。
この章の構成は、次のとおりです。
9.1 IAMのトークンベース認証のサポート
Oracle Databaseリリース23aiでは、JDBC Thinドライバは、Oracle Cloud Infrastructure (OCI) Identity Access Management (IAM)の拡張サポートを提供します。
データベースへの接続中、JDBCアプリケーションはデータベースにトークンを提供します。データベースは、認証サービスからリクエストする公開キーでトークンを検証し、対応するユーザー・グループ・メンバーシップ情報を取得し、データベース・スキーマとロール・マッピングを検索してデータベースへのユーザー認証を完了します。
さらに、アプリケーションは署名済ヘッダーを送信することで、トークンに埋め込まれた公開キーとペアになる秘密キーを保有していることを証明します。トークンと署名の両方が有効で、IAMユーザーとデータベース・ユーザーの間にマッピングが存在している場合は、JDBCアプリケーションにデータベースへのアクセスが許可されます。
トークンベースの認証は、次の方法でサポートされます。
9.1.1 ファイル・システムの使用
データベース・トークンがファイル・システムで使用できるようになっていると、たとえば、Oracle Cloud Infrastructureコマンドライン・インタフェース(OCI CLI)を使用している場合は、このトークンを使用してデータベースに接続するようにJDBCドライバを構成できます。
この目的には、CONNECTION_PROPERTY_TOKEN_AUTHENTICATIONを使用できます。これは、次の方法で指定できます。
ojdbc.propertiesファイルとして- JVMシステム・プロパティとして
- 接続文字列の問合せセクションのパラメータとして
OracleDataSource.setConnectionProperties(Properties)に渡されたPropertiesオブジェクトによって- Oracle Net記述子の
SECURITYセクションのパラメータとして
JDBCは、このパラメータを指定できる次の2つのタイプの接続文字列をサポートしています。
- Oracle Net記述子として、このパラメータを次のように指定できます。
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(HOST=dbhost)(PORT=1522)(PROTOCOL=tcps))(SECURITY=(SSL_SERVER_DN_MATCH=ON) (TOKEN_AUTH=OCI_TOKEN))(CONNECT_DATA=(SERVICE_NAME=my.example.com))) - 接続プロパティとして、このパラメータを次のように指定できます。
jdbc:oracle:thin:@tcps:dbhost:1522/my.example.com?oracle.jdbc.tokenAuthentication=OCI_TOKEN&oracle.jdbc.tokenLocation =”/path/to/my/token”
CONNECTION_PROPERTY_TOKEN_AUTHENTICATIONがOCI_TOKENに設定されている場合、CONNECTION_PROPERTY_TOKEN_LOCATIONは、ドライバによるアクセス・トークンの取得元になるファイル・システム・パスを指定します。デフォルトの場所は、$HOME/.oci/db-token/です。このプロパティは、デフォルト以外の場所を指定するために別の値を設定できます。このプロパティで指定するパスは、tokenおよびoci_db_key.pemという名前のファイルが含まれているディレクトリにする必要があります。
ノート:
- Oracle Net記述子スタイルのURLに
TOKEN_LOCATIONパラメータが含まれている場合、そのパラメータの値は、CONNECTION_PROPERTY_TOKEN_LOCATIONで定義した値より優先されます。 - トークン・ファイルには、JSON Webトークン(JWT)がUTF-8エンコード・テキストの単一行で含まれている必要があります。JWTフォーマットは、RFC 7519によって規定されています。
- トークンの場所には、
oci_db_key.pemという名前の秘密キー・ファイルも含まれている必要があります。秘密キー・ファイルにはPEM形式を使用して、base64エンコーディングのRSA秘密キーがPKCS#8エンコーディングで含まれている必要があります
接続プロパティCONNECTION_PROPERTY_TOKEN_AUTHENTICATION (oracle.jdbc.tokenAuthentication)をOAUTHに設定し、接続プロパティCONNECTION_PROPERTY_TOKEN_LOCATION (oracle.jdbc.tokenLocation)をファイル・システム上のベアラー・トークンを指すように設定することもできます。この場合、デフォルトの場所が設定されていないため、場所を次のいずれかに設定する必要があります。
- ディレクトリ(この場合、ドライバは
tokenという名前のファイルをロードします) - 完全修飾ファイル名
これは、次の方法で実行できます。
ojdbc.propertiesファイルの構成# Enable the OAUTH authentication mode oracle.jdbc.tokenAuthentication=OAUTH # Specify the location of the Bearer token location oracle.jdbc.tokenLocation=/home/user1/mytokens/jwtbearertoken- JDBC URLの使用
jdbc:oracle:thin:@tcps:adb.mydomain.oraclecloud.com:1522/xyz.adb.oraclecloud.com? oracle.jdbc.tokenAuthentication=OAUTH&oracle.jdbc.tokenLocation=/home/user/token - JDBC URLに対するTNS形式の使用:
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCPS)(PORT=1521)(HOST=adb.mydomain.oraclecloud.com))(CONNECT_DATA= (SERVICE_NAME=xyz.adb.oraclecloud.com))(SECURITY=(TOKEN_AUTH=OAUTH)(TOKEN_LOCATION=/home/user1/mytokens/jwtbearertoken)))"
9.1.2 oracle.jdbc.accessToken接続プロパティの使用
CONNECTION_PROPERTY_ACCESS_TOKEN (oracle.jdbc.accessToken)をアクセス・トークン値に設定します。
これは、次の方法で実行できます。
ノート:
トークン値に含まれる可能性がある等号(=)をエスケープするには、トークン値を二重引用符("")で囲む必要があります。- JDBC URLの使用
jdbc:oracle:thin:@tcps:adb.mydomain.oraclecloud.com:1522/xyz.adb.oraclecloud.com?oracle.jdbc.accessToken="ey...5c" - 記述子URLの使用
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=mydomain.com)(PORT=5525)) (CONNECT_DATA=(SERVICE_NAME=myservice.com)))? oracle.jdbc.accessToken="ey...5c" ojdbc.propertiesファイルの構成# Enable the OAUTH authentication mode oracle.jdbc.accessToken="ey...5c"または
# Enable the OAUTH authentication mode oracle.jdbc.accessToken=${DATABASE_ACCESS_TOKEN}ここで、アクセス・トークンは
DATABASE_ACCESS_TOKEN環境変数の値です。ノート:
アクセス・トークンが提供されている場合、ドライバによってOAUTHモードが自動的に設定されるため、oracle.jdbc.tokenAuthentication=OAUTHを設定する必要はありません。
9.1.3 OracleConnectionBuilderインタフェースの使用
データベース・アクセス・トークンによる認証のために、OracleConnectionBuilder.accessTokenメソッドをコールします。このメソッドは、アプリケーションが認証サービスから取得するトークン値を受け入れます。
このメソッドを使用してトークンを渡すと、TOKEN_AUTH=OCI_TOKEN接続文字列の設定がオーバーライドされます。つまり、JDBCは通常どおりファイル・システムからトークンを読み取らなくなるということです。かわりに、JDBCはaccessTokenメソッドに指定されたAccessTokenオブジェクトを使用するようになります。
この場合、JDBCは秘密キーを使用して署名を生成し、IAMデータベース・アクセス・トークンとともにデータベースに送信します。最初に、データベースはIAMの公開キーでトークンを検証します。その次に、JDBCによって生成された署名を、トークンに埋め込まれている公開キーで復号化して検証します。復号化された署名が有効な場合は、JDBCが秘密キーを保有していることの証明になります。
単一のURLで構成された単一インスタンスのOracleDataSourceクラスにより、OracleConnectionBuilderインタフェースのインスタンスが作成されます。こうしたインスタンスは、O5Logonによる従来の認証をサポートしながら、トークンベースの認証もサポートします。その次に、アプリケーションは、ユーザーとパスワードを構成するメソッドまたはトークンを構成するメソッドをコールします。ただし、このビルダーはトークンとユーザー名またはパスワードの両方を使用して構成することはできません。accessTokenメソッドとpasswordメソッドまたはuserメソッドの両方がNULL以外の値で起動されたると、このビルダーとの接続の作成時に無効な構成を示すSQLExceptionがスローされます。
9.1.4 OracleDataSourceクラスの使用
データベース・アクセス・トークンによる認証のために、OracleCommonDataSource.setTokenSupplier(AccessToken accessToken)メソッドをコールします。
このメソッドでは、このDataSourceとの接続を作成するときに、アクセス・トークンを生成するサプライヤ・ファンクションを設定します。サプライヤ・ファンクションは、このDataSourceによる接続の作成のたびに起動されます。サプライヤによって生成されたアクセス・トークンのインスタンスは、クライアント認証のためにOracle Databaseでサポートされているトークン・タイプを表している必要があります。サプライヤは、スレッド・セーフになっている必要があります。
ノート:
AccessToken.createJsonWebTokenCache(Supplier)メソッドは、ユーザー定義のSupplierからのトークンをキャッシュする、スレッド・セーフのSupplierを作成するために使用します。
このDataSourceはトークン・サプライヤとユーザー名またはパスワードの両方を使用して構成することはできません。setUser(String)、setPassword(String)、 setConnectionProperties(java.util.Properties)またはsetConnectionProperty(String, String)メソッドを起動して、このDataSourceをユーザー名またはパスワードで構成し、setTokenSuppliersetTokenSupplier(AccessToken accessToken)メソッドを起動してトークン・サプライヤを構成すると、このDataSourceとの接続を作成するときに無効な構成を示すSQLExceptionがスローされます。
アクセス・トークンは本質的に一時的なものであり、1時間以内に期限切れになります。そのため、OracleDataSourceクラスのインスタンスが接続を作成するたびに、新しく生成されたトークンを取得できるようにするSupplierタイプを使用してください。Supplierは、トークンの有効期限が切れるまで、同じトークンを複数回生成できます。トークンの有効期限が切れると、Supplierは、そのトークンを生成しなくなり、それよりも有効期限が後になる新しいトークンを生成するようになります。
9.2 Azure ADのトークンベース認証のサポート
このリリースのOracle Databaseでは、JDBC Thinドライバは、Azure Active Directory (Azure AD) OAuth2アクセス・トークンのサポートを提供します。
データベースへの接続中、JDBCアプリケーションはデータベースにトークンを提供します。データベースは、認証サービスからリクエストする公開キーでトークンを検証し、対応するユーザー・グループ・メンバーシップ情報を取得し、データベース・スキーマとロール・マッピングを検索してデータベースへのユーザー認証を完了します。
トークンベースの認証は、次の方法でサポートされます。
9.2.1 ファイル・システムの使用
ファイル・システムでデータベース・トークンが使用可能な場合は、データベースへの接続にこのトークンを使用するようにJDBCドライバを構成できます。
この目的には、CONNECTION_PROPERTY_TOKEN_AUTHENTICATIONを使用できます。これは、次の方法で指定できます。
ojdbc.propertiesファイルとして- JVMシステム・プロパティとして
- 接続文字列の問合せセクションのパラメータとして
OracleDataSource.setConnectionProperties(Properties)に渡されたPropertiesオブジェクトによって- Oracle Net記述子の
SECURITYセクションのパラメータとして
JDBCは、このパラメータを指定できる次の2つのタイプの接続文字列をサポートしています。
- Oracle Net記述子として、このパラメータを次のように指定できます。
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(HOST=dbhost)(PORT=1522)(PROTOCOL=tcps))(SECURITY=(SSL_SERVER_DN_MATCH=ON) (TOKEN_AUTH=OAUTH)(TOKEN_LOCATION=/path/to/my/token))) - 接続プロパティとして、このパラメータを次のように指定できます。
jdbc:oracle:thin:@tcps:dbhost:1522/my.example.com?oracle.jdbc.tokenAuthentication=OAUTH&oracle.jdbc.tokenLocation =”/path/to/my/token”
CONNECTION_PROPERTY_TOKEN_AUTHENTICATIONがOAUTHに設定されている場合、CONNECTION_PROPERTY_TOKEN_LOCATIONは、アクセス・トークンの取得元になるファイル・システム・パスを指定します。この場合、デフォルトの場所はありません。トークンの場所を設定する必要があります。これは、tokenという名前のファイルにあるトークンを含むディレクトリです。たとえば、ディレクトリmytokendirectoryにtokenという名前のファイルが含まれている場合、次のようにトークンの場所を設定します。/path/to/mytokendirectoryノート:
- Oracle Net記述子スタイルのURLに
TOKEN_LOCATIONパラメータが含まれている場合、そのパラメータの値は、CONNECTION_PROPERTY_TOKEN_LOCATIONで定義した値より優先されます。 - トークン・ファイルには、JSON Webトークン(JWT)がUTF-8エンコード・テキストの単一行で含まれている必要があります。JWTフォーマットは、RFC 7519によって規定されています。
接続プロパティCONNECTION_PROPERTY_TOKEN_AUTHENTICATION (oracle.jdbc.tokenAuthentication)をOAUTHに設定し、接続プロパティCONNECTION_PROPERTY_TOKEN_LOCATION (oracle.jdbc.tokenLocation)をファイル・システム上のベアラー・トークンを指すように設定することもできます。この場合、デフォルトの場所が設定されていないため、場所を次のいずれかに設定する必要があります。
- ディレクトリ(この場合、ドライバは
tokenという名前のファイルをロードします) - 完全修飾ファイル名
これは、次の方法で実行できます。
ojdbc.propertiesファイルの構成# Enable the OAUTH authentication mode oracle.jdbc.tokenAuthentication=OAUTH # Specify the location of the Bearer token location oracle.jdbc.tokenLocation=/home/user1/mytokens/jwtbearertoken- JDBC URLの使用
jdbc:oracle:thin:@tcps:adb.mydomain.oraclecloud.com:1522/xyz.adb.oraclecloud.com? oracle.jdbc.tokenAuthentication=OAUTH&oracle.jdbc.tokenLocation=/home/user/token - JDBC URLに対するTNS形式の使用:
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCPS)(PORT=1521)(HOST=adb.mydomain.oraclecloud.com))(CONNECT_DATA= (SERVICE_NAME=xyz.adb.oraclecloud.com))(SECURITY=(TOKEN_AUTH=OAUTH)(TOKEN_LOCATION=/home/user1/mytokens/jwtbearertoken)))"
9.2.2 oracle.jdbc.accessToken接続プロパティの使用
CONNECTION_PROPERTY_ACCESS_TOKEN (oracle.jdbc.accessToken)をアクセス・トークン値に設定します。
これは、次の方法で実行できます。
ノート:
トークン値に含まれる可能性がある等号(=)をエスケープするには、トークン値を二重引用符("")で囲む必要があります。- JDBC URLの使用
jdbc:oracle:thin:@tcps:adb.mydomain.oraclecloud.com:1522/xyz.adb.oraclecloud.com?oracle.jdbc.accessToken="ey...5c" - 記述子URLの使用
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=mydomain.com)(PORT=5525)) (CONNECT_DATA=(SERVICE_NAME=myservice.com)))? oracle.jdbc.accessToken="ey...5c" ojdbc.propertiesファイルの構成# Enable the OAUTH authentication mode oracle.jdbc.accessToken="ey...5c"または
# Enable the OAUTH authentication mode oracle.jdbc.accessToken=${DATABASE_ACCESS_TOKEN}ここで、アクセス・トークンは
DATABASE_ACCESS_TOKEN環境変数の値です。ノート:
アクセス・トークンが提供されている場合、ドライバによってOAUTHモードが自動的に設定されるため、oracle.jdbc.tokenAuthentication=OAUTHを設定する必要はありません。
9.2.3 OracleConnectionBuilderインタフェースの使用
データベース・アクセス・トークンによる認証のために、OracleConnectionBuilder.accessTokenメソッドをコールします。
このメソッドは、アプリケーションが認証サービスから取得するトークン値を受け入れます。このメソッドを使用してトークンを渡すと、TOKEN_AUTH=OCI_TOKEN接続文字列の設定、その後TOKEN_AUTH=OAUTHがオーバーライドされます。つまり、JDBCは通常どおりファイル・システムからトークンを読み取らなくなるということです。かわりに、JDBCはaccessTokenメソッドに指定されたAccessTokenオブジェクトを使用するようになります。
単一のURLで構成された単一インスタンスのOracleDataSourceクラスにより、OracleConnectionBuilderインタフェースのインスタンスが作成されます。こうしたインスタンスは、O5Logonによる従来の認証をサポートしながら、トークンベースの認証もサポートします。その次に、アプリケーションは、ユーザーとパスワードを構成するメソッドまたはトークンを構成するメソッドをコールします。ただし、このビルダーはトークンとユーザー名またはパスワードの両方を使用して構成することはできません。accessTokenメソッドとpasswordメソッドまたはuserメソッドの両方がNULL以外の値で起動されたると、このビルダーとの接続の作成時に無効な構成を示すSQLExceptionがスローされます。
9.2.4 OracleDataSourceクラスの使用
データベース・アクセス・トークンによる認証のために、OracleCommonDataSource.setTokenSupplier(AccessToken accessToken)メソッドをコールします。
このメソッドでは、このDataSourceとの接続を作成するときに、アクセス・トークンを生成するサプライヤ・ファンクションを設定します。サプライヤ・ファンクションは、このDataSourceによる接続の作成のたびに起動されます。サプライヤによって生成されたアクセス・トークンのインスタンスは、クライアント認証のためにOracle Databaseでサポートされているトークン・タイプを表している必要があります。サプライヤは、スレッド・セーフになっている必要があります。
ノート:
AccessToken.createJsonWebTokenCache(Supplier)メソッドは、ユーザー定義のSupplierからのトークンをキャッシュする、スレッド・セーフのSupplierを作成するために使用します。
このDataSourceはトークン・サプライヤとユーザー名またはパスワードの両方を使用して構成することはできません。setUser(String)、setPassword(String)、 setConnectionProperties(java.util.Properties)またはsetConnectionProperty(String, String)メソッドを起動して、このDataSourceをユーザー名またはパスワードで構成し、setTokenSuppliersetTokenSupplier(AccessToken accessToken)メソッドを起動してトークン・サプライヤを構成すると、このDataSourceとの接続を作成するときに無効な構成を示すSQLExceptionがスローされます。
アクセス・トークンは本質的に一時的なものであり、1時間以内に期限切れになります。そのため、OracleDataSourceクラスのインスタンスが接続を作成するたびに、新しく生成されたトークンを取得できるようにするSupplierタイプを使用してください。Supplierは、トークンの有効期限が切れるまで、同じトークンを複数回生成できます。トークンの有効期限が切れると、Supplierは、そのトークンを生成しなくなり、それよりも有効期限が後になる新しいトークンを生成するようになります。
9.3 Oracle Advanced Securityのサポート
この項では、次の概念について説明します。
9.3.1 Oracle Advanced Securityの概要
Oracle Advanced Securityでは、次のセキュリティ機能をサポートしています。
-
ネットワーク暗号化
エンタープライズ・ネットワークおよびインターネット上でやりとりされる機密情報は、復号化キーによってのみ解読できる形式に情報を変換する暗号化アルゴリズムにより保護できます。たとえば、AESです。
送信中にネットワークの整合性を保証するために、Oracle Advanced Securityでは、暗号化によってセキュアなメッセージ・ダイジェストを生成します。Oracle Database 12cリリース1 (12.1)以降、ハッシュ・アルゴリズムのSHA-2リストもサポートされているので、Oracle Advanced Securityでは次のハッシュ・アルゴリズムを使用して、セキュアなメッセージ・ダイジェストを生成し、ネットワーク上で送信される各メッセージにこれを含めます。
これにより、やりとりされるデータは、データの変更、パケットの削除、反射攻撃などの攻撃から保護されます。
次のコードの抜粋に、前述のアルゴリズムのいずれかを使用したチェックサムの計算方法を示します。
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_CHECKSUM_TYPES, "( SHA1)"); prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_CHECKSUM_LEVEL, "REQUIRED");
-
厳密認証
分散環境でネットワーク・セキュリティを確保するには、ユーザーを認証し、資格証明を確認する必要があります。パスワード認証は、認証で最も一般的な手段です。Oracle Databaseでは、Oracle認証アダプタを使用して厳密な認証を行います。Oracle認証アダプタは、デジタル証明書を使用したTLSを含む様々なサード・パーティ認証サービスをサポートします。Oracle Databaseは、業界で標準的な次の認証方式をサポートしています。
-
Kerberos
-
Remote Authentication Dial-In User Service(RADIUS)
-
Transport Layer Security(TLS)
-
9.3.2 JDBC OCIドライバによるOracle Advanced Securityのサポート
JDBC OCIドライバを使用している場合は、Oracleクライアントがインストールされているコンピュータから実行していることが想定されるため、Oracle Advanced Securityと組込みサード・パーティ機能のサポートは、Oracleクライアントによって提供されるサポートとほとんど同じです。Advanced Security機能が使用されているかどうかは、クライアント・コンピュータのsqlnet.oraファイル内の、関連する設定の内容によって判断できます。
ノート:
Oracle Database 12cリリース1 (12.1)以降、sqlnet.oraファイルにあるOCI固有の構成パラメータのかわりに、新しいXML構成ファイルoraaccess.xmlにある構成パラメータを使用することをお薦めします。ただし、sqlnet.oraファイル内の構成パラメータもまだサポートされています。
パスワードを指定せずにデータベースに接続しようとすると、JDBC OCIドライバは、外部認証を使用しようとします。JDBC OCIドライバを使用して、パスワードを入力しないでデータベースに接続する例を次に示します。
TLS認証
次のコードでは、TLS認証を使用してデータベースに接続する方法を示します:
例9-1 TLS認証を使用したデータベースへの接続
import java.sql.*;
import java.util.Properties;
public class test
{
public static void main( String [] args ) throws Exception
{
String url = "jdbc:oracle:oci:@"
+"(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=localhost)(PORT=5221))"
+"(CONNECT_DATA=(SERVICE_NAME=orcl)))";
Driver driver = new oracle.jdbc.OracleDriver();
Properties props = new Properties();
Connection conn = driver.connect( url, props );
conn.close();
}
}
データソースの使用
次のコードでは、データソースを使用してデータベースに接続する方法を示します。
例9-2 データソースを使用したデータベースへの接続
import java.sql.*;
import javax.sql.*;
import java.util.Properties;
import oracle.jdbc.pool.*;
public class testpool {
public static void main( String args ) throws Exception
{ String url = "jdbc:oracle:oci:@" +"(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=localhost)(PORT=5221))"
+"(CONNECT_DATA=(SERVICE_NAME=orcl)))";
OracleConnectionPoolDataSource ocpds = new OracleConnectionPoolDataSource();
ocpds.setURL(url);
PooledConnection pc = ocpds.getPooledConnection();
Connection conn = pc.getConnection();
}
}
ノート:
Javaに関する前述の重要な例外は、アプリケーションでネイティブ・スレッドを使用している場合にのみ、Transport Layer Security (TLS)プロトコルがOracle JDBC OCIドライバでサポートされているという点です。通常、グリーン・スレッドがデフォルトで設定されているため、特に注意が必要です。
9.3.3 JDBC ThinドライバによるOracle Advanced Securityのサポート
JDBC Thinドライバでは、Oracleクライアントがインストールされていること、またはsqlnet.oraファイルが存在していることを前もって想定できません。
したがって、Javaアプローチを使用してOracle Advanced Securityをサポートします。Oracle Advanced Securityを実装するJavaクラスは、ojdbc8.jar、ojdbc11.jarおよびojdbc17.jarファイルに含まれています。暗号化と整合性のためのセキュリティ・パラメータは、通常のようにsqlnet.oraファイル内に設定されるのではなく、JavaのPropertiesオブジェクトか、またはシステム・プロパティを使用して設定されます。
9.4 ログイン認証のサポート
JDBCを介した基本ログイン認証では、Oracleサーバーへの他のログイン方法と同様に、ユーザー名とパスワードが要求されます。Javaプロパティ・オブジェクトを使用するか、またはgetConnectionメソッドを直接コールして、ユーザー名とパスワードを指定します。これは、使用しているクライアント側Oracle JDBCドライバにかかわらず適用されますが、サーバー側内部ドライバを使用している場合には、特殊な直接接続を使用しており、ユーザー名またはパスワードを要求しないため、関係ありません。
Oracle Database 12cリリース1 (12.1.0.2)以降、Oracle JDBC Thinドライバは、PBKDF2-SHA2アルゴリズムをサポートしているJDK 8などのJDKを使用してアプリケーションを実行する場合、O7L_MRクライアント機能をサポートしています。JDK 7を使用してアプリケーションを実行する場合は、PBKDF2-SHA2アルゴリズムをサポートしているサードパーティ製セキュリティ・プロバイダを追加する必要があります。そうしないと、O7L_MRクライアント機能を必要とする新規の12aパスワード検証機能が、ドライバでサポートされません。
SQLNET.ALLOWED_LOGON_VERSION_SERVERパラメータを12aに設定してOracle Database 12cリリース1 (12.1.0.2)を使用している場合は、次の点に注意してください。
-
12.1.0.2 Oracle JDBC Thinドライバと、JDK 8、または
PBKDF2-SHA2アルゴリズムをサポートしているサードパーティ製セキュリティ・プロバイダを追加したJDK 7も、使用する必要があります -
旧バージョンのOracle JDBC Thinドライバを使用すると、次のエラーが発生します。
ORA-28040: No matching authentication protocol
-
12.1.0.2 Oracle JDBC ThinドライバをJDK 7とともに使用する場合も、
PBKDF2-SHA2アルゴリズムをサポートしているサードパーティ製セキュリティ・プロバイダを追加していないと、同じエラーが発生します。
9.5 厳密認証のサポート
Oracle Advanced Securityでは、Oracle Databaseユーザーに対する外部認証が可能です。外部認証には、RADIUS、Kerberos、証明書ベースの認証、トークン・カードおよびスマート・カードなどが使用されます。この認証方法は、厳密認証と呼ばれます。Oracle JDBCドライバでサポートしている厳密認証方法は次のとおりです。
- Kerberos
- RADIUS
- TLS
9.6 ネットワーク暗号化と整合性のサポート
この項では、ネットワークの暗号化および整合性のサポートについて説明します。
ノート:
-
Oracle Database 21c以降、古い暗号化およびハッシュ・アルゴリズムは非推奨になりました。
非推奨のアルゴリズムには、
DBMS_CRYPTOおよびネイティブ・ネットワーク暗号化の場合はMD4、MD5、DES、3DESおよびRC4関連アルゴリズム、透過的データ暗号化(TDE)の場合は3DESがあります。安全性の低い古い暗号化アルゴリズムを削除すると、これらのアルゴリズムが誤って使用されることがなくなります。セキュリティ要件を満たすために、Advanced Encryption Standard (AES)などの最新の暗号化アルゴリズムを使用することをお薦めします。 - Oracleでは、Oracle Databaseリリース11.2以降における、ネイティブ・ネットワーク暗号化環境に影響を与える必要なセキュリティ機能強化に対応するために、ダウンロード可能なパッチを提供しています。このパッチは、My Oracle Supportノート2118136.2で入手できます。
この項では、次の概念について説明します。
9.6.1 JDBCによるネットワーク暗号化と整合性のサポートの概要
サーバーでの関連部分の設定によっては、Javaデータベース・アプリケーションで、Oracle DatabaseとOracle Advanced Securityのネットワーク暗号化および整合化の機能を使用できます。JDBC OCIドライバを使用している場合は、Oracleクライアントの場合と同様にパラメータを設定します。Thinドライバを使用している場合は、Javaプロパティ・オブジェクトを使用してパラメータを設定します。
暗号化は、クライアント側暗号化レベル設定と、サーバー側暗号化レベル設定の組合せに基づいて、有効または無効になります。同様に、整合性はクライアント側整合性レベル設定と、サーバー側整合性レベル設定の組合せに基づいて、有効または無効になります。
暗号化と整合性は、REJECTED、ACCEPTED、REQUESTEDおよびREQUIREDの同じ設定レベルをサポートしています。表9-1は、クライアント側とサーバー側の設定の組合せごとに、この機能がオンになるかオフになるかを示しています。リモートOS認証(TCP経由)はセキュリティ上問題があるため、デフォルトで無効にされています。
表9-1 暗号化または整合性のためのクライアント/サーバー間ネゴシエーション
| クライアント/サーバー設定のマトリックス | クライアントRejected | クライアントAccepted (デフォルト) | クライアントRequested | クライアントRequired |
|---|---|---|---|---|
|
サーバーRejected |
OFF |
OFF |
OFF |
接続に失敗 |
|
サーバーAccepted (デフォルト) |
OFF |
OFF |
ON |
ON |
|
サーバーRequested |
OFF |
ON |
ON |
ON |
|
サーバーRequired |
接続に失敗 |
ON |
ON |
ON |
表9-1が示すように、たとえば、クライアントが暗号化を要求し、サーバーが拒否した場合は、暗号化はオフになります。整合性の場合も同様です。逆に、サーバーが暗号化を要求し、クライアントが受け入れる場合は、暗号化はオンになります。整合性の場合も同様です。
関連項目:
ネットワークの暗号化および整合性の機能の詳細は、『Oracle Databaseセキュリティ・ガイド』を参照してください。ノート:
整合性パラメータ名には、まだchecksumという用語が使用されていますが、この用語はパラメータ以外では使用されません。事実上、checksumとintegrityはシノニムです。9.6.2 JDBC OCIドライバによるデータ暗号化と整合性のサポート
JDBC OCIドライバを使用している場合は、Oracleクライアントのインストールを伴うOracleクライアント設定が想定されるため、クライアントでのsqlnet.oraファイルの設定によって、すべてのOracleクライアントの場合と同様に、ネットワーク暗号化または整合性を使用可能または使用不可にし、関連するパラメータを設定できます。
ノート:
Oracle Database 12cリリース1 (12.1)以降、sqlnet.oraファイルにあるOCI固有の構成パラメータのかわりに、新しいXML構成ファイルoraaccess.xmlにある構成パラメータを使用することをお薦めします。ただし、sqlnet.oraファイル内の構成パラメータもまだサポートされています。
表9-2に、クライアント・パラメータについてまとめます。
表9-2 暗号化と整合性のためのOCIドライバ・クライアント・パラメータ
| パラメータの説明 | パラメータ名 | 可能な設定 |
|---|---|---|
|
クライアント暗号化レベル |
|
|
|
クライアント暗号化選択リスト |
|
|
|
クライアント整合性レベル |
|
|
|
クライアント整合性選択リスト |
|
|
9.6.3 JDBC Thinドライバによるデータ暗号化と整合性のサポート
JDBC Thinドライバによるネットワーク暗号化および整合性のパラメータ設定のサポートは、前の項で説明したJDBC OCIドライバ・サポートと似ています。Javaプロパティ・オブジェクトを介して対応するパラメータを設定し、データベース接続のオープン中にこれを使用できます。
データ暗号化と整合性レベルのデフォルト値は、サーバー側もクライアント側もACCEPTEDです。これにより、サーバー側とクライアント側のいずれかの接続を構成して、接続ペアに必要なセキュリティ・レベルを獲得できます。これにより、Oracleサーバーに接続する複数のOracleクライアントがある場合、すべての接続の暗号化と整合性を有効にするために、サーバー側のsqlnet.oraファイルで暗号化と整合性レベルをREQUESTEDに変更するだけでよいので、プログラムの効率性が向上します。クライアンの設定を個別に変更する必要がないので、時間と労力を節約できます。
oracle.jdbc.OracleConnectionインタフェースで定義されているJDBC Thinドライバのパラメータのリストを次に示します。
- CONNECTION_PROPERTY_THIN_NET_ENCRYPTION_LEVELパラメータ
- CONNECTION_PROPERTY_THIN_NET_ENCRYPTION_TYPESパラメータ
- CONNECTION_PROPERTY_THIN_NET_CHECKSUM_LEVELパラメータ
- CONNECTION_PROPERTY_THIN_NET_CHECKSUM_TYPESパラメータ
- CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_SERVICESパラメータ
ノート:
-
Oracle Advanced SecurityのThinドライバのサポートは、JDBCクラスのJARファイルに直接組み込まれています。そのため、国内版と輸出版で別々のバージョンはありません。輸出版には適するパラメータ設定のみを使用できます。
9.6.3.1 CONNECTION_PROPERTY_THIN_NET_ENCRYPTION_LEVELパラメータ
CONNECTION_PROPERTY_THIN_NET_ENCRYPTION_LEVELパラメータは、クライアントがサーバーとのネゴシエートに使用するセキュリティのレベルを定義します。
次の表では、このパラメータの属性について説明します:
表9-3 CONNECTION_PROPERTY_THIN_NET_ENCRYPTION_LEVELの属性
| 属性 | 値 |
|---|---|
|
パラメータ・タイプ |
String |
|
パラメータ・クラス |
静的 |
|
設定できる値 |
|
|
デフォルト値 |
|
|
構文 |
|
|
例 |
|
9.6.3.2 CONNECTION_PROPERTY_THIN_NET_ENCRYPTION_TYPESパラメータ
CONNECTION_PROPERTY_THIN_NET_ENCRYPTION_TYPESパラメータは、使用する暗号化アルゴリズムを定義します。
次の表では、このパラメータの属性について説明します:
表9-4 CONNECTION_PROPERTY_THIN_NET_ENCRYPTION_TYPESの属性
| 属性 | 説明 |
|---|---|
|
パラメータ・タイプ |
String |
|
パラメータ・クラス |
静的 |
|
設定できる値 |
AES256 (AES 256ビット・キー)、AES192 (AES 192ビット・キー)、AES128 (AES 128ビット・キー) |
|
構文 |
|
|
例 |
|
9.6.3.3 CONNECTION_PROPERTY_THIN_NET_CHECKSUM_LEVELパラメータ
CONNECTION_PROPERTY_THIN_NET_CHECKSUM_LEVELパラメータは、データ整合性のためにサーバーとネゴシエートする際のセキュリティのレベルを定義します。
次の表では、このパラメータの属性について説明します:
表9-5 CONNECTION_PROPERTY_THIN_NET_CHECKSUM_LEVELの属性
| 属性 | 説明 |
|---|---|
|
パラメータ・タイプ |
String |
|
パラメータ・クラス |
静的 |
|
設定できる値 |
|
|
デフォルト値 |
|
|
構文 |
|
|
例 |
|
9.6.3.4 CONNECTION_PROPERTY_THIN_NET_CHECKSUM_TYPESパラメータ
CONNECTION_PROPERTY_THIN_NET_CHECKSUM_TYPESパラメータは、使用するデータ整合性アルゴリズムを定義します。
次の表では、このパラメータの属性について説明します。
表9-6 CONNECTION_PROPERTY_THIN_NET_CHECKSUM_TYPESの属性
| 属性 | 説明 |
|---|---|
|
パラメータ・タイプ |
String |
|
パラメータ・クラス |
静的 |
|
設定できる値 |
SHA1 |
|
構文 |
|
|
例 |
|
9.6.3.5 CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_SERVICESパラメータ
CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_SERVICESパラメータは、使用する認証サービスを決定します。
次の表では、このパラメータの属性について説明します:
表9-7 CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_SERVICESの属性
| 属性 | 説明 |
|---|---|
|
パラメータ・タイプ |
String |
|
パラメータ・クラス |
静的 |
|
設定できる値 |
|
|
構文 |
|
|
例 |
|
9.6.4 Javaでの暗号化および整合性パラメータの設定
Javaプロパティ・オブジェクト(つまり、java.util.Propertiesのインスタンス)を使用して、JDBC Thinドライバでサポートされている、ネットワーク暗号化および整合性のパラメータを設定します。
次の例では、Javaプロパティ・オブジェクトをインスタンス化し、それを使用して表9-3の各パラメータを設定し、その後そのプロパティ・オブジェクトを使用してデータベース接続をオープンしています。
...
Properties prop = new Properties();
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_ENCRYPTION_LEVEL, "REQUIRED");
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_ENCRYPTION_TYPES, "( AES256 )");
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_CHECKSUM_LEVEL, "REQUESTED");
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_CHECKSUM_TYPES, "( SHA1 )");
OracleDataSource ods = new OracleDataSource();
ods.setConnectionProperties(prop);
ods.setURL("jdbc:oracle:thin:@localhost:5221:main");
Connection conn = ods.getConnection();
...
暗号化タイプおよびチェックサム・タイプの値は、丸カッコで囲み、リスト形式で指定できます。複数の値を指定した場合は、サーバーとクライアントの間のネゴシエーションにより、実際に使用される値が決定されます。
例
例9-3は、データベースに接続して問合せを実行する前に、ネットワーク暗号化と整合性のパラメータを設定する完成したクラスの例です。
ノート:
この例にある文字列REQUIREDは、AnoServicesクラスとServiceクラスの機能によって動的に取り出されます。この方法で文字列を取り出すことも、前の例のようにソフトウェア・コードに含めることもできます。
この例を実行する前に、sqlnet.oraファイルで暗号化を有効にする必要があります。たとえば、次のコードは、暗号化についてAES256、AES192およびAES128を、チェックサムについてはSHA1をオンにする場合の例です。
SQLNET.ENCRYPTION_SERVER = ACCEPTED SQLNET.CRYPTO_CHECKSUM_SERVER = ACCEPTED SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER = (SHA1) SQLNET.ENCRYPTION_TYPES_SERVER = (AES256, AES192, AES128)
例9-3 ネットワーク暗号化および整合性のパラメータの設定
import java.sql.*;
import java.util.Properties;
import oracle.net.ano.AnoServices;
import oracle.jdbc.*;
import oracle.jdbc.pool.*;
public class DemoAESAndSHA1
{
static final String USERNAME= "HR";
static final String PASSWORD= "hr";
static final String URL = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=5221))"
+"(CONNECT_DATA=(SERVICE_NAME=orcl)))";
public static final void main(String[] argv)
{
DemoAESAndSHA1 demo = new DemoAESAndSHA1();
try
{
demo.run();
}catch(SQLException ex)
{
ex.printStackTrace();
}
}
void run() throws SQLException
{
OracleDataSource ods = new OracleDataSource();
Properties prop = new Properties();
// We require the connection to be encrypted with either AES256 or AES192.
// If the database does not accept such a security level, then the connection attempt will fail.
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_ENCRYPTION_LEVEL, AnoServices.ANO_REQUIRED);
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_ENCRYPTION_TYPES, "( " + AnoServices.ENCRYPTION_AES256 + "," + AnoServices.ENCRYPTION_AES192 + ")");
// We also require the use of the SHA1 algorithm for network integrity checking.
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_CHECKSUM_LEVEL, AnoServices.ANO_REQUIRED);
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_CHECKSUM_TYPES, "( " + AnoServices.CHECKSUM_SHA1 + " )");
prop.setProperty("user", DemoAESAndSHA1.USERNAME);
prop.setProperty("password", DemoAESAndSHA1.PASSWORD);
ods.setConnectionProperties(prop);
ods.setURL(DemoAESAndSHA1.URL);
OracleConnection oraConn = (OracleConnection) ods.getConnection();
System.out.println("Connection created! Encryption algorithm is: " + oraConn.getEncryptionAlgorithmName() + ", network integrity algorithm is: " + oraConn.getDataIntegrityAlgorithmName());
oraConn.close();
}
}9.7 TLSのサポート
この節では、以下のトピックについて説明します。
9.7.1 JDBCによるTLSのサポートの概要
Oracle Database 23aiでは、Transport Layer Security (TLS)プロトコルがサポートされています。TLSは広く使用されている業界標準のプロトコルで、セキュアなネットワーク通信を提供します。TLSは、認証、データの暗号化およびデータの整合性を提供します。標準TCP/IPプロトコルのセキュリティ拡張で、インターネット通信に使用されます。
TLSでは、認証機能、および公開と秘密キー・ペアによる暗号化の機能を提供するのに、X.509v3標準準拠のデジタル証明書が使用されます。TLSではまた、データのプライバシと整合性を保証するために、秘密キー暗号化とデジタル署名も使用されます。TLSを介したネットワーク接続が開始されると、クライアントとサーバーでは次のようなステップを含むTLSハンドシェイクが実行されます:
-
クライアントとサーバーとの間で、使用する暗号スイートを決めるためのネゴシエーションが行われます。これには、データ転送に使用する暗号化アルゴリズムの決定も含まれます。
-
サーバーが自分の証明書をクライアントに送信し、クライアントは、その証明書が信頼できる認証機関(CA)によって署名されているかどうかを検証します。このステップにより、サーバーの身元が検証されます。
-
クライアント認証が必要な場合は、クライアントが自分自身の証明書をサーバーに送信し、サーバーは、その証明書が信頼できるCAによって署名されているかどうかを検証します。
-
クライアントとサーバーが、公開キー暗号化を使用してキー情報を交換します。この情報に基づき、双方でセッション・キーが生成されます。クライアントとサーバーとの間の以降のやりとりはすべて、このセッション・キーのセットと、ネゴシエーションにより決定した暗号スイートを使用して、暗号化/復号化されます。
TLSに関する用語
TLSのコンテキストでは、次の用語がよく使用されます:
-
証明書: 証明書とは、公開キーとエンティティをバインドする、デジタル署名付きドキュメントのことです。証明書は、公開キーが適切なエンティティに属していることを検証するために使用します。
-
認証機関: 認証機関(CA)は、デジタル署名付き証明書(他のエンティティによって使用される)を発行するエンティティです。認証局とも呼ばれます。
-
暗号スイート: 暗号スイートとは、TLS対応のネットワーク上で送信されるデータを暗号化するために使用される、暗号化アルゴリズムとキー・サイズのセットのことです。
-
秘密キー: 秘密キーは、ネットワークを介して伝送されることのない、文字どおり秘密のキーです。秘密キーは、対応する公開キーを使用して暗号化されたメッセージを復号化するために使用されます。また、証明書に署名する際にも使用されます。その証明書を検証する際には、対応する公開キーが使用されます。
-
公開キー: 公開キーとは、公開したり、電子メール・メッセージのような通常の手段で送信したりできる暗号化キーのことです。公開キーは、TLS経由で送信されるメッセージを暗号化するために使用されます。また、対応する秘密キーによって署名された証明書を検証する際にも使用されます。
-
キー・ストアまたはウォレット: ウォレットとは、資格証明の認証や署名を格納するために使用される、パスワード保護付きのコンテナのことです。ウォレット内には、TLSで必要となる、秘密キー、証明書、および信頼できる証明書が格納されます。
-
セキュリティ・プロバイダ: セキュリティに関連したいくつかの機能を提供するJava実装。プロバイダは、キーストア・ファイルのデコードを行います。
-
キーストア・サービス(KSS): Oracle Platform Securityサービスのコンポーネント。KSSを使用すると、キーストアは
kss://スキームを使用したURIとして(ファイル名ではなく)参照されます。
JavaバージョンのTLS
Java Secure Socket Extension (JSSE)は、TLSプロトコルのJavaバージョンを使用するためのフレームワークと実装を提供するものです。JSSEは、データの暗号化、サーバーとクライアントの認証、およびメッセージの整合性保持をサポートします。アプリケーション開発者が直接アプリケーションに統合できる基礎要素が提供されるため、開発者は複雑なセキュリティ・アルゴリズムやハンドシェイク・メカニズムから解放され、アプリケーション開発が簡略化されます。JSSEは、Java Development Kit (JDK) 1.4以上に統合され、TLSバージョン2.0と3.0をサポートします。
Oracle JDBCドライバでTLSを使用する前に、JavaTM Secure Socket Extension (JSSE)フレームワークをよく理解しておくことをお薦めします。
JSSE標準のApplication Program Interface(API)は、javax.net、javax.net.sslおよびjavax.security.certの各パッケージで使用できます。これらのパッケージには、ソケット、サーバー・ソケット、TLSソケットおよびTLSサーバー・ソケットを作成および構成するためのクラスが用意されています。これらのパッケージには、セキュアなHTTP接続、JDK1.1ベースのプラットフォームと互換性がある公開キー証明書API、および信頼のおける主要なマネージャ用のインタフェースも用意されています。
TLSは、Oracle Database 18cの環境においても、他のあらゆるネットワーク環境の場合と同様に機能します。
ノート:
プログラムでJSSEを使用するには、JavaTM Secure Socket Extension (JSSE)フレームワークをよく理解している必要があります。9.7.2 証明書とウォレットの管理について
Oracle Databaseサーバーは、JDBCクライアント(ThinまたはOCIのいずれか)とTLS接続を確立するために、ウォレットに格納されている自身の証明書を送信します。クライアントで証明書やウォレットが必要となるかどうかは、サーバーの構成によって決まります。
ノート:
- Oracle JDBC Thinドライバは、JSSEフレームワークを使用してTLS接続を作成します。これはデフォルトのプロバイダ(SunJSSE)を使用してTLSコンテキストを作成します。ただし、お客様独自のプロバイダを指定できます。
- サーバー上で
SSL_CLIENT_AUTHENTICATIONパラメータが設定されていないかぎり、クライアント用の証明書は不要です。
このクライアント証明書は、Oracleウォレット、Microsoft Certificate Store (MCS)、Javaキー・ストアまたはLinuxのcertsフォルダ(/etc/ssl/certs)にある場合があります。複数の証明書が存在する場合、接続用の正しいクライアント証明書は、次の2つの方法のどちらかでクライアントによってプルされます:
- 証明書別名の使用: この場合は、クライアント証明書をその別名によって一意に識別できます。Oracle Database 23aiリリース以降では、接続文字列で
SSL_CERTIFICATE_ALIASSECURITYパラメータを使用して別名を構成できます。 - 証明書拇印の使用: この場合は、クライアント証明書をその拇印によって一意に識別できます。Oracle Database 23aiリリース以降では、接続文字列で
SSL_CERTIFICATE_THUMBPRINTSECURITYパラメータを使用して拇印を設定できます。また、Easy Connect Plus URLのSSL_CERTIFICATE_THUMBPRINTパラメータ、またはCONNECTION_PROPERTY_THIN_SSL_CERTIFICATE_THUMBPRINTJDBCプロパティのどちらかを使用してそれを設定できます。
9.7.3 キーと証明書のコンテナについて
Javaクライアントは、プロバイダさえあれば、Oracleウォレット、JKS、PKCS12など複数の種類のコンテナを使用することができます。Oracleウォレットの場合、SunJSSEプロバイダによって提供されるPKCS12サポートがPKCS12のすべての機能をサポートしているわけではないため、OraclePKIプロバイダを使用する必要があります。OraclePKIプロバイダを使用するには、$ORACLE_HOME/jlibディレクトリにoraclepki.jarファイルが必要です。
9.7.4 JDBC Thinドライバを使用したTLSバージョン1.3でのデータベース接続
この項では、TLS v1.3を使用してデータベースに接続するようにOracle JDBC Thinドライバを構成するステップについて説明します。
ノート:
- JDK 8 (JDK 8u341)以降は、TLS 1.3バージョンが自動的に有効になります。
-
プロトコル・バージョンを構成せずに、JDK実装によって最も安全なプロトコル・バージョンが選択されるようにすることをお薦めします。特定のニーズにあわせてプロトコル・バージョンを選択する必要がある場合は、次のいずれかの方法で実行できます:
- 接続プロパティの使用:
CONNECTION_PROPERTY_THIN_SSL_VERSION={1.3, 1.2}を設定します - システム・プロパティの使用:
-Doracle.net.ssl_version="1.3", "1.2"を設定します - 接続記述子の使用: 接続URLで
(security=(ssl_server_dn_match=yes)(SSL_VERSION=1.3))を使用します
- 接続プロパティの使用:
関連項目:
詳細は、Oracle Database JDBC Java APIリファレンスを参照してください-
必ずJDKの最新の更新を使用します
更新されたバージョンにはTLSバージョン1.3の使用に必要なバグ修正が含まれているため、JDK 17、JDK 11またはJDK 8の最新の更新を使用します。
-
JKSファイルまたはOracle Walletを使用します
ノート:
Oracle Databaseリリース18c以降、ojdbc.propertiesという新しい構成ファイルでTLSの構成プロパティを指定できます。このファイルを使用すると、クラウドでのデータベース・サービスへの接続が容易になります。
前述のステップをすべて実行した後に問題が発生した場合、トレースをオンにして-Djavax.net.debug=allオプションを使用して問題を診断します。
9.7.5 TLS接続の自動構成
Oracle Databaseリリース18c以降、デフォルト値を使用するか、セキュリティ・プロバイダを手動で追加または更新することなく接続構成値を解決するためのプログラム・ロジックを使用することができます。次の2つの方法で構成値を解決できます。
9.7.5.1 プロバイダの解決
特定のキーストア・タイプの場合、JDBCドライバはキーストアをロードするために使用されるプロバイダ実装を解決します。これらのタイプの場合、Javaセキュリティを使用してプロバイダを登録する必要はありません。プロバイダ実装がCLASSPATHにある場合、ドライバはセキュリティ・プロバイダをインスタンス化できます。
次のキーストア・タイプは、既知のプロバイダにマップされます。
-
SSO:
oracle.security.pki.OraclePKIProvider -
KSS:
oracle.security.jps.internal.keystore.provider.FarmKeyStoreProvider
ドライバは、指定されたタイプにプロバイダが登録されていない場合にのみ、プロバイダを解決しようとします。
oraclepki.jarファイルがCLASSPATHにある場合、ドライバはOracle PKIプロバイダを次の方法で自動的にロードできます。
java –cp oraclepki.jar:ojdbc11.jar –D javax.net.ssl.keyStore=/path/to/wallet/cwallet.sso MyApp同様に、oracle.net.wallet_location接続プロパティの指定値の場合、ドライバはOracle PKIプロバイダを次の方法で自動的にロードできます。
java –cp .:oraclepki.jar:ojdbc11.jar –D oracle.net.wallet_location=file:/path/to/wallet/cwallet.sso MyAppノート:
orapkiツールによって作成されたPKCS12タイプ(ewallet.p12ファイル)の場合、orapkiツールによって作成されたPKCS12ファイルにはASN1 Key Bag要素(タイプ・コード: 1.2.840.113549.1.12.10.1.1)が含まれているため、Javaセキュリティを使用してOraclePKIProviderを登録する必要があります。Sun PKCS12実装はKey Bagタイプをサポートしていないため、ewallet.p12ファイルの読取りを試みると、エラーがスローされます。HotSpotおよびOpen JDKユーザーの場合、SunプロバイダはPKCS12プロバイダとしてバンドルされます。つまり、PKCS12プロバイダにはすでに登録済のプロバイダがあり、ドライバはこれをオーバーライドしようとしません。
9.7.5.2 キーストア・タイプ(KSS)の自動解決
JDBCドライバでは、javax.net.ssl.keyStoreおよびjavax.net.ssl.trustStoreプロパティの値に基づいて共通のキーストア・タイプを解決できるため、これらのプロパティを使用してタイプを指定する必要がなくなります。
認識済のファイル拡張子を持つキーストアまたはトラスト・ストア
認識済のファイル拡張子を持つキーストアまたはトラスト・ストアは、次のタイプにマップされます。
-
ファイル拡張子
.jksは、JKSとしてjavax.net.ssl.keyStoreTypeに解決されます。java –cp ojdbc11.jar –D javax.net.ssl.keyStore=/path/to/keystore/keystore.jks MyApp -
ファイル拡張子
.ssoは、SSOとしてjavax.net.ssl.keyStoreTypeに解決されます。java –cp ojdbc11.jar –D javax.net.ssl.keyStore=/path/to/keystore/keystore.sso MyApp -
ファイル拡張子
.p12は、PKCS12としてjavax.net.ssl.keyStoreTypeに解決されます。java –cp ojdbc11.jar –D javax.net.ssl.keyStore=/path/to/keystore/keystore.p12 MyApp -
ファイル拡張子
.pfxは、PKCS12としてjavax.net.ssl.keyStoreTypeに解決されます。java –cp ojdbc11.jar –D javax.net.ssl.keyStore=/path/to/keystore/keystore.pfx MyApp
URIを使用したキーストアまたはトラスト・ストア
キーストアまたはトラスト・ストアがkss://スキームを使用したURIである場合、KSSタイプにマップされます。
java –cp ojdbc11.jar –D javax.net.ssl.keyStore=kss://MyStripe/MyKeyStore MyAppノート:
デフォルト・タイプの解決をオーバーライドするために、javax.net.ssl.trustStoreTypeおよびjavax.net.ssl.keyStoreTypeプロパティを設定できます。
9.7.6 デフォルトのTLSコンテキストのサポート
TLS構成に対してよりきめ細やかな制御を必要とするアプリケーションの場合は、SSLContext.getDefaultメソッドによって返されるSSLContextを使用するように、JDBCドライバを構成できます。ドライバでデフォルトのSSLContextを使用するには、次のいずれかの方法を使用します。
-
javax.net.ssl.keyStore=NONE -
javax.net.ssl.trustStore=NONE
デフォルトのSSLContextを使用して、ファイルベースではないキーストア・タイプをサポートできます。このようなキーストア・タイプの一般的な例には、ハードウェアベースのスマート・カードが含まれます。load(KeyStore.LoadStoreParameter)メソッドへのプログラム的なコールを必要とするキーストア・タイプもこのカテゴリに属します。
9.7.6.1 SSLContextインスタンスのキャッシュのサポート
Oracle Databaseリリース23ai (23.6.0.0.0)以降、JDBC ThinドライバはSSLContextインスタンスのキャッシュをサポートしています。
接続でOracle DatabaseインスタンスとのTLSセッションを確立するためのSSLContextが必要な場合に、SSLConfigインスタンス(キー)を使用してSSLContextCacheが問合せされます。同じSSLConfigに対するSSLContextが存在する場合は、そのSSLContextが接続に返されます。それ以外の場合は、新しいSSLContextが作成され、キャッシュされ、接続に返されます。
SSLContextCacheには、SSLContextインスタンスに関する次の情報が格納されます:
- SSLContextの作成に使用されるファイル(キーストア、トラストストアまたはウォレット・ファイル)のフルパス
- 前述の各ファイルの最終変更時間
- SSLContextインスタンスの最終使用のタイムスタンプ
- SSLContextインスタンスの作成に使用されるプロバイダの名前
SSLContextインスタンスのキャッシュには、次の利点があります:
- Transport Layer Security (TLS)セッション再開のサポート: TLSセッションの再開は、同じSSLContextインスタンスが様々なSSLセッション(SSLEngine)の作成に使用されている場合にのみ機能します。セッション・キャッシュは、SSLContextインスタンスで保持されます。
- パフォーマンスの向上: SSLContextインスタンスをキャッシュすると、接続ごとにファイル・システムからトラストストアおよびキーストアを読み取る必要がなくなるため、パフォーマンスが向上します。同様のTLS構成を持つ接続には、同じSSLContextインスタンスを再利用できます。
SSLContextCacheのデフォルト・サイズは15です。最大許容サイズに達すると、新しいエントリを追加する前に、最も長い期間使用されていないエントリがキャッシュから削除されます。キャッシュ・サイズは、oracle.net.sslContextCacheSizeシステム・プロパティを使用して変更できます。このプロパティを0 (ゼロ)に設定すると、キャッシュは無効になります。
9.7.7 TLS接続に対するSNIサポート
Oracle Databaseリリース23ai (23.7)以降、JDBC ThinドライバはServer Name Indication (SNI)をサポートしています。SNIは、暗号化されていないホスト名をClientHelloメッセージで送信する際に使用されるTLS拡張機能です。
TLS接続の確立のたびに、リスナーとフォアグラウンド・データベース・プロセスの両方でTLSハンドシェイクを実行する必要があり、これによって全体的な接続確立時間が遅くなります。
SNIを使用してクライアントは、暗号化されていない形式のターゲット・データベース・サービスの情報をTLS ClientHelloメッセージで送信できます。リスナーはこの情報を使用して、TLSハンドシェイクを実行せずに、フォアグラウンド・データベース・プロセスにリクエストを渡します。したがって、リスナーとのTLSハンドシェイクがないため、接続の確立時間が短縮されます。
次のいずれかのオプションを使用して、SNIサポートを有効にできます:
oracle.net.useSNI接続プロパティ。たとえば:OracleDataSource ods = new OracleDataSource(); ods.setURL("jdbc:oracle:thin:@tcps://mydbhost:3484/mydbservice"); ods.setUser("myusername"); ods.setPassword(<password>); ods.setConnectionProperty(OracleConnection.CONNECTION_PROPERTY_NET_USE_SNI, "true"); Connection conn = ods.getConnection(); conn.close();- 簡易接続URL。たとえば:
jdbc:oracle:thin:@tcps://mydbhost:3484/myservice?wallet_location=mywallet&use_sni=true - 接続記述子。たとえば:
jdbc:oracle:thin:@((DESCRIPTION=(USE_SNI=TRUE)(ADDRESS=(PROTOCOL=TCPS)(HOST=mydbhost)(PORT=3484)) (CONNECT_DATA=(SERVICE_NAME=myservice))(SECURITY=(WALLET_LOCATION=mywallet)))
9.7.8 キーストア・サービスのサポート
このリリースのOracle Databaseでは、JDBCドライバでのキーストア・サービス(KSS)のサポートが導入されています。つまり、WebLogic Serverでキーストア・サービスを構成した場合、JDBCアプリケーションを既存のキーストア・サービス構成と統合できるようになりました。
ドライバは、キーストア・サービスによって管理されるキーストアをロードできます。javax.net.ssl.keyStoreプロパティまたはjavax.net.ssl.trustStoreプロパティの値がkss://のスキームのURIである場合、ドライバはキーストア・サービスからキーストアをロードします。
権限ベースの保護の場合、次のパーミッションをojdbc JARファイルに付与する必要があります。
permission KeyStoreAccessPermission "stripeName=*,keystoreName=*,alias=*", "read";この権限は、すべてのキーストアへのアクセス権を付与します。アクセス権の範囲を制限するには、アスタリスクのワイルドカード(*)を、特定のアプリケーション・ストライプおよびキーストア名と置き換えます。ドライバは、キーストアを権限付きアクションとしてロードできません。これは、KeyStoreAccessPermissionもアプリケーションのコード・ベースに付与する必要があることを意味します。
9.8 Kerberosのサポート
この項では、次の項目について説明します。
9.8.1 JDBCによるKerberosのサポートの概要
Kerberosはネットワーク経由で認証ツールと強固な暗号化ツールを提供するネットワーク認証プロトコルです。Kerberosは秘密キー暗号化を使用する方式で、全社の情報システムのセキュリティ確保を容易に実現できます。Kerberosプロトコルは強固な暗号化を使用しているため、安全でないネットワーク接続を経由しても、クライアントまたはサーバーがサーバーまたはクライアントに対して身元を証明することができます。Kerberosを使用して身元を証明したクライアントおよびサーバーは、すべての通信を暗号化して、業務においてプライバシとデータ整合性を保全することができます。
Kerberosアーキテクチャでは、Key Distribution Center (KDC)と呼ばれる信頼できる認証サービスが軸となります。Kerberos環境のユーザーおよびサービスはプリンシパルと呼ばれ、各プリンシパルはKDCと秘密鍵(パスワードなど)を共有します。プリンシパルはHRなどのユーザーの場合も、データベース・サーバーのインスタンスの場合もあります。
12cリリース1以降、Oracle DatabaseはKerberosのレルム間認証をサポートしています。取得したレルムをKerberos構成ファイルのdomain_realmsセクションに適切に追加すると、ある特定のレルム内で、別のレルムのサービスにアクセスできます。
リリース19c以降、Oracle DatabaseはKerberosの制約付き委任をサポートしています。この機能により、oracle.jdbc.OracleConnectionBuilderインタフェースに新しいメソッドOracleConnectionBuilder gssCredential(GSSCredential credential)が追加されました。このメソッドは、ユーザーのGSSCredentialを受け入れ、ドライバのKerberos認証中に委任します。
関連項目:
Oracle Database JDBC Java APIリファレンス9.8.2 Kerberosを使用するためのWindowsの構成
klist、kinitなどのツールを提供する良質なKerberosクライアントは、次のリンクの場所にあります。
http://web.mit.edu/kerberos/dist/index.html
このクライアントでは便利なGUIも提供しています。
WindowsマシンでKerberosを構成するには、次の変更を行う必要があります。
- デスクトップで「マイ コンピュータ」アイコンを右クリックします。
- 「プロパティ」を選択します。「システムのプロパティ」ダイアログ・ボックスが表示されます。
- 「詳細」タブを選択します。
- 「環境変数」をクリックします。「環境変数」ダイアログ・ボックスが表示されます。
- 「新規」をクリックして新しい利用者変数を追加します。「新しいユーザー変数」ダイアログ・ボックスが表示されます。
- 「変数名」フィールドに「
KRB5CCNAME」と入力します。 - 「変数値」フィールドに「
FILE:C:\Documents and Settings\<user_name>\krb5cc」と入力します。 - 「OK」をクリックして「新しいユーザー変数」ダイアログ・ボックスを閉じます。
- 「OK」をクリックして「環境変数」ダイアログ・ボックスを閉じます。
- 「OK」をクリックして「システムのプロパティ」ダイアログ・ボックスを閉じます。
ノート:
C:\WINDOWS\krb5.iniファイルは、krb5.confファイルと内容が同じです。
9.8.4 Kerberosを使用するコード例
次の例は、Oracle Database 23ai JDBC Thinドライバの一部であるKerberos認証機能を示しています。このデモは、次の2つの使用例を説明しています。
-
最初のシナリオでは、OSがユーザー名と資格証明をメンテナンスします。資格証明はキャッシュに格納され、ドライバは資格証明を取得してからサーバーの認証を受けようとします。この使用例はモジュール
connectWithDefaultUser()にあります。ノート:
-
デモのこの部分を実行する前に、次のコマンドを使用して、有効な資格証明を持っていることを確認してください。
> /usr/kerberos/bin/kinit client where, the password is welcome. -
次のコマンドを使用してチケットをリストします。
> /usr/kerberos/bin/klist
-
-
2番目の使用例は、アプリケーションがユーザーの資格証明を制御する事例です。これは、複数のWebユーザーが各自の資格証明を持っているアプリケーション・サーバーの場合です。この使用例はモジュール
connectWithSpecificUser()にあります。ノート:
このデモを実行するには、作業用の設定として、稼働中のKerberosサーバーと、Kerberos認証を使用するように構成されているOracle Databaseサーバーが必要です。例をコンパイルして実行するには、使用されているURLを変更する必要があります。
例9-4 Kerberos認証を使用したデータベースへの接続
import com.sun.security.auth.module.Krb5LoginModule;
import java.io.IOException;
import java.security.PrivilegedExceptionAction;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Properties;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleDriver;
import oracle.net.ano.AnoServices;
public class KerberosJdbcDemo
{
String url ="jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)"+
"(HOST=oracleserver.mydomain.com)(PORT=5221))(CONNECT_DATA=" +
"(SERVICE_NAME=orcl)))";
public static void main(String[] arv)
{
/* If you see the following error message [Mechanism level: Could not load
* configuration file c:\winnt\krb5.ini (The system cannot find the path
* specified] it's because the JVM cannot locate your kerberos config file.
* You have to provide the location of the file. For example, on Windows,
* the MIT Kerberos client uses the config file: C\WINDOWS\krb5.ini:
*/
// System.setProperty("java.security.krb5.conf","C:\\WINDOWS\\krb5.ini");
System.setProperty("java.security.krb5.conf","/home/Jdbc/Security/kerberos/krb5.conf");
KerberosJdbcDemo kerberosDemo = new KerberosJdbcDemo();
try
{
System.out.println("Attempt to connect with the default user:");
kerberosDemo.connectWithDefaultUser();
}
catch (Exception e)
{
e.printStackTrace();
}
try
{
System.out.println("Attempt to connect with a specific user:");
kerberosDemo.connectWithSpecificUser();
}
catch (Exception e)
{
e.printStackTrace();
}
}
void connectWithDefaultUser() throws SQLException
{
OracleDriver driver = new OracleDriver();
Properties prop = new Properties();
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_SERVICES,
"("+AnoServices.AUTHENTICATION_KERBEROS5+")");
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_KRB5_MUTUAL,
"true");
/* If you get the following error [Unable to obtain Principal Name for
* authentication] although you know that you have the right TGT in your
* credential cache, then it's probably because the JVM can't locate your
* cache. *
* Note that the default location on windows is "C:\Documents and Settings\krb5cc_username".
*/
// prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_KRB5_CC_NAME, /*
On Linux:
> which kinit
/usr/kerberos/bin/kinit
> ls -l /etc/krb5.conf
lrwxrwxrwx 1 root root 47 Jun 22 06:56 /etc/krb5.conf -> /home/Jdbc/Security/kerberos/krb5.conf
> kinit client
Password for client@MYORACLE.COM:
> klist
Ticket cache: FILE:/tmp/krb5cc_5088
Default principal: client@MYORACLE.COM
Valid starting Expires Service principal
11/02/06 09:25:11 11/02/06 19:25:11 krbtgt/MYORACLE.COM@MYORACLE.COM
Kerberos 4 ticket cache: /tmp/tkt5088
klist: You have no tickets cached
*/
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_KRB5_CC_NAME,
"/tmp/krb5cc_5088");
Connection conn = driver.connect(url,prop);
String auth = ((OracleConnection)conn).getAuthenticationAdaptorName();
System.out.println("Authentication adaptor="+auth);
printUserName(conn);
conn.close();
}
void connectWithSpecificUser() throws Exception
{
Subject specificSubject = new Subject();
// This first part isn't really meaningful to the sake of this demo. In
// a real world scenario, you have a valid "specificSubject" Subject that
// represents a web user that has valid Kerberos credentials.
Krb5LoginModule krb5Module = new Krb5LoginModule();
HashMap sharedState = new HashMap();
HashMap options = new HashMap();
options.put("doNotPrompt","false");
options.put("useTicketCache","false");
options.put("principal","client@MYORACLE.COM");
krb5Module.initialize(specificSubject,newKrbCallbackHandler(),sharedState,options);
boolean retLogin = krb5Module.login();
krb5Module.commit();
if(!retLogin)
throw new Exception("Kerberos5 adaptor couldn't retrieve credentials (TGT) from the cache");
// to use the TGT from the cache:
// options.put("useTicketCache","true");
// options.put("doNotPrompt","true");
// options.put("ticketCache","C:\\Documents and Settings\\user\\krb5cc");
// krb5Module.initialize(specificSubject,null,sharedState,options);
// Now we have a valid Subject with Kerberos credentials. The second scenario
// really starts here:
// execute driver.connect(...) on behalf of the Subject 'specificSubject':
Connection conn =
(Connection)Subject.doAs(specificSubject, new PrivilegedExceptionAction()
{
public Object run()
{
Connection con = null;
Properties prop = new Properties();
prop.setProperty(AnoServices.AUTHENTICATION_PROPERTY_SERVICES,
"(" + AnoServices.AUTHENTICATION_KERBEROS5 + ")");
try
{
OracleDriver driver = new OracleDriver();
con = driver.connect(url, prop);
} catch (Exception except)
{
except.printStackTrace();
}
return con;
}
});
String auth = ((OracleConnection)conn).getAuthenticationAdaptorName();
System.out.println("Authentication adaptor="+auth);
printUserName(conn);
conn.close();
}
void printUserName(Connection conn) throws SQLException
{
Statement stmt = null;
try
{
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select user from dual");
while(rs.next())
System.out.println("User is:"+rs.getString(1));
rs.close();
}
finally
{
if(stmt != null)
stmt.close();
}
}
}
class KrbCallbackHandler implements CallbackHandler
{
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException
{
for (int i = 0; i < callbacks.length; i++)
{
if (callbacks[i] instanceof PasswordCallback)
{
PasswordCallback pc = (PasswordCallback)callbacks[i];
System.out.println("set password to 'welcome'");
pc.setPassword((new String("welcome")).toCharArray());
} else
{
throw new UnsupportedCallbackException(callbacks[i],
"Unrecognized Callback");
}
}
}
}
9.8.5 Kerberosの制約付き委任のサポート
Oracle Databaseリリース19c以降では、ThinドライバでKerberosの制約付き委任の機能がサポートされています。
安全に行うため、この実装ではGSSCredentialユーティリティが使用されるようになっています。この目的のために、OracleConnectionBuilderインタフェースが、GSSCredentialオブジェクトを受け入れることができるように拡張されました。
例9-5 制約付き委任の使用
次の例では、コードに制約付き委任を実装する方法を示します:
OracleDataSource ods = new OracleDataSource();
ods.setURL(url);
ods.setConnectionProperties(prop);
con = ods.createConnectionBuilder()
.gssCredential(impersonatedGssUserCreds)
.build();
9.8.6 Kerberos認証の拡張
Oracle Databaseリリース23ai以降のKerberos認証では、KerberosLoginModuleをインスタンス化する必要や、CredentialCache内のチケット認可チケット(TGT)を使用できる必要はありません。
このリリースでは、拡張された次のKerberos認証方法を使用してOracle Databaseに接続できます。
9.8.6.1 ユーザー・プロパティとパスワード・プロパティを使用したKerberos認証
簡易認証(O5Logon)のユーザー・プロパティとパスワード・プロパティを構成するのと同じ方法でKerberosプリンシパル・プロパティとパスワード・プロパティを構成できるようになりました。JDBC Thinドライバでは、これらの値を使用して、アプリケーションのKerberosLoginModuleが初期化され、Kerberos認証の構成が簡略化されます。
PASSWORD_AUTHパラメータをKERBEROS5に設定する必要があります。oracle.jdbc.passwordAuthentication接続プロパティを使用してPASSWORD_AUTHをKERBEROS5に設定することもできます。ただし、接続文字列で指定された値のほうが優先度が高くなります。
例9-6 Kerberos認証: ユーザー・プロパティとパスワード・プロパティの使用
次の例では、Kerberosプリンシパルおよびパスワードを構成する方法を示します:
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleDriver;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class KerberosExample {
private static String KERBEROS_PRINCIPAL = "client@EXAMPLE.COM";
private static String PASSWORD = <password>;
private static String URL ="jdbc:oracle:thin:@(DESCRIPTION=(SECURITY=(PASSWORD_AUTH=KERBEROS5))(ADDRESS=(PROTOCOL=TCP)"+
"(HOST=myserver.example.com)(PORT=5221))(CONNECT_DATA=(SERVICE_NAME=orcl)))";
public static void main(String a[]) {
try{
Properties prop = new Properties();
prop.setProperty("oracle.net.authentication_services", "(KERBEROS5)");
prop.setProperty("user", KERBEROS_PRINCIPAL); // Kerberos Principal
prop.setProperty("password", PASSWORD); // Kerberos Password
OracleDriver driver = new OracleDriver();
Connection conn = driver.connect(URL, prop);
String auth = ((OracleConnection)conn).getAuthenticationAdaptorName();
System.out.println ("Authentication adaptor=" + auth);
conn.close();
}
catch(SQLException e) {
e.printStackTrace();
}
}
}9.8.6.2 JAAS構成を使用したKerberos認証
このリリースでは、JDBC接続プロパティを介してJAAS構成ファイルを指定できます。Thinドライバでは、デフォルトで、Oracle JDKにバンドルされているデフォルトのKerberosログイン・モジュール(com.sun.security.auth.module.Krb5LoginModule)が使用されます。アプリケーションにおいてこの動作をオーバーライドする必要がある場合は、JAAS構成を使用します。
次のコード例では、JAAS構成を使用してKerberos認証を構成する方法を示します:
import java.sql.Connection;
import java.util.Properties;
import oracle.jdbc.OracleDriver;
import oracle.jdbc.OracleConnection;
public class JAASKerberosAuthentication {
// Set the following properties
private final static String DB_URL = "jdbc:oracle:thin:@(DESCRIPTION=" +
"(ADDRESS=(PROTOCOL=TCP)(HOST=myserver.example.com)(PORT=5221))" +
"(CONNECT_DATA=(SERVICE_NAME=orcl)))";
private final static String KERBEROS_CONFIG_FILE = "/etc/krb5.conf";
private final static String JAAS_CONFIG_FILE_PATH = "/myworkdir/jaas.conf";
private final static String KERBEROS_LOGIN_MODULE_NAME = "kprb5module";
public static void main(String a[]) throws Exception {
// Set JAAS configuration
System.setProperty("java.security.auth.login.config",JAAS_CONFIG_FILE_PATH);
// Set Kerberos Configuration
System.setProperty("java.security.krb5.conf", KERBEROS_CONFIG_FILE);
OracleDriver driver = new OracleDriver();
Properties prop = new Properties();
prop.setProperty("oracle.net.authentication_services", "(KERBEROS5)");
prop.setProperty("oracle.net.KerberosJaasLoginModule", KERBEROS_LOGIN_MODULE_NAME);
Connection conn = driver.connect(DB_URL, prop);
String auth = ((OracleConnection) conn).getAuthenticationAdaptorName();
System.out.println("Got Connection. Authentication adaptor=" + auth);
conn.close();
}
}
前述の例では、/myworkdir/JAAS.confディレクトリ内の次のJAAS構成ファイルを使用しています:
kprb5module {
com.sun.security.auth.module.Krb5LoginModule required
doNotPrompt=true useTicketCache=true ticketCache="file:/tmp/krb5cc_5088";
};9.9 RADIUSのサポート
この項では、次の概念について説明します。
9.9.1 JDBCによるRADIUSのサポートの概要
Oracle Database 11gリリース1で、リモート認証ダイアルイン・ユーザー・サービス(RADIUS)が導入されました。RADIUSは、最も広く知られている、リモートでの認証とアクセスを可能にするクライアント/サーバー・セキュリティ・プロトコルです。Oracle Advanced Securityは、この標準をクライアント/サーバー・ネットワーク環境で使用して、RADIUSプロトコルをサポートするあらゆる認証方式の使用を可能にします。RADIUSは、トークン・カードやスマートカードなど、いろいろな認証メカニズムで使用できます。
9.9.3 RADIUSを使用するコード例
次の例は、Oracle Database 12cリリース1 (12.1)のJDBC Thinドライバに含まれている新しいRADIUS認証機能を示しています。作業用の設定として、稼働中のRADIUSサーバーと、RADIUS認証を使用するように構成されているOracle Databaseサーバーが必要です。例をコンパイルして実行するには、指定されているURLを変更する必要があります。
例9-7 RADIUS認証を使用したデータベースへの接続
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleDriver;
import oracle.net.ano.AnoServices;
public class RadiusJdbcDemo
{
String url ="jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)"+
"(HOST=oracleserver.mydomain.com)(PORT=5221))(CONNECT_DATA=" +
"(SERVICE_NAME=orcl)))";
public static void main(String[] arv)
{
RadiusJdbcDemo radiusDemo = new RadiusJdbcDemo();
try
{
radiusDemo.connect();
}
catch (Exception e)
{
e.printStackTrace();
}
}
/*
* This method attempts to logon to the database using the RADIUS
* authentication protocol.
*
* It should print the following output to stdout:
* -----------------------------------------------------
* Authentication adaptor=RADIUS
* User is:ASO
* -----------------------------------------------------
*/
void connect() throws SQLException
{
OracleDriver driver = new OracleDriver();
Properties prop = new Properties();
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_SERVICES,
"("+AnoServices.AUTHENTICATION_RADIUS+")");
// The user "aso" needs to be properly setup on the radius server with
// password "1234".
prop.setProperty("user","aso");
prop.setProperty("password","1234");
Connection conn = driver.connect(url,prop);
String auth = ((OracleConnection)conn).getAuthenticationAdaptorName();
System.out.println("Authentication adaptor="+auth);
printUserName(conn);
conn.close();
}
void printUserName(Connection conn) throws SQLException
{
Statement stmt = null;
try
{
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select user from dual");
while(rs.next())
System.out.println("User is:"+rs.getString(1));
rs.close();
}
finally
{
if(stmt != null)
stmt.close();
}
}
}9.9.4 チャレンジ・レスポンス認証のサポート
RADIUSチャレンジ・レスポンス認証は対話型認証であり、RADIUSサーバーは表示されるチャレンジへの有効なレスポンスをリクエストします。Oracle Databaseリリース23ai以降、JDBC Thinドライバはこの認証をサポートしています。
チャレンジ・レスポンス認証では、ユーザー名およびパスワードを使用して最初のレベルの認証が実行されます。次に、RADIUSサーバーは、アプリケーションが応答する必要があるアプリケーションにチャレンジを送信します。チャレンジを処理するには、特定のヒントを使用して、レスポンスの生成を実行するアプリケーションでハンドラを構成する必要があります。ヒントはバイト配列としてハンドラに提供され、バイト配列の値はRADIUSサーバーのチャレンジ・レスポンス認証の構成よって異なります。
ハンドラは次の2つの方法で構成できます。
oracle.net.radius_challenge_response_handler接続プロパティの使用ConnectionBuilder.radiusChallengeResponseHandlerメソッドの使用
oracle.net.radius_challenge_response_handler接続プロパティの使用
oracle.net.radius_challenge_response_handler接続プロパティを使用して、チャレンジを処理するクラスの完全修飾名を構成します。このハンドラ・クラスは、java.util.function.Function<byte[], byte[]>インタフェースを実装する必要があります。次の例は、oracle.net.radius_challenge_response_handler接続プロパティを使用してRADIUSチャレンジ・レスポンス認証を構成する方法を示しています。
import oracle.jdbc.OracleConnection;
import oracle.jdbc.pool.OracleDataSource;
import java.sql.SQLException;
import java.util.Properties;
import java.util.function.Function;
public class RadiusExample {
private static String USER = "myRadiusUser";
private static String PASSWORD = "myRadiusPwd";
private static String URL ="jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)"+
"(HOST=myserver.example.com)(PORT=5221))(CONNECT_DATA=(SERVICE_NAME=orcl)))";
public static void main(String a[]) {
try {
OracleDataSource ods = new OracleDataSource();
Properties prop = new Properties();
prop.setProperty("oracle.net.authentication_services", "RADIUS");
prop.setProperty("user", USER);
prop.setProperty("password", PASSWORD);
prop.setProperty("oracle.net.radius_challenge_response_handler", "MyChallengeResponseHandler");
ods.setConnectionProperties(prop);
ods.setURL(URL);
OracleConnection conn = (OracleConnection) ods.getConnection();
System.out.println("Got Connection. Authentication adaptor="+ conn.getAuthenticationAdaptorName());
conn.close();
}
catch(SQLException e) {
e.printStackTrace();
}
}
class MyChallengeResponseHandler implements Function<byte[], byte[]> {
@Override
public byte[] apply(byte[] hint) {
// TODO: use the hint to produce the challenge response
byte[] response = null;
return response;
}
}
}ConnectionBuilder.radiusChallengeResponseHandlerメソッドの使用
新しいConnectionBuilder.radiusChallengeResponseHandlerメソッドを使用してハンドラを構成できます。ハンドラ・ラムダ/インスタンスを指定するには、このメソッドを使用します。次の例は、radiusChallengeResponseHandlerメソッドを使用してRADIUSチャレンジ・レスポンス認証を構成する方法を示しています。
import oracle.jdbc.OracleConnection;
import oracle.jdbc.pool.OracleDataSource;
import java.sql.SQLException;
import java.util.Properties;
public class RadiusExample {
private static String USER = "myRadiusUser";
private static String PASSWORD = "myRadiusPwd";
private static String URL ="jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)"+
"(HOST=myserver.example.com)(PORT=5221))(CONNECT_DATA=(SERVICE_NAME=orcl)))";
public static void main(String a[]) {
try {
OracleDataSource ods = new OracleDataSource();
Properties prop = new Properties();
prop.setProperty("oracle.net.authentication_services", "RADIUS");
prop.setProperty("user", USER);
prop.setProperty("password", PASSWORD);
ods.setConnectionProperties(prop);
ods.setURL(URL);
OracleConnection conn = ods.createConnectionBuilder()
.radiusChallengeResponseHandler(RadiusExample::getResponse).build();
System.out.println("Got Connection. Authentication adaptor="+ conn.getAuthenticationAdaptorName());
conn.close();
}
catch(SQLException e) {
e.printStackTrace();
}
}
private static byte[] getResponse(byte[] hint) {
// TODO: use the hint to produce the challenge response
byte[] response = null;
return response;
}
}
9.10 ネイティブ・ネットワーク暗号化によるFIPSのサポート
Oracle Databaseリリース19c以降、JDBC Thinドライバは連邦情報処理規格(FIPS)をサポートしています。
FIPSサポートを有効にするには、CONNECTION_PROPERTY_THIN_NET_SET_FIPS_MODEを使用してください。デフォルトでは、このプロパティはfalseに設定されます。ネイティブ・ネットワーク暗号化のFIPSモードを有効にするには、trueに設定する必要があります。
ノート:
TLS接続によるFIPSでは、この構成は必要ありません。例9-8 アプリケーションでのFIPSモードの有効化
次の例は、アプリケーションでFIPSモードを有効にする方法を示しています:
import java.sql.*;
import java.util.*;
import oracle.jdbc.*;
import java.security.*;
import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;
public class TestFIPS {
static String driver = "thin";
static String protocol = "tcp";
static String user = "scott";
static String password = "<password>";
static String url = "jdbc:oracle:" + driver + ":@(DESCRIPTION=(ADDRESS=(PROTOCOL=" + protocol + ")(HOST=" +
System.getenv("HOST") + ")(PORT=3484))(CONNECT_DATA=(SERVICE_NAME=myservice.com))(SECURITY=(ENCRYPTION_CLIENT=REQUESTED)))";
public static void main(String[] args) throws Exception {
System.setProperty("org.bouncycastle.fips.approved_only", "true");
Provider bcFipsProvider = new BouncyCastleFipsProvider();
Security.insertProviderAt(bcFipsProvider, 1);
Properties props = new Properties();
props.setProperty("user", user);
props.setProperty("password", password);
props.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_SET_FIPS_MODE, "true");
show("DEBUG: Properties: " + props);
try (Connection conn = DriverManager.getConnection(url, props);) {
checkConn(conn);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void checkConn(Connection conn) throws Exception {
String sql = "select user from dual";
try (Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql);){
String user = "";
while (rs.next()) {
user = rs.getString(1);
}
show("Connect with user : " + user);
String EncryptionAlgorithmName = ((OracleConnection) conn).getEncryptionAlgorithmName();
show("Connection EncryptionAlgorithmName : " + EncryptionAlgorithmName);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void show(String msg) {
System.out.println(msg);
}
private static void doSQL(Connection conn, String sql) throws SQLException {
try (Statement stm = conn.createStatement()){
stm.execute(sql);
}
}
}9.11 JDBCでのPEMのサポート
Oracle Databaseリリース23ai (バージョン23.6)以降、JDBC ThinドライバはPEM (Privacy Enhanced Mail)ファイルをサポートしています。このファイルは、公開キーおよび証明書情報を格納および送信する際に使用できます。
oracle.net.wallet_location JDBCプロパティを使用して、PEMファイルでJDBCドライバを構成できます。PEMファイルでパスワードが使用される場合は、oracle.net.wallet_passwordプロパティも使用します。次のいくつかの例で、ドライバの構成方法を示します:
oracle.net.wallet_location=file:/<path>/ewallet.pem
oracle.net.wallet_location=(SOURCE=(METHOD=FILE)(METHOD_DATA=(DIRECTORY=/<path_to_directory>)))
oracle.net.wallet_location="data:;base64,<Base64_representation_of_the_bytes_in_ewallet.pem>"次のいずれかの方法で、接続文字列にPEMファイルの場所を設定します:
- TNS接続文字列の使用:
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=host)(PORT=5521))(CONNECT_DATA= (SERVICE_NAME=<service_name>))(SECURITY=(WALLET_LOCATION=/<mywallets>/ewallet.pem))) - EasyConnect URLの使用:
jdbc:oracle:thin:@tcps://host:port/<service_name>?wallet_location=/mywallets/ewallet.pemまたは
jdbc:oracle:thin:@tcps://host:port/servicename?wallet_location=/mywallets/
9.11.1 一元化されたPEMファイル構成
この項では、暗号化されていないPEMファイルと暗号化されたPEMファイルを使用して、PEMファイルの一元的な構成方法を説明するコード・スニペットを示します。
暗号化されていないPEMファイルの使用
暗号化されていないPEMファイルは、変更を加えずにVaultシークレットに格納し、次のJSONファイルを使用してドライバを構成できます:
{
"connect_descriptor": "...",
"user": "scott",
"password": {
"type": "ocivault",
"value": "ocid1.vaultsecret.oc1.phx.amaaaaaxxxx",
"authentication": {
"method": "OCI_INSTANCE_PRINCIPAL"
}
},
"wallet_location": {
"type": "ocivault",
"value": "ocid1.vaultsecret.oc1.phx.amaaaaY",
"authentication": {
"method": "OCI_INSTANCE_PRINCIPAL"
}
},
"jdbc": {
"oracle.jdbc.ReadTimeout": 1000,
"defaultRowPrefetch": 20,
"autoCommit": "false"
}}暗号化されたPEMファイルの使用
暗号化されたPEMファイルは、変更を加えずにVaultシークレットに格納し、次のJSNファイルを使用してドライバを構成できます:
{
"connect_descriptor": "...",
"user": "scott",
"password": {
"type": "ocivault",
"value": "ocid1.vaultsecret.oc1.phx.amaaaaaxxxx",
"authentication": {
"method": "OCI_INSTANCE_PRINCIPAL"
}
},
"wallet_location": {
"type": "ocivault",
"value": "ocid1.vaultsecret.oc1.phx.amaaaaY",
"authentication": {
"method": "OCI_INSTANCE_PRINCIPAL"
}
},
"wallet_password": {
"type": "ocivault",
"value": "ocid1.vaultsecret.oc1.phx.amabbbbaxxxx",
"authentication": {
"method": "OCI_INSTANCE_PRINCIPAL"
}
},
"jdbc": {
"oracle.jdbc.ReadTimeout": 1000,
"defaultRowPrefetch": 20,
"autoCommit": "false"
}}9.12 セキュアな外部パスワード・ストア(SEPS)のサポート
データベースへの接続にアプリケーションでパスワード資格証明を使用するような大規模なデプロイメントの場合、クライアント側のOracleウォレットを使用してこのような資格証明を格納できます。Oracle Walletは、認証およびサインインの資格証明の格納に使用されるセキュアなソフトウェア・コンテナです。
クライアント側のOracleウォレットにデータベースのパスワード資格証明を格納すると、アプリケーション・コードやバッチ・ジョブ、スクリプトにユーザー名とパスワードを埋め込む必要がなくなります。このため、スクリプトやアプリケーション・コード内にパスワードが露出する危険性が減少し、ユーザー名やパスワードを変更するたびにコードを変更する必要がなくなるため、管理が単純化されます。また、アプリケーション・コードを変更する必要がないため、これらのユーザー・アカウントに対してパスワード管理ポリシーをさらに簡単に強制適用できるようになります。
資格証明は、次の方法で格納できます:
- 接続記述子の使用:
mkstore -wrl ./client_wallet -createCredential \(DESCRIPTION=\(ADDRESS=\(PROTOCOL=tcp\) \(HOST=<servername>\)\(PORT=5560\)\)\(CONNECT_DATA=\(SERVICE_NAME=<service_name>\)\)\) <user_name> <password>JDBC URLの形式は次のとおりです:
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS(PROTOCOL=tcp)(HOST=<servername>)(PORT=5560))(CONNECT_DATA=(SERVICE_NAME=<service_name>))) - デフォルト・キーの使用:
mkstore -wrl .\walletpath -createEntry oracle.security.client.default_username <user_name> mkstore -wrl .\walletpath -createEntry oracle.security.client.default_password <password> orapkiコマンドライン・インタフェースの使用:$ orapki secretstore create_entry -wallet <wallet> -pwd <password> -default -alias oracle.security.client.default_username -secret <username> $ orapki secretstore create_entry -wallet <wallet> -pwd <password> -default -alias oracle.security.client.default_password -secret <password>
oracle.net.wallet_location接続プロパティを設定して、ウォレットの場所を指定できます。JDBCドライバは、このウォレットからユーザー名とパスワードのペアを取得できます。
ノート:
OracleウォレットをJDBCアプリケーションで開くと、セキュリティ上の理由から、ウォレット所有者(作成者)のみがアクセスできるようにウォレット・ファイルの権限が調整されます。関連項目:
-
セキュアな外部パスワード・ストアの管理方法の詳細は、Oracle Database JDBC Java APIリファレンスを参照してください
-
セキュアな外部パスワード・ストアを使用するようにクライアントを構成する方法およびそのパスワード・ストア内の資格証明を管理する方法の詳細は、『Oracle Database管理者ガイド』を参照してください。