{"id":604,"date":"2017-08-17T12:09:13","date_gmt":"2017-08-17T10:09:13","guid":{"rendered":"http:\/\/www.loicmathieu.fr\/wordpress\/?p=604"},"modified":"2017-08-17T12:13:44","modified_gmt":"2017-08-17T10:13:44","slug":"kerberos-authentification-avec-springsecurity","status":"publish","type":"post","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/kerberos-authentification-avec-springsecurity\/","title":{"rendered":"Authentification Kerberos avec SpringSecurity"},"content":{"rendered":"<p><h2>Introduction<\/h2><\/p>\n<p>J&rsquo;ai r\u00e9cemment impl\u00e9ment\u00e9 une authentification (automatique) avec Kerberos. Ce protocole permet d&rsquo;authentifier automatiquement un utilisateur depuis sa session utilisateur (session windows par exemple). Via Kerberos, on authentifie donc un utilisateur sans lui demander son mot de passe ce qui est un plus (il n&rsquo;a pas \u00e0 se re-logguer : on utilise le contexte d&rsquo;authentification de Windows) en se basant sur le fait que s&rsquo;il a ouvert une session utilisateur en son nom &#8230; alors tout est OK!<\/p>\n<p>En impl\u00e9mentant \u00e7a, j&rsquo;ai eu pas mal de soucis dont j&rsquo;ai eu du mal \u00e0 trouver des solutions dans les ressources disponibles aujourd&rsquo;hui, d&rsquo;o\u00f9 l&rsquo;id\u00e9e de ce petit article.<\/p>\n<p><em><strong>Attention : je ne suis pas expert Kerberos, donc certains termes\/certaines assertions ne sont peut \u00eatre pas correcte, j&rsquo;exprime ici la mani\u00e8re dont j&rsquo;en ai compris le fonctionnement.<\/strong><\/em><\/p>\n<h2>Comment marche Kerberos :<\/h2>\n<p>Kerberos expliqu\u00e9 \u00e0 un enfant de 5 ans (en anglais) : <a href=\"http:\/\/www.roguelynn.com\/words\/explain-like-im-5-kerberos\" target=\"_blank\">http:\/\/www.roguelynn.com\/words\/explain-like-im-5-kerberos<\/a>\/<\/p>\n<p>R\u00e9sum\u00e9 en quelques lignes : Kerberos est un protocol d&rsquo;authentification par ticket:  le ticket est g\u00e9n\u00e9r\u00e9 par un syst\u00e8me tiers (le KDC &#8211; Key Distribution Center), inject\u00e9 dans un header HTTP, lut par votre navigateur. Ce ticket peut ensuite \u00eatre utilis\u00e9 par votre application qui va le faire valider par le KDC et peut ensuite s&rsquo;assurer de la validit\u00e9e de l&rsquo;authentification en r\u00e9cup\u00e9rant le contexte d&rsquo;authentification de votre session utilisateur (votre nom d&rsquo;utilisateur entre autre) depuis ce ticket.<\/p>\n<h2>Impl\u00e9mentation avec Spring Security kerberos<\/h2>\n<p>Site du projet : <a href=\"http:\/\/projects.spring.io\/spring-security-kerberos\/\" target=\"_blank\"><a href=\"http:\/\/projects.spring.io\/spring-security-kerberos\/\">http:\/\/projects.spring.io\/spring-security-kerberos\/<\/a><\/a><\/p>\n<h3>Configuration de la s\u00e9curit\u00e9<\/h3>\n<p>Pour commencer, vous avez besoin de deux composants permettant d&rsquo;initier une n\u00e9gociation Kerberos, et de configurer ceux-ci dans la configuration Spring Security. Un exemple ici en Spring Config : <\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Configuration\n@EnableWebMvcSecurity\npublic class SecurityConfig extends WebSecurityConfigurerAdapter {\n        @Autowired private AuthenticationManager authenticationManager;\n\n        \/**\n     * cr\u00e9\u00e9 un bean SpnegoAuthenticationProcessingFilter (filtre de n\u00e9gociation Kerberos)\n     * @return\n     *\/\n    @Bean\n    public SpnegoAuthenticationProcessingFilter spnegoAuthenticationProcessingFilter() {\n        SpnegoAuthenticationProcessingFilter filter = new SpnegoAuthenticationProcessingFilter();\n        filter.setAuthenticationManager(this.authenticationManager);\n        return filter;\n    }\n\n    \/**\n     * cr\u00e9\u00e9 un bean SpnegoEntryPoint (point d'entr\u00e9 de la n\u00e9gociation Kerberos)\n     * @return\n     *\/\n    @Bean\n    public SpnegoEntryPoint spnegoEntryPoint() {\n        return new SpnegoEntryPoint(\"\/login\");\n    }\n\n    \/**\n     * @inheritDoc\n     *\/\n    @Override\n    protected void configure(HttpSecurity http) throws Exception {\n        \/\/configuration Kerberos\n        http.exceptionHandling().authenticationEntryPoint(spnegoEntryPoint());\n        http.addFilterBefore(spnegoAuthenticationProcessingFilter(), BasicAuthenticationFilter.class);\n        \/\/... autre conf ...\n    }\n}\n<\/pre>\n<p>Ceci permettra, sur la page de login (ici \/login) de d\u00e9clencher une n\u00e9gociation Kerberos. Le navigateur va alors lire le ticket Kerberos et le mettre \u00e0 disposition pour le service d&rsquo;authentification Kerberos.<\/p>\n<h3>Configuration Kerberos<\/h3>\n<p>Pour le ticket Kerberos soit valid\u00e9, il faut fournir un ensemble de configuration, c&rsquo;est l\u00e0 que c&rsquo;est le plus compliqu\u00e9 et le plus sp\u00e9cifique \u00e0 votre configuration Kerberos. Il vous faudra l&rsquo;aide de vos administrateur du KDC (Key Distribution Center : vos administrateur Microsoft Active Directory pour une session windows) pour avoir un keytab et un krb5.ini. Ceux-ci permettent de faire le lien entre votre application et le KDC. <\/p>\n<p>Pour vous aider \u00e0 vous retrouver dans tous \u00e7a :<\/p>\n<ul><li>Le service principal doit \u00eatre de la forme : <strong>HTTP\/hostname@realm<\/strong> : exemple HTTP\/myhost.exemple.com@PC.EXEMPLE.COM. Attention, le hostname doit \u00eatre celui utilis\u00e9 dans le navigateur pour acc\u00e9der \u00e0 votre application.<\/li>\n\n<li><strong>Le keytab doit \u00eatre g\u00e9n\u00e9r\u00e9 pour le service principal que vous utilisez<\/strong>, il permet \u00e0 l&rsquo;host de votre application de s&rsquo;authentifier aupr\u00e8s du KDC<\/li>\n\n<li><strong>Votre krb5.ini doit contenir le realm utilis\u00e9 et le lien entre celui-ci et le KDC<\/strong> (un exemple plus bas), il permet \u00e0 votre application de savoir o\u00f9 se situe le KDC<\/li>\n<\/ul>\n<p>Une fois que vous avez tous ceci, il vous faut configurer Kerberos, voici un petit exemple via Spring Config :<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Configuration\npublic class KerberosConfiguration {\n    @Resource private UserDetailsService userDetailsService;\/\/votre UserDetailService permettant de charger votre utilisateur via son userName\n    @Value(\"${kerberos.service_principal}\") private String servicePrincipal;\n    @Value(\"${kerberos.keytab_location}\") private String keytabLocation;\n    @Value(\"${kerberos.krb5_ini}\") private String krb5iniLocation;\n\n    \/**\n     * cr\u00e9\u00e9 un bean KerberosServiceAuthenticationProvider pour l'authentification Kerberos\n     * @return\n     *\/\n    @Bean\n    public KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider() {\n        KerberosServiceAuthenticationProvider provider = new KerberosServiceAuthenticationProvider();\n        provider.setTicketValidator(sunJaasKerberosTicketValidator());\n        provider.setUserDetailsService(this.userDetailsService);\n        return provider;\n    }\n\n    \/**\n     * cr\u00e9\u00e9 un bean de type SunJaasKerberosTicketValidator : c'est lui qui validera le ticket Kerberos (le header)\n     * @return\n     *\/\n    @Bean\n    public SunJaasKerberosTicketValidator sunJaasKerberosTicketValidator() {\n        System.setProperty(\"java.security.krb5.conf\", krb5iniLocation);\n        SunJaasKerberosTicketValidator ticketValidator = new SunJaasKerberosTicketValidator();\n        ticketValidator.setServicePrincipal(servicePrincipal);\n        ticketValidator.setKeyTabLocation(new FileSystemResource(keytabLocation));\n        return ticketValidator;\n    }\n}\n<\/pre>\n<p>Et voici un exemple de krb5.ini :<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n[libdefaults]\n dns_lookup_realm = true\n ticket_lifetime = 24h\n renew_lifetime = 7d\n forwardable = true\n rdns = false\n default_realm = PC.EXEMPLE.COM\n default_ccache_name = KEYRING:persistent:%{uid}\n permitted_enctypes = aes128-cts aes256-cts arcfour-hmac-md5\n\n[realms]\nPC.EXEMPLE.COM = {\n        kdc = MYKDC.PC.EXEMPLE.COM\n        admin_server = MYKDC.PC.EXEMPLE.COM\n        default_domain = PC.EXEMPLE.COM\n}\n\n[domain_realm]\n.pc.exemple.com = PC.EXEMPLE.COM\npc.exemple.com = PC.EXEMPLE.COM\n\n[logging]\n    kdc = FILE:\/var\/log\/krb5\/krb5kdc.log\n    admin_server = FILE:\/var\/log\/krb5\/kadmind.log\n    default = SYSLOG:NOTICE:DAEMON\n\n<\/pre>\n<h3>Votre user service<\/h3>\n<p>Gr\u00e2ce \u00e0 kerberos, le navigateur va directement passer le contexte d&rsquo;authentification de votre session Windows au KDC qui le validera. Ensuite, vous aurez une authentification Spring Security valide &#8230; mais sans autres informations sur votre utilisateur que son login Windows.<\/p>\n<p>Pour aller plus loin, il vous faudra impl\u00e9menter votre propre UserDetailService qui ira, depuis le login de l&rsquo;utilisateur, charger l&rsquo;utilisateur depuis l&rsquo;AD\n\/un LDAP\/ une base. A vous de voir en fonction de l&rsquo;endroit o\u00f9 vous stockez les informations de l&rsquo;utilisateur, et surtout, ses droits!\n\n<\/p>\n<p>Avec Kerberos, l&rsquo;int\u00e9gration d&rsquo;un load balancer se trouve compliqu\u00e9. En effet, la n\u00e9gociation Kerberos s&rsquo;effectue depuis le navigateur et depuis le host de votre application. Si l&rsquo;URL de votre application est http:\/\/loadbalancer.exemple.com et que vos hosts sont host1.exemple.com et host2.exemple.com alors vous aurez un ticket Kerberos sur un principal HTTP\/loadbalancer.exemple.com@PC.EXEMPLE.COM et pas un ticket sur le principal HTTP\/host1.exemple.com@PC.EXEMPLE.COM.<\/p>\n<p>Pour r\u00e9soudre ce probl\u00e8me, il faut sur chaque host derri\u00e8re le loadbalancer utiliser le m\u00eame principal et le m\u00eame keytab qui sont celui du loadbalancer et pas celui de l&rsquo;host. C&rsquo;est la seule mani\u00e8re que j&rsquo;ai trouv\u00e9 de contourner le probl\u00e8me (m\u00eame si certain articles expliquent qu&rsquo;il faut g\u00e9n\u00e9rer un keytab avec deux principal : un pour l&rsquo;host et un pour le loadbalancer je n&rsquo;ai pas r\u00e9ussit \u00e0 faire fonctionner cette configuration)\u00e0.<\/p>\n<p>Voici deux articles sur le sujet :<\/p>\n<ul><li><a href=\"https:\/\/ssimo.org\/blog\/id_019.html\" target=\"_blank\">https:\/\/ssimo.org\/blog\/id_019.html<\/a><\/li>\n\n<li><a href=\"https:\/\/devcentral.f5.com\/questions\/apm-how-to-create-a-keytab-file-with-multiple-spns\" target=\"_blank\">https:\/\/devcentral.f5.com\/questions\/apm-how-to-create-a-keytab-file-with-multiple-spns<\/a><\/li>\n<\/ul>\n<p><\/p>","protected":false},"excerpt":{"rendered":"<p>Introduction J&rsquo;ai r\u00e9cemment impl\u00e9ment\u00e9 une authentification (automatique) avec Kerberos. Ce protocole permet d&rsquo;authentifier automatiquement un utilisateur depuis sa session utilisateur (session windows par exemple). Via Kerberos, on authentifie donc un utilisateur sans lui demander son mot de passe ce qui est un plus (il n&rsquo;a pas \u00e0 se re-logguer : on utilise le contexte d&rsquo;authentification de Windows) en se basant sur le fait que s&rsquo;il a ouvert une session utilisateur en son nom &#8230; alors tout est OK! En impl\u00e9mentant&#8230;<p class=\"read-more\"><a class=\"btn btn-default\" href=\"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/kerberos-authentification-avec-springsecurity\/\">Lire la suite<span class=\"screen-reader-text\"> Lire la suite<\/span><\/a><\/p><\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":4,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"","footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[9],"tags":[],"class_list":["post-604","post","type-post","status-publish","format-standard","hentry","category-informatique"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":827,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/devfest-lille-2018\/","url_meta":{"origin":604,"position":0},"title":"Devfest Lille 2018","author":"admin","date":"vendredi  6 juillet 2018","format":false,"excerpt":"Il y a quelques semaines, j'ai eu la chance d'assister au DevFest Lille, organis\u00e9 par le GDG Lille. Mon impression globale : une tr\u00e8s bonne organisation, des locaux sympa (merci l'IMT Lille-Douai), des talks int\u00e9r\u00e9ssant et beaucoup de bonne humeur! Voici un petit retour sur les talks auxquels j'ai assist\u00e9s\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1330,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/devoxx-france-2021-ledition-9-3-4\/","url_meta":{"origin":604,"position":1},"title":"Devoxx France 2021 &#8211; l&rsquo;\u00e9dition 9 3\/4","author":"admin","date":"vendredi  1 octobre 2021","format":false,"excerpt":"Cette semaine, c'est Devoxx France. Et pour la premi\u00e8re fois depuis pas mal de temps, je sors de chez moi, et j'y vais ! Je vous \u00e9cris ces mots dans le train de retour de la deuxi\u00e8me journ\u00e9e, pas de troisi\u00e8me pour moi cette ann\u00e9e. J'ai assist\u00e9 \u00e0 quelques talks,\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":40,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/integration-continue\/","url_meta":{"origin":604,"position":2},"title":"Int\u00e9gration Continue avec Cruise Control","author":"admin","date":"mercredi 14 novembre 2007","format":false,"excerpt":"Derni\u00e8rement, j'ai essay\u00e9 un serveur d'int\u00e9gration continue : Cruise Control. Je vais donc vous en parler ici. Tout d'abord, qu'est-ce que l'int\u00e9gration continue: L'int\u00e9gration continue est une technique de d\u00e9veloppement\/management de projet qui implique d'int\u00e9grer tr\u00e8s fr\u00e9quemment le travail de tout les membres. Ensuite, une compilation automatique doit \u00eatre lanc\u00e9\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1258,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/profiler-une-application-java-dans-un-conteneur-deploye-dans-kubernetes-avec-jfr-java-flight-recorder\/","url_meta":{"origin":604,"position":3},"title":"Profiler une application Java dans un conteneur d\u00e9ploy\u00e9 dans kubernetes avec JFR &#8211; Java Flight Recorder","author":"admin","date":"lundi 12 avril 2021","format":false,"excerpt":"La plupart des clients chez lesquels j'interviens aujourd'hui utilisent Kubernetes pour d\u00e9ployer leurs applications. Bien que Kubernetes soit un super outil, si on a besoin de ce type d'outil (qui est une discussion dans laquelle je ne rentrerais pas ici), il peut apporter une certaine complexit\u00e9 quant aux moyens de\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":391,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/chti-jug-drools-v5-et-drools-planner\/","url_meta":{"origin":604,"position":4},"title":"Ch&rsquo;ti Jug: Drools v5 et Drools Planner","author":"admin","date":"samedi 13 f\u00e9vrier 2010","format":false,"excerpt":"Jeudi 21 janvier s'est tenu dans les locaux de l'Universit\u00e9 de Lille 1 une session du Ch'ti Jug sponsoris\u00e9e par Cylande sur Drools:\u00a0 Drools, avec Cylande et l'Universit\u00e9 Lille 1 Pour ceux qui ne savent pas ce qu'est le Ch'ti Jug ou ce qu'est un Jug, voir l'introduction de mon\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":966,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/1-an-chez-zenika\/","url_meta":{"origin":604,"position":5},"title":"1 an chez Zenika","author":"admin","date":"mardi  3 septembre 2019","format":false,"excerpt":"Aujourd'hui est un jour sp\u00e9cial, cela fait un an que je suis arriv\u00e9 chez Zenika, apr\u00e8s 9 ans en tant qu'architecte logiciel dans la DSI d'un grand groupe de retail. Et apr\u00e8s un an, quel est donc le bilan ? Tout d'abord, Zenika m'a surpris. Lors des \u00e9changes que j'ai\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/posts\/604","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/comments?post=604"}],"version-history":[{"count":0,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/posts\/604\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/media?parent=604"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/categories?post=604"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/tags?post=604"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}