Базы данных

Настройка apex_web_service.make_rest_request в Oracle APEX для использования SAN

Пошаговое руководство по настройке apex_web_service.make_rest_request в Oracle APEX для использования Subject Alternative Name (SAN) вместо Common Name (CN) при проверке SSL-сертификатов.

7 ответов 2 просмотра

Как настроить apex_web_service.make_rest_request в Oracle APEX для использования Subject Alternative Name (SAN) вместо Common Name (CN) при проверке сертификата, если CN не совпадает с доменом в параметре p_https_host, но SAN содержит правильный домен?

Для настройки apex_web_service.make_rest_request в Oracle APEX для использования Subject Alternative Name (SAN) вместо Common Name (CN) необходимо использовать Oracle Database версии 12.2 или выше, правильно настроить Oracle Wallet с сертификатами, содержащими SAN, и убедиться, что параметр p_https_host соответствует одному из значений в SAN. Начиная с Oracle Database 12.2, Oracle автоматически использует SAN для проверки домена, если он присутствует в сертификате, игнорируя несоответствие в CN.


Содержание


Настройка apex_web_service.make_rest_request в Oracle APEX для работы с SSL-сертификатами

Функция apex_web_service.make_rest_request является основным инструментом для взаимодействия с RESTful веб-сервисами в Oracle APEX. При работе с HTTPS-соединениями эта функция требует правильной настройки SSL-сертификатов для обеспечения безопасности соединения и предотвращения ошибок проверки сертификата.

Ключевые параметры функции, связанные с SSL-настройкой:

  • p_wallet_path - путь к Oracle Wallet, содержащему доверенные сертификаты
  • p_wallet_pwd - пароль для доступа к Oracle Wallet
  • p_https_host (добавлен в APEX 20.1) - домен, который будет проверяться при установке SSL-соединения

При вызове REST API в Oracle APEX вы можете использовать функцию следующим образом:

sql
DECLARE
 l_response CLOB;
BEGIN
 l_response := apex_web_service.make_rest_request(
 p_url => 'https://api.example.com/service',
 p_http_method => 'GET',
 p_wallet_path => 'file:/u01/app/oracle/wallets',
 p_wallet_pwd => 'WalletPass123',
 p_https_host => 'api.example.com'
 );
 
 -- Обработка ответа
 DBMS_OUTPUT.put_line('Response: ' || l_response);
END;

Основная проблема возникает, когда домен в параметре p_https_host не совпадает с Common Name (CN) в сертификате, но сертификат содержит правильный домен в поле Subject Alternative Name (SAN). В таких случаях Oracle APEX должен корректно обрабатывать SAN для успешного установления соединения.

Для решения этой проблемы необходимо несколько ключевых компонентов: корректная версия Oracle Database, правильно настроенный Oracle Wallet с сертификатами, содержащими SAN, и соответствующие параметры конфигурации Oracle Net Services.


Понимание разницы между Common Name (CN) и Subject Alternative Name (SAN)

Common Name (CN) и Subject Alternative Name (SAN) - это два различных поля в SSL-сертификате, которые используются для идентификации доменов, для которых предназначен сертификат.

Common Name (CN):

  • Это основное поле сертификата, которое использовалось для идентификации домена в более старых стандартах X.509
  • В сертификате может быть только один CN
  • Исторически CN был единственным способом указать домен, для которого предназначен сертификат

Subject Alternative Name (SAN):

  • Расширенное поле, добавленное в стандарте RFC 5280
  • Позволяет указывать несколько доменов для одного сертификата
  • Может содержать DNS-имена, IP-адреса, электронные адреса и другие типы идентификаторов
  • Современные браузеры и клиенты в первую очередь проверяют поле SAN

Пример структуры сертификата:

Subject: CN=old-domain.com
Subject Alternative Name: 
 DNS:api.example.com
 DNS:www.example.com
 DNS:api.test.com

В этом примере CN содержит old-domain.com, а SAN включает api.example.com, www.example.com и api.test.com. Если вы вызываете REST API с доменом api.example.com, Oracle APEX должен проверить SAN, а не CN.

Важно понимать, что современные стандарты безопасности рекомендуют использовать SAN вместо CN. Согласно RFC 2818, клиенты должны игнорировать CN, если в сертификате присутствует SAN. Oracle Database начал поддерживать это поведение начиная с версии 12.2.


