Showing posts with label cloud. Show all posts
Showing posts with label cloud. Show all posts

Saturday, January 26, 2019

Why Azure supports only unicast traffic?

Заинтересовался таким вопросом: почему микрософтовское облачко, Azure, не позволяет групповой (multicast) и широковещательный (broadcast) трафик между виртуальными машинами? Не означает ли это, что они используют на уровне ниже IP не Ethernet, а какой-то свой протокол, специально под облако заточенный?

(Я не имел дела с Амазоном, но и там та же петрушка, насколько я понимаю.)

Ответ: в общем, да.

В Azure решают проблему создания миллионов виртуальных сетей поверх единой физической благодаря протоколу VXLAN - если Ethernet-фрейм, посылаемый виртуалкой, предназначается для виртуалки на другом хосте, то он инкапсулируется виртуальным свитчем (процессом, бегущим на гипервизоре) внутрь UDP-пакета, и этот пакет доставляется по физической сети этому другому хосту. Там виртуальный свитч извлекает оригинальный фрейм и передаёт его своей виртуалке. Для обоих виртуальных машин всё выглядит так, словно они сидят в одном сегменте Ethernet.

Как в такой архитектуре можно передавать multicast или broadcast трафик? Два способа:

1. Рассовывать его по пакетам-носителям типа multicast и посылать их всем хостам, на которых определёна та же виртуальная Ethernet-сеть (насколько я понимаю, ей в Azure соответствует объект Subnet).

2. Рассовывать его по пакетам-носителям типа unicast и размножать их: посылать отдельную копию для каждого хоста из того же списка.

Обе опции проблемны. Допустим, у нас есть 1000 хостов, но из них виртуалки в этой сети существуют лишь на 20-ти. Тогда:
  • В первом случае нам придётся доставлять пакет-носитель всей тысяче хостов. Раутеры и свитчи в физической сети между ними понятия не имеют, какие виртуальные сети существуют на каких хостах, и потому оптимизировать трафик, доставляя такой пакет лишь заинтересованным в нём хостам (подобно тому, как это делается функцией IGMP snooping в традиционных VLAN-ах) не могут. Стало быть, если у нас какая-то виртуалка сгенерирует multicast-поток в 100Mbps, то каждый хост в датацентре получит все эти 100Mbps, в большинстве случаев совершенно для него бесполезные.
  • Во втором же случае поток в 100Mbps приведёт к тому, что хосту-отправителю придётся высылать 1.9Gbps (и даже слегка больше, учитывая overhead), высылая на каждый пакет с виртуалки девятнадцать своих, по одному на каждый хост с той же сетью.
То есть оба варианта могут значительно добавить нагрузку на облако - на сеть и на процессорное время, потраченное на обработку бесполезного трафика. Именно поэтому инженеры Azure решили, что единственным разрешённым видов трафик будет unicast. На каждый пакет, посылаемый виртуалкой, будет приходиться максимум один пакет, посылаемый по физической сети меж хостами - либо вообще ни одного, если предназначен он виртуалке на том же хосте.

Тут внимательный читатель воскликнет - позвольте, а как же ARP? Как же виртуалки будут узнавать MAC-адреса друг друга или раутеров, и что вообще будет писаться в поле "destination MAC" исходящих пакетов?

А вот что: на любой ARP-запрос с виртуалки vSwitch, то есть процесс, бегущий на хосте, ответит одним и тем же фальшивым MAC-адресом: 12:34:56:78:9a:bc. То есть любой пакет, на любой IP-адрес, будет послан виртуалкой на этот destination MAC.

Ну хорошо, а как же тогда пакеты доставлять? На адрес A в той же сети пакет ушёл с этим MAC, и на адрес B в ней же, и на адрес C в другой сети, и на адрес D вообще где-то в Интернете - и у всех MAC одинаковый. Что же с ним делать?

