Безопасность приложений SharePoint 2013

Система разрешений в новой архитектуре приложений в SharePoint 2013 (о которых я писал ранее) до сих пор вызывает много вопросов. Попробую прояснить некоторые из них:

Введение

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

В FullTrust возможно повышение привилегий путем создания объекта SPSite с токеном более привилегированного пользователя (SPUserToken.SystemAccount). Код с повышенными привилегиями может делать всё (вообще всё). Поэтому любое решение или опасно, или почти бесполезно. Еще одна проблема повышения привилегий – невозможно отследить какой пользователь и какие действия вызвали изменения, потому что везде будет один и тот же пользователь даже для разных решений.

App Principals

Для решения проблем обозначенных выше, приложения решили сделать участниками системы безопасности (principal), также как и пользователей. Это означает что у каждого приложения есть свой App Principal, которому назначаются права.

Пользователь сопоставляется со своим principal в процессе аутентификации, то есть при передаче логина\пароля (или токена) от пользователя к SharePoint.

А как же происходит аутентификация приложений, ведь нету логинов и паролей у приложений...

Этот процесс описывает простая схема:

image

Схема не совсем точная, но в общем описывает процесс правильно.

Если не вдаваться в детали, то выполняются такие условия:

  1. Если пользователь аутентифицирован и происходит запрос к AppWeb, то используется App Principal + User Principal (внутренняя аутентификация).
  2. Если пользователь не аутентифицирован, но в запросе указан access token (внешняя аутентификация), то
    • Если в access token указан user identity, то то используется App Principal + User Principal.
    • Если в access token не указан user identity, то то используется App Principal  с App Only-Policy.
  3. Во всех остальных случаях аутентификация для приложения не происходит.

Внутренняя аутентификация

Скриншот манифеста свежесозданного SharePoint-hosted app, обратите внимание на элемент AppPrincipal.

image

Внутренняя аутентификация называется так, потому что все процессы аутентификации приложения происходят внутри SharePoint. Вам для этого не надо ничего писал и\или настраивать (только DNS для AppWeb).

Внутренняя аутентификация используется именно для SharePoint-hosted app и JavaScript кода. В других случаях сложно повторить условия для внутренней аутентификации. Чтобы нельзя было обойти внутреннюю аутентификацию и проверку прав приложения AppWeb создается на уникальном домене. Это позволяет блокировать JavaScipt обращения, используя same origin policy, которая встроена в браузер.

Есть еще возможность размещать клиентский JavaScript внешнем сайте, и он будут обращаться к AppWeb и будет работать аутентификация приложения.

Внешняя аутентификация

Если же поменять тип приложения на Provider-hosted , то можно увидеть такой манифест:

image

В элементе AppPrincipal появилось RemoteWebApplication. ClientId="*" заменяется на идентификатор приложения при отладке или публикации.

access token должен содержать идентификатор приложения, чтобы SharePoint мог привязать AppPrincipal. Для формирования Access token используется oauth или s2s trust. Оба доступны только в серверном коде внешнего приложения и не доступны в клиентском JavaScript.

Основная проблема в том, что нельзя одновременно указать внутреннюю и внешнюю аутентификацию. То есть нормально обращаться к SharePoint сможет или серверный код на внешнем сайте или JavaScript на AppWeb. Учитывая что многие стандартные компоненты SharePoint используют JSOM, то они не будут работать при внешней аутентификации. Это делает AppWeb почти бесполезным для Provider-hosted приложений.

OAuth

OAuth это протокол (правильнее сказать фреймворк), который описывает протоколы и сценарии аутентификации приложений в вебе. В Office 365 используется схема с тремя действующими лицами:

  • Приложение
  • Access Control Service (ACS)
  • SharePoint

SharePoint и приложение доверяют ACS, SharePoint не доверяет приложению напрямую (и правильно делает :) ).

Процесс аутентификации выглядит так:

  1. Пользователь нажимает на плитку приложения.
  2. SharePoint запрашивает у ACS так называемый context token по ClientId приложения и отдает context token клиенту (браузеру). Context token подписан с помощью ClientSecret, который известен ACS и приложению.
  3. Браузер делает POST запрос на адрес приложения и передает context token.
  4. Приложение проверяет context token с помощью ClientSecret и извлекает refresh token.
  5. Далее по refresh token приложение может получить access token от ACS и обращаться с ним к SharePoint.

Описание на MSDN: http://msdn.microsoft.com/en-us/library/office/fp142382.aspx

Параметры ClientId и ClientSecret вы получаете при регистрации в Office Store или при добавлении нового app principal на странице /_layouts/15/appregnew.aspx.