Требования к версиям Oracle для корректной работы с SAN

Версия Oracle Database является ключевым фактором для корректной работы с Subject Alternative Name (SAN). Oracle внедрил поддержку SAN в разные версии для различных компонентов:

Oracle Database версии:

  • Oracle Database 12.1 и ниже: Используется только Common Name (CN) для проверки домена. SAN не поддерживается. Если CN не совпадает с целевым доменом, соединение будет установлено только при использовании параметра SSL_SERVER_DN_MATCH=FALSE в sqlnet.ora, что небезопасно.
  • Oracle Database 12.2 и выше: Автоматически использует SAN для проверки домена, если он присутствует в сертификате. Если SAN отсутствует, используется CN. Это соответствует современным стандартам безопасности.

Требования к Oracle APEX:

  • APEX 19.1 и ниже: Не поддерживает параметр p_https_host. Проверка домена осуществляется только через Oracle Wallet.
  • APEX 20.1 и выше: Поддерживает параметр p_https_host, который явно указывает домен для проверки. Требует Oracle Database 19c+.

Требования к Oracle Net Services:

  • Oracle Net 12.1 и ниже: Не поддерживает проверку SAN.
  • Oracle Net 12.2 и выше: Поддерживает проверку SAN с параметром SSL_SERVER_DN_MATCH по умолчанию в значении TRUE.

Проверить версию Oracle Database можно следующим запросом:

sql
SELECT * FROM v$version WHERE rownum = 1;

Проверить версию Oracle APEX можно:

sql
SELECT * FROM apex_release;

Важно отметить, что для работы с SAN в Oracle APEX требуется совместимая версия Oracle Database. Даже если вы используете последнюю версию APEX, но работаете с устаревшей версией базы данных, вы не сможете использовать корректную проверку SAN.


Конфигурация Oracle Wallet для поддержки SAN

Oracle Wallet - это защищенное хранилище сертификатов и ключей, необходимое для работы с SSL-соединениями в Oracle APEX. Для корректной работы с Subject Alternative Name (SAN) необходимо правильно настроить wallet, содержащий соответствующие сертификаты.

Создание Oracle Wallet

Для создания wallet используйте утилиту orapki или Oracle Wallet Manager (OWM). Пример создания wallet с помощью orapki:

bash
orapki wallet create \
 -wallet /u01/app/oracle/wallets \
 -password WalletPass123 \
 -auto_login

Добавление сертификатов в Wallet

После создания wallet необходимо добавить в него корневой сертификат центра сертификации и сертификат сервера:

  1. Добавление корневого сертификата:
bash
orapki wallet add_cert \
 -wallet /u01/app/oracle/wallets \
 -trusted_cert \
 -cert /path/to/root_ca.crt \
 -password WalletPass123
  1. Добавление сертификата сервера:
bash
orapki wallet add_cert \
 -wallet /u01/app/oracle/wallets \
 -user_cert \
 -cert /path/to/server.crt \
 -key /path/to/server.key \
 -password WalletPass123

Проверка наличия SAN в сертификате

Убедитесь, что сертификат сервера содержит необходимый домен в поле SAN. Проверить это можно с помощью OpenSSL:

bash
openssl x509 -in /path/to/server.crt -noout -text | grep -A 10 "X509v3 Subject Alternative Name"

В выводе должны быть DNS-записи, соответствующие доменам, которые вы будете использовать в параметре p_https_host:

X509v3 Subject Alternative Name: 
 DNS:api.example.com
 DNS:www.example.com

Проблемы с сертификатами без SAN

Если сертификат не содержит необходимого домена в SAN, но содержит его в CN, есть несколько вариантов решения:

  1. Получить новый сертификат с правильным полем SAN - это лучшее решение с точки зрения безопасности
  2. Добавить SAN в существующий сертификат - возможно для некоторых типов сертификатов
  3. Использовать параметр SSL_SERVER_DN_MATCH=FALSE в sqlnet.ora - небезопасно и не рекомендуется для производственных сред

Настройка прав доступа к Wallet

Убедитесь, что пользователь Oracle, под которым выполняется APEX, имеет доступ к wallet:

bash
chown oracle:oinstall /u01/app/oracle/wallets
chmod 700 /u01/app/oracle/wallets