Ответ: а ничего не делать. Облаку плевать на MAC, доставка происходит прямо по IP-адресу получателя. То есть - к примеру, vSwitch получает от виртуалки пакет, где dst IP = 1.2.3.4 и dst MAC = 12:34:56:78:9a:bc. Если адрес 1.2.3.4 принадлежит другой виртуалке на том же хосте и той же сети, то пакет будет передан ей, и конец делу. Если же на другом хосте - то пакет будет обёрнут в VXLAN-пакет на адрес того хоста, и послан туда. Там, соответственно, будет декапсулирован и передан по назначению.

То есть традиционный Ethernet-свитчинг  в Azure customer networks  реально не используется - Ethernet лишь эмулируется для виртуалок. Этим эти сети отличаются от customer networks в OpenStack или CloudStack, где виртуальные и физические свитчи по-прежнему имеют дело с MAC-адресами.

Отсюда следуют несколько важных следствий:

1. Любой протокол не на основе IP (скажем, IPX, если кто ещё помнит такой) работать в Azure не может по определению.

2. Нельзя просто раздать виртуалкам дополнительные адреса (secondary IPs, loopback adapters) или передавать через них трафик из других сетей (скажем, использовать их для VPN) и ожидать, что всё будет работать. Нет. Облако должно знать, какие адреса относятся к каким машинам. Если машина посылает пакет с source IP, который ей не принадлежит и о котором облако не знает, он будет выкинут нафиг.
Есть два способа это починить:

  • если этот source IP относится к тому же сабнету - то можно облаку указать его как secondary IP этой виртуалки.
  • или же можно указать, что виртуалка занимается передачей чужого трафика (включить IP forwarding) и настроить на неё user-defined route (UDR), чтобы ответы на эти адреса приходили к ней. Обычно это делают, если виртуалка работает как firewall / VPN gateway.
3. Допустим, у нас есть сеть 10.10.10.0/24, в ней есть две машины (10.10.10.11 и 10.10.10.12), и для обеих определён общий default gateway, 10.10.10.1.
И допустим, что вторая виртуалка работает VPN-гейтом, передавая трафик от удалённой сети 192.168.12.0/24.
Тогда чтобы позволить первой машинке общаться с этой удалённой сетью, в обычных сетях нам надо было бы определить на ней маршрут через вторую:
    route -p add 192.168.12.0/24 10.10.10.12

Но в Azure в этом нет необходимости. Поскольку в тот момент, что первая виртуалка пошлёт пакет на адрес, скажем, 192.168.12.222 - будет совершенно неважно, имела ли она в мыслях передать его напрямую, или на дефолтовый гейт 10.10.10.1, или на VPN-гейт 10.10.10.12, и чей именно MAC-адрес она запрашивала по ARP миллисекундой ранее. Пакет будет выглядеть совершенно одинаково:
src IP  = 10.10.10.11,     dst IP  = 192.168.12.222
src MAC = some_MAC_of_VM1, dst MAC = 12:34:56:78:9a:bc


После чего произойдёт следующее: vSwitch проверит свою таблицу маршрутов и узрит в ней user-defined route: на сеть 192.168.12.0/24 ступай через 10.10.10.12. После чего пакет передан второй виртуалке - либо напрямую, если она на том же хосте, что и первая, либо, если она на другом хосте - то через туннель VXLAN между этими хостами.

Вот такие пироги.

Thursday, December 27, 2018

Highly-available Fileserver in a IaaS cloud

Вот есть, скажем, IaaS-облачко, а в нём виртуалка с Windows, работает файловым сервером - публикует папки по обычному протоколу SMB. Хочется, чтобы если она упадёт, файлы были доступны с какой-нибудь другой. Как этого добиться минимальными средствами?

Казалось бы, для такого совершенно стандартного желания и решение должно быть совершенно стандартным, особенно уж для такой неновой и распространённой штуки, как общие папки Windows: поставь такую-то фичу, и щёлкни раз-два-три. Ага, щас!


Вариант 1 - shared storage

