Предоставление, настройка и защита облачного редактора TinaCMS на AWS

Недавно я впервые создал веб-сайт с TinaCMS и Gatsby и обнаружил, что процесс разработки проходит относительно гладко. Единственный вопиющий пробел в опыте разработчиков, который я обнаружил, заключался в настройке облачного редактора, которым я хотел бы поделиться в этом руководстве. Поскольку облачный редактор запускается из сборки для разработки, я не буду обсуждать ваши производственные сборки и развертывания TinaCMS в этом руководстве. Если вам интересно, я использовал процесс CD с действиями GitHub для создания и развертывания новых статических ресурсов на S3 (с CloudFront и статическим веб-хостингом) в производственной среде при каждой новой фиксации в основной ветке моего проекта.

Прежде чем мы начнем, я хотел бы объяснить, что для того, чтобы разрешить облачное редактирование TinaCMS с помощью Gatsby в реальном времени, вам в настоящее время необходимо запустить два отдельных экземпляра вашего проекта; один как редактор частного облака, а другой как ваш рабочий веб-сайт. Я считаю, что это может измениться, как только TinaCMS выпустит свой продукт TinaCMS Teams, но текущая рекомендация - это Gatsby Cloud (https://tinacms.org/blog/using-tinacms-on-gatsby-cloud), что я оказалось, что мой клиент едва ли может использовать его из-за ограничений ветки и предварительного просмотра.

Это руководство поможет вам настроить, подготовить и защитить облачный редактор TinaCMS с помощью Gatsby и AWS. Надеюсь, это сэкономит вам время и деньги :-).

В этом руководстве я буду периодически ссылаться на коммиты, но вот последний репозиторий tinacms-cloud-editor-tutorial.

Обзор

Настроить проект TinaCMS

Прежде чем мы начнем, убедитесь, что на вашем компьютере установлены node, npm и yarn.

Давайте начнем с клонирования канонического gatsby-starter-tinacms, установки зависимостей и локального запуска проекта, чтобы убедиться, что он работает должным образом. Если у вас уже есть настройка проекта TinaCMS / Gatsby, вы можете следовать ей из своего собственного проекта.

git clone https://github.com/tinacms/gatsby-starter-tinacms.git
cd gatsby-starter-tinacms
yarn install
yarn start

Если все работает, как ожидалось, создайте новое репо на GitHub, установите исходный пульт для вновь созданного репо и запустите свой код. Обязательно замените удаленный URL своим собственным.

git remote set-url origin [email protected]:user/project.git
git push origin master

Настройте Gatsby для облачного редактирования TinaCMS

Если вы перейдете к своему gatsby-config.js файлу, вы увидите, где TinaCMS включается через плагин.

{
  resolve: "gatsby-plugin-tinacms",
  options: {
    plugins: ["gatsby-tinacms-git", "gatsby-tinacms-remark", "gatsby-tinacms-json"],
    sidebar: {
      hidden: process.env.NODE_ENV === "production",
      position: "displace"
    },
  },
},

Подподключаемый модуль gatsby-tinacms-git - это тот, который позволит нашему редактору взаимодействовать с нашим репозиторием git при внесении обновлений, поэтому, если вы следуете примеру своего собственного проекта, убедитесь, что вы установили и добавили этот подключаемый модуль. Также обратите внимание на конфигурацию, которая скрывает «боковую панель» редактора, когда приложение создается для производства. Это соответствует тому, чего мы хотим достичь.

Чтобы проинформировать наш облачный редактор о том, куда нужно отправлять обновления контента, давайте заменим объявление плагина gatsby-tinacms-git более подробной конфигурацией. Обязательно замените значение gitRemote на SSH-адрес вашего удаленного репозитория git. Не стесняйтесь заменять информацию о фиксации чем угодно.