Важные моменты:

  •  Context token передается приложению POST запросом. При переходе н другую страницу в приложении context token не сохранится. Само приложение должно это делать. В Visual Studio 2013 включили класс SharePointContext, который управляет сохранением токенов в сессии.
  • Из-за использования POST нельзя реализовать OAuth на клиентском JavaScript. Даже не пытайтесь.
  • SharePoint и ACS напрямую не обращается к вашему приложению, кроме случаев использования Remote Event Receiver или Workflow. Поэтому SharePoint абсолютно все равно где и на чем работает ваше приложение. Это например позволяет отлаживать облачные приложения на локальной машине.

OAuth полагается на SSL, так как все токены передаются незащищенными от перехвата. Любое приложение SharePoint для Office 365 должно иметь SSL сертификат.

Как я писал ранее, в onprem по-умолчанию не работает OAuth и используется его расширение S2STrust. Можно интегрировать onprem ферму с тенантом office365, тогда появится возможность устанавливать provider-hosted приложения из маркета. Подробнее тут: http://msdn.microsoft.com/en-us/library/office/dn155905.aspx

S2S Trust

В onprem варианте вместо “трехногого” OAuth используется “двуногий” вариант, называемый Server-to-Server Trust. Суть в том что SharePoint доверяет серверу приложения. Для установления факта доверия в SharePoint должен быть добавлен Trusted Token Issuer, а это требует сертификата. Приложение этим сертификатом подписывает запросы на получение access token пользователя.

В “двуногой” схеме никаких context token и refresh token не используется. Приложение должно само аутентифицировать пользователя и передавать данные о текущем пользователе в SharePont. Да, это позволяет приложению притворяться любым пользователем.

Такие приложения называются приложением с высоким доверием (High trust), в отличие от full trust права приложения все-таки ограничиваются.

Подробнее тут: http://msdn.microsoft.com/en-us/library/office/fp179901.aspx

Права приложений

Независимо от того, какой вид аутентификации приложения используется,  приложению назначаются разрешения. Права приложения отличаются от прав пользователей:

  • Требуемые права задаются в манифесте.
  • Права приложению даются при установке по принципу “все или ничего”.
  • Права приложений не используют иерархию объектов SharePoint.

Вот так выглядит запрос прав манифесте, указываются области и требуемые права:

image

Полный список возможных разрешений: http://msdn.microsoft.com/en-us/library/office/fp142383.aspx

Для вычисления эффективных разрешений права пользователя и права приложения пересекаются. Porvider-hosted app может также получить app-only access token, если в манифесте приложения было указано app-only policy.

image

Надо учитывать что все это работает только для CSOM и REST вызовов. Обычные (устаревшие) веб-сервисы не поддерживают аутентификацию с помощью access token.

Права – основной источник проблем для приложений. Если вы дадите приложению недостаточно прав, то ошибки буду очень непонятными. Иногда сочетание прав для некоторой операции крайне неочевидно, например:

  • Публикация в социальную ленту требует Social Write, Tenant Write, User Profiles Read, если не дадите одно из них вам скажут “Social list not found” или что-то в этом роде.
  • Добавление типов контента на подсайт требует sitecollection read, хотя если вы будете тестировать приложение на корневом сайте, то прав web manage может хватить.

Есть еще возможность запрашивать права “на лету”, но это тема для отдельной статьи. Пока можете прочитать описание на MSDN: http://msdn.microsoft.com/en-us/library/office/jj687470.aspx

Заключение

Большая часть сложностей аутентификации приложений скрыто от глаз программистов, с помощью внутренних механизмов SharePoint и классов хелперов SharePointContext и TokenHelper. Тем не менее надо хорошо понимать внутренние механизмы, особенно разграничения доступа, чтобы успешно создавать приложения.

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

Изучайте, развивайтесь.



SharePoint Solutions vs Apps

Если вы еще не в курсе что такое apps (приложения), то прочтите предыдущий пост.

На этот рас попробуем разобраться когда надо использовать приложения, а когда стоит делать решения.

Приложения и решения не пересекаются вообще. Для приложений важна изоляция, чтобы приложение не повиляло на ферму и не делало то, чего делать нельзя. Для решений важна интеграция с платформой. Решения могут использовать возможности SharePoint, дополнять и улучшать их.

Microsoft предлагает всем делать приложения, в соответствии с cloud-first политикой. Считается что если сделать приложение, то оно заработает в Office 365 и onprem. Но именно в этом заключается первое заблуждение относительно приложений.

Первое заблуждение

Люди думают что onprem приложения также хорошо работают, как в облаке. На самом деле приложения, сделанные для Office 365 сложно использовать onprem.

Во-первых provider-hosted app просто так не заработают onprem, потому что onprem не работает OAuth. Можно настроить интеграцию onprem с Office 365, но это порядка на два сложнее и затратнее, чем сделать приложение.

Во-вторых можно настроить Server-to-Server Trust (S2S), но для такого приложения потребуется изменение исходного кода, деплой во внутренней сети, powershell скрипт для установки, который требует farm admin привилегий.

