Аутентификация API и TLS
Узел защищает свои владельческие поверхности с помощью HTTP Basic, сверяясь с файлом секрета на диске. Owner API v3 кошелька использует токен, полученный с паролем кошелька. Внешние поверхности не требуют учётных данных, поскольку интерактивный перевод требует, чтобы принимающая сторона была доступна для стороннего участника. Терминация TLS остаётся на усмотрение оператора.
Поверхности
| Поверхность | Порт по умолчанию | Учётные данные | Кто должен вызывать |
|---|---|---|---|
Node /v1/* | 3413 | Basic, api_secret_path, на весь префикс | Вы, с той же машины |
Node /v2/owner | 3413 | Basic, api_secret_path | Вы, с той же машины |
Node /v2/foreign | 3413 | Опциональный Basic, foreign_api_secret_path | Всё, что читает цепочку |
Wallet Owner /v3/owner | 3420 | Токен из open_wallet, внутри зашифрованного конверта | Вы, с той же машины |
Wallet Owner /v2/owner | 3420 | Нет. Заменён на /v3/owner | Ничего. Привяжите слушатель к loopback |
Wallet Foreign /v2/foreign | 3415 | Нет | Контрагент, оплачивающий вам |
Foreign API кошелька принимает слейт (Slate), возвращает частично подписанный слейт, формирует coinbase для майнера, настроенного на выплату в этот кошелёк, и сообщает свою версию. Ограничьте доступ к нему на уровне прокси.
Учётные данные /v1 узла распространяются на весь префикс, включая операции чтения цепочки, открытые
на /v2/foreign. См. поверхность v1 REST.
api_secret_path указывает на разный файл в конфигурации каждого бинарника. Обе поверхности узла читают файл
узла, которым является .api_secret.
Доступ владельца к кошельку
/v3/owner защищён токеном, а не HTTP-учётными данными. Каждый метод трейта v3 принимает токен (api/src/owner_rpc_s.rs:78), а
его получение означает завершение ECDH-рукопожатия и последующий вызов open_wallet с паролем кошелька.
Пароль является ключом доступа. См. зашифрованное рукопожатие.
Первый вызов устанавливает общий ключ и не несёт учётных данных:
curl -s \
-d '{"jsonrpc":"2.0","method":"init_secure_api","params":{"ecdh_pubkey":"<your compressed public key, hex>"},"id":1}' \
http://127.0.0.1:3420/v3/owner
Помимо этих учётных данных, каждый метод на /v3/owner принимает token, а токен поступает из open_wallet, которому
требуется пароль кошелька. owner_api_listen_interface по умолчанию равен 127.0.0.1; для удалённого доступа используйте туннель
к loopback. Слушатель — controller/src/controller.rs:123.
Полный список методов, зашифрованный конверт и информация о том, какие вызовы перемещают средства, находятся на странице Owner API кошелька.
Учётные данные узла
Префикс /v1 узла и /v2/owner используют HTTP Basic с именем пользователя буквально epic и содержимым
файла секрета в качестве пароля:
Authorization: Basic base64("epic:" + <secret file contents>)
Узел создаёт ~/.epic/<network>/.api_secret при первом запуске и указывает на него в api_secret_path, поэтому это работает без настройки:
curl -u epic:$(cat ~/.epic/main/.api_secret) \
-d '{"jsonrpc":"2.0","method":"get_status","params":[],"id":1}' \
http://127.0.0.1:3413/v2/owner
Файлы секретов содержат одну случайную буквенно-цифровую строку из 20 символов без завершающего
символа новой строки (config/src/config.rs:84), а сравнение выполняется за постоянное время (api/src/auth.rs:74). Realm равен EpicAPI на
владельческой поверхности и EpicForeignAPI на внешней. Отклонённый вызов, в любом из бинарников, возвращает
401 с заголовком WWW-Authenticate и телом ошибки JSON-RPC:
{"jsonrpc": "2.0", "error": {"code": -32600, "message": "Unauthorized"}, "id": null}
- При закомментированном
api_secret_pathслушатель работает без учётных данных. - Пустой
.api_secretперегенерируется с новым значением, а не читается как «нет секрета», поэтому очистка файла не отключает аутентификацию (config/src/config.rs:96). OPTIONSпропускается до проверки учётных данных, что обеспечивает работу CORS preflight.
Опциональные учётные данные на внешней поверхности узла
foreign_api_secret_path заставляет /v2/foreign узла также требовать учётные данные. Создайте секрет самостоятельно и укажите
его абсолютный путь:
head -c 40 /dev/urandom | base64 | tr -dc 'A-Za-z0-9' | head -c 20 > ~/.epic/main/.foreign_api_secret
[server]
foreign_api_secret_path = "/home/you/.epic/main/.foreign_api_secret"
Realm равен EpicForeignAPI, имя пользователя по-прежнему epic. Проверьте с помощью:
curl -s -o /dev/null -w '%{http_code}\n' -X POST http://127.0.0.1:3413/v2/foreign
# 401 после установки секрета
Учётные данные, которые кошелёк передаёт узлу
node_api_secret_path указывает в обратном направлении: это то, что кошелёк отправляет при обращении к узлу, и по
умолчанию равен <wallet dir>/.api_secret. При значениях по умолчанию узел и кошелёк совместно используют ~/.epic/<network>/ и
разрешают его в один и тот же файл, поэтому они согласованы без дополнительной настройки. Если
изменить секрет узла, переместить любой из каталогов или направить кошелёк на другой узел — это
ключ, который нужно обновить.
TLS
Оба бинарника принимают одну и ту же пару, по умолчанию закомментированную:
tls_certificate_file = "/path/to/fullchain.pem"
tls_certificate_key = "/path/to/privkey.pem"
Указание сертификата переключает слушатель с HTTP на HTTPS. Указание сертификата без ключа является ошибкой при запуске. Сертификаты читаются как PEM-цепочка; ключи могут быть в формате PKCS#1, PKCS#8 или SEC1 PEM. Файл, который не удаётся открыть, разобрать или который не соответствует своему сертификату, останавливает процесс вместо отката к HTTP, поэтому неверная пара явно завершается ошибкой при запуске.
Встроенные подкоманды epic client обращаются к узлу через http:// (src/bin/cmd/client.rs:160). Используйте curl для работы с
TLS-слушателем.