{
  resolve: "gatsby-plugin-tinacms",
  options: {
    plugins: [{
      resolve: "gatsby-tinacms-git",
      options: {
        gitRemote: "[email protected]:user/project.git",
        defaultCommitMessage: 'Edited with TinaCMS',
        defaultCommitName: 'Cloud Editor',
        defaultCommitEmail: '[email protected]',
      },
    }, "gatsby-tinacms-remark", "gatsby-tinacms-json"],
    sidebar: {
      hidden: process.env.NODE_ENV === "production",
      position: "displace"
    },
  },
},

Теперь ваш локальный редактор TinaCMS должен быть подключен к вашему проекту на GitHub. Перейдите к блогу по адресу http://localhost:8000, щелкните синий карандаш в левом нижнем углу браузера, внесите некоторые изменения в текст и нажмите «Сохранить».

Вы только что создали коммит, который был отправлен на GitHub из редактора TinaCMS! Перейдите к своему проекту в GitHub и убедитесь, что фиксация была отправлена ​​в вашу ветку.

Соответствующий коммит: https://github.com/Integral-Stack/tinacms-cloud-editor-tutorial/commit/349d5093e55b38d7db6c92ab9e2aee48cc969e5d

Добавить аутентификацию в Gatsby

Мы собираемся разместить CMS в Интернете, и нам нужен способ ограничить доступ к ней только надежным редакторам веб-сайта.

Мы могли бы попытаться ограничить доступ с помощью белого списка IP-адресов или геолокации в AWS, но ни один из них не даст нам точного и удобного контроля, который мы можем получить с помощью аутентификации учетных данных.

Базовая аутентификация - не самый безопасный метод ограничения доступа к нашему редактору, но он, безусловно, самый быстрый и его будет достаточно для нашей ситуации.

Чтобы обеспечить максимальную безопасность с помощью базовой аутентификации, убедитесь, что ваш пароль имеет большое количество элементов и длину. Мы также включим https, что необходимо, поскольку базовая аутентификация кодируется только в base64 перед отправкой по сети. И, наконец, мы запустим наш редактор из ветки, отличной от master. Таким образом, если наш облачный редактор когда-либо будет взломан, максимум, что может сделать злоумышленник, - это добавить кучу новых коммитов в ветку, которая даже не развертывается в производственной среде.

Начнем с установки пакета express-basic-auth.

yarn add express-basic-auth

К счастью, Гэтсби дал нам крючок для нашего экземпляра приложения Express, который упростит установку базовой аутентификации. Просто добавьте в свой gatsyb-config.js файл следующее:

const basicAuth = require("express-basic-auth")

module.exports = {
  siteMetadata: {
  ...
  },
  developMiddleware: app => {
    app.use(basicAuth({
      users: { test: 'test' },
      challenge: true,
      realm: 'your app name', 
    }))
  },
  ...
}

Это добавляет базовую аутентификацию ко всем входящим запросам в приложение. Очевидно, что в конечном итоге мы добавим имя пользователя / пароль, но мы будем тестировать с «test» в качестве имени пользователя и пароля. Вам нужно будет установить свойства задачи и области, чтобы браузеры пользователей знали, что они должны запрашивать имя пользователя / пароль при попытке доступа к веб-сайту.

Теперь перезапустите процесс и попробуйте получить доступ к http://localhost:8000. Вы должны получить запрос в диалоговом окне имени пользователя и пароля. Если вы правильно введете учетные данные, вы сможете получить доступ к сайту.

Соответствующий коммит: https://github.com/Integral-Stack/tinacms-cloud-editor-tutorial/commit/5de19cd413e38e484610ba5623a83155c81af7fa

Безопасные секреты

Теперь, когда мы начинаем изучать возможность добавления конфиденциальных данных в наше приложение, нам нужно убедиться, что мы не раскрываем какие-либо из этих секретов широкой публике. Фактически раскрытие конфиденциальных данных - это угроза безопасности приложений OWASP №3. Мы собираемся сделать это самым простым способом, интегрировав dotenv для Node и внедрив наши конфиденциальные данные во время выполнения.