Удобнее всего, конечно, чтобы у двух виртуалок был общий диск. Тогда на них можно настроить Failover Cluster, в нём запустить fileserver role с такой прекрасной фичей, как Transparent Failover, которая позволяет клиентским приложениям вообще не чувствовать, что сервер сменился. Клиенты будут обращаться по некоему floating IP, который будет переходить с сервера на сервер вместе с ролью в случае фэйловера. Скажем, в данном примере этому IP соответствует DNS-имя Filer:

Но увы! наше облачко такое не предоставляет.


Вариант 2 - репликация

Пускай у каждой из виртуалок будет свой местный диск, а мы будем файлы между ними синхронизировать.
В набор Windows Server для таких дел входит DFS Replication (DFS-R).

Достоинства:
  • фича входит в стандартный набор в Windows Server, ей сто лет в обед.
На этом достоинства заканчиваются и начинаются недостатки:
  • главный - никаких гарантий по части целостности данных. Один клиент может изменять файл на одном сервере, а другой в то же - тот же файл на другом сервере, и пожалуйста: конфликт;
  • если файл залочен клиентом, то изменения в нём копироваться не будут, пока клиент замок не снимет; пример - логи. Стало быть, его чтение с другого сервера реальное содержание не покажет;
  • очень непрозрачный и недокументированный способ работы. Пример: если файлы синхронизуются более-менее сразу, то вот изменения в NTFS permissions или ownership - со здоровенной задержкой, могущей доходить минут до 20. В чём логика, догадываюсь - такое изменение может переписать ACLs сверху вних по здоровеннейшему дереву, так что лучше подождать, пока юзер закончит их вносить, и лишь затем реплицировать. Но вот не документировано это нигде. В случае накладок, десинхронизации, конфликтов понять, что именно пошло не так, очень тяжело.
Схожий по функциям софт от прочих производителей я не пробовал, но наверняка и у них те же ограничения.

Поскольку это не кластер, и никакого floating IP между серверами нет, как нам обеспечить переключение? Тут может помочь другая фича - DFS-Namespaces или DFS-N, она позволяет распределять клиентов между двумя или более серверами. К Replication она отношения прямого не имеет - она просто позволяет замаскировать UNC-пути к общим папкам на разных серверах за одним общим путём, и неважно, каким образом файлы на этих серверах оказались. К примеру, при обращении к контроллеру домена example.org по пути \\example.org\SHARED\Folder, SMB-клиент Windows получит ссылки на два пути:
  • \\server1.example.org\SharedFolder
  • \\server2.example.org\SharedFolder
Он выберет одну из них и будет работать соответственно либо с одним сервером, либо с другим - а если тот перестанет отвечать, переключится на другой.

Фича полезная, но failover достаточно медленный - если сервер вдруг пропадает с горизонта, то клиент сперва пытается посылать пакеты по существующему TCP-соединению, затем - открыть новые на тот же сервер, и лишь затем - пойти на следующий сервер по списку, полученному от DFS namespace. Уходит на это секунд 80.

Ещё возможность: просто определить DNS-имя, указывающее на IP-адреса обоих серверов -  к примеру:
  • filer.example.org = 192.168.10.100
  • filer.example.org = 192.168.20.100
Тогда клиенты распределятся между серверами - получив от DNS оба адреса, одни выберут первый, а другие - второй. Если же выбранный адрес перестанет отвечать, SMB-клиент достаточно умён, чтобы переключиться на второй - см. ниже про failover. Занимает процесс около 30-ти секунд.

Недостаток - не будет работать протокол аутентификации Kerberos, поскольку SMB-служба на каждом сервере привязана к его личному computer account в Active Directory, а аккаунт - к его личному хостнейму. Привязать же общий хостнейм к обоим аккаунтам нельзя. Можно ли запустить SMB-службу не под локальным аккаунтом (SYSTEM), а под доменным - обычным юзерским или gMSA? Не знаю, не пробовал.

Впрочем, всегда есть в запасе старый добрый NTLM.


Вариант 3 - виртуальный shared storage

