Secure Shell (SSH) – это сетевой протокол, который позволяет пользователям безопасно подключаться с одного компьютера к другому удаленно. Большинство людей, использующих SSH, являются системными администраторами, и наиболее часто этот протокол используется для удаленного управления сервером.
Неважно, на каком этапе своей технической карьеры вы находитесь; если вы работаете с серверами, SSH как протокол понадобится вам для модификации или обслуживания удаленных серверов в бесчисленных случаях. Возможно, вы повысили безопасность своего сервера, используя SSH-сертификат вместо имени пользователя и пароля. Однако кто-то со злым умыслом все равно может получить доступ к этим методам аутентификации. Вот почему стоит включить многофакторную аутентификацию (MFA) для вашего SSH-сервера.
API tru.ID PhoneCheck подтверждает принадлежность номера мобильного телефона, проверяя наличие активной SIM-карты с тем же номером. Этот метод не только создает удобство для пользователей, но и значительно более безопасен, чем традиционные методы, такие как SMS OTP. API tru.ID обращается непосредственно к мобильной сети, а не полагается на уязвимые протоколы SS7, обеспечивая проверку SIM-карты в режиме реального времени менее чем за 2 секунды.
- Прежде чем начать
- Начало работы
- Определите основные переменные
- Создать установку
- Регистрация пользователей
- Разрешить пользователю вход
- Создание PhoneCheck
- Получение учетных данных
- Создание маркеров доступа
- Создайте PhoneCheck
- Генерировать QR-код
- Настроить опрос
- Добавьте ForceCommand
- Завершение PhoneCheck
- Установите сторонние зависимости
- Создайте веб-крючок
- Настройка контейнера Docker
- Установка плагина SSH
- Регистрация пользователя
- Попытка входа в систему
- Завершение
- Ресурсы
Прежде чем начать
Чтобы следовать этому руководству, вам понадобятся:
- Учетная запись tru.ID
- Мобильный телефон с активной SIM-картой для передачи данных
- Docker, установленный локально
- Node, установленный локально
Начало работы
На GitHub была создана ветка репозитория, содержащая базовый код, необходимый для начала работы.
В терминале клонируйте ветку starter-files
для этого репозитория с помощью следующей команды:
git clone -b starter-files git@github.com:tru-ID/tru-id-ssh-auth.git
Если вас интересует готовый код, вы можете найти полный пример в ветке main
. Чтобы получить этот код, выполните:
git clone -b main git@github.com:tru-ID/tru-id-ssh-auth.git
Для выполнения API-запросов PhoneCheck
требуется учетная запись tru.ID, поэтому прежде чем продолжить, убедитесь, что вы ее создали.
Теперь перейдите в консоль tru.ID и создайте проект. После создания проекта, прежде чем закрыть окно или уйти, убедитесь, что вы скачали файл учетных данных tru.json
и переместили его в корневой каталог каталога проекта tru-id-ssh-auth
.
В файле учетных данных вы найдете ваш project_id
, project_name
, доступные вашему проекту диапазоны, а также ваши client_id
и client_secret
, которые вы будете использовать для создания токена аутентификации для выполнения запросов API.
Определите основные переменные
По всему коду вы будете повторно использовать несколько битов информации; это такие переменные, как, например, URL PhoneCheck и целевой каталог, в который установлен ваш проект. Ниже строки VERSION=1
в файле ssh-auth
добавьте следующее:
# Base URL information
DATA_RESIDENCY=eu
BASE_URL="https://$DATA_RESIDENCY.api.tru.id"
# API Check URLs
PHONE_CHECK_URL="$BASE_URL/phone_check/v0.2/checks"
GET_PHONE_CHECK_URL="$BASE_URL/phone_check/v0.2/checks/"
CREATE_AUTH_TOKEN_URL="$BASE_URL/oauth2/v1/token"
APP_ROOT=`dirname $0`
CONFIG_FILE="$APP_ROOT/tru-id-ssh-auth.conf"
DEST_DIRECTORY="/usr/local/bin/"
# Empty Global Variables
BASIC_AUTH_USER=
BASIC_AUTH_PASSWORD=
ACCESS_TOKEN=
Вы можете изменить только два значения:
Создать установку
Большая часть этого проекта будет находиться в одном единственном файле bash, с несколькими доступными командами. Первая – это команда install
, которая копирует соответствующий код в нужный каталог установки. Вы также примените команду ForceCommand
к конфигурационному файлу SSHd, который вы добавите позже в учебнике.
Начните с поиска функции require_curl
в файле ssh-auth
. Ниже этой функции require_curl
добавьте следующий код, который будет вашей новой функцией install()
:
function install() {
config_file="${DEST_DIRECTORY}tru-id-ssh-auth/tru-id-ssh-auth.conf"
set -e
echo "Making directory in ${DEST_DIRECTORY}"
mkdir "/usr/local/bin/tru-id-ssh-auth"
set +e
if [[ ! -r `dirname "${DEST_DIRECTORY}"` ]]
then
echo "${DEST_DIRECTORY} is not writable. Try again using sudo"
return $FAIL
fi
echo "Copying /root/tru-id-ssh-auth/ to ${DEST_DIRECTORY}..."
cp -r "/root/tru-id-ssh-auth" "${DEST_DIRECTORY}"
echo "Setting up permissions..."
chmod 755 $DEST_DIRECTORY
if [[ ! -f ${config_file} ]]
then
echo "Generating initial config on ${config_file}..."
echo "header=tru.ID SSH Auth initialised." > "${config_file}"
else
echo "A config file was found on ${config_file}. Edit it manually if you want to change the API key"
fi
chmod 644 ${config_file}
echo ""
echo "To enable tru.ID authentication on a user the following command: "
echo ""
echo " ${DEST_DIRECTORY}tru-id-ssh-auth/ssh-auth register-user <username> <phone-number-inc-country-code>"
echo " Example: ${DEST_DIRECTORY}tru-id-ssh-auth/ssh-auth register-user test 447000000000"
echo ""
echo "To uninstall tru.ID SSH type:"
echo ""
echo " ${DEST_DIRECTORY}tru-id-ssh-auth/ssh-auth uninstall"
echo ""
echo " Restart the SSH server to apply changes"
echo ""
}
В этой новой функции есть несколько шагов. К ним относятся:
- Создайте каталог для размещения установленного приложения,
/usr/local/bin/tru-id-ssh-auth
. - Проверить, что каталог доступен для записи. Если нет, то выдайте ошибку.
- Скопируйте файлы проекта во вновь созданный каталог назначения.
- Проверьте, существует ли файл конфигурации. Если нет, то создайте его.
- Вывести текст в Terminal, инструктируя пользователей, как использовать и удалить приложение.
Как уже говорилось ранее, для деинсталляции этого скрипта необходима дополнительная функциональность. Ниже созданной функции install()
добавьте следующую функцию uninstall()
:
function uninstall() {
find_sshd_config
if [[ $1 != "quiet" ]]
then
echo "Uninstalling tru.ID SSH from $SSHD_CONFIG..."
fi
if [[ -w $SSHD_CONFIG ]]
then
sed -ie '/^ForceCommand.*tru-id-ssh-auth.*/d' $SSHD_CONFIG
fi
if [[ $1 != "quiet" ]]
then
echo "tru.ID SSH was uninstalled."
echo "Now restart the ssh server to apply changes and then remove ${DEST_DIRECTORY}/tru-id-ssh-auth"
fi
}
Первая строка в этой новой функции должна вызвать функцию find_sshd_config()
, поэтому добавим следующее:
function find_sshd_config() {
echo "Trying to find sshd_config file"
if [[ -f /etc/sshd_config ]]
then
SSHD_CONFIG="/etc/sshd_config"
elif [[ -f /etc/ssh/sshd_config ]]
then
SSHD_CONFIG="/etc/ssh/sshd_config"
else
echo "Cannot find sshd_config in your server. tru.ID SSH Auth will be enabled when you add your specific ForceCommand to the sshd config file."
fi
}
Новая функция находит файл sshd_config
вашего сервера и сохраняет его расположение в качестве глобальной переменной.
Функции install()
и uninstall()
недоступны, пока вы не добавите их в качестве параметра. В списке команд для этого проекта найдите строку:
case $1 in
Этот раздел кода содержит функциональность, которая понимает различные аргументы в команде при запуске вашего сценария bash. Поэтому ниже строки case
добавьте следующие два новых аргумента командной строки:
install)
check_dependencies
install
;;
uninstall)
uninstall
;;
Регистрация пользователей
Процесс аутентификации SIM требует индивидуальной регистрации пользователей путем ввода номера телефона и связывания его с именем пользователя, чтобы можно было пройти верификацию с помощью API PhoneCheck от tru.ID.
Для регистрации нового пользователя создайте новую функцию register_user()
, скопировав приведенный ниже пример в ваш файл ssh_auth
:
function register_user() {
config_file="${DEST_DIRECTORY}tru-id-ssh-auth/tru-id-ssh-auth.conf"
if [[ $2 && $3 ]]
then
echo "user=$2:$3" >> ${config_file}
echo "" >> ${config_file}
echo "User was registered"
else
echo "Cannot register user"
fi
}
Ваша новая функция register_user()
находит файл tru-id-ssh-auth.conf
и добавляет следующую строку: user={имя пользователя}:{номер телефона}
.
В нижней части файла найдите строку case $1 in
. Ниже этой строки включите функцию register_user()
в качестве аргумента командной строки, добавив следующее:
register-user)
check_dependencies
register_user "$@"
;;
Разрешить пользователю вход
После успешной проверки PhoneCheck будет вызвана функция run_shell
, которая сообщит плагину, что пользователю разрешен доступ к его SSH-сессии. В файле ssh-auth
добавьте следующую функцию:
# Once successful, allows user to proceed with access to server
function run_shell() {
if [[ "$SSH_ORIGINAL_COMMAND" != "" ]]
then
exec /bin/bash -c "${SSH_ORIGINAL_COMMAND}"
elif [ $SHELL ]
then
exec -l $SHELL
fi
exit $?
}
Создание PhoneCheck
Получение учетных данных
Для выполнения вызовов API tru.ID вам необходимо получить учетные данные вашего проекта, которые вы можете найти в файле tru.json
, перенесенном в ваш проект ранее. Приведенная ниже функция get_credentials()
извлекает client_id
и client_secret
из этого файла, а затем устанавливает их в качестве двух глобальных переменных: BASIC_AUTH_USER
и BASIC_AUTH_PASSWORD
. Добавьте эту новую функцию в ваш файл ssh-auth
:
function get_credentials() {
FILE="${DEST_DIRECTORY}tru-id-ssh-auth/tru.json"
if [ -f "$FILE" ]; then
BASIC_AUTH_USER=$(jq -r ".credentials[].client_id" ${FILE})
BASIC_AUTH_PASSWORD=$(jq -r ".credentials[].client_secret" ${FILE})
return $OK
fi
echo "Unable to retrieve project credentials. Please make sure your project directory has a `tru.json` file."
exit $FAIL
}
Создание маркеров доступа
Следующей частью создания PhoneCheck
через API является добавление функциональности для генерации маркеров доступа с использованием учетных данных вашего проекта tru.ID. Эта новая функциональность будет делать POST запрос на https://{DATA_RESIDENCY}.api.tru.id/oauth2/v1/token
, с заголовком, содержащим ваши BASIC_AUTH_USER
и BASIC_AUTH_PASSWORD
, сопряженные с :
между ними, а затем вся строка кодируется в base64. Полученный токен доступа будет использоваться для дальнейших безопасных запросов к API tru.ID.
Скопируйте приведенную ниже функцию create_access_token()
в ваш файл ssh_auth
.
# Creates an access token needed to create a PhoneCheck request.
function create_access_token() {
get_credentials
CREDENTIALS=$(echo -ne "$BASIC_AUTH_USER:$BASIC_AUTH_PASSWORD" | base64 -w 0);
# Make request to get access token
response=`curl
--header "Authorization: Basic $CREDENTIALS"
--header "Content-Type: application/x-www-form-urlencoded"
--request POST $CREATE_AUTH_TOKEN_URL
--data-urlencode "grant_type=client_credentials"
--data-urlencode "scope=phone_check coverage" --silent`
curl_exit_code=$?
# Parses response to get the access token
ACCESS_TOKEN=$(jq -r .access_token <<< "${response}" )
if [ $curl_exit_code -ne 0 ]
then
echo $curl_exit_code
echo "Error running curl"
fi
}
Создайте PhoneCheck
Вы создали функции, позволяющие получать учетные данные вашего проекта из файла tru.json
; ваша следующая функция использует учетные данные из этого файла для создания маркера доступа, который вы будете использовать для аутентифицированных вызовов API.
Следующим шагом в этом руководстве является инициализация PhoneCheck, которая будет делать следующее:
- Получать текущего пользователя, пытающегося войти в систему.
- Прочитайте конфигурационный файл, чтобы узнать, зарегистрирован ли у этого пользователя номер телефона, чтобы потребовался шаг MFA.
- Сделайте
POST
запрос кhttps://{DATA_RESIDENCY}.api.tru.id/phone_check/v0.2/checks"
с номером телефона пользователя.
Скопируйте приведенную ниже функцию в ваш файл ssh_auth
, чтобы добавить описанную функциональность в ваш проект:
function create_check() {
config_file="${DEST_DIRECTORY}tru-id-ssh-auth/tru-id-ssh-auth.conf"
current_user=$USER;
phone_number="";
while read line; do
if [[ $line =~ user=$current_user: ]] ; then
phone_number=$(echo "${line}" | sed s/user=${current_user}://g);
fi
done <${config_file}
if [ "$phone_number" == "" ]; then
echo "Phone Number is empty"
return 0
fi
# Checking Credentials are installed
get_credentials
# Creating an Access Token
create_access_token
# Making a Phone Check request"
response=`curl
--header "Authorization: Bearer $ACCESS_TOKEN"
--header "Content-Type: application/json"
--request POST $PHONE_CHECK_URL
--data-raw "{"phone_number":"${phone_number}"}" --silent`
curl_exit_code=$?
if [ $curl_exit_code -ne 0 ]
then
echo "Error running curl"
return 1;
fi
# Handling Phone Check Response
check_id=$(jq -r .check_id <<< "${response}" )
status=$(jq -r .status <<< "${response}" )
check_url=$(jq -r ._links.check_url.href <<< "${response}" )
return $CHECK_STATUS;
}
Генерировать QR-код
Когда пользователь создал PhoneCheck
, следующим шагом в потоке MFA будет открытие на устройстве пользователя URL-адреса проверки своего оператора мобильной сети.
Самый простой способ для пользователя открыть URL – это QR-код. Если вы проверите свой Dockerfile
в каталоге проекта, вы уже установили библиотеку qr
, когда собирали контейнер Docker. Поэтому следующим шагом будет получение check_url
из ответа PhoneCheck
. Этот check_url
должен быть преобразован в QR-код и отображен для пользователя.
Внутри create_check()
найдите строку check_url=$(jq -r ._links.check_url.href <<< "${ответ}" )
, а ниже добавьте следующее:
# Generate QR code
qr --ascii "${check_url}" > "qrcode.txt"
sleep 1
cat ~/qrcode.txt
Настроить опрос
Следующим шагом в этом процессе будет проверка конечной точки API tru.ID https://{DATA_RESIDENCY}.api.tru.id/phone_check/v0.2/checks/{check_id}
, чтобы определить, было ли соответствие между номером телефона и запросом на URL проверки или нет. После создания чека пользователю дается двухминутное окно для открытия URL. Приложение будет делать запросы к API каждые пять секунд для обновления статуса.
Если значение статуса COMPLETED
и тело ответа содержит значение match
как true
, то пропустите пользователя; в противном случае откажите в доступе к серверу.
Скопируйте новую функцию start_polling()
в ваш файл ssh_auth
:
function start_polling() {
# Check every 5 seconds for status on Check.
interval_in_seconds=5
CHECK_STATUS=$FAIL
while true;
do
# Check status of phone check
response=`curl
--header "Authorization: Bearer $ACCESS_TOKEN"
--header "Content-Type: application/json"
--request GET $GET_PHONE_CHECK_URL/${check_id} --silent`
curl_exit_code=$?
if [ $curl_exit_code -ne 0 ]
then
echo "Error running curl"
return $FAIL;
fi
status=$(jq -r .status <<< "${response}" )
match=$(jq -r .match <<< "${response}" )
# If check is complete, output
if [[ "$status" != "PENDING" && "$status" != "ACCEPTED" ]]; then
if [ "$status" == "COMPLETED" ]; then
if [ "$match" == "true" ]; then
CHECK_STATUS=$OK;
run_shell
else
echo "No match found!"
CHECK_STATUS=$FAIL
return $FAIL;
fi
elif [ "$status" == "EXPIRED" ]; then
echo "Check Expired";
CHECK_STATUS=$FAIL
return $FAIL;
elif [ "$status" == "ERROR" ]; then
echo "Check Error Received";
CHECK_STATUS=$FAIL
return $FAIL;
else
echo "$status"
echo "404, no status was found";
CHECK_STATUS=$FAIL
return $FAIL;
fi
break;
fi
# Otherwise continue
sleep $interval_in_seconds;
done
}
Вам нужно вызвать эту новую функцию внутри вашей функции create_check()
. Найдите строку cat ~/qrcode.txt
, а ниже добавьте следующую строку, чтобы вызвать функцию start_polling
:
# Start polling
start_polling
Добавьте create_check
в качестве аргумента командной строки, найдя строку: case $1 in
, и добавив следующее:
create-check)
check_dependencies
create_check "$@"
;;
Добавьте ForceCommand
В вашем файле ssh-auth
вы уже вызвали функцию add_force_command
, но она еще не существует для добавления ForceCommand
в ваш файл sshd_config
. Поэтому добавьте эту функцию:
function add_force_command() {
echo "Trying to add force command to $SSHD_CONFIG"
find_sshd_config
auth_ssh_command="$1"
if [[ -w $SSHD_CONFIG ]]
then
echo "Adding 'ForceCommand ${auth_ssh_command} login' to ${SSHD_CONFIG}"
uninstall "quiet" # remove previous installations
echo -e "nForceCommand ${auth_ssh_command} login" >> ${SSHD_CONFIG}
echo ""
check_sshd_config_file
echo " MAKE SURE YOU DO NOT MOVE/REMOVE ${auth_ssh_command} BEFORE UNINSTALLING tru.ID SSH Plugin"
sleep 5
fi
}
Если вы следуете этому руководству, используя Docker, откройте файл sshd_config
в каталоге вашего проекта и в нижней части этого файла добавьте следующую команду force:
ForceCommand /usr/local/bin/tru-id-ssh-auth/ssh-auth create-check
После добавления вы можете перейти к завершению PhoneCheck. Однако, если вы устанавливаете программу на сервер, пожалуйста, продолжите инструкцию ниже:
Примечание: Если вы следуете этому руководству, используя контейнер Docker, вам не понадобится этот фрагмент кода; однако при установке на сервер, отличный от Docker, эта строка необходима, и ее нужно не комментировать. Найдите строку
chmod 644 ${config_file}
внутри вашей функцииinstall()
и добавьте следующую; ее также нужно будет откомментировать.
# When following this tutorial, leave the line below commented out.
# Restarting your SSH server within Docker will restart the whole Docker container.
# add_force_command "${DEST_DIRECTORY}tru-id-ssh-auth/ssh-auth create-check"
Завершение PhoneCheck
Последним шагом в процессе PhoneCheck является завершение PhoneCheck. Когда мобильное устройство открывает URL проверки оператора мобильной сети, оно перенаправляется обратно на ваш redirect_url
, который при последнем запросе будет иметь ответ, содержащий code
. Этот код необходимо отправить через API с вашими учетными данными, чтобы завершить PhoneCheck.
В вашем репозитории starter-files
вы найдете шаблон веб-сервера, встроенного в node. Это веб-сервер, который будет содержать код вашего redirect_url
, который будет выполнять эту функциональность.
Установите сторонние зависимости
В терминале перейдите в каталог webserver
и выполните следующую команду для установки сторонних библиотек, необходимых для этого руководства. Эти библиотеки включают express
для функциональности веб-сервера, ngrok
для обеспечения общедоступного URL и http-signature
для проверки подписи в запросе API.
npm install
Создайте веб-крючок
Найдите конечную точку:
app.get("/", async (req, res) => {
res.send('hello');
});
И замените его на:
app.get("/complete-check", async (req, res) => {
if (!req.query) {
res.status(400).send("body missing");
return;
}
const { code, check_id } = await req.query;
if (!code) {
res.status(400).send("code missing");
return;
}
if (!check_id) {
res.status(400).send("check_id missing");
return;
}
if (req.query.redirect_url) {
const verified = await tru.verifySignature(req.query.redirect_url);
if (!verified) {
res.status(400).send("signature not verified");
return;
}
}
});
В приведенном выше примере вы создаете новый вебхук /complete-check
, который доступен с помощью запроса GET
. Этот запрос принимает три параметра в URL, check_id
, code
и redirect_url
. Эти параметры используются для завершения PhoneCheck. После проверки на то, что они были включены, код проверяет, действительна ли подпись для url перенаправления.
Далее, в директории webserver
создайте новый файл tru.js
, в котором вы добавите функциональность API tru.ID. В этом файле первым делом добавьте зависимости, которые будут использоваться, а также определите глобальные переменные и объекты. Добавьте следующее:
const moment = require("moment");
const fetch = require("node-fetch");
const httpSignature = require("http-signature");
const jwksClient = require("jwks-rsa");
const config = require("../tru.json");
const tru_api_base_url = 'https://eu.api.tru.id';
const keyClient = jwksClient({
jwksUri: `${tru_api_base_url}/.well-known/jwks.json`,
});
// token cache in memory
const TOKEN = {
accessToken: undefined,
expiresAt: undefined,
};
При выполнении запроса к конечной точке API tru.ID вам понадобится токен доступа:
async function getAccessToken() {
// check if existing valid token
if (TOKEN.accessToken !== undefined && TOKEN.expiresAt !== undefined) {
// we already have an access token let's check if it's not expired
// I'm removing 1 minute just in case it's about to expire better refresh it anyway
if (
moment()
.add(1, "minute")
.isBefore(moment(new Date(TOKEN.expiresAt)))
) {
// token not expired
return TOKEN.accessToken;
}
}
const url = `${tru_api_base_url}/oauth2/v1/token`;
const toEncode = `${config.credentials[0].client_id}:${config.credentials[0].client_secret}`;
const auth = Buffer.from(toEncode).toString('base64');
const requestHeaders = {
Authorization: `Basic ${auth}`,
"Content-Type": "application/x-www-form-urlencoded",
};
const res = await fetch(url, {
method: "post",
headers: requestHeaders,
body: new URLSearchParams({
grant_type: "client_credentials",
scope: "phone_check coverage",
}),
});
if (!res.ok) {
return res.status(400).body("Unable to create access token")
}
const json = await res.json();
// update token cache in memory
TOKEN.accessToken = json.access_token;
TOKEN.expiresAt = moment().add(json.expires_in, "seconds").toString();
return json.access_token;
}
Необходима новая функция patchPhoneCheck
, которая будет делать PATCH
запрос к API tru.ID: /phone_check/v0.2/checks/${checkId}
, с кодом, содержащимся в теле. Это метод проверки того, что владелец SIM-карты был тем, кто запросил PhoneCheck. В ваш файл tru.js
добавьте следующую новую функцию:
async function patchPhoneCheck(checkId, code) {
const url = `${tru_api_base_url}/phone_check/v0.2/checks/${checkId}`;
const body = [{ op: "add", path: "/code", value: code }];
const token = await getAccessToken();
const requestHeaders = {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json-patch+json",
};
const res = await fetch(url, {
method: "patch",
headers: requestHeaders,
body: JSON.stringify(body),
});
if (!res.ok) {
return res;
}
const json = await res.json();
return json;
}
Как объяснялось ранее, вам необходимо проверить подпись, предоставленную с помощью redirect_url
, чтобы убедиться, что она не была изменена каким-либо образом. Это можно сделать с помощью следующей функции, поэтому добавьте ее в свой файл:
async function verifySignature(originalUrl) {
try {
const url = new URL(originalUrl);
const signature = Buffer.from(
url.searchParams.get("authorization"),
"base64"
).toString("utf-8");
const date = Buffer.from(url.searchParams.get("date"), "base64").toString(
"utf-8"
);
url.searchParams.delete("authorization");
url.searchParams.delete("date");
const originalRequest = {
url: `${url.pathname}${url.search}`,
method: "get",
hostname: url.hostname,
headers: {
date,
host: url.host,
authorization: signature,
},
};
const parsedOriginalRequest = httpSignature.parseRequest(originalRequest, {
clockSkew: 300,
});
const jwk = await keyClient.getSigningKey(parsedOriginalRequest.keyId);
const verified = httpSignature.verifySignature(
parsedOriginalRequest,
jwk.getPublicKey()
);
return verified;
} catch (err) {
console.error(err);
return false;
}
}
Две новые функции patchPhoneCheck
и verifySignature
должны быть доступны в вашем файле index.js
, поэтому в нижней части файла tru.js
добавьте следующие экспорты для этих двух функций:
module.exports = {
patchPhoneCheck,
verifySignature
};
Вернитесь в свой файл index.js
, вверху среди require, добавьте строку:
const tru = require("./tru");
Найдите конечную точку complete-check
, и в нижней части этой функции добавьте следующее:
try {
const check = await tru.patchPhoneCheck(check_id, code);
if (check.status === "COMPLETED" && check.match) {
res.status(200).send('Verification complete, please close this tab and return to your SSH session.');
return;
} else {
// verification failed = user not authenticated
res.status(401).send("Verification failed, false match");
return;
}
} catch (err) {
console.log(err);
if (err.status) {
res.status(err.status || 500).send(err.message);
} else {
res.status(500).send("Unexpected Server error");
}
return;
}
Приведенный выше код вызывает patchPhoneCheck
, созданный в вашем файле tru.js
, который делает PATCH
запрос к API tru.ID с телом, содержащим code
, необходимый для завершения процесса PhoneCheck.
Теперь в терминале, в директории webserver
, выполните следующую команду и обратите внимание на вывод ngrok
url:
npm start
В вашем файле ssh-auth
найдите строку: # API Check URLs
и ниже нее добавьте следующее, заменив <Your NGROK URL>
на ngrok URL, который вы записали в предыдущем шаге:
BACKEND_SERVER="<Your NGROK URL>"
REDIRECT_URL="$BACKEND_SERVER/complete-check"
Чтобы конечным редиректом был указанный вами URL webhook, найдите строку ниже:
--data-raw "{"phone_number":"${phone_number}"}" --silent`
И замените ее на:
--data-raw "{"phone_number":"${phone_number}", "redirect_url":"${REDIRECT_URL}"}" --silent`
Настройка контейнера Docker
В этом руководстве используется контейнер Docker для целей разработки. Чтобы создать этот контейнер Docker и запустить его, вам потребуется:
- Создать и запустить свой контейнер Docker. В ходе этого процесса внутренний порт
22
(ssh) будет сопоставлен с внешним портом223
. - Откройте контейнер Docker с помощью сессии bash.
Итак, в Терминале выполните следующие две команды:
docker-compose up --build -d
docker-compose exec ssh bash
Установка плагина SSH
Теперь вы добавили многофакторную аутентификацию в процесс аутентификации SSH. Когда ваш контейнер Docker создан и запущен, перейдите в каталог проекта в том же экземпляре терминала. По умолчанию это каталог /root/tru-id-ssh-auth/
. Затем выполните команду ./ssh-auth install
для установки вашей копии каталога проекта в /usr/local/bin/
.
Примечание: Это определено в вашем
Dockerfile
в строке:ADD . /root/tru-id-ssh-auth
.
cd /root/tru-id-ssh-auth/
./ssh-auth install
Команда ./ssh-auth install
выполнит следующее:
- Скопируйте каталог проекта из
/root/tru-id-ssh-auth/
в/usr/local/bin/tru-id-ssh-auth/
. - Создайте конфигурационный файл
/usr/local/bin/tru-id-ssh-auth/tru-id-ssh-auth.conf
.
Регистрация пользователя
Установив плагин, теперь необходимо включить проверку пользователя (пользователей). Это сохранит имя и номер телефона пользователя в недавно созданном вами конфигурационном файле. Затем приложение сравнит их с учетными данными, введенными при попытке пользователя войти в систему. В том же Терминале выполните следующую команду, заменив заполнители на ваши действительные данные:
Примечание: Пользователь и пароль Docker –
test
.
/usr/local/bin/tru-id-ssh-auth/ssh-auth register-user <username> <phone-number-inc-country-code>
# For example: /usr/local/bin/tru-id-ssh-auth/ssh-auth register-user test 447000000000
Попытка входа в систему
Теперь вы все настроили. Чтобы проверить, все ли работает, откройте новый сеанс терминала и выполните следующую команду для входа в SSH-сервер:
ssh test@127.0.0.1 -p 223
В примере конфигурации Docker используется имя пользователя test
и пароль test
.
Завершение
Вот и все! Теперь вы ввели шаг многофакторной аутентификации для процесса SSH аутентификации вашего сервера, используя API tru.ID PhoneCheck
. Прелесть этого метода заключается в том, что он ограничивает ввод пользователя, требуя от него только ввести свои учетные данные SSH, а затем отсканировать QR-код, ему не нужно ждать, пока код придет, например, через SMS или другим способом. Процесс MFA выполняется в фоновом режиме после сканирования QR-кода на мобильном устройстве.
Ресурсы
- Руководство по интеграции tru.ID PhoneCheck
- Справочник по API PhoneCheck