Устанавливать dotenv не нужно, потому что он уже включен в пакет с Gatsby. Однако нам нужно будет добавить оператор require в начало нашего gatsby-config.js, чтобы правильно загрузить наш файл:

require("dotenv").config({ path: ".env.cloud" })
const basicAuth = require("express-basic-auth")

...
modules.exports = {

Я намеренно называю dotenv чем-то, что не противоречит нашей обычной настройке dotenv. Не беспокойтесь, если файл не существует, dotenv не выдаст ошибок при его отсутствии. Теперь давайте создадим наш .env.cloud файл в корне нашего проекта.

Теперь мы хотим добавить его в наш .gitignore файл, чтобы он не фиксировался в нашем репо:

# Live Github updates
.env.cloud

В наш .env.cloud файл мы добавим несколько переменных. Убедитесь, что вы правильно указали значения, особенно надежное имя пользователя и пароль:

AUTH_USER=*********
AUTH_PW=***************
ENABLE_AUTH=true
TINA_GIT_DEBOUNCE_MS=3000

Я добавил Tina Git Debounce к 3000 мс, потому что я заметил проблемы GraphQL в облачном редакторе, когда оставил это значение по умолчанию 1000 мс.

Переменные среды, связанные с аутентификацией, позволят нам переключаться и безопасно использовать нашу базовую аутентификацию. Для этого потребуются следующие обновления вашего промежуточного программного обеспечения в gatsby-config.js:

developMiddleware: app => {
  if (process.env.ENABLE_AUTH) {
    app.use(
      basicAuth({
        users: { [process.env.AUTH_USER]: process.env.AUTH_PW },
        challenge: true,
        realm: "your app name",
      })
    )
  }
},

Перезапустите приложение и убедитесь, что ваше новое имя пользователя и пароль работают правильно. После подтверждения убедитесь, что вы зафиксировали и отправили весь новый код на GitHub.

Соответствующий коммит: https://github.com/Integral-Stack/tinacms-cloud-editor-tutorial/commit/d33eef357af4569f9e232699fca794604403a0dc

Настроить ресурсы AWS

Поздравляем, вы дошли до части руководства, посвященной DevOps. Теперь мы собираемся переместить наш редактор в облако.

Если вы новичок в AWS, вы можете изучить другие руководства, чтобы ознакомиться с ним и, по крайней мере, научиться защищать свою учетную запись. Если у вас уже есть учетная запись AWS, войдите в систему. Мы собираемся начать с подготовки нашего экземпляра EC2.

После входа в свою учетную запись AWS перейдите на панель управления EC2 и «запустите» экземпляр. Мы собираемся выбрать по умолчанию «Amazon Linux 2 AMI (HVM), тип тома SSD» для типа инстанса «t2.micro». Если вы имеете право на бесплатный уровень, этот выбор считается бесплатным, а в противном случае цена по запросу для этой конфигурации очень дешевая. Если вы хотите сэкономить еще больше денег, вы можете изучить спотовые или зарезервированные экземпляры. Облачный редактор в основном должен обрабатывать трафик от нескольких редакторов.

На странице «Настроить» мы можем оставить все значения по умолчанию.

На странице «Добавить хранилище» мы будем использовать хранилище EBS по умолчанию.

На странице «Добавить теги» мы добавим пару «ключ-значение» Name: YourAppName, чтобы ее было легче отслеживать.

На странице «Группы безопасности» мы хотим создать новую группу безопасности для облачного редактора, к которому будет осуществляться доступ через SSH (порт 22), а также настраиваемое правило TCP, чтобы открыть редактор. на порт 8000. Затем следуйте инструкциям по запуску экземпляра.

Перед запуском экземпляра вам будет предложено с помощью модального окна выбрать или создать пару ключей для нового экземпляра. Создайте новую пару, назовите ее соответствующим образом, загрузите и запустите свой экземпляр.

Прежде чем мы начнем подготовку экземпляра, я предлагаю вам настроить эластичный IP-адрес и присоединить его к новому запущенному экземпляру. Эластичные IP-адреса бесплатны, если они привязаны к экземпляру. Это сохранит DNS и IP по умолчанию, так что IP и DNS не будут освобождены, если мы остановим и запустим наш экземпляр.

Подготовка экземпляра EC2

Теперь, когда вы скачали свой ключ PEM, давайте подготовимся к подключению к нашему экземпляру через SSH. Мы переместим наш pem-ключ из папки загрузок в папку .ssh. Затем мы защитим наш pem-ключ с помощью команды chmod, разрешив доступ только user, read.

mv ~/Downloads/YourAppKP.pem ~/.ssh
chmod 400 ~/.ssh/YourAppKP.pem

Чтобы подключиться через SSH, нам понадобится наш общедоступный IP-адрес IPv4 нашего запущенного экземпляра. Вернитесь в браузер, перейдите на страницу «Экземпляры» и щелкните свой экземпляр, чтобы просмотреть сведения о нем. Общедоступный IP-адрес должен быть доступен на вкладке «Описание».

Мой публичный IP-адрес 3.224.202.92. Обязательно замените это своим собственным IP-адресом в следующей команде.

ssh -i ~/.aws/YourAppKP.pem  [email protected]

После запуска этой команды вы должны подключиться к своему экземпляру EC2 через SSH. Давайте подготовим экземпляр к использованию, установив необходимые зависимости.

sudo yum update -y
sudo yum install git -y
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
. ~/.nvm/nvm.sh
nvm install v12
npm install -g yarn

Если все прошло гладко, теперь на вашем экземпляре будут установлены git, node 12. *, npm и yarn. Следующее, что нам нужно сделать, это разрешить нашему экземпляру связываться с GitHub через пару ключей, которую мы сгенерируем в нашем экземпляре. Замените следующую команду своим адресом электронной почты и следуйте подсказкам по умолчанию.

ssh-keygen -t rsa -b 4096 -C "[email protected]"

Теперь нам нужно переместить наш недавно созданный открытый ключ в настройки GitHub учетной записи, которую мы использовали для настройки нашего репо. Выполните следующую команду и скопируйте вывод открытого ключа.

cat ~/.ssh/id_rsa.pub

Войдите в GitHub и перейдите в раздел Настройки - ›Ключи SSH и GPG, а затем нажмите кнопку« Новый ключ SSH ». Дайте ключу название, вставьте свой открытый ключ и сохраните.

Теперь ваш экземпляр должен иметь возможность отправлять и извлекать данные из репозитория GitHub. Вернитесь в командную строку EC2 и клонируйте свой проект на экземпляр. Замените название проекта своим собственным.

git clone [email protected]:Integral-Stack/tinacms-cloud-editor-tutorial.git

Запустите свой облачный редактор

Из нашей командной строки SSH давайте cd в проект и установим наши зависимости npm.

cd tinacms-cloud-editor-tutorial
yarn install

Теперь используйте vim или nano для создания файла с именем .env.cloud, а затем скопируйте и вставьте переменные среды из локального .env.cloud файла в этот новый файл. Когда это будет сделано, вы можете удалить .env.cloud из репо локально. Он нужен нам только для облачного редактора.

Перед запуском облачного редактора мы также захотим повысить нашу безопасность, запустив его из ветки, отличной от master. Это означает, что изменения, внесенные на наш веб-сайт через облачный редактор, будут зафиксированы и отправлены в эту новую ветку на GitHub. Если вы создаете производственные сборки из master, это защитит кого-то от любого ущерба, если ваши учетные данные облачного редактора будут скомпрометированы. Имейте в виду, что с этой стратегией вам нужно будет периодически делать PR с обновлениями контента в мастере и развертывать их в производстве. Я собираюсь использовать ветку под названием cloud-editor, но вы можете использовать все, что захотите.

git checkout -b cloud-editor

Теперь мы готовы запустить наш облачный редактор. Нам нужно будет запустить приложение с хостом 0.0.0.0 (INADDR_ANY), а не localhost, чтобы оно было должным образом открыто для общественности через нашу группу безопасности, которую мы настроили ранее. Нам также нужно будет запустить процесс отдельно от нашего сеанса SSH, чтобы он мог работать и работать в фоновом режиме.

По этим двум причинам мы просто не можем просто запустить yarn start. Давайте протестируем команду запуска сервера, которую мы будем использовать, прежде чем двигаться дальше.

yarn develop -H 0.0.0.0 -S

Если вы получите следующую ошибку, вам нужно будет создать каталог ca-certificates.

cp: cannot create regular file ‘/usr/local/share/ca-certificates/devcert.cer’: No such file or directory

Выполните следующую команду, чтобы создать этот каталог:

# Run this command to fix the error
sudo mkdir /usr/local/share/ca-certificates

Как только вы подтвердите, что ваш сервер разработки может работать в облаке, мы захотим запустить нашу команду в автономном режиме. Для этого мы будем использовать nohup.

nohup yarn develop -H 0.0.0.0 -S &

Мы не увидим вывод команды, но мы можем проверить, что сервер разработки Gatsby запущен и работает, посетив действующий сайт. Для этого вернитесь в консоль AWS EC2 и скопируйте свой адрес «Public DNS (IPv4)» из вкладки «Описание», вставьте его в свой браузер. Не забудьте добавить https:// в начале URL-адреса и добавить порт :8000 в конец, прежде чем нажимать Enter. Мой URL-адрес выглядит так:

https://ec2–3–224–202–92.compute-1.amazonaws.com:8000

Поскольку мы используем самозаверяющий сертификат SSL, вы должны перейти на следующую страницу, где вам нужно будет нажать «Дополнительно» - ›« Перейти к… »в чтобы получить доступ к сайту. Вам будет предложено только одно сообщение с этим сообщением.

Если ваш облачный редактор загружается, поздравляем! Сначала вам будет предложено ввести имя пользователя и пароль, после чего вы сможете вносить изменения на свою веб-страницу. Второе, что вам нужно будет проверить, - это функция TinaCMS «Сохранить». Это действие должно сгенерировать и отправить новую фиксацию из вашего экземпляра EC2 в GitHub. После сохранения некоторых изменений перейдите на GitHub и убедитесь, что фиксация отображается в текущей ветке, которую вы выполняете.

На этом урок завершен. Прокомментируйте или задайте вопросы ниже.

Как мы можем улучшить?

Инфраструктура как код.

Теоретически сервер должен быть подготовлен с помощью кода. Это означает использование образа докера Linux с node и установку yarn и git через Dockerfile. Кроме того, вы захотите внедрить все свои секреты в контейнер во время выполнения.

Если вы хотите пойти по пути AWS, это, вероятно, будет включать использование ECS для управления контейнерами и внедрение ваших секретов из хранилища параметров или диспетчера секретов. Эти секреты должны быть определены в определении задачи ECS, чтобы они вводились во время выполнения. В этой настройке вы сможете выполнить сопоставление портов через Docker с целью хоста 8000 и выставить приложение на порт 80. Контейнер (ы) будет находиться за балансировщиком нагрузки приложения, что позволит вам настроить DNS в Route53. чтобы указать на ALB, и вы можете легко добавить https, настроив сертификат SSL с помощью диспетчера сертификатов.

И, если вы хотите сделать еще один шаг вперед, вы можете настроить это с помощью шаблонов CloudFormation, чтобы ресурсы AWS предоставлялись с помощью кода.

Это много! Если кто-то решит это сделать, дайте мне знать, потому что я хотел бы использовать код.