Если облако не предоставляет shared storage, давайте построим его сами!
Тут, конечно, напрашивается воткнуть ещё одну виртуалку, которая будет предоставлять диски для наших файлсерверов по протоколу iSCSI - и тогда мы можем построить красивенький Failover Cluster и радоваться. Но это будет, естественно, самообман, потому как тогда наш iSCSI-сервер станет единой точкой отказа - если он рухнет, то всему хана.

Стало быть, надо подымать не одну виртуалку, а пару-тройку и реплицировать между ними на сей раз не файлы, а блоки. Что сразу же сильно усложняет систему: нам-то хотелось всего-навсего, чтобы пара Windows-машинок подменяла друг друга в случае чего, а тут приходится сооружать целый зоопарк.


Можно попытаться функции совместить: а пускай наши файлсервера заодно и работают как virtual SAN - синхронизируют между собой некий виртуальный диск и к нему же и подключаются как iSCSI-клиенты (то, что называется модным словом hyper-converged).
Но:
  • это повышает риск - надо полагаться на то, что при поломке, падении, перезагрузке не только Failover Cluster отработает как надо, но и virtual SAN.
  • вариантов virtual SAN очень много, но большинство из них под Линукс. Стало быть, на наши виртуалочки их не воткнёшь.
  • вероятно, что количество виртуалок всё равно придётся повышать до трёх, чтобы избежать возможности split brain.
На практике я опробовал два подхода к этому снаряду:

1. Windows S2D - первый кандидат, поскольку готовая фича в Windows Server 2016. Очень хотелочь бы опробовать, но увы. У неё суровые требования к локальным дискам, которые без хаканья на уровне VMware обойти нельзя. А облачко подобных игр не позволяет.

2. StarWind vSAN - привлёк внимание тем, что написан для Windows и интересной бизнес-моделью: разница между платной и бесплатной версиями лишь в отсутствии в бесплатном варианте техподдержки и графической консоли - управление идёт через PowerShell. Освоить ихний PowerShell совсем несложно, но:
  • требует он скрупулёзной внимательности и аккуратности, особенно если создаёшь много дисков; цена опечатки может быть слишком высока.
  • увы, багов слишком много. Диски могут рассинхронизироваться навсегда от простой перезагрузки; одни и те же команды могут выполняться раз выполняться, а раз - выдавать совершенно невразумительные ошибки; траблшутить всё это одному - не легче, чем DFS, а то и тяжелее. И привести эти баги могут к очень тяжёлым последствиям.
Основательно намучившись, решил, что в продакшене у меня никакого Старвинда не будет. Возможно, что при работе через платный GUI вдруг та же система проявляет чудеса надёжности, но мне это что-то сомнительно.


Конечный вариант - слоноптица

В конце остановился на совмещении вариантов 1 и 2: дублировать файлы с помощью DFS Replication, но при этом использовать плавающий адрес Failover Cluster для доступа к ним.


Иными словами, если у нас есть \\server1.example.org и \\server2.example.org, то для доступа к файлам мы будем использовать  некое третье имя - скажем, \\filer.example.org - и оно будет привязано к кластерному IP-адресу, переходящему от одного сервера к другому в случае падения. Или же IP-адресам, в случае если наши сервера сидят в разных сетях.

Строится это следующим образом:
  1. Определяем DFS-R между двумя машинами.
  2. Добавляем обе в Failover Cluster. Поскольку shared storage у нас нету, используем какой-нибудь удалённый shared folder как quorum witness - или Azure как cloud witness.
  3. Создаём в кластере empty role, даём этой роли некое имя, привязываем к IP-адресу, прописываем в DNS. Computer account в Active Directory для этой роли не создаётся - незачем.
  4. Определяем на каждой машине те же shared folders на основе дерева, синхронизируемого посредством DFS-R.
Это позволяет, с одной стороны, использовать локальные диски. а с другой, избежать недостатков DFS:
  • все клиенты юзают тот же сервер, который будет предоставлять замок на запись в конкретный файл лишь одному из них. Чтение изменений в файле доступны всем сразу.
  • соответственно, нет конфликтов между серверами, все изменения идут в одном направлении.
  • очень быстрый graceful failover, если оба сервера в той же сети (не graceful - не очень). См. ниже.