В-третьих – поддержка apps в onpremise варианте требует тщательной настройки  - приложения службы, DNS, сертификаты. Особенно часто возникают проблемы если надо выставить ферму с apps в интернет.

Единственный тип приложений, которые можно поставить из маркета, без дополнительных телодвижений – SharePoint-hosted. Но и тут есть проблемы...

Второе заблуждение

Люди считают что SharePoint-hosted app удобно использовать чтобы задействовать возможности SharePoint. На самом это возможно в очень ограниченных сценариях.

Напомню что SharePoint-hosted app – это артефакты SharePoint и JavaScript, размещаемые на отдельном сайте (AppWeb). Подробнее тут - http://www.instantquick.com/index.php/sharepoint-2013-app-web-versus-host-web-redux?c=elumenotion-blog-archive/sharepoint-2013-and-office-365-apps.

Проблемы:

Третье заблуждение

Люди считают что авторизация приложений (разрешения) поможет сделать эти приложения более безопасными. На самом деле разрешения зачастую работают против разработчиков и не способствуют повышению безопасности.

Во-первых для некоторых действий требуется слишком много разрешений. Например запись в социальную ленту требует прав записи в весь Тенант (в Office365) или во всю ферму (в onprem).  Такой высокий уровень разрешений позволяет делать приложению что угодно с вашими данными.

Во-вторых, чтобы установить приложение, пользователь его устанавливающий должен обладать правами, которое требует приложение. Например поставить приложение, требующее прав на тенант (даже только чтение), сможет только админ фермы.

В-третьих в маркет не принимают приложения, требующие full control. То есть серьезное приложение, использующее потенциал SharePoint, поставить из маркета невозможно.

Выводы

  1. SharePoint-hosted приложения подходят только для небольшого изолированного функционала. Например информеров погоды\пробок и (не дай бог) дней рождения.
  2. Provider-hosted в onprem имеет смысл только для интеграции существующего приложения в SharePoint. Создавать новое слишком накладно.
  3. В office 365 имеет смысл делать provider-hosted (с хостингом в Auzre Websites). Но мало что удастся получить приложению от SharePoint. Поэтому скорее будет вариант построить веб-приложение, а потом интегрировать с SharePoint. Примерно так работает новый LightSwitch.

Вкратце приложения имеет смысл делать или для чего-то простого, или для интеграции отдельных веб-приложений в SharePoint. А для всего остального...

Используйте Sandboxed Solution

Если вы начали возмущаться, говорить что Microsoft запретил Sandbox, то будете правы, почти. Microsoft запретил серверный код в Sandboxed решениях. И то “запретил” – громко сказано, сейчас он работает как в облаке, так и onprem.

Но вы можете в вашем решении разворачивать JavaScript код, типы контента, списки, страницы, шаблоны сайтов, workflow (в 2013 они декларативные), схему поиска и прочие радости. При этом также сохраняя стабильность фермы, даже если вы запускаете серверный код. Хотя потребность в серверном коде в SharePoint 2013 гораздо меньше.

Все новые возможности SharePoint 2013 (CSOM\REST, Client-Side Rendering) доступны для решений, также как для приложений. При этом для установки достаточно быть sitecollection администратором. Пока еще работает серверный код в Sandbox, вы можете легко делать Event Receiver.

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

Когда возможностей sandbox не хватит для реализации функционала вы можете сделать FullTrust решение, которые выставляет User Code Proxy и веб-части, а ваше Sandbox решение их использует. А в Office365, в случае нехватки возможностей Sandbox, можно в iframe показывать внешний сайт и делать Remote Event Receivers.

Заключение

По странному стечению обстоятельств новые возможности SharePoint вдохнули жизнь в концепцию, которую Microsoft пытался похоронить. Sandboxed решения свободны от недостатков SharePoint-hosted приложений, при этом гораздо проще, чем provider-hosted. Именно с них стоит начинать разработку для SharePoint, кроме самых простых случаев.

Кстати маркет можно использовать для привлечения клиентов, сделав прототип\демо вашего приложения в SharePoint-hosted варианте, и предлагая установить sandboxed ршение уже вне маркета.



SharePoint Apps Intro

С момента релиза SharePoint 2013 прошел ровно год. Я специально не писал ничего про Apps, собирал информацию и анализировал опыт.

Что такое Apps

Краткий дисклеймер для тех, кто не в курсе что такое Apps. Идея apps заключается в том, что пользователи смогут самостоятельно устанавливать приложения для SharePoint из Market или внутреннего каталога компании. Примерно также, как это происходит на мобильных устройствах. Но, в отличии от мобильных устройств, любой посторонний код для SharePoint очень опасен. Поэтому нужно этот код максимально изолировать, ограничить в правах и жестко контролировать.