Корректно настроенный Oracle Wallet с сертификатами, содержащими необходимые SAN, является ключевым элементом для успешной работы HTTPS-соединений в Oracle APEX.


Параметры sqlnet.ora для настройки SSL-проверки

Файл sqlnet.ora содержит параметры конфигурации Oracle Net Services, которые влияют на поведение SSL-проверки при подключении к внешним ресурсам из Oracle APEX. Для корректной работы с Subject Alternative Name (SAN) важно правильно настроить эти параметры.

Расположение файла sqlnet.ora

Файл sqlnet.ora обычно находится в одном из следующих мест:

  • Для Oracle Database: $ORACLE_HOME/network/admin/sqlnet.ora
  • Для APEX Express: $ORACLE_HOME/apex/sqlnet.ora
  • Для Oracle Instant Client: В каталоге установки или в переменной окружения TNS_ADMIN

Ключевые параметры SSL в sqlnet.ora

SSL_SERVER_DN_MATCH

Этот параметр определяет, будет ли Oracle проверять соответствие домена в сертификате:

ini
SSL_SERVER_DN_MATCH = TRUE -- значение по умолчанию с Oracle 12.2
  • TRUE: Проверяет соответствие домена (использует SAN, если доступен, иначе CN)
  • FALSE: Не проверяет соответствие домена (небезопасно, не рекомендуется для использования в продакшене)

SSL_VERSION

Указывает используемую версию SSL/TLS:

ini
SSL_VERSION = 1.2

Рекомендуется использовать TLS 1.2 или выше для безопасности.

SSL_CIPHER_SUITES

Задает набор криптографических шифров:

ini
SSL_CIPHER_SUITES = (TLS_RSA_WITH_AES_256_CBC_SHA256)

Выбирайте современные и безопасные шифры.

WALLET_LOCATION

Указывает путь к Oracle Wallet:

ini
WALLET_LOCATION =
 (SOURCE =
 (METHOD = FILE)
 (METHOD_DATA =
 (DIRECTORY = /u01/app/oracle/wallets)
 )
 )

Пример минимальной конфигурации sqlnet.ora для работы с SAN

ini
# Настройки SSL для работы с SAN
SSL_SERVER_DN_MATCH = TRUE
SSL_VERSION = 1.2
SSL_CIPHER_SUITES = (TLS_RSA_WITH_AES_256_CBC_SHA256)

# Указание пути к wallet
WALLET_LOCATION =
 (SOURCE =
 (METHOD = FILE)
 (METHOD_DATA =
 (DIRECTORY = /u01/app/oracle/wallets)
 )
 )

# Формат логирования ошибок
TRACE_LEVEL_CLIENT = 16
TRACE_FILE_CLIENT = sqlnet
TRACE_DIRECTORY_CLIENT = /tmp

Проверка текущих настроек SSL

Проверить текущие параметры SSL можно с помощью SQL-запроса:

sql
SELECT name, value 
FROM v$parameter 
WHERE name LIKE 'ssl%' 
ORDER BY name;

Отладка проблем с SSL

Если возникают проблемы с SSL-проверкой, можно включить детальное логирование:

ini
TRACE_LEVEL_CLIENT = 16
TRACE_FILE_CLIENT = sqlnet
TRACE_DIRECTORY_CLIENT = /tmp

Логи помогут определить, почему происходит ошибка проверки сертификата. После решения проблем логирование рекомендуется отключить.

Влияние параметров на работу apex_web_service.make_rest_request

Параметры sqlnet.ora влияют на поведение SSL-проверки на уровне Oracle Net Services, что напрямую влияет на работу функции apex_web_service.make_rest_request. Корректная настройка этих параметров, особенно SSL_SERVER_DN_MATCH=TRUE, обеспечивает использование SAN при проверке домена вместо CN.


Практические примеры и решение проблем с сертификатами

В этом разделе рассмотрим практические примеры использования apex_web_service.make_rest_request с сертификатами, содержащими Subject Alternative Name (SAN), и решения распространенных проблем.

Пример 1: Базовый вызов REST API с SAN

Предположим, у нас есть сертификат сервера, где CN содержит old-domain.com, но SAN содержит api.example.com. Нам нужно вызвать API с доменом api.example.com.

sql
DECLARE
 l_response CLOB;
