Вызовы Apex уходят из Salesforce, а не из вашего VPN
VPN на ноутбуке даёт браузеру путь, но не Apex или Marketing Cloud. Сопоставьте реального вызывающего с публичным шлюзом или квалифицированным частным подключением.
Частный API отвечает в браузере в тот момент, когда ноутбук подключается к VPN, поэтому интеграция должна работать. Она не работает, потому что код, выполняющий вызов, запускается совсем в другом месте. Apex выполняется на серверах приложений Salesforce, а серверная активность в Marketing Cloud — в среде выполнения этого продукта. Ни то, ни другое не наследует туннель вашего ноутбука. Выполните это как короткую процедуру: определите вызывающего, выберите вход, до которого этот вызывающий может добраться, соедините путь от начала до конца, а затем проверьте из самой среды выполнения.
Напишите карточку вызывающего до любого изменения сети
Заполните пять полей и откажитесь угадывать любое из них. Продукт исполнения и контекст определяют всё дальнейшее, поэтому начинайте оттуда, а не с межсетевого экрана сервера.
| Field | What it must answer |
|---|---|
| Runtime | Which product and execution context issues the request? |
| Endpoint | Which hostname must that runtime resolve, and to what? |
| Path | Which supported public entry or private connection carries it? |
| Identity | Which credential and which operation is the API asked to authorize? |
| Failure | How do responses return, and what happens when the path is down? |
Вкладка браузера и вызов Apex — два разных клиента, и работающий браузер доказывает лишь то, что путь существует с вашего рабочего стола. Если поле среды выполнения говорит Apex, уместный вопрос — с каких адресов выходит Salesforce, а не какие адреса есть у вашего ноутбука. Поэтому туннель, который позволяет API загрузиться в браузере, может оставить интеграцию падающей с тем же тайм-аутом, что и раньше. Карточка вызывающего нужна, чтобы остановить эту ошибку до того, как кто-то отредактирует межсетевой экран.
Выберите вход, которым вызывающий действительно может пользоваться
Оба варианта законны и решают разные задачи. Первый — намеренный публичный вход: шлюз API по HTTPS или интеграционный сервис, который аутентифицирует вызывающего, применяет узкие разрешения и держит защищённое подключение к частному backend. Это не то же самое, что выставить каждый сервис backend или пробросить порт управления в интернет.
Второй — квалифицированное частное подключение. Документация Salesforce по исходящему Private Connect описывает маршрутизацию поддерживаемых вызовов через Outbound Network Connection, привязанное к именованным учётным данным, согласно определённой схеме AWS PrivateLink. У функции есть ограничения по редакции, лицензии и продукту, поэтому подтвердите соответствие организации, прежде чем проектировать вокруг неё.
Ни один из вариантов не является клиентом OpenVPN, установленным внутри Salesforce, и старое утверждение, будто каждая интеграция обязана достигать публичного backend, слишком широко там, где подходит поддерживаемое частное подключение. Выберите то, что поддерживает среда выполнения, и затем доведите путь до реального API: конечная точка AWS не знает ваш локальный ресурс и не наследует маршрут ноутбука. DNS, маршрутизация backend, политика доступа и обратный трафик должны следовать выбранной архитектуре. Недоделанный частный путь отказывает так, что это выглядит в точности как проблема аутентификации.
Соедините частный путь от начала до конца
Двигайтесь от API наружу и остановитесь на первом разрыве. Подтвердите, что backend отвечает локально, затем что частная конечная точка до него доходит, а затем что именованные учётные данные и их исходящее подключение нацелены на эту конечную точку.
curl -sS -m 5 -o /dev/null -w '%{http_code}\n' http://10.40.8.20:8080/health
dig +short api.partner.example
sf apex run --file scripts/apex/callout-check.apex --target-org integrationПервая команда доказывает, что backend здоров изнутри частной сети, вторая показывает, во что разрешается имя, а третья выполняет вызов из реальной среды выполнения Salesforce. 200 от первой и сбой от третьей локализуют разрыв в пути или учётных данных, а не в сервисе.
Держите область идентичности точной во время подключения. Именованные учётные данные сами не исправляют недоступную конечную точку, потому что учётные данные и частное подключение — связанные настройки с разными задачами. Список разрешённых IP сужает сетевой допуск и не является учётными данными API, поэтому сохраняйте обычную проверку TLS и собственный процесс аутентификации и ротации сервиса. Если тест проходит только после отключения проверки сертификата, вы нашли проблему имени хоста, а не пути, и сертификат всё равно должен совпадать.
Проверьте из среды выполнения, затем запишите откат
Примите безвредный разрешённый запрос из среды выполнения интеграции, а не со своей машины. Запишите наблюдённый источник принимающего сервиса, аутентифицированный субъект, результат и один намеренно отклонённый запрос, который должен завершиться неудачей.
curl -sS -o /dev/null -w '%{http_code} %{remote_ip}\n' https://api.partner.example/v1/ping
curl -sS -o /dev/null -w '%{http_code}\n' -H 'Authorization: Bearer invalid' https://api.partner.example/v1/pingВыполните те же две проверки из собственной сети backend, чтобы наблюдённый источник можно было сравнить с тем, что выдала среда выполнения. 200, за которым следует 401 или 403, — нужная форма; два 200 означают, что путь отказа на самом деле не применяется.
Напишите откат до того, как он понадобится: какую запись списка разрешённых, именованные учётные данные или исходящее подключение вы изменили, кому это принадлежит и как восстановить прежнее значение. Затем замкните цикл, назвав в заявке облачного вызывающего и полный путь сервиса, чтобы никто не открыл ту же проблему снова как проблему VPN.