Но стоит учитывать:
  • мы лишаемся возможности распределять нагрузку между серверами (нам это особенно и не нужно - она и так мала).
  • если файл был открыт на запись, были внесены изменения, записаны на диск, но сервер рухнул перед тем, как замок был снят - значит, реплицированы эти изменения не были. Если рухнувший сервер подымется перед тем, как тот же файл был изменён на втором - репликация произойдёт. Если после - то реплицирована будет версия файла со второго сервера, поскольку у неё будет метка времени посвежее.

Дополнения и уточнения
Свидетель из Фрязино

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

Почему? Для избежания неприятной ситуации под названием "split brain", когда оба сервера считают себя главными и могут, в отсутствии координации друг с другом, искорёжить данные.

Как этого избежать? Есть два варианта:
  • Добавить третий сервер в кластер - и заодно в replication group DFS-R, чтобы копия файлов была на всех трёх.
  • Добавить так называемого "свидетеля" (witness).
Свидетель этот является не процессом, как сервер, а просто-напросто неким "журналом", куда оба сервера могут писать, отмечаясь, что они живы и указывая, кто из них в активной роли. 
  • Если сервер обнаруживает, что не слышит второй, но "свидетель" доступен - он продолжает работать.
  • Если он обнаруживает, что не может связаться ни со вторым, ни со "свидетелем" - он останавливается.
  • Если оба сервера общаются нормально, но "свидетель" отвалился - они продолжают работать как обычно.

В Windows 2016 есть три варианта для witness:
  1. Либо это shared disk, общий для всех узлов кластера - но мы начали с того, что наше облако таких не предоставляет. Если предоставляет - нам не нужна эта морока с DFS-R, стоит выстроить просто обычный Failover Cluster по рецептам Microsoft.
  2. Либо эта shared folder на каком-то третьем SMB-сервере - но тогда надо иметь этот сервер. Его не надо подключать в кластер, достаточно, чтобы он был доступен с обоих кластерных узлов. Это может быть контроллер домена, к примеру.
  3. Либо (новая фишка Win2016) это может быть blob в микрософтовском облаке - в Azure storage account. Но тогда надо располагать подпиской на Azure.

Немного технических потрохов про failover:

Скорость переключения очень зависит от того, происходит ли оно в результате того, что бывший активный сервер сам сдаёт полномочия (graceful failover - по команде админа или из-за "мягкой" перезагрузки) - или же в результате резкого падения сервера или полной потери связи с ним. Если graceful может занять до 5 секунд, то hard failover - до 20-ти. Разница происходит от того, что оставшемуся серверу надо во втором случае установить, что ранее активный признаков жизни не подаёт - ни напрямую, не через witness (см. ниже) - а в первом тот может сообщить и сам.

После того, как второй сервер решает тянуть одеяло на себя, события могут развиваться по следующим сценариям:

Внутри одной сети (VLAN, subnet):

Перенос кластерного IP - очень быстрая операция, прозрачная для клиента: сервер, забирающий его к себе, отсылает ряд пакетов Gratuitous ARP (GARP), прописывающих новый MAC-адрес для этого IP в ARP-таблице подключённых к той же сети раутеров или клиентов. Заодно и свитчи, физические или виртуальные, прописывают у себя, на каком порту сидит этот MAC. Всё, трафик продолжает течь как тёк.
Естественно, TCP-подключения при этом слетят - поскольку новый сервер вдруг получит какие-то TCP-пакеты без SYN-флага. Но поскольку при этом он отошлёт RST, клиент возобновит их сразу же, без попыток повторных передач.

Между разными сетями:

Естественно, перекинуть floating IP из сети в сеть нельзя, да и незачем. Решается эта задача вот как. Наш Failover Cluster в курсе о существовании двух сетей - по каждой на сервер. Мы можем привязать нашу кластерную "роль" к двум IP-адресам - по одному на сеть - и прописать между ними "OR dependancy". Иными словами, для того, чтобы "роль" запустилась на хосте, достаточно, чтобы один из этих адресов был доступен.

Затем мы прописываем оба адреса в DNS на одно и то же имя - к примеру:
  • filer.example.org = 192.168.10.100
  • filer.example.org = 192.168.20.100
SMB-клиенты при запросе получают из DNS оба адреса и пытаются параллельно подключиться на оба. Лишь один из них ответит (в этом разница со случаем, если бы мы просто приписали к этому имени частные IP-адреса server1 и server2, о чём см. выше).

Если посреди работы с одним из адресов он перестаёт отвечать - Windows пытается в течении 15 секунд повторять (retransmit) запрос на уровне того же TCP-соединения - а затем посылает RST и снова пытается подключиться на оба одновременно. И если наш Failover Cluster отработал как положено - то соединение на второй адрес будет установлено благополучно.

В обоих вариантах, ещё пара секунд уйдёт на аутентификацию клиента против нового сервера - по Kerberos или NTLM.

Какой вариант быстрее? Это, как сказано выше, зависит от того, насколько быстро передадут друг другу роль наши сервера.
В случае graceful failover - переключить IP-адреса между двумя MAC-адресами в той же сети берёт намного меньше времени, чем дождаться, пока SMB-клиент начнёт стучаться по запасному адресу.
В случае же hard failover - наибольшую задержку обеспечит сам кластер.

Но и даже в наихудшем случае оба варианта всё же куда быстрее, чем переключение между двумя UNC-путями, полученными от DFS-N.


Ещё свидетель. Но совсем другой. И сугубо опциональный.

Есть некий способ сократить время, которое SMB-клиент тратит на переподключение. Идея в следующем: подключившись к кластеру по floating IP, клиент получает адреса всех узлов кластера. Затем он устанавливает соединение на один из неактивных узлов, и просит тот сообщить ему по дружески, если активный вдруг отвалится  - предполагается, что узлы кластера узнают об этом событии раньше, чем клиенты. Если клиент получит такую подсказку - то начнёт переподключение немедленно, не ожидая, пока существующее TCP-соединение вылетит по таймауту.

Называется этот узел-подсказчик опять таки witness - и он, хотя имеет прямое отношение к Failover Cluster и к shared folders, не имеет ничего общего со "свидетелем" для координации кластера, о котором рассказано выше. Спасибо Микрософту за этот гнусный бардак в терминологии.

Несмотря на то, что звучит эта идея интересно, у себя я это включать большого смысла не вижу, и вот почему:
  • в случае переключения между узлами кластера в той же сети IP-адрес остаётся тем же, и клиент будет пытаться переподключиться на него же. Если новый активный узел этот адрес ещё не подобрал - неважно, продолжает ли клиент стучаться по тому же TCP-соединению, или пытается установить новое, один чёрт он в ответ ничего не получит. Если же подобрал - то на попытку retransmission по старому соединению он моментально ответит сегментом RST, после чего клиент тут же откроет новое.
  • В случае hard failover между узлами в разных сетях, новому активному узлу возьмёт даже больше времени принять на себя роль, чем клиенту - переподключиться по запасному адресу.
Таким образом, единственный случай, где есть смысл в этом протоколе - это graceful failover в кластере, разнесённом по двум разным сетям. Но дело ещё и в том, что он не очень-то дружелюбен к файерволлам. Для того, чтобы он работал, нам надо дополнительно к SMB на floating IP позволить также RPC на него же, а так же RPC на все индивидуальные адреса кластерных узлов. Поскольку открывать при этом клиентам доступ на личные SMB-службы этих узлов не хочется, эта бодяга требует двух правил вместо одного:
  1. SMB на адрес fileserver role
  2. RPС на адрес fileserver role + адреса серверов