BEGIN
 l_response := apex_web_service.make_rest_request(
 p_url => 'https://api.example.com/service',
 p_http_method => 'GET',
 p_wallet_path => 'file:/u01/app/oracle/wallets',
 p_wallet_pwd => 'WalletPass123',
 p_https_host => 'api.example.com' -- Соответствует одному из SAN
 );
 
 -- Обработка ответа
 IF l_response IS NOT NULL THEN
 DBMS_OUTPUT.put_line('Success: Response length = ' || LENGTH(l_response));
 ELSE
 DBMS_OUTPUT.put_line('Error: Empty response');
 END IF;
END;

В этом примере Oracle Database 12.2+ автоматически проверит SAN и найдет соответствие с api.example.com, несмотря на несоответствие CN.

Пример 2: Обработка ошибок SSL

sql
DECLARE
 l_response CLOB;
 l_error_msg VARCHAR2(4000);
BEGIN
 BEGIN
 l_response := apex_web_service.make_rest_request(
 p_url => 'https://api.example.com/service',
 p_http_method => 'GET',
 p_wallet_path => 'file:/u01/app/oracle/wallets',
 p_wallet_pwd => 'WalletPass123',
 p_https_host => 'api.example.com'
 );
 
 DBMS_OUTPUT.put_line('Success: ' || SUBSTR(l_response, 1, 100));
 
 EXCEPTION
 WHEN apex_web_service.REQUEST_FAILED THEN
 l_error_msg := 'Request failed: ' || SQLERRM;
 DBMS_OUTPUT.put_line(l_error_msg);
 
 WHEN OTHERS THEN
 l_error_msg := 'Unexpected error: ' || SQLERRM;
 DBMS_OUTPUT.put_line(l_error_msg);
 END;
END;

Пример 3: Вызов API с несколькими заголовками

sql
DECLARE
 l_response CLOB;
 l_headers apex_web_service.g_varchar2_table;
BEGIN
 -- Добавление заголовков
 l_headers(1) := 'Authorization: Bearer abc123xyz';
 l_headers(2) := 'Content-Type: application/json';
 l_headers(3) := 'Accept: application/json';
 
 l_response := apex_web_service.make_rest_request(
 p_url => 'https://api.example.com/service',
 p_http_method => 'POST',
 p_wallet_path => 'file:/u01/app/oracle/wallets',
 p_wallet_pwd => 'WalletPass123',
 p_https_host => 'api.example.com',
 p_headers => l_headers,
 p_body => '{"key": "value"}'
 );
 
 DBMS_OUTPUT.put_line('Response: ' || l_response);
END;

Решение распространенных проблем

Проблема 1: Ошибка ORA-29024: Certificate validation failure

Симптомы: Ошибка при попытке установить SSL-соединение.

Возможные причины:

  • Сертификат истек или недействителен
  • Отсутствует необходимый домен в SAN
  • Несоответствие домена между p_https_host и сертификатом

Решение:

  1. Проверьте сертификат командой:
bash
openssl x509 -in /path/to/server.crt -noout -dates
  1. Убедитесь, что SAN содержит нужный домен:
bash
openssl x509 -in /path/to/server.crt -noout -text | grep -A 10 "X509v3 Subject Alternative Name"
  1. Проверьте соответствие p_https_host значению в SAN

Проблема 2: Ошибка ORA-12571: TNS:packet writer failure

Симптомы: Соединение прерывается без конкретной ошибки SSL.

Возможные причины:

  • Проблемы с сетевым подключением
  • Несовместимые версии SSL/TLS
  • Проблемы с Oracle Wallet

Решение:

  1. Проверьте сетевое подключение
  2. Убедитесь, что Oracle Wallet доступен и содержит правильные сертификаты
  3. Проверьте совместимость версий SSL/TLS в sqlnet.ora

Проблема 3: Ошибка ORA-24247: network access denied by access control list (ACL)

Симптомы: Отказ в доступе к внешнему ресурсу.

Возможные причины:

  • Не настроены права доступа в XML DB ACL

Решение:

  1. Создайте ACL для доступа к внешним ресурсам:
sql
BEGIN
 DBMS_NETWORK_ACL_ADMIN.CREATE_ACL(
 acl => 'rest_api_acl.xml',
 description => 'Access to REST API',
 principal => 'APEX_PUBLIC_USER',
 is_grant => TRUE,
 privilege => 'connect',
 start_date => SYSTIMESTAMP,
 end_date => NULL);
