Безопасность всегда вызывала у меня интерес, с тех пор, как я впервые разработал AppFuse и выяснил, как обеспечить безопасность J2EE еще в 2004 году. Я взломал AppFuse, чтобы иметь функцию Remember Me , затем перешел на Acegi / Spring Security. Spring Security обладает необходимыми мне функциями, даже если для его настройки требуется почти 100 строк XML. В наши дни это намного лучше, и его JavaConfig — в сочетании с Spring Boot — довольно приятный.
Это была первая часть моей жизни в сфере безопасности. Второй этап начался ночью, когда я встретил Триш и узнал, что она продала продукты безопасности. Она знала об OWASP и их 10 лучших правилах. Именно Триш вдохновила меня на создание презентации по безопасности веб-приложений на Java . Мне очень понравилось писать эту презентацию, сравнивая платформы безопасности Apache Shiro, Spring Security и Java EE. Я проконтролировал первый раз, когда представил несколько постов и скринкастов . Хм, может мне стоит обновить презентацию / скринкасты, чтобы использовать только конфигурацию Java ( #NoXML ) и представить ее на пару конференций в этом году? Я отвлекся.
За последние пару недель мне пришлось сделать всплеск безопасности. Я пытался заставить аутентификацию SAML работать с Okta и сервером Active Directory моего клиента. К счастью, кто-то настроил интеграцию AD, поэтому все, что мне нужно было сделать, это попробовать несколько разных языков / сред. Я искал и нашел okta-образцы ThoughtWorks , которые включают примеры с использованием Node.js и Sinatra (Ruby + JRuby). Я также нашел пример Spring SAML, который включает одну из моих любимых вещей в JavaLand: конфигурация на основе Java.
Я рад сообщить, что мне удалось заставить все эти приложения работать с настройкой Okta моего клиента. Эта статья расскажет вам, как я это сделал. Для каждого приложения я создал новое приложение в Okta, используя его «Шаблон приложения SAML 2.0», и добавил себя на вкладку «Люди» приложения. Каждый раздел ниже содержит конфигурацию, которую я использовал для Okta. В приведенных ниже инструкциях предполагается, что вы похожи на меня, разработчика, на котором установлены Java 8, Node и Ruby, но нет конкретной платформы. Когда я пишу это, у меня все работает на моем Mac с Yosemite, но я написал инструкции ниже, используя один из моих старых ноутбуков, свежий после обновления Yosemite.
Первым делом я заказал образцы ThoughtWorks.
git clone https://github.com/ThoughtWorksInc/okta-samples.git
Node.js
Я начал с получения примера Node.js. Для конфигурации Okta я использовал:
настройка | Стоимость |
---|---|
Метка приложения | Пример Okta Node.js |
Принудительная аутентификация | ложный |
URL обратной ссылки | HTTP: // локальный: 3000 / Войти / обратный вызов |
Имя ID Формат | Адрес электронной почты |
Получатель | HTTP: // локальный: 3000 / |
Ограничение аудитории | HTTP: // локальный: 3000 / |
authnContextClassRef | PasswordProtectedTransport |
отклик | подписанный |
Утверждение | подписанный |
Запрос | Сжатый |
Назначения | HTTP: // локальный: 3000 / Войти / обратный вызов |
Заявления об атрибутах | электронная почта | $ {user.email}, ПгвЬЫат | $ {user.firstName} |
Образец Node.js использует Express , а также passport и passport-saml . Паспортные пакеты используются для обработки аутентификации SAML, а connect — для сжатия запросов с вашего локального сервера.
Единственное, что мне нужно было сделать, чтобы приложение Node.js работало, — это вставить строку сертификата X509 и целевой URL-адрес в config.json
приложение из приложения Okta. В интерфейсе администратора Okta я нажал на вкладку «Вход в систему» и нажал кнопку «Просмотр инструкций по установке». Я скопировал значение «URL перенаправления входа» и скопировал его в значение entryPoint файла config.json . Затем я скачал сертификат и открыл его в vi. Я выполнил следующие две команды, чтобы удалить ^ M и окончания строк ( подробнее здесь ).
Затем я скопировал все между -----BEGIN CERTIFICATE-----
и -----END CERTIFICATE-----
и вставить его в CERT значения config.json. Мне пришлось удалить комментарии из config.json, чтобы все работало.
После внесения этих изменений я смог запустить «npm install» и «npm start» и успешно войти в систему по адресу http: // localhost: 3000.
Рубин
Образец Ruby использует Sinatra , omniauth и omniauth-saml . Чтобы запустить приложение okta-ruby-sinatra, мне пришлось начать с установки Bundler.
sudo gem install bundler
Затем я установил все необходимые гемы для этого проекта, используя следующую команду.
bundle install
Это привело к следующей ошибке:
An error occurred while installing nokogiri (1.6.1), and Bundler cannot continue. Make sure that `gem install nokogiri -v '1.6.1'` succeeds before bundling
Я попробовал предложение Бандлера, но оно провалилось:
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension. /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby extconf.rb mkmf.rb can't find header files for ruby at /System/Library/Frameworks/Ruby. framework/Versions/2.0/usr/lib/ruby/include/ruby.h
Затем я попытался обновить до Xcode 6.1.1. Я получил ту же ошибку, и запуск «bundle update sinatra» и «sudo gem update —system» ничего не помог. Я нашел старый ответ Stack Overflow, в котором предлагалось запустить «xcode-select —install» для установки инструментов разработчика командной строки Xcode. После этого я запустил «sudo gcc», чтобы принять все лицензионные соглашения Apple. Я снова запустил «комплектную установку», и на этот раз он завершился ошибкой:
----- libxml2 is missing. please visit http://nokogiri.org/tutorials/installing_nokogiri.html for help with installing dependencies. ----- ... An error occurred while installing nokogiri (1.6.1), and Bundler cannot continue. Make sure that `gem install nokogiri -v '1.6.1'` succeeds before bundling.
Я снова попробовал предложенное Бандлером: «sudo gem install nokogiri -v ‘1.6.1’». Это не сработало, поэтому я попытался «обновить пакет», и в конце концов это сработало. В последний раз я запустил «пакетную установку», а затем «ruby app.rb». Запустился WEBrick, и я создал приложение Okta Ruby Example на Okta со следующими настройками.
настройка | Стоимость |
---|---|
Метка приложения | Пример Okta Ruby |
Принудительная аутентификация | ложный |
URL обратной ссылки | HTTP: // локальный: 4567 / авториз / SAML / обратный вызов |
Имя ID Формат | Адрес электронной почты |
Получатель | HTTP: // локальный: 4567 |
Ограничение аудитории | HTTP: // локальный: 4567 |
authnContextClassRef | PasswordProtectedTransport |
отклик | подписанный |
Утверждение | подписанный |
Запрос | Сжатый |
Назначения | HTTP: // локальный: 4567 / авториз / SAML / обратный вызов |
Заявления об атрибутах | электронная почта | $ {user.email}, ПгвЬЫат | $ {user.firstName} |
Чтобы настроить Синатру с настройками Отки, я начал с переименования config.yml.sample
файла:
mv config.yml.sample config.yml
В административном интерфейсе Otka для приложения я щелкнул вкладку «Вход в систему» и нажал кнопку «Просмотр инструкций по установке». Я скопировал значение «URL перенаправления входа» и скопировал его в значение target_url config.yml . Затем я загрузил сертификат и выполнил следующую команду в каталоге, в который я его скачал.
openssl x509 -noout -fingerprint -in "okta.cert"
Я скопировал отпечатки пальцев в config.yml по отпечаткам пальцев значения и перезапустить приложение. Я открыл http: // localhost: 4567 в своем браузере и смог успешно войти в систему.
JRuby
Чтобы начать с JRuby, я сначала прочитал README проекта. В нем упоминаются проблемы с «nokogiri» и объясняется, что проект содержит исправленную версию nokogiri 1.6.0. Поскольку я знал, что существует более поздняя версия, я изменил Gemfile
и удалил информацию о версии и пути из последней строки. Я скопировал config.yml
из проекта Ruby и выполнил следующие команды, чтобы установить Bundler, зависимости проекта и запустить приложение.
jruby -S gem install bundler jruby -S bundle install
Запуск второй команды привел к следующей ошибке:
Your jruby version is 1.7.18, but your Gemfile specified jruby 1.7.4
Я изменил, Gemfile
чтобы указать «1.7.18» и попытался снова. На этот раз это сработало. Я запустил приложение, используя следующую команду:
jruby app.rb
undefined method `auth' for Sinatra::Application:Class
Когда я попытался войти по адресу http: // localhost: 4567 , я увидел бесконечное перенаправление и следующую ошибку в моей консоли.
W, [2015-01-08T08:53:22.514000 #56144] WARN -- : attack prevented by Rack::Protection::SessionHijacking 0:0:0:0:0:0:0:1 - - [08/Jan/2015 08:53:22] "GET / HTTP/1.1" 302 - 0.0190 0:0:0:0:0:0:0:1 - - [08/Jan/2015:08:53:22 MST] "GET / HTTP/1.1" 302 0
Переполнение стека указывает на то, что это проблема, вызванная старой версией защиты стойки . Запуск «jruby -S bundle update rack-protection» обновил проект для использования rack-protection 1.5.3 (был 1.5.1). После перезапуска и повторной попытки я получил следующую ошибку:
I, [2015-01-08T08:59:32.679000 #56176] INFO -- omniauth: (saml) Callback phase initiated. E, [2015-01-08T08:59:34.747000 #56176] ERROR -- omniauth: (saml) Authentication failure! invalid_ticket: Onelogin::Saml::ValidationError, Digest mismatch 0:0:0:0:0:0:0:1 - - [08/Jan/2015:08:59:34 -0700] "POST /auth/saml/callback HTTP/1.1" 302 9 2.0760 0:0:0:0:0:0:0:1 - - [08/Jan/2015:08:59:34 -0700] "GET /auth/failure?message=invalid_ticket&strategy=saml HTTP/1.1" 404 449 0.0080 0:0:0:0:0:0:0:1 - - [08/Jan/2015:08:59:34 MST] "GET /auth/failure?message=invalid_ticket&strategy=saml HTTP/1.1" 404 449 - -> /auth/failure?message=invalid_ticket&strategy=saml 0:0:0:0:0:0:0:1 - - [08/Jan/2015:08:59:34 -0700] "GET /__sinatra__/404.png HTTP/1.1" 200 18893 0.0200 0:0:0:0:0:0:0:1 - - [08/Jan/2015:08:59:32 MST] "POST /auth/saml/callback HTTP/1.1" 302 9 - -> /auth/saml/callback 0:0:0:0:0:0:0:1 - - [08/Jan/2015:08:59:34 MST] "GET /__sinatra__/404.png HTTP/1.1" 200 18893 http://localhost:4567/auth/failure?message=invalid_ticket&strategy=saml -> /__sinatra__/404.png
На данный момент единственной вещью, отличной от моей рабочей версии и моего старого ноутбука, была версия Java. У моего старого ноутбука была «build 1.8.0_05-b13», поэтому я обновил до последней версии Java 8 (обновление 25). Это не помогло, поэтому я попытался обновить все пакеты с помощью «jruby -S bundle update». Это тоже не удалось, так что я решил попробовать версию JRuby, которая была на моем рабочем ноутбуке (версия 1.7.16.1). Я установил Homebrew , запустил «brew install jruby», удалил более новую версию из моего пути и понизил версию в Gemfile
. Мне пришлось переустановить Bundler и зависимости проектов с помощью следующих команд.
jruby -S gem install bundler jruby -S bundle install
Та же ошибка снова. Я вернулся Gemfile.lock
и выполнил единственную команду обновления пакета, которую я запускал на своем рабочем ноутбуке:
$ jruby -S bundle update sinatra
К сожалению, это все еще не решило проблему. Я скопировал проект с моего рабочего ноутбука и попытался запустить этот проект. Это не удалось, доказав, что это проблема среды, а не проекта / кода. Я попытался перезагрузиться, и когда это не сработало, я сдался. Довольно странно, что это не сработало на новой установке Yosemite — мне потребовалось менее 10 минут, чтобы все заработало изначально.
весна
Образцом Spring, с которым я работал в Okta, был образец spring-boot-security-saml-образца Винченцо Де Нотариса . В этом проекте используются Spring Boot и Spring Security SAML . Я создал приложение «Okta Spring Example» на Okta со следующими настройками.
настройка | Стоимость |
---|---|
Метка приложения | Okta Spring Пример |
Принудительная аутентификация | ложный |
URL обратной ссылки | HTTP: // локальный: 8080 / SAML / SSO |
Имя ID Формат | Адрес электронной почты |
Получатель | HTTP: // локальный: 8080 / SAML / SSO |
Ограничение аудитории | ком: vdenotaris: весна: зр |
authnContextClassRef | PasswordProtectedTransport |
отклик | подписанный |
Утверждение | подписанный |
Запрос | несжатого |
Назначения | HTTP: // локальный: 8080 / SAML / SSO |
Заявления об атрибутах | электронная почта | $ {user.email}, ПгвЬЫат | $ {user.firstName} |
Самая большая вещь, которую я узнал, пытаясь получить правильные значения, заключалась в том, что для параметра Request должно быть установлено значение Uncompressed .
После клонирования проекта GitHub на жесткий диск я добавил нового поставщика единого входа, добавив новый компонент в WebSecurityConfig.java
. URL-адрес, полученный от интерфейса администратора Okta: Вход> Просмотр инструкций по настройке> Общедоступная ссылка (в нижней части страницы).
@Bean(name = "idp-okta") public ExtendedMetadataDelegate ssoOktaExtendedMetadataProvider() throws MetadataProviderException { @SuppressWarnings({ "deprecation"}) HTTPMetadataProvider httpMetadataProvider = new HTTPMetadataProvider("https://client.okta.com/app/random-key-here/sso/saml/metadata", 5000); httpMetadataProvider.setParserPool(parserPool()); ExtendedMetadataDelegate extendedMetadataDelegate = new ExtendedMetadataDelegate(httpMetadataProvider, extendedMetadata()); extendedMetadataDelegate.setMetadataTrustCheck(false); extendedMetadataDelegate.setMetadataRequireSignature(false); return extendedMetadataDelegate; }
Для работы SSL-соединения мне пришлось скачать сертификат и импортировать его в хранилище ключей приложения. Чтобы сделать это в Chrome, я зашел на https://client.okta.com, щелкнул значок блокировки в адресной строке, а затем перетащил / бросил изображение сертификата на мой рабочий стол. Это привело к *.okta.com.cer
файлу на моем рабочем столе. Я добавил его в хранилище ключей, используя следующие команды (спасибо Stack Overflow ).
keytool -importcert -file ~/Desktop/\*.okta.com.cer -keystore src/main/resources/saml/samlKeystore.jks
Когда мне предложили ввести пароль, я ввел «nalle123». Это значение указывается в bean- keyManager
компоненте WebSecurityConfig.java . Затем я добавил этого поставщика в список поставщиков в metadata
компоненте.
@Bean @Qualifier("metadata") public CachingMetadataManager metadata() throws MetadataProviderException { List<MetadataProvider> providers = new ArrayList<MetadataProvider>(); providers.add(ssoOktaExtendedMetadataProvider()); providers.add(ssoCircleExtendedMetadataProvider()); return new CachingMetadataManager(providers); }
После внесения этих изменений я запустил приложение, используя «mvn spring-boot: run». Я перешел на http: // localhost: 8080, выбрал Okta в качестве моего Idp и успешно вошел в систему!
Резюме
В этой статье показано, как я получил приложения Node.js, Ruby и Spring, работающие с поддержкой SAML от Okta. Мой опыт с этим, когда я впервые попробовал это: Node был очень простым, Ruby был немного сложнее, JRuby был легким, а Spring занял несколько дней. Как вы можете заметить из этой статьи, Ruby / JRuby были самыми трудными для работы на чистой машине.
В целом, работа с Okta до сих пор была приятным опытом. Надеюсь, что эта статья поможет вам получить хороший опыт.