Кажется мы то уже слышали в 2010 году, и тогда это были Sandbox Solutions? Именно! Мотивация такая же, как и раньше – увеличить стабильность фермы и дать больше возможности устанавливать решения пользователям.

Но Microsoft решил пойти шире и сказал что apps вообще не должны работать на серверах SharePoint. Это может быть JavaScript в браузере, или внешний веб-сервис, общающийся с SharePoint с помощью клиентской объектной модели.

Так как код становится внешним, по отношению к SharePoint, то там можно использовать любые языки и библиотеки. Angular или Backbone на клиенте, ASP.NET MVC+EF или даже PHP+MySQL на сервере.

Архитектура Apps

Здесь и далее я буду называть apps - приложениями, а solutionsрешениями.

Приложения ставятся на сайт (SPWeb) из того же интерфейса, из кодоторого создаются списки. Более того, теперь списки тоже называются приложениями, но это не более чем маркетинговый ход.

Технически приложения для SharePoint представляют манифест, который описывает как можно обратиться к App. Способов на самом деле немного:

  • Переход по ссылке на сайт приложения, это обязательно для любого приложения.
  • Отображение в iframe на странице SharePoint, примерно как веб-часть в решении.
  • Переход по ссылке или отображение в iframe в виде диалога из Ribbon или меню, примерно как custom action в решении.

Еще можно привязать внешний event receiver, но это уже нужно делать в коде приложения.

А теперь главный вопрос: где же будет работать приложение?

Тут два варианта:

  • Внешний, по отношению к SharePoint, веб-сервер. Его разработчик должен самостоятельно развернуть, настроить SSL, обеспечить доступность, изоляцию между экземплярами приложений, и прочие радости. Это называется Provider-hosted app. Есть еще вариант автоматического развертывания сайта в Azure из пакета приложения (AutoHosted), но он, спустя год после релиза, толком не работает в Office 365, а onprem скорее всего никогда не будет.
  • Подсайт в SharePoint. Для экземпляра приложения может быть создан отдельный сайт (appweb). На сайт можно разворачивать обычные артефакты SharePoint – страницы, файлы, списки, workflows. Серверный код нельзя деплоить, поэтому доступен только код на JavaScript. AppWeb автоматически удаляется при удалении приложения. Это называется SharePoint-hosted.

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

Маркет и монетизация приложений

Главная завлекаловка для разработчиков – возможность монетизировать приложения. Приложение может быть плантым и иметь разные варианты лицензирования. Платные приложения можно распространять только через маркет, при этом приложения проверяются людьми до попадания в маркет и требуется соблюдение правил (правила).

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

Что может делать приложение

Потенциально почти все. Клиентская объектная модель покрывает очень много возможностей – работа с артефактами SharePoint (сайтами, списками, элементами), поиск, таксономия, профили пользователей, публикация, социальные возможности, BCS и даже Project Server.

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

Еще есть app-only policy, когда права пользователя не учитываются, учитываются только разрешения приложения. Это как повышение привилегий, которого так не хватало в Sandbox. Но, увы, не работает в JavaScript коде.

Стоит ли использовать apps?

Спустя год вполне можно оценить насколько apps получили распространение, достаточно заглянть в маркет: http://office.microsoft.com/en-us/store/results.aspx?avg=osu150. Приложений не просто мало, а очень мало. Немалая часть из них – не живые. Также можно найти аналитику по использованию приложений -  http://www.instantquick.com/index.php/one-month-since-release-observations-lessons-learned-and-future-plans.

Среди моих знакомых мало кто пишет apps, несмотря на то что половина новых проектов стартует на SharePoint 2013.

Есть мнение что apps вообще не приносят ничего полезного для разработчиков: http://blog.furuknap.net/sharepoint-2013-app-model-solves-non-problems-only.

Все это составляет грустную картину про приложения. В следующий раз постараюсь проанализировать недостатки apps и дать развернутый ответ для чего стоит использовать приложения и решения SharePoint...



Материалы со встречи RuSUG 17.10.2013

Мой доклад про TypeScript  в SharePoint



Доклад Виталия Жукова про поиск:



Спасибо всем, кто пришел.



Встреча RuSUG 17-го октября. Наконец-то...

Мы долго ждали и верили и наконец-то... Встреча Russian SharePoint User Group сотоится 17-го котября 2013 года в Microsoft Technology Center на Белорусской в 19:00.

На встрече будут два доклада: мой про TypeScript и применение его в разработке для SharePoint, доклад Виталия Жукова (http://blog.vitalyzhukov.ru/) про Поиск в SharePoint 2013.

Ссылка на эвент на фейсбуке https://www.facebook.com/events/220294124804312

Регистрация обязательна (иначе вас в Microsoft Technology Center не пустят): http://rusug.timepad.ru/event/85241/