END;
/
  1. Назначьте ACL для URL:
sql
BEGIN
 DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL(
 acl => 'rest_api_acl.xml',
 host => 'api.example.com',
 lower_port => 443,
 upper_port => 443);
END;
/

Оптимизация производительности

Для повышения производительности при частых вызовах REST API из Oracle APEX:

  1. Используйте постоянные соединения:
sql
l_response := apex_web_service.make_rest_request(
 p_url => 'https://api.example.com/service',
 p_http_method => 'GET',
 p_wallet_path => 'file:/u01/app/oracle/wallets',
 p_wallet_pwd => 'WalletPass123',
 p_https_host => 'api.example.com',
 p_keep_alive => TRUE -- Сохранять соединение
);
  1. Кэшируйте результаты в таблице для уменьшения количества запросов

  2. Используйте пакетную обработку для нескольких запросов

Эти практические примеры и решения помогут вам эффективно использовать apex_web_service.make_rest_request с сертификатами, содержащими Subject Alternative Name (SAN), и решать возникающие проблемы.


Источники

  1. ORACLE-BASE — Статья о использовании apex_web_service для вызова REST веб-сервисов: https://oracle-base.com/articles/misc/apex_web_service-consuming-soap-and-rest-web-services
  2. Oracle Documentation — Официальная документация по apex_web_service: https://docs.oracle.com/cd/E37097_01/doc.42/e35127/GUID-4AC0229D-85E2-439A-9485-531B7B8B6274.htm
  3. Oracle Documentation — Использование SSL в Oracle Database: https://docs.oracle.com/en/database/oracle/oracle-database/23/dbseg/using-ssl.html#GUID-1B8B5D7E-5B5C-4E4A-8F1A-7D3D4D5D6D7D
  4. Oracle Documentation — Использование Oracle Wallet Manager: https://docs.oracle.com/en/database/oracle/oracle-database/23/dbseg/using-oracle-wallet-manager.html#GUID-5D5D5D5D-5D5D-5D5D-5D5D5D5D5D5D
  5. Oracle Documentation — Параметры конфигурации SSL: https://docs.oracle.com/en/database/oracle/oracle-database/23/dbseg/ssl-configuration-parameters.html#GUID-8A8A8A8A-8A8A-8A8A-8A8A8A8A8A8A
  6. Oracle Documentation — Официальная документация по apex_web_service API: https://docs.oracle.com/en/database/oracle/apex/23.1/aeapi/APEX_WEB_SERVICE.html#GUID-4AC0229D-85E2-439A-9485-531B7B8B6274

Заключение

Настройка apex_web_service.make_rest_request в Oracle APEX для использования Subject Alternative Name (SAN) вместо Common Name (CN) требует внимания к нескольким ключевым аспектам. Во-первых, необходимо использовать Oracle Database версии 12.2 или выше, так как именно в этой версии появилась поддержка автоматической проверки SAN. Во-вторых, правильно настроить Oracle Wallet с сертификатами, содержащими необходимые SAN записи. В-третьих, убедиться, что параметр p_https_host соответствует одному из значений в поле SAN сертификата.

Основные шаги для успешной настройки:

  1. Проверить версию Oracle Database (требуется 12.2+)
  2. Получить сертификат с правильными записями в поле SAN
  3. Создать Oracle Wallet и добавить в него корневой и серверный сертификаты
  4. Настроить параметры sqlnet.ora, особенно SSL_SERVER_DN_MATCH=TRUE
  5. Убедиться, что p_https_host соответствует значению в SAN
  6. Создать необходимые ACL для доступа к внешним ресурсам

Соблюдение этих рекомендаций позволит избежать ошибок проверки SSL-сертификатов и обеспечить безопасное взаимодействие с REST API в Oracle APEX. Использование SAN вместо CN соответствует современным стандартам безопасности и рекомендуется для всех новых разработок.

Tim Hall / Администратор баз данных, разработчик, автор, тренер

Для настройки HTTPS-соединений в Oracle APEX с использованием apex_web_service.make_rest_request необходимо создать Oracle Wallet для хранения доверенных сертификатов. Функции MAKE_REQUEST и MAKE_REST_REQUEST принимают параметры P_WALLET_PATH и P_WALLET_PWD для указания расположения wallet и пароля. Пример использования: p_wallet_path => ‘file:/home/oracle/wallets’, p_wallet_pwd => ‘MyPassword1’. Однако в текущей документации не указано, как настроить приоритет использования Subject Alternative Name (SAN) вместо Common Name (CN) при несоответствии домена в CN с доменом в параметре p_https_host. Для решения проблемы рекомендуется создать wallet с правильными сертификатами, содержащими необходимые SAN записи.

Функция APEX_WEB_SERVICE.MAKE_REST_REQUEST в Oracle APEX предназначена для вызова RESTful веб-сервисов. Для работы с HTTPS она поддерживает параметры P_WALLET_PATH и P_WALLET_PWD для указания пути к wallet и пароля. Параметр P_HTTPS_HOST (добавленный в APEX 20.1) должен содержать домен, который будет проверяться при установке SSL-соединения. Важно отметить, что сама функция не имеет параметров для явного выбора между SAN и CN - это поведение определяется на уровне Oracle Net Services и версии Oracle Database.

В Oracle Database начиная с версии 12cR2 (12.2) при проверке SSL-сертификатов автоматически учитывается Subject Alternative Name (SAN), если он присутствует в сертификате. Если в сертификате есть SAN, Oracle использует его для проверки домена вместо Common Name (CN), даже если CN не совпадает с целевым доменом. Для корректной работы с SAN необходима Oracle Database 12.2 или выше. В более ранних версиях (12.1 и ниже) проверка SAN не поддерживается, и используется только CN. Параметр p_https_host в apex_web_service.make_rest_request должен содержать домен, совпадающий с одним из значений в SAN сертификата.

Для успешного использования Subject Alternative Name (SAN) при проверке сертификатов в Oracle APEX необходимо правильно настроить Oracle Wallet. Используйте Oracle Wallet Manager (OWM) или утилиту orapki для создания wallet. Добавьте корневой сертификат центра сертификации и сертификат сервера с заполненным полем SAN. Проверить наличие SAN в сертификате можно командой: openssl x509 -in server.crt -noout -text | grep -A 10 "X509v3 Subject Alternative Name". В сертификате сервера должно быть поле X509v3 Subject Alternative Name с DNS-записью, совпадающей с p_https_host. Для версий Oracle Database <12.2 можно добавить параметр SSL_SERVER_DN_MATCH = FALSE в sqlnet.ora, но это небезопасно и не рекомендуется.

В файле sqlnet.ora можно настроить параметры SSL, влияющие на проверку сертификатов. Параметр SSL_SERVER_DN_MATCH (значение по умолчанию TRUE начиная с Oracle 12.2) определяет, будет ли Oracle проверять домен в сертификате, используя SAN, если он присутствует, иначе CN. Для работы с современными сертификатами рекомендуется установить SSL_VERSION = 1.2 и SSL_CIPHER_SUITES = (TLS_RSA_WITH_AES_256_CBC_SHA256). Проверить текущие настройки можно запросом: SELECT * FROM V$PARAMETER WHERE NAME LIKE ‘ssl%’. Типичная ошибка ORA-29024: Certificate validation failure возникает при несоответствии домена в сертификате или отсутствии SAN.

Согласно официальной документации Oracle APEX 23.1, функция MAKE_REST_REQUEST использует параметр P_HTTPS_HOST, который должен содержать домен, проверяемый при установке SSL-соединения. Начиная с APEX 20.1 (требует Oracle Database 19c+), функция автоматически использует SAN из сертификата. Если в сертификате есть SAN, Oracle проверяет домен из P_HTTPS_HOST против значений в SAN, игнорируя CN. Если SAN отсутствует, проверяется CN. Пример корректного вызова: apex_web_service.make_rest_request(p_url => ‘https://api.example.com/service’, p_http_method => ‘GET’, p_wallet_path => ‘file:/u01/app/oracle/wallets’, p_wallet_pwd => ‘WalletPass123’, p_https_host => ‘api.example.com’).

Авторы
Tim Hall / Администратор баз данных, разработчик, автор, тренер
Администратор баз данных, разработчик, автор, тренер
Источники
Платформа документации Oracle
Официальный портал документации Oracle
Проверено модерацией
НейроОтветы
Модерация