Пролетна интеграция на Kerberos Security с MiniKdc

Защита отгоре

Току-що обявих новия курс Learn Spring Security, включително пълния материал, фокусиран върху новия стек OAuth2 в Spring Security 5:

>> ПРЕГЛЕД НА КУРСА

1. Общ преглед

В този урок ще предоставим общ преглед на Spring Security Kerberos.

Ще напишем Kerberos клиент в Java, който се оторизира за достъп до нашата Kerberized услуга. И ние ще стартираме наш собствен вграден център за разпространение на ключове, за да извършим пълно удостоверяване от край до край Kerberos. Всичко това, без никаква външна инфраструктура, необходима благодарение на Spring Security Kerberos.

2. Kerberos и неговите предимства

Kerberos е мрежов протокол за удостоверяване, създаден от MIT през 80-те години, особено полезен за централизиране на удостоверяването в мрежа.

През 1987 г. MIT го пусна в общността с отворен код и все още е в активно развитие. През 2005 г. той беше канонизиран като IETF стандарт подRFC 4120.

Обикновено Kerberos се използва в корпоративна среда . Там той защитава средата по такъв начин, че потребителят да не трябва да удостоверява всяка услуга поотделно . Това архитектурно решение е известно като Single Sign-on .

Просто казано, Kerberos е билетна система. Потребителят се удостоверява веднъж и получава билет за издаване на билет (TGT). След това мрежовата инфраструктура обменя TGT за билети за услуги. Тези билети за услуги позволяват на потребителя да взаимодейства с инфраструктурни услуги, стига TGT да е валиден, което обикновено е за няколко часа.

Така че, чудесно е, че потребителят се подписва само в един момент. Но има и полза за сигурността: В такава среда паролата на потребителя никога не се изпраща по мрежата . Вместо това Kerberos го използва като фактор за генериране на друг таен ключ, който ще се използва за криптиране и декриптиране на съобщения.

Друго предимство е, че можем да управляваме потребители от централно място, да речем едно, което е подкрепено от LDAP. Следователно, ако деактивираме акаунт в нашата централизирана база данни за даден потребител, тогава ще отнемем неговия достъп в нашата инфраструктура. По този начин администраторите не трябва да отменят достъпа поотделно във всяка услуга.

Въведение в SPNEGO / Kerberos Authentication през пролетта предоставя задълбочен преглед на технологията.

3. Керберизирана среда

И така, нека създадем среда за удостоверяване с протокола Kerberos. Средата ще се състои от три отделни приложения, които ще работят едновременно.

Първо, ще имаме Център за разпространение на ключове, който ще действа като точка за удостоверяване. След това ще напишем приложение за клиент и услуга, което ще конфигурираме да използва протокол Kerberos.

Сега стартирането на Kerberos изисква малко инсталация и конфигурация. Въпреки това ще използваме Spring Security Kerberos, така че ще стартираме Центъра за разпространение на ключове програмно, във вграден режим. Освен това показаният по-долу MiniKdc е полезен в случай на тестване на интеграция с Kerberized инфраструктура.

3.1. Стартиране на Център за разпространение на ключове

Първо ще стартираме нашия Център за разпространение на ключове, който ще издаде TGT за нас:

String[] config = MiniKdcConfigBuilder.builder() .workDir(prepareWorkDir()) .principals("client/localhost", "HTTP/localhost") .confDir("minikdc-krb5.conf") .keytabName("example.keytab") .build(); MiniKdc.main(config);

По принцип сме дали на MiniKdc набор от принципали и конфигурационен файл; освен това казахме на MiniKdc как да се обади на keytab, който генерира.

MiniKdc ще генерира файл krb5.conf , който ще предоставим на нашите клиентски и сервизни приложения. Този файл съдържа информацията къде да намерим нашия KDC - хоста и порта за дадено царство.

MiniKdc.main стартира KDC и трябва да изведе нещо като:

Standalone MiniKdc Running --------------------------------------------------- Realm : EXAMPLE.COM Running at : localhost:localhost krb5conf : .\spring-security-sso\spring-security-sso-kerberos\krb-test-workdir\krb5.conf created keytab : .\spring-security-sso\spring-security-sso-kerberos\krb-test-workdir\example.keytab with principals : [client/localhost, HTTP/localhost]

3.2. Приложение на клиента

Нашият клиент ще бъде приложението Spring Boot, което използва RestTemplate за извършване на повиквания към външен REST API.

But, we're going to use KerberosRestTemplate instead. It'll need the keytab and the client's principal:

@Configuration public class KerberosConfig { @Value("${app.user-principal:client/localhost}") private String principal; @Value("${app.keytab-location}") private String keytabLocation; @Bean public RestTemplate restTemplate() { return new KerberosRestTemplate(keytabLocation, principal); } }

And that's it! KerberosRestTemplate negotiates the client side of the Kerberos protocol for us.

So, let's create a quick class that will query some data from a Kerberized service, hosted at the endpoint app.access-url:

@Service class SampleClient { @Value("${app.access-url}") private String endpoint; private RestTemplate restTemplate; // constructor, getter, setter String getData() { return restTemplate.getForObject(endpoint, String.class); } }

So, let's create our Service Application now so that this class has something to call!

3.3. Service Application

We'll use Spring Security, configuring it with the appropriate Kerberos-specific beans.

Also, note that the service will have its principal and use the keytab, too:

@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Value("${app.service-principal:HTTP/localhost}") private String servicePrincipal; @Value("${app.keytab-location}") private String keytabLocation; @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/home").permitAll() .anyRequest().authenticated() .and() .exceptionHandling() .authenticationEntryPoint(spnegoEntryPoint()) .and() .formLogin() .loginPage("/login").permitAll() .and() .logout().permitAll() .and() .addFilterBefore(spnegoAuthenticationProcessingFilter(authenticationManagerBean()), BasicAuthenticationFilter.class); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .authenticationProvider(kerberosAuthenticationProvider()) .authenticationProvider(kerberosServiceAuthenticationProvider()); } @Bean public KerberosAuthenticationProvider kerberosAuthenticationProvider() { KerberosAuthenticationProvider provider = new KerberosAuthenticationProvider(); // provider configuration return provider; } @Bean public SpnegoEntryPoint spnegoEntryPoint() { return new SpnegoEntryPoint("/login"); } @Bean public SpnegoAuthenticationProcessingFilter spnegoAuthenticationProcessingFilter( AuthenticationManager authenticationManager) { SpnegoAuthenticationProcessingFilter filter = new SpnegoAuthenticationProcessingFilter(); // filter configuration return filter; } @Bean public KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider() { KerberosServiceAuthenticationProvider provider = new KerberosServiceAuthenticationProvider(); // auth provider configuration return provider; } @Bean public SunJaasKerberosTicketValidator sunJaasKerberosTicketValidator() { SunJaasKerberosTicketValidator ticketValidator = new SunJaasKerberosTicketValidator(); // validator configuration return ticketValidator; } }

Note that we've configured Spring Security for SPNEGO authentication. This way, we'll be able to authenticate through the HTTP protocol, though we can also achieve SPNEGO authentication with core Java.

4. Testing

Now, we'll run an integration test to show that our client successfully retrieves data from an external server over the Kerberos protocol. To run this test, we need to have our infrastructure running, so MiniKdc and our Service Application both must be started.

Basically, we'll use our SampleClient from the Client Application to make a request to our Service Application. Let's test it out:

@Autowired private SampleClient sampleClient; @Test public void givenKerberizedRestTemplate_whenServiceCall_thenSuccess() { assertEquals("data from kerberized server", sampleClient.getData()); }

Note that we can also prove that the KerberizedRestTemplate is important by hitting the service without it:

@Test public void givenRestTemplate_whenServiceCall_thenFail() { sampleClient.setRestTemplate(new RestTemplate()); assertThrows(RestClientException.class, sampleClient::getData); }

As a side note, there's a chance our second test could re-use the ticket already stored in the credential cache. This would happen due to the automatic SPNEGO negotiation used in HttpUrlConnection.

As a result, the data might actually return, invalidating our test. Depending on our needs, then, we can disable ticket cache usage through the system property http.use.global.creds=false.

5. Conclusion

In this tutorial, we explored Kerberos for centralized user management and how Spring Security supports the Kerberos protocol and SPNEGO authentication mechanism.

Използвахме MiniKdc, за да издигнем вграден KDC и създадохме много прост Kerberized клиент и сървър. Тази настройка беше удобна за проучване и особено удобна, когато създадохме интеграционен тест, за да тестваме нещата.

Сега току-що надраскахме повърхността. За да се потопите по-дълбоко, разгледайте уики страницата Kerberos или нейната RFC. Също така официалната страница с документация ще бъде полезна. Освен това, за да видим как нещата могат да бъдат направени в основната java, следващият урок на Oracle го показва подробно.

Както обикновено, кодът може да бъде намерен на нашата страница в GitHub.

Сигурност отдолу

Току-що обявих новия курс Learn Spring Security, включително пълния материал, фокусиран върху новия стек OAuth2 в Spring Security 5:

>> ПРЕГЛЕД НА КУРСА