Во-первых, это усложняет конфигурацию, а во-вторых, открытие доступа к RPC само по себе является дополнительным риском. Поэтому овчинка, на мой взгляд, выделки не стоит.

Впрочем, насколько я понимаю, придуман witness protocol не столько для кластерного файлсервера общего назначения, о котором этот пост, сколько для Scale-Out File Server. А в рамках Scale-Out не существует floating IP - соединения устанавливаются на адреса самих серверов. В этом случае заранее знать, что такой-то адрес отвалился и стучаться к нему незачем, действительно имеет большой смысл. Впрочем, Scale-Out я тут не рассматриваю.

Monday, April 24, 2017

Google Apps as SAML IdP

Ознакомился с возможностями Гугла в качестве Identity Provider по протоколу SAML.
Вкратце: не впечатлён. Понимаю теперь, почему ЖЖ, StackOverflow и прочие, тысячи их, используют oAuth.

Недостатки такие:

  • Identity сайта / приложения, желающего опознавать гугл-юзеров по SAML, криптографически никак не проверяется, запросы не подписываются, да и возможности залить соответствующий ключ Гуглу для проверки нету.
    Единственное, что проверяется - что строка "Entity ID", указанная Гуглу при регистрации приложения, соответствуюет полю <saml:Issuer> в запросе. Есть совпадение - и ладушки.

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

    Ответ, правда, подписывается честь по чести. Возможности зашифровать его, впрочем нету, да и нечем - ключ, как сказано выше, указать негде.

  • В отличие от сценария с oAuth, Гугл никак не предупреждает юзера, что собирается передавать информацию о нём третьей стороне, и уж тем более не разъясняет, какую именно.
    Просто получаешь страничку аутентификации, проходишь её и возвращаешься на исходный сайт, без каких-либо комментариев. Нехорошо, товарищи гугловцы.

  • Недостаток, несколько смягчающий два предыдущих: очень убогие возможности по части юзерских атрибутов, которые можно прописать в ответе запрашивающему приложению. Можно указать имя, фамилию, e-mail, номер телефона или адрес (а вот это для фишеров уже интересно!), а из корпоративной информации - название должности, департамент и cost center (что бы это не значило). Фсё. Группы, к которым юзер принадлежит в Google Apps, указать никак нельзя, к глубокому моему удивлению.
    ADFS по этому критерию кроет Гугл, как бык овцу.

  • А да, и касается вся эта бодяга исключительно юзеров G-Suite (Google Apps). Обычные юзеры, с @gmail.com в названии, могут не волноваться.

Недостаток у oAuth про сравнению с SAML, правда, тоже есть: он требует от приложения знать конкретный API, от которого оно будет получать информацию после получения юзерского согласия - гугловский ли, фейсбучный или твиттеровский. SAML более стандартизирован (и оттого сложен, как моя жизнь). Хотя при "феодальной" модели, при которой identity provider'ов для 90% сетевого населения можно пересчитать по пальцам, этот недостаток не очень-то заметный.

А вот что может рассматриваться и как преимущество, и как недостаток, так это то, что в oAuth приложение обретает долгосрочный доступ к юзерским данным (тем, к которым ему разрешили лезть). А вот в SAML этого нет - что оно получило при аутентификации, тем и придётся довольствоваться.

И наконец, однозначное преимущество SAML в том, что он не требует прямой связи между приложением и IdP. Сайт с приложением может сидеть во внутренней сети и никуда из неё не выходить, а IdP - в Интернете (тот же Гугл), и весь обмен между ними будет проходить через юзерский браузер.


А вот чем очень приятно впечатлён, это опен-сорсной библиотекой Keycloak, которую использовал, чтобы встроить SAML  в свою маленькую Java-апликацию. Вставляешь servlet filter - и готово, можешь считать юзерский аккаунт и, положим, департамент, через привычные, милые сердцу вызовы getUserPrincipal() и isUserInRole()Причём, поскольку это стандартный servlet filter, можешь гонять свою апликашку на любом Java-сервере - хошь Tomcat, хошь Glassfish, хошь JBoss.