Вы просматриваете документацию Apigee Edge .
Перейдите в документацию Apigee X.info
Симптом
Клиентское приложение получает HTTP-статус 503 с сообщением "Сервис недоступен" в ответ на запрос к API. В трассировке пользовательского интерфейса вы увидите, что в потоке целевого запроса для неудачного запроса к API указано "Получено фатальное Received fatal alert: bad_certificate .
Если у вас есть доступ к журналам обработчика сообщений, вы увидите сообщение об ошибке « Received fatal alert: bad_certificate для неудачного запроса API. Эта ошибка наблюдается в процессе установления SSL-соединения между обработчиком сообщений и бэкэнд-сервером в двухсторонней конфигурации TLS .
Сообщение об ошибке
Клиентское приложение получает следующий код ответа:
HTTP/1.1 503 Service Unavailable
Кроме того, вы можете увидеть следующее сообщение об ошибке:
{
"fault": {
"faultstring":"The Service is temporarily unavailable",
"detail":{
"errorcode":"messaging.adaptors.http.flow.ServiceUnavailable"
}
}
} Пользователи частного облака увидят следующую ошибку для конкретного запроса API в журналах обработчика сообщений /opt/apigee/var/log/edge-message-processor/system.log :
2017-10-23 05:28:57,813 org: org-name env: env-name api: apiproxy-name rev: revision-number messageid: message_id NIOThread@0 ERROR HTTP.CLIENT - HTTPClient$Context.handshakeFailed() : SSLClientChannel[C: IP address : port # Remote host: IP address : port # ]@65461 useCount=1 bytesRead=0 bytesWritten=0 age=529ms lastIO=529ms handshake failed , message: Received fatal alert: bad_certificate
Возможные причины
Возможные причины этой проблемы следующие:
| Причина | Описание | Инструкции по устранению неполадок, применимые для |
| Сертификат клиента отсутствует | В хранилище ключей, используемом в целевой конечной точке целевого сервера, отсутствует клиентский сертификат. | Пользователи частных и публичных облачных решений на периферии сети |
| Несоответствие центра сертификации | Центр сертификации конечного сертификата (первого сертификата в цепочке сертификатов) в хранилище ключей обработчика сообщений не совпадает ни с одним из центров сертификации, принимаемых бэкэнд-сервером. | Пользователи частных и публичных облачных решений на периферии сети |
Общие этапы диагностики
- Включите трассировку в пользовательском интерфейсе Edge, выполните вызов API и воспроизведите проблему.
- В результатах трассировки пользовательского интерфейса пройдите по каждому этапу и определите, где произошла ошибка. Ошибка, скорее всего, произошла в потоке целевого запроса.
- Изучите поток выполнения, в котором отображается ошибка; вы должны увидеть ошибку, как показано в приведенном ниже примере трассировки:

- Как видно на скриншоте выше, ошибка error.cause имеет вид "Получено критическое предупреждение: bad_certificate" .
- Если вы используете частное облако , следуйте приведенным ниже инструкциям:
- Идентификатор сообщения для неудачного запроса API можно получить, определив значение заголовка ошибки "
X-Apigee.Message-ID" в фазе, указанной AX в трассировке. - Найдите этот идентификатор сообщения в журнале обработчика сообщений
/opt/apigee/var/log/edge-message-processor/system.logи определите, сможете ли вы найти какую-либо дополнительную информацию об ошибке:2017-10-23 05:28:57,813 org:org-name env:env-name api:apiproxy-name rev:revision-number messageid:message_id NIOThread@0 ERROR HTTP.CLIENT - HTTPClient$Context.handshakeFailed() : SSLClientChannel[C:IP address:port # Remote host:IP address:port #]@65461 useCount=1 bytesRead=0 bytesWritten=0 age=529ms lastIO=529ms handshake failed, message: Received fatal alert: bad_certificate 2017-10-23 05:28:57,813 org:org-name env:env-name api:apiproxy-name rev:revision-number messageid:message_id NIOThread@0 ERROR HTTP.CLIENT - HTTPClient$Context.handshakeFailed() : SSLInfo: KeyStore:java.security.KeyStore@52de60d9 KeyAlias:KeyAlias TrustStore:java.security.KeyStore@6ec45759 2017-10-23 05:28:57,814 org:org-name env:env-name api:apiproxy-name rev:revision-number messageid:message_id NIOThread@0 ERROR ADAPTORS.HTTP.FLOW - RequestWriteListener.onException() : RequestWriteListener.onException(HTTPRequest@6071a73d) javax.net.ssl.SSLException: Received fatal alert: bad_certificate at sun.security.ssl.Alerts.getSSLException(Alerts.java:208) ~[na:1.8.0_101] at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1666) ~[na:1.8.0_101] at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1634) ~[na:1.8.0_101] at sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:1800) ~[na:1.8.0_101] at com.apigee.nio.NIOSelector$SelectedIterator.findNext(NIOSelector.java:496) [nio-1.0.0.jar:na] at com.apigee.nio.util.NonNullIterator.computeNext(NonNullIterator.java:21) [nio-1.0.0.jar:na] at com.apigee.nio.util.AbstractIterator.hasNext(AbstractIterator.java:47) [nio-1.0.0.jar:na] at com.apigee.nio.NIOSelector$2.findNext(NIOSelector.java:312) [nio-1.0.0.jar:na] at com.apigee.nio.NIOSelector$2.findNext(NIOSelector.java:302) [nio-1.0.0.jar:na] at com.apigee.nio.util.NonNullIterator.computeNext(NonNullIterator.java:21) [nio-1.0.0.jar:na] at com.apigee.nio.util.AbstractIterator.hasNext(AbstractIterator.java:47) [nio-1.0.0.jar:na] at com.apigee.nio.handlers.NIOThread.run(NIOThread.java:59) [nio-1.0.0.jar:na]
В журнале обработчика сообщений содержится трассировка стека для ошибки
Received fatal alert: bad_certificate, но никакой дополнительной информации, указывающей на причину этой проблемы, нет.
- Идентификатор сообщения для неудачного запроса API можно получить, определив значение заголовка ошибки "
- Для дальнейшего изучения этой проблемы вам потребуется перехватить TCP/IP-пакеты с помощью инструмента tcpdump .
- Если вы используете частное облако , то можете перехватывать TCP/IP-пакеты на бэкэнд-сервере или в обработчике сообщений. Предпочтительно перехватывать их на бэкэнд-сервере, поскольку расшифровка пакетов происходит именно там.
- Если вы используете публичное облако , то перехватывайте TCP/IP-пакеты на бэкэнд-сервере.
- После того, как вы определились с местом, где хотите перехватывать TCP/IP-пакеты, используйте приведенную ниже команду tcpdump для захвата TCP/IP-пакетов.
tcpdump -i any -s 0 host <IP address> -w <File name>
Если вы обрабатываете TCP/IP-пакеты на процессоре сообщений, используйте публичный IP-адрес бэкэнд-сервера в команде
tcpdump.Если для бэкэнд-сервера/обработчика сообщений используется несколько IP-адресов, то вам потребуется использовать другую команду tcpdump. Для получения дополнительной информации об этом инструменте и других вариантах этой команды обратитесь к документации tcpdump .
- Проанализируйте TCP/IP-пакеты с помощью инструмента Wireshark или аналогичного инструмента, с которым вы знакомы.
Вот анализ данных тестовых TCP/IP-пакетов, выполненный с помощью инструмента Wireshark:

- Сообщение №4 в приведенном выше дампе tcpdump показывает, что обработчик сообщений (источник) отправил сообщение "Client Hello" на серверную часть (получатель).
- Сообщение № 5 показывает, что серверная часть подтверждает получение сообщения Client Hello от обработчика сообщений.
- Бэкенд-сервер отправляет сообщение "Server Hello" вместе со своим сертификатом, а затем запрашивает у клиента отправку своего сертификата в сообщении №7.
- Обработчик сообщений завершает проверку сертификата и подтверждает получение сообщения ServerHello от бэкэнд-сервера в сообщении № 8.
- Обработчик сообщений отправляет свой сертификат на серверную часть в сообщении № 9.
- Серверная часть подтверждает получение сертификата обработчика сообщений в сообщении № 11.
Однако система немедленно отправляет обработчику сообщений сообщение Fatal Alert: Bad Certificate (сообщение № 12). Это указывает на то, что сертификат, отправленный обработчиком сообщений, был недействительным, и, следовательно, проверка сертификата на бэкэнд-сервере завершилась неудачей. В результате рукопожатие SSL завершилось неудачей, и соединение будет разорвано.

Теперь давайте посмотрим на сообщение № 9, чтобы проверить содержимое сертификата, отправленного обработчиком сообщений:

- Как вы можете заметить, серверная часть не получила сертификат от клиента ( длина сертификата: 0) . Следовательно, серверная часть отправляет критическое предупреждение: Неверный сертификат.
- Обычно это происходит, когда клиент, то есть обработчик сообщений (процесс на основе Java):
- В хранилище ключей отсутствует клиентский сертификат, или;
- Не удается отправить клиентский сертификат. Это может произойти, если не удается найти сертификат, выданный одним из допустимых центров сертификации бэкэнд-сервера. Это означает, что если центр сертификации конечного сертификата клиента (т.е. первого сертификата в цепочке) не совпадает ни с одним из допустимых центров сертификации бэкэнд-сервера, то обработчик сообщений не отправит сертификат.
Рассмотрим каждую из этих причин по отдельности следующим образом.
Причина: Отсутствует клиентский сертификат
Диагноз
Если в хранилище ключей, указанном в разделе SSL Info целевой конечной точки или целевого сервера, используемого в целевой конечной точке, отсутствует сертификат, то это и является причиной данной ошибки.
Выполните следующие шаги, чтобы определить, является ли это причиной:
- Определите хранилище ключей, используемое в целевой конечной точке или целевом сервере для конкретного API-прокси, выполнив следующие шаги:
- Получите имя ссылки на хранилище ключей из элемента Keystore в разделе SSLInfo в целевой конечной точке или целевом сервере.
Рассмотрим пример раздела SSLInfo в конфигурации целевой конечной точки:
<SSLInfo> <Enabled>true</Enabled> <ClientAuthEnabled>true</ClientAuthEnabled> <KeyStore>ref://myKeystoreRef</KeyStore> <KeyAlias>myKey</KeyAlias> <TrustStore>ref://myTrustStoreRef</TrustStore> </SSLInfo>
- В приведенном выше примере имя ссылки на хранилище ключей — " myKeystoreRef".
- Перейдите в пользовательский интерфейс Edge и выберите API-прокси -> Конфигурации среды.
Выберите вкладку «Ссылки» и найдите имя ссылки на хранилище ключей. Запишите имя в столбце «Ссылка» для конкретной ссылки на хранилище ключей. Это будет имя вашего хранилища ключей.

- В приведенном выше примере вы можете заметить, что myKeystoreRef содержит ссылку на "myKeystore". Следовательно, имя хранилища ключей — myKeystore.
- Получите имя ссылки на хранилище ключей из элемента Keystore в разделе SSLInfo в целевой конечной точке или целевом сервере.
- Проверьте, содержит ли это хранилище ключей сертификат, используя пользовательский интерфейс Edge или API «Список сертификатов для хранилища ключей» .
- Если хранилище ключей содержит сертификаты, перейдите к разделу «Причина: несоответствие центра сертификации» .
- Если хранилище ключей не содержит сертификата, то именно по этой причине обработчик сообщений не отправляет клиентский сертификат.
Разрешение
- Убедитесь, что правильная и полная цепочка клиентских сертификатов загружена в соответствующее хранилище ключей в обработчике сообщений.
Причина: Несоответствие центра сертификации
Как правило, когда сервер запрашивает у клиента отправку сертификата, он указывает набор принятых издателей или центров сертификации. Если издатель/центр сертификации конечного сертификата (т.е. первого сертификата в цепочке сертификатов) в хранилище ключей обработчика сообщений не совпадает ни с одним из центров сертификации, принятых бэкэнд-сервером, то обработчик сообщений (который представляет собой процесс на основе Java ) не отправит сертификат на бэкэнд-сервер.
Выполните следующие шаги, чтобы убедиться в этом:
- Вывести список сертификатов для API хранилища ключей .
- Получите подробную информацию о каждом сертификате, полученном на шаге №1 выше, используя API «Получить сертификат для хранилища ключей» .
- Запишите имя эмитента конечного сертификата (т.е. первого сертификата в цепочке сертификатов), хранящегося в хранилище ключей.
Образец сертификата листа
{ "certInfo" : [ { "basicConstraints" : "CA:FALSE", "expiryDate" : 1578889324000, "isValid" : "Yes", "issuer" : "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com", "publicKey" : "RSA Public Key, 2048 bits", "serialNumber" : "65:00:00:00:d2:3e:12:d8:56:fa:e2:a9:69:00:06:00:00:00:d2", "sigAlgName" : "SHA256withRSA", "subject" : "CN=nonprod-api.mycompany.com, OU=ITS, O=MyCompany, L=MELBOURNE, ST=VIC, C=AU", "subjectAlternativeNames" : [ ], "validFrom" : 1484281324000, "version" : 3 } ], "certName" : "nonprod-api.mycompany.com.key.pem-cert" }В приведенном выше примере эмитентом/центром сертификации является
"CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com" - Определите список разрешенных сервером издателей или центров сертификации, используя один из следующих методов:
Метод №1: Используйте команду openssl, указанную ниже:
openssl s_client -host <backend server host name> -port <Backend port#> -cert <Client Certificate> -key <Client Private Key>
Обратитесь к разделу «Допустимые имена центров сертификации клиентских сертификатов» в выводе этой команды, как показано ниже:
Acceptable client certificate CA names /C=AU/ST=VIC/L=MELBOURNE/O=MyCompany/OU=ITS/CN=nonprod-api.mycompany.com /C=AU/ST=VIC/L=MELBOURNE/O=MyCompany/OU=ITS/CN=nonprod-api.mycompany.com
Метод №2: Проверьте пакет
Certificate Requestв TCP/IP-пакетах, где серверная часть запрашивает у клиента отправку сертификата:В приведенных выше примерах TCP/IP-пакетов пакет
Certificate Request— это сообщение № 7. Обратитесь к разделу «Отличительные имена», в котором указаны допустимые центры сертификации бэкэнд-сервера.
Проверьте, совпадает ли центр сертификации, полученный на шаге №3, со списком принятых издателей или центров сертификации бэкэнд-сервера, полученным на шаге №4. В случае несоответствия обработчик сообщений не отправит клиентский сертификат на бэкэнд-сервер.
В приведенном выше примере вы можете заметить, что эмитент конечного сертификата клиента в хранилище ключей обработчика сообщений не совпадает ни с одним из принятых центров сертификации бэкэнд-сервера. Следовательно, обработчик сообщений не отправляет сертификат клиента на бэкэнд-сервер. Это приводит к сбою SSL-рукопожатия, и бэкэнд-сервер отправляет сообщение "
Fatal alert: bad_certificate".
Разрешение
- Убедитесь, что сертификат с издателем/центром сертификации, соответствующим издателю/центру сертификации конечного сертификата клиента (первого сертификата в цепочке), хранится в хранилище доверенных сертификатов бэкэнд-сервера.
- В примере, описанном в этом руководстве, для решения проблемы в хранилище доверенных сертификатов на бэкэнд-сервере был добавлен сертификат с издателем
"issuer" : "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com".
Если проблема сохраняется, перейдите к разделу «Необходимо собрать диагностическую информацию» .
Необходимо собрать диагностическую информацию.
Если проблема сохраняется даже после выполнения вышеуказанных инструкций, пожалуйста, соберите следующую диагностическую информацию. Свяжитесь со службой поддержки Apigee Edge и предоставьте её:
- Если вы являетесь пользователем публичного облака, предоставьте следующую информацию:
- Название организации
- Название среды
- Имя API-прокси
- Выполните команду curl для воспроизведения ошибки.
- Файл трассировки, отображающий ошибку.
- TCP/IP-пакеты, перехваченные на бэкэнд-сервере.
- Если вы являетесь пользователем частного облака, предоставьте следующую информацию:
- Полное сообщение об ошибке.
- Пакет API-прокси
- Файл трассировки, отображающий ошибку.
- Журналы обработчика сообщений
/opt/apigee/var/log/edge-message-processor/logs/system.log - TCP/IP-пакеты, перехваченные на бэкэнд-сервере или в обработчике сообщений.
- Результат выполнения команды Get cert for keystore API .
- Пожалуйста, укажите, какие разделы этого руководства вы уже пробовали, а также любые другие замечания, которые помогут нам ускорить решение